2 Copyright © 2003-2006, The AROS Development Team. All rights reserved.
6 /* This is based on muimaster/class/text.c (first string version)
7 * and on rom/intuition/str*.c
10 #define MUIMASTER_YES_INLINE_STDARG
17 #include <exec/types.h>
18 #include <clib/alib_protos.h>
20 #include <proto/exec.h>
21 #include <proto/dos.h>
22 #include <proto/graphics.h>
23 #include <proto/intuition.h>
24 #include <proto/utility.h>
25 #include <proto/muimaster.h>
26 #include <proto/locale.h>
29 #include <devices/rawkeycodes.h>
33 #include "muimaster_intern.h"
38 #include "clipboard.h"
44 extern struct Library
*MUIMasterBase
;
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 ULONG BufferSize
; /* memory allocated */
60 STRPTR SecBuffer
; /* Buffer for secret string */
61 ULONG NumChars
; /* string length */
62 ULONG BufferPos
; /* cursor (insert/delete) position */
63 ULONG MarkPos
; /* cursor text marking start pos */
64 LONG DispPos
; /* leftmost visible char */
65 ULONG DispCount
; /* number of visible chars */
75 struct MUI_EventHandlerNode ehn
;
76 struct MUI_PenSpec_intern inactive_text
;
77 struct MUI_PenSpec_intern active_text
;
78 struct MUI_PenSpec_intern marked_text
;
79 struct MUI_PenSpec_intern marked_bg
;
80 struct MUI_PenSpec_intern cursor
;
85 #define MSDF_ADVANCEONCR (1<<0)
86 #define MSDF_LONELYEDITHOOK (1<<1)
87 #define MSDF_MARKING (1<<2)
88 #define MSDF_KEYMARKING (1<<3)
89 #define MSDF_NOINPUT (1<<4)
90 #define MSDF_STAYACTIVE (1<<5)
108 /**************************************************************************
109 Buffer_SetNewContents
110 Allocate memory for buffer
111 **************************************************************************/
112 static BOOL
Buffer_Alloc(struct MUI_StringData
*data
)
115 (STRPTR
) AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
116 if (NULL
== data
->Buffer
)
118 bug("MUIC_String: Can't allocate %ld bytes for buffer1\n",
119 data
->BufferSize
* sizeof(char));
122 if (data
->msd_useSecret
)
125 (STRPTR
) AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
126 if (NULL
== data
->SecBuffer
)
128 bug("MUIC_String: Can't allocate %ld bytes for buffer2\n",
129 data
->BufferSize
* sizeof(char));
130 FreeVec(data
->Buffer
);
138 /**************************************************************************
139 Buffer_SetNewContents
140 Initialize buffer with a string, replace former content if any
141 **************************************************************************/
142 static BOOL
Buffer_SetNewContents(struct MUI_StringData
*data
,
145 if (NULL
== data
->Buffer
)
151 if (data
->msd_useSecret
)
152 data
->SecBuffer
[0] = 0;
157 data
->NumChars
= strlen(str
);
158 if (data
->NumChars
>= data
->BufferSize
)
159 data
->NumChars
= data
->BufferSize
- 1;
161 if (data
->msd_useSecret
)
163 strncpy(data
->SecBuffer
, str
, data
->BufferSize
);
164 data
->SecBuffer
[data
->BufferSize
- 1] = 0;
166 for (i
= 0; i
< data
->NumChars
; i
++)
167 data
->Buffer
[i
] = 0x78;
168 data
->Buffer
[data
->NumChars
] = 0;
172 strncpy(data
->Buffer
, str
, data
->BufferSize
);
173 data
->Buffer
[data
->BufferSize
- 1] = 0;
178 // avoid to BufferPos jumps to end of string if characters are inserted
180 if (data
->BufferPos
> data
->NumChars
)
181 data
->BufferPos
= data
->NumChars
;
186 /**************************************************************************
188 Add a char on cursor position
189 **************************************************************************/
190 static BOOL
Buffer_AddChar(struct MUI_StringData
*data
, unsigned char code
)
194 if (data
->Buffer
== NULL
)
197 if (data
->NumChars
+ 1 >= data
->BufferSize
)
200 if (data
->msd_useSecret
)
202 dst
= &data
->SecBuffer
[data
->BufferPos
+ 1];
204 memmove(dst
, &data
->SecBuffer
[data
->BufferPos
],
205 data
->NumChars
- data
->BufferPos
);
207 data
->Buffer
[data
->NumChars
] = 0x78;
208 data
->Buffer
[data
->NumChars
+ 1] = 0;
212 dst
= &data
->Buffer
[data
->BufferPos
+ 1];
214 memmove(dst
, &data
->Buffer
[data
->BufferPos
],
215 data
->NumChars
- data
->BufferPos
);
219 dst
[data
->NumChars
- data
->BufferPos
] = 0;
227 static WORD
Buffer_GetWordStartIndex(struct MUI_StringData
*data
,
230 WORD index
= startindex
;
234 if (data
->Buffer
[index
- 1] == ' ')
244 static WORD
Buffer_GetWordEndIndex(struct MUI_StringData
*data
,
247 WORD index
= startindex
;
249 while (index
< data
->NumChars
)
251 if (data
->Buffer
[index
] == ' ')
261 static WORD
Buffer_GetPrevWordIndex(struct MUI_StringData
*data
,
264 WORD index
= startindex
;
271 ((data
->Buffer
[index
- 1] == ' ') &&
272 (data
->Buffer
[index
] != ' ')))
282 static WORD
Buffer_GetSuccWordIndex(struct MUI_StringData
*data
,
285 WORD index
= startindex
;
287 while (index
< data
->NumChars
)
291 if ((index
== data
->NumChars
) ||
292 ((data
->Buffer
[index
- 1] == ' ') &&
293 (data
->Buffer
[index
] != ' ')))
302 static BOOL
Buffer_GetMarkedRange(struct MUI_StringData
*data
, WORD
*start
,
305 WORD markstart
= data
->MarkPos
;
306 WORD markstop
= data
->BufferPos
;
308 markstart
= MIN(markstart
, data
->NumChars
);
309 markstart
= MAX(markstart
, 0);
311 markstop
= MIN(markstop
, data
->NumChars
);
312 markstop
= MAX(markstop
, 0);
314 if (markstart
> markstop
)
316 markstart
^= markstop
;
317 markstop
^= markstart
;
318 markstart
^= markstop
;
321 switch (data
->MultiClick
)
329 markstart
= Buffer_GetWordStartIndex(data
, markstart
);
330 markstop
= Buffer_GetWordEndIndex(data
, markstop
);
336 markstop
= data
->NumChars
;
341 if (markstart
== markstop
)
349 //kprintf("Buffer_GetMarkedRange: returning %d .. %d\n",
350 // markstart, markstop);
355 static BOOL
Buffer_AnythingMarked(struct MUI_StringData
*data
)
357 if (!(data
->msd_Flags
& MSDF_MARKING
))
360 return Buffer_GetMarkedRange(data
, NULL
, NULL
);
363 static BOOL
Buffer_KillMarked(struct MUI_StringData
*data
)
365 WORD markstart
= data
->MarkPos
;
366 WORD markstop
= data
->BufferPos
;
369 //kprintf("\nBuffer_KillMarked 1 markpos %d bufferpos %d numchars %d\n",
370 // markstart, markstop, data->NumChars);
372 if (!(data
->msd_Flags
& MSDF_MARKING
))
375 data
->msd_Flags
&= ~MSDF_MARKING
;
377 if (!Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
380 //kprintf("Buffer_KillMarked 2 markstart %d markstop %d\n",
381 // markstart, markstop);
383 if (markstart
> markstop
)
385 markstart
^= markstop
;
386 markstop
^= markstart
;
387 markstart
^= markstop
;
390 marklen
= markstop
- markstart
;
392 //kprintf("Buffer_KillMarked: markstart %d markstop %d\n",
393 // markstart, markstop);
395 memmove(&data
->Buffer
[markstart
],
396 &data
->Buffer
[markstart
+ marklen
],
397 data
->NumChars
- markstart
- marklen
+ 1);
399 data
->NumChars
-= marklen
;
400 data
->BufferPos
= markstart
;
405 /**************************************************************************
407 **************************************************************************/
408 IPTR
String__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
410 struct MUI_StringData
*data
;
411 struct TagItem
*tags
, *tag
;
412 CONST_STRPTR str
= NULL
;
415 obj
= (Object
*) DoSuperNewTags(cl
, obj
, NULL
,
416 /* MUIA_FillArea, TRUE, */
417 TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
421 data
= INST_DATA(cl
, obj
);
422 data
->msd_useSecret
= FALSE
;
423 data
->msd_Align
= MUIV_String_Format_Left
;
424 data
->BufferSize
= 80;
427 Buffer_SetNewContents(data
, ""); /* <-- isnt this pointless? */
429 /* parse initial taglist */
430 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
434 case MUIA_String_Accept
:
435 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
438 case MUIA_String_Reject
:
439 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
442 case MUIA_String_AdvanceOnCR
:
443 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
447 case MUIA_String_AttachedList
:
448 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
451 case MUIA_String_Secret
:
452 data
->msd_useSecret
= (BOOL
) tag
->ti_Data
;
455 case MUIA_String_Contents
:
456 str
= (CONST_STRPTR
) tag
->ti_Data
;
459 case MUIA_String_EditHook
:
460 data
->msd_EditHook
= (struct Hook
*)tag
->ti_Data
;
463 case MUIA_String_Format
:
464 data
->msd_Align
= (LONG
) tag
->ti_Data
;
467 case MUIA_String_Integer
:
468 snprintf(integerbuf
, 19, "%ld", tag
->ti_Data
);
472 case MUIA_String_LonelyEditHook
:
473 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
474 MSDF_LONELYEDITHOOK
);
477 case MUIA_String_MaxLen
:
478 data
->BufferSize
= tag
->ti_Data
;
479 if (data
->BufferSize
< 1)
480 data
->BufferSize
= 1;
483 case MUIA_String_Columns
: /* BetterString */
484 data
->Columns
= (WORD
) tag
->ti_Data
;
487 case MUIA_String_NoInput
: /* BetterString */
488 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
491 case MUIA_String_StayActive
: /* BetterString */
492 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
499 if (Buffer_Alloc(data
))
501 Buffer_SetNewContents(data
, str
);
504 if (NULL
== data
->Buffer
)
506 CoerceMethod(cl
, obj
, OM_DISPOSE
);
510 D(bug("String_New(%p)\n", obj
));
512 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
513 data
->ehn
.ehn_Priority
= 0;
514 data
->ehn
.ehn_Flags
= 0;
515 data
->ehn
.ehn_Object
= obj
;
516 data
->ehn
.ehn_Class
= cl
;
518 CurrentTime(&data
->OldClick_Sec
, &data
->OldClick_Micro
);
523 /**************************************************************************
525 **************************************************************************/
526 IPTR
String__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
528 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
530 FreeVec(data
->Buffer
);
531 FreeVec(data
->SecBuffer
);
533 D(bug("String_Dispose %p\n", obj
));
535 return DoSuperMethodA(cl
, obj
, msg
);
538 /**************************************************************************
540 **************************************************************************/
541 IPTR
String__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
543 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
544 struct TagItem
*tags
= msg
->ops_AttrList
;
547 while ((tag
= NextTagItem(&tags
)) != NULL
)
551 case MUIA_String_Contents
:
552 Buffer_SetNewContents(data
, (STRPTR
) tag
->ti_Data
);
553 data
->msd_RedrawReason
= NEW_CONTENTS
;
554 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
555 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
558 case MUIA_String_Accept
:
559 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
562 case MUIA_String_Reject
:
563 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
566 case MUIA_String_AttachedList
:
567 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
570 case MUIA_String_Integer
:
574 snprintf(buf
, 19, "%ld", tag
->ti_Data
);
575 set(obj
, MUIA_String_Contents
, buf
);
579 case MUIA_String_AdvanceOnCR
:
580 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
584 case MUIA_String_BufferPos
:
585 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
586 data
->msd_Flags
&= ~MSDF_MARKING
;
587 data
->msd_RedrawReason
= MOVE_CURSOR
;
588 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
591 case MUIA_String_DisplayPos
:
592 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
593 data
->DispPos
= data
->BufferPos
; // move both pos
594 data
->msd_Flags
&= ~MSDF_MARKING
;
595 data
->msd_RedrawReason
= MOVE_CURSOR
;
596 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
599 case MUIA_String_NoInput
: /* BetterString */
600 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
603 case MUIA_String_StayActive
: /* BetterString */
604 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
608 case MUIA_String_SelectSize
: /* BetterString */
609 // TODO: Implement OM_SET(MUIA_String_SelectSize)!
615 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
619 /**************************************************************************
621 **************************************************************************/
622 IPTR
String__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
624 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
626 #define STORE *(msg->opg_Storage)
627 switch (msg
->opg_AttrID
)
629 case MUIA_String_Contents
:
630 if (data
->msd_useSecret
)
631 STORE
= (IPTR
) data
->SecBuffer
;
633 STORE
= (IPTR
) data
->Buffer
;
636 case MUIA_String_Secret
:
637 STORE
= (IPTR
) data
->msd_useSecret
;
640 case MUIA_String_Accept
:
641 STORE
= (IPTR
) data
->msd_Accept
;
644 case MUIA_String_Reject
:
645 STORE
= (IPTR
) data
->msd_Reject
;
648 case MUIA_String_AttachedList
:
649 STORE
= (IPTR
) data
->msd_AttachedList
;
652 case MUIA_String_Integer
:
656 get(obj
, MUIA_String_Contents
, &buf
);
660 StrToLong(buf
, &val
);
666 case MUIA_String_MaxLen
:
667 STORE
= (IPTR
) data
->BufferSize
;
670 case MUIA_String_AdvanceOnCR
:
671 STORE
= (data
->msd_Flags
& MSDF_ADVANCEONCR
) ? TRUE
: FALSE
;
674 case MUIA_String_BufferPos
:
675 STORE
= data
->BufferPos
;
678 case MUIA_String_DisplayPos
:
679 STORE
= data
->DispPos
;
682 case MUIA_String_NoInput
: /* BetterString */
683 STORE
= (data
->msd_Flags
& MSDF_NOINPUT
) ? TRUE
: FALSE
;
686 case MUIA_String_StayActive
: /* BetterString */
687 STORE
= (data
->msd_Flags
& MSDF_STAYACTIVE
) ? TRUE
: FALSE
;
690 case MUIA_String_SelectSize
: /* BetterString */
691 if (data
->msd_Flags
& MSDF_MARKING
)
693 WORD markstart
, markstop
;
695 if (Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
697 LONG size
= markstop
- markstart
;
699 if (data
->MarkPos
< data
->BufferPos
)
714 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
718 /**************************************************************************
720 **************************************************************************/
721 IPTR
String__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
722 struct MUIP_Setup
*msg
)
724 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
726 if (0 == DoSuperMethodA(cl
, obj
, (Msg
) msg
))
729 data
->is_active
= FALSE
;
730 set(obj
, MUIA_Background
,
731 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
733 zune_pen_spec_to_intern(
734 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
735 string_text_inactive
, &data
->inactive_text
);
736 zune_penspec_setup(&data
->inactive_text
, muiRenderInfo(obj
));
738 zune_pen_spec_to_intern(
739 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
740 string_text_active
, &data
->active_text
);
741 zune_penspec_setup(&data
->active_text
, muiRenderInfo(obj
));
743 zune_pen_spec_to_intern(
744 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
745 string_text_marked
, &data
->marked_text
);
746 zune_penspec_setup(&data
->marked_text
, muiRenderInfo(obj
));
748 zune_pen_spec_to_intern(
749 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
750 string_bg_marked
, &data
->marked_bg
);
751 zune_penspec_setup(&data
->marked_bg
, muiRenderInfo(obj
));
753 zune_pen_spec_to_intern(
754 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
755 string_cursor
, &data
->cursor
);
756 zune_penspec_setup(&data
->cursor
, muiRenderInfo(obj
));
758 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
762 /**************************************************************************
764 **************************************************************************/
765 IPTR
String__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
766 struct MUIP_Cleanup
*msg
)
768 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
770 D(bug("String_Cleanup %p\n", obj
));
771 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
773 zune_penspec_cleanup(&data
->inactive_text
);
774 zune_penspec_cleanup(&data
->active_text
);
775 zune_penspec_cleanup(&data
->marked_text
);
776 zune_penspec_cleanup(&data
->marked_bg
);
777 zune_penspec_cleanup(&data
->cursor
);
779 return (DoSuperMethodA(cl
, obj
, (Msg
) msg
));
782 /**************************************************************************
784 **************************************************************************/
785 IPTR
String__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
786 struct MUIP_AskMinMax
*msg
)
788 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
790 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
792 if (data
->Columns
>= 0)
794 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
795 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
796 msg
->MinMaxInfo
->MaxWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
800 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* 4;
801 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* 12;
802 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
805 msg
->MinMaxInfo
->MinHeight
+= _font(obj
)->tf_YSize
;
806 msg
->MinMaxInfo
->DefHeight
+= _font(obj
)->tf_YSize
;
807 msg
->MinMaxInfo
->MaxHeight
+= _font(obj
)->tf_YSize
;
809 /* D(bug("String_AskMinMax(%p): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n", */
810 /* obj, msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
811 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
812 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
818 static WORD
MaxDispPos(struct IClass
*cl
, Object
*obj
)
820 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
821 WORD numfit
, max_disppos
, numchars
;
822 struct TextExtent te
;
825 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
827 /* D(bug("MaxDispPos(current length: %d, bufferpos=%d)\n", */
828 /* data->NumChars, data->BufferPos)); */
830 /* D(bug("cursor_at_end: %d\n", cursor_at_end)); */
832 if (cursor_at_end
) /* Cursor at end of string ? */
834 /* D(bug("Making cursor last char\n")); */
835 numchars
= data
->NumChars
+ 1; /* Take cursor into account */
837 /* This has already been done by UpdateDisp() which called us
838 strinfo->Buffer[strinfo->NumChars] = 0x20;
844 numchars
= data
->NumChars
;
847 /* Find the amount of characters that fit into the bbox, counting
848 ** from the last character in the buffer and forward,
850 numfit
= TextFit(_rp(obj
),
851 &(data
->Buffer
[numchars
- 1]),
852 numchars
, &te
, NULL
, -1, _mwidth(obj
), _mheight(obj
));
854 max_disppos
= numchars
- numfit
;
856 /* if ((max_disppos > 0) && (!cursor_at_end))
860 /* D(bug("Numchars w/cursor: %d, Numfit: %d, maxdisppos=%d " */
861 /* "bbox->Width = %d te->te_Width = %d\n", */
862 /* numchars, numfit, max_disppos, _mwidth(obj), te.te_Width)); */
868 static void UpdateDisp(struct IClass
*cl
, Object
*obj
)
870 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
871 struct TextExtent te
;
874 /* If the cursor is at the trailing \0, insert a SPACE instead */
875 if (data
->BufferPos
== data
->NumChars
)
876 data
->Buffer
[data
->NumChars
] = 0x20;
878 /* In this function we check if the cursor has gone outside
879 ** of the visible area (because of application setting
880 ** strinfo->BufferPos or strinfo->DispPos to a different value, or
881 ** because of user input).
882 ** This is made a bit difficult by the rule (R), that there
883 ** should NOT be available space on the right, and characters
884 ** scrolled out at the left, at the same time.
885 ** We have 3 possible scenarios:
886 ** 1) Cursor to the left of DispPos:
887 ** Set DispPos to the lowest of BufferPos and the
888 ** maximum allowed disppos (according to (R) ).
889 ** 2) Cursor to the right of visible area:
890 ** Set dispose sou that the cursor is the last visible character.
891 ** This afheres to (R).
892 ** 3) Cursor inside visible area. Do a check on rule (R),
893 ** and if DispPos > max allowed, then adjust it down,
894 ** so that the last character in the buffer becomes last character
895 ** displayed. (The cursor will still be visible after adjustion)
898 /* 1) Cursor to the left of visible area */
899 if (data
->BufferPos
< data
->DispPos
)
903 max_disppos
= MaxDispPos(cl
, obj
);
904 data
->DispPos
= MIN(data
->BufferPos
, max_disppos
);
906 else /* Cursor equal to the right of disppos [ 2) or 3) ] */
910 /* How many pixels are there from current 1st displayed to cursor? */
911 strsize
= TextLength(_rp(obj
),
912 data
->Buffer
+ data
->DispPos
,
913 data
->BufferPos
- data
->DispPos
+ 1);
915 /* 2) More than fits into the gadget ? */
916 if (strsize
> _mwidth(obj
))
918 /* Compute new DispPos such that the cursor is at the right */
919 data
->DispPos
= data
->BufferPos
921 &(data
->Buffer
[data
->BufferPos
]),
922 data
->NumChars
, &te
, NULL
, -1,
923 _mwidth(obj
), _mheight(obj
)) + 1;
925 /* D(bug("cursor right of visible area, new disppos: %d\n", */
926 /* data->DispPos)); */
928 else /* 3). Cursor inside gadget */
932 max_disppos
= MaxDispPos(cl
, obj
);
933 if (data
->DispPos
> max_disppos
)
934 data
->DispPos
= max_disppos
;
936 } /* if (cursor inside or to the right of visible area ) */
940 /* Update the DispCount */
941 /* It might be necessary with special handling for centre aligned gads */
942 dispstr
= &(data
->Buffer
[data
->DispPos
]);
943 /* D(bug("DispCount before = %d\n", data->DispCount)); */
944 data
->DispCount
= TextFit(_rp(obj
), dispstr
,
945 data
->NumChars
- data
->DispPos
,
946 &te
, NULL
, 1, _mwidth(obj
), _mheight(obj
));
947 /* D(bug("DispCount after = %d\n", data->DispCount)); */
949 /* 0-terminate string */
950 data
->Buffer
[data
->NumChars
] = 0x00;
954 /* Gets left position of text in the string gadget */
955 static UWORD
GetTextLeft(struct IClass
*cl
, Object
*obj
)
957 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
959 STRPTR dispstr
= &(data
->Buffer
[data
->DispPos
]);
963 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
964 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
966 switch (data
->msd_Align
)
968 case MUIV_String_Format_Left
:
969 text_left
= _mleft(obj
);
972 case MUIV_String_Format_Center
:
974 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
976 textwidth
+= TextLength(_rp(obj
), " ", 1);
977 text_left
= _mleft(obj
) + ((_mwidth(obj
) - textwidth
) / 2);
978 /* D(bug("GetTextLeft: dispstr=%s, dispstrlen=%d, textw=%d, " */
980 /* dispstr, dispstrlen, textwidth, text_left)); */
984 case MUIV_String_Format_Right
:
986 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
989 textwidth
+= TextLength(_rp(obj
), " ", 1);
990 text_left
= _mleft(obj
) + (_mwidth(obj
) - 1 - textwidth
);
997 /* Gets right offset of text in the string gadget */
998 static UWORD
GetTextRight(struct IClass
*cl
, Object
*obj
)
1000 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1001 UWORD text_right
= 0;
1002 STRPTR dispstr
= &(data
->Buffer
[data
->DispPos
]);
1006 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
1007 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1009 switch (data
->msd_Align
)
1011 case MUIV_String_Format_Left
:
1013 _mleft(obj
) + TextLength(_rp(obj
), dispstr
, dispstrlen
);
1016 case MUIV_String_Format_Center
:
1018 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1021 textwidth
+= TextLength(_rp(obj
), " ", 1);
1022 text_right
= _mright(obj
) - ((_mwidth(obj
) - textwidth
) / 2);
1026 case MUIV_String_Format_Right
:
1027 text_right
= _mright(obj
);
1030 return (text_right
);
1034 /* Updates the stringdata in case user has set some fields */
1035 static VOID
UpdateStringData(struct IClass
*cl
, Object
*obj
)
1037 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1039 data
->NumChars
= strlen(data
->Buffer
);
1041 if (data
->BufferPos
> data
->NumChars
)
1043 data
->BufferPos
= data
->NumChars
;
1047 static VOID
TextM(Object
*obj
, struct MUI_StringData
*data
,
1048 STRPTR text
, WORD textlen
, WORD markstart
, WORD markend
)
1050 struct RastPort
*rp
= _rp(obj
);
1054 if (data
->is_active
)
1055 textpen
= data
->active_text
.p_pen
;
1057 textpen
= data
->inactive_text
.p_pen
;
1059 //kprintf("TextM: textlen %d markstart %d markend %d ... \n",
1060 // textlen, markstart, markend);
1062 /* <unmarked><marked><unmarked> */
1066 len
= MIN(markstart
, textlen
);
1071 //kprintf("A: %d ", len);
1073 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1074 Text(rp
, text
, len
);
1081 len
= MIN(markend
- len
, textlen
);
1086 //kprintf("B: %d ", len);
1087 SetABPenDrMd(_rp(obj
), data
->marked_text
.p_pen
,
1088 data
->marked_bg
.p_pen
, JAM2
);
1089 Text(rp
, text
, len
);
1097 //kprintf("C: %d ", textlen);
1099 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1100 Text(rp
, text
, textlen
);
1105 /**************************************************************************
1107 **************************************************************************/
1108 IPTR
String__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
1109 struct MUIP_Draw
*msg
)
1111 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1117 UWORD textleft_save
;
1118 WORD markstart
= 0, markstop
= 0;
1120 /* D(bug("\nString_Draw(%p) %ldx%ldx%ldx%ld reason=%ld msgflgs=%ld " */
1122 /* "displ=%ld len=%ld buf='%s'\n",obj,_mleft(obj),_mtop(obj), */
1123 /* _mwidth(obj),_mheight(obj), data->msd_RedrawReason, msg->flags, */
1124 /* data->BufferPos, data->DispPos, data->NumChars, data->Buffer)); */
1126 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1128 if (!(msg
->flags
& MADF_DRAWUPDATE
) && !(msg
->flags
& MADF_DRAWOBJECT
))
1131 SetFont(_rp(obj
), _font(obj
));
1132 if (data
->is_active
)
1133 textpen
= data
->active_text
.p_pen
;
1135 textpen
= data
->inactive_text
.p_pen
;
1137 /* Update the stringdata in case of user change */
1138 UpdateStringData(cl
, obj
);
1140 /* Update the DispPos and DispCount fields so that the gadget renders
1142 UpdateDisp(cl
, obj
);
1144 text_top
= _mtop(obj
)
1145 + ((_mheight(obj
) - _rp(obj
)->Font
->tf_YSize
) >> 1)
1146 + _rp(obj
)->Font
->tf_Baseline
;
1148 dispstr
= data
->Buffer
+ data
->DispPos
;
1149 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1150 textleft_save
= text_left
= GetTextLeft(cl
, obj
);
1152 // little flicker improvement, don't redraw first part of string
1153 // when adding a char
1154 if (msg
->flags
& MADF_DRAWUPDATE
&&
1155 data
->msd_RedrawReason
== DO_ADDCHAR
&&
1156 data
->msd_Align
== MUIV_String_Format_Left
&& data
->DispPos
== 0)
1158 text_left
+= TextLength(_rp(obj
), dispstr
, data
->BufferPos
- 1);
1159 dispstr
+= data
->BufferPos
- 1;
1160 dispstrlen
-= data
->BufferPos
- 1;
1161 DoMethod(obj
, MUIM_DrawBackground
, text_left
, _mtop(obj
),
1162 _mwidth(obj
) - text_left
+ _mleft(obj
), _mheight(obj
),
1163 text_left
, _mtop(obj
), 0);
1165 else if (msg
->flags
& MADF_DRAWUPDATE
)
1167 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1168 _mwidth(obj
), _mheight(obj
), _mleft(obj
), _mtop(obj
), 0);
1171 SetABPenDrMd(_rp(obj
), textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1172 Move(_rp(obj
), text_left
, text_top
);
1174 if ((data
->msd_Flags
& MSDF_MARKING
)
1175 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1177 TextM(obj
, data
, dispstr
, dispstrlen
, markstart
- data
->DispPos
,
1178 markstop
- data
->DispPos
);
1183 Text(_rp(obj
), dispstr
, dispstrlen
);
1185 if (data
->is_active
) // active, draw cursor
1187 UWORD cursoroffset
= data
->BufferPos
- data
->DispPos
;
1189 dispstr
= data
->Buffer
+ data
->DispPos
;
1190 text_left
= textleft_save
;
1192 SetABPenDrMd(_rp(obj
), data
->active_text
.p_pen
,
1193 data
->cursor
.p_pen
, JAM2
);
1194 text_left
+= TextLength(_rp(obj
), dispstr
, cursoroffset
);
1197 Move(_rp(obj
), text_left
, text_top
);
1199 ((data
->BufferPos
< data
->NumChars
)
1200 ? dispstr
+ cursoroffset
: (STRPTR
) " "), 1);
1204 data
->msd_RedrawReason
= NO_REASON
;
1208 /**************************************************************************
1209 Returns whether object needs redrawing
1210 **************************************************************************/
1211 static int String_HandleVanillakey(struct IClass
*cl
, Object
*obj
,
1212 unsigned char code
, UWORD qual
)
1214 struct MUI_StringData
*data
=
1215 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1218 D(bug("String_HandleVanillakey: code=%d qual=%d\n", code
, qual
));
1223 doinput
= (data
->msd_Flags
& MSDF_NOINPUT
) ? FALSE
: TRUE
;
1225 if (doinput
&& (code
== '\b')) /* backspace */
1227 if (Buffer_KillMarked(data
))
1232 if (data
->BufferPos
> 0)
1236 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1238 shift
= data
->BufferPos
;
1239 data
->msd_RedrawReason
= NEW_CONTENTS
;
1244 data
->msd_RedrawReason
= DO_BACKSPACE
;
1247 strcpy(&data
->Buffer
[data
->BufferPos
- shift
],
1248 &data
->Buffer
[data
->BufferPos
]);
1249 data
->BufferPos
-= shift
;
1250 data
->NumChars
-= shift
;
1256 if (doinput
&& (code
== 21)) // ctrl-u == NAK (like shift-bs)
1258 if (Buffer_KillMarked(data
))
1263 if (data
->BufferPos
> 0)
1265 strcpy(&data
->Buffer
[0], &data
->Buffer
[data
->BufferPos
]);
1266 data
->NumChars
-= data
->BufferPos
;
1267 data
->BufferPos
= 0;
1268 data
->msd_RedrawReason
= NEW_CONTENTS
;
1274 if (doinput
&& (code
== 127)) /* del */
1276 if (!Buffer_KillMarked(data
))
1278 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1280 data
->Buffer
[data
->BufferPos
] = 0;
1281 data
->NumChars
= data
->BufferPos
;
1282 data
->msd_RedrawReason
= NEW_CONTENTS
;
1286 if (data
->BufferPos
< data
->NumChars
)
1288 strcpy(&data
->Buffer
[data
->BufferPos
],
1289 &data
->Buffer
[data
->BufferPos
+ 1]);
1293 data
->msd_RedrawReason
= DO_DELETE
;
1299 if (doinput
&& (code
== 11)) // ctrl-k == VT == \v (like shift-del)
1301 if (!Buffer_KillMarked(data
))
1303 data
->Buffer
[data
->BufferPos
] = 0;
1304 data
->NumChars
= data
->BufferPos
;
1305 data
->msd_RedrawReason
= NEW_CONTENTS
;
1310 if (doinput
&& (code
== 24)) /* ctrl x == ascii cancel */
1312 if (!Buffer_KillMarked(data
))
1314 data
->Buffer
[0] = 0;
1315 data
->BufferPos
= 0;
1317 data
->msd_RedrawReason
= NEW_CONTENTS
;
1322 if (code
== 1) // ctrl-a, linestart
1324 data
->BufferPos
= 0;
1325 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1329 if (code
== 26) // ctrl-z, lineend
1331 data
->BufferPos
= data
->NumChars
;
1332 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1336 if (((ToLower(code
) == 'c') || (ToLower(code
) == 'x')) &&
1337 (qual
& IEQUALIFIER_RCOMMAND
))
1339 WORD markstart
, markstop
;
1341 if ((data
->msd_Flags
& MSDF_MARKING
)
1342 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1344 clipboard_write_text(&data
->Buffer
[markstart
],
1345 markstop
- markstart
);
1347 if (doinput
&& (ToLower(code
) == 'x'))
1349 Buffer_KillMarked(data
);
1353 data
->BufferPos
= markstop
;
1354 data
->msd_Flags
&= ~MSDF_MARKING
;
1361 if (doinput
&& (ToLower(code
) == 'v') && (qual
& IEQUALIFIER_RCOMMAND
))
1365 struct Locale
*locale
= OpenLocale(NULL
);
1367 retval
= Buffer_KillMarked(data
);
1368 if ((text
= clipboard_read_text()))
1370 STRPTR text2
= text
;
1373 while ((c
= *text2
++))
1375 if (!IsPrint(locale
, c
))
1377 if (!(Buffer_AddChar(data
, c
)))
1383 clipboard_free_text(text
);
1386 CloseLocale(locale
);
1391 if (data
->msd_Accept
!= NULL
)
1393 /* Check if character is accepted */
1394 if (NULL
== strchr(data
->msd_Accept
, code
))
1398 if (data
->msd_Reject
!= NULL
)
1400 /* Check if character is rejected */
1401 if (NULL
!= strchr(data
->msd_Reject
, code
))
1410 struct Locale
*locale
= OpenLocale(NULL
);
1412 if (!(code
>= 0x09 && code
<= 0x0D) && IsPrint(locale
, code
))
1414 Buffer_KillMarked(data
);
1415 if (Buffer_AddChar(data
, code
))
1417 data
->msd_RedrawReason
= DO_ADDCHAR
;
1422 CloseLocale(locale
);
1425 data
->msd_RedrawReason
= DO_UNKNOWN
;
1430 /**************************************************************************
1432 **************************************************************************/
1433 IPTR
String__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
1434 struct MUIP_HandleEvent
*msg
)
1436 struct MUI_StringData
*data
=
1437 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1440 BOOL edited
= FALSE
;
1441 LONG muikey
= msg
->muikey
;
1442 BOOL cursor_kills_marking
= FALSE
;
1444 if ((data
->msd_Flags
& MSDF_MARKING
)
1445 && !(data
->msd_Flags
& MSDF_KEYMARKING
))
1447 cursor_kills_marking
= TRUE
;
1450 if (muikey
== MUIKEY_NONE
)
1452 if (msg
->imsg
->Class
== IDCMP_RAWKEY
)
1454 static LONG muikeytable
[3][2] = {
1455 {MUIKEY_LEFT
, MUIKEY_RIGHT
},
1456 {MUIKEY_WORDLEFT
, MUIKEY_WORDRIGHT
},
1457 {MUIKEY_LINESTART
, MUIKEY_LINEEND
}
1459 WORD dirindex
= -1, amountindex
= 0;
1461 switch (msg
->imsg
->Code
)
1473 muikey
= MUIKEY_LINESTART
;
1477 muikey
= MUIKEY_LINEEND
;
1483 if ((dirindex
!= -1) && (muikey
== MUIKEY_NONE
))
1486 Qualifier
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
1490 else if (msg
->imsg
->Qualifier
& IEQUALIFIER_CONTROL
)
1495 muikey
= muikeytable
[amountindex
][dirindex
];
1501 D(bug("String_HandleEvent: muikey %d, imsg %p is_active=%d\n", muikey
,
1502 msg
->imsg
, data
->is_active
));
1503 if (muikey
!= MUIKEY_NONE
&& data
->is_active
)
1505 retval
= MUI_EventHandlerRC_Eat
;
1510 if (cursor_kills_marking
)
1513 data
->BufferPos
= MIN(data
->BufferPos
, data
->MarkPos
);
1514 if (data
->BufferPos
> 0)
1517 data
->msd_Flags
&= ~MSDF_MARKING
;
1519 else if (data
->BufferPos
> 0)
1524 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1528 if (cursor_kills_marking
)
1531 data
->BufferPos
= MAX(data
->BufferPos
, data
->MarkPos
);
1532 data
->msd_Flags
&= ~MSDF_MARKING
;
1534 else if (data
->BufferPos
< data
->NumChars
)
1538 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1541 case MUIKEY_WORDLEFT
:
1542 if (data
->BufferPos
> 0)
1545 Buffer_GetPrevWordIndex(data
, data
->BufferPos
);
1547 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1549 if (cursor_kills_marking
)
1551 data
->msd_Flags
&= ~MSDF_MARKING
;
1555 case MUIKEY_WORDRIGHT
:
1556 if (data
->BufferPos
< data
->NumChars
)
1559 Buffer_GetSuccWordIndex(data
, data
->BufferPos
);
1561 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1563 if (cursor_kills_marking
)
1565 data
->msd_Flags
&= ~MSDF_MARKING
;
1569 case MUIKEY_LINESTART
:
1570 data
->BufferPos
= 0;
1572 if (cursor_kills_marking
)
1574 data
->msd_Flags
&= ~MSDF_MARKING
;
1578 case MUIKEY_LINEEND
:
1579 data
->BufferPos
= data
->NumChars
;
1581 if (cursor_kills_marking
)
1583 data
->msd_Flags
&= ~MSDF_MARKING
;
1588 if (data
->msd_AttachedList
)
1589 set(data
->msd_AttachedList
,
1590 MUIA_List_Active
, MUIV_List_Active_Up
);
1593 if (data
->msd_AttachedList
)
1594 set(data
->msd_AttachedList
,
1595 MUIA_List_Active
, MUIV_List_Active_Down
);
1598 if (data
->msd_AttachedList
)
1599 set(data
->msd_AttachedList
,
1600 MUIA_List_Active
, MUIV_List_Active_PageUp
);
1602 case MUIKEY_PAGEDOWN
:
1603 if (data
->msd_AttachedList
)
1604 set(data
->msd_AttachedList
,
1605 MUIA_List_Active
, MUIV_List_Active_PageDown
);
1608 if (data
->msd_AttachedList
)
1609 set(data
->msd_AttachedList
,
1610 MUIA_List_Active
, MUIV_List_Active_Top
);
1613 if (data
->msd_AttachedList
)
1614 set(data
->msd_AttachedList
,
1615 MUIA_List_Active
, MUIV_List_Active_Bottom
);
1621 get(obj
, MUIA_String_Contents
, &buf
);
1623 if (data
->msd_Flags
& MSDF_STAYACTIVE
)
1625 /* Do not change active object */
1627 else if (data
->msd_Flags
& MSDF_ADVANCEONCR
)
1629 set(_win(obj
), MUIA_Window_ActiveObject
,
1630 MUIV_Window_ActiveObject_Next
);
1632 else if (!(data
->msd_Flags
& MSDF_STAYACTIVE
))
1634 set(_win(obj
), MUIA_Window_ActiveObject
,
1635 MUIV_Window_ActiveObject_None
);
1638 set(obj
, MUIA_String_Acknowledge
, buf
);
1642 case MUIKEY_WINDOW_CLOSE
:
1643 data
->is_active
= FALSE
;
1644 set(obj
, MUIA_Background
,
1645 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1646 DoMethod(obj
, MUIM_GoInactive
);
1653 } // if (muikey != MUIKEY_NONE)
1657 UWORD code
= msg
->imsg
->Code
;
1658 //UWORD qual = msg->imsg->Qualifier;
1659 WORD x
= msg
->imsg
->MouseX
;
1660 WORD y
= msg
->imsg
->MouseY
;
1662 //bug("String_HandleEvent: parsing imsg %p, class=%ld\n",
1663 // msg->imsg, msg->imsg->Class);
1665 switch (msg
->imsg
->Class
)
1667 case IDCMP_MOUSEBUTTONS
: /* set cursor and activate it */
1668 if (code
== SELECTDOWN
)
1670 //bug("String_HandleEvent: code == SELECTDOWN, x=%d y=%d\n",
1673 if (_isinobject(x
, y
))
1675 UWORD text_left
, text_right
;
1677 retval
= MUI_EventHandlerRC_Eat
;
1679 CurrentTime(&data
->NewClick_Sec
, &data
->NewClick_Micro
);
1680 if (DoubleClick(data
->OldClick_Sec
,
1681 data
->OldClick_Micro
, data
->NewClick_Sec
,
1682 data
->NewClick_Micro
))
1688 data
->MultiClick
= 0;
1690 data
->OldClick_Sec
= data
->NewClick_Sec
;
1691 data
->OldClick_Micro
= data
->NewClick_Micro
;
1693 //kprintf("multiclick %d\n", data->MultiClick);
1695 if (!data
->is_active
)
1697 //bug("String got button, lets activate\n");
1698 data
->is_active
= TRUE
;
1699 data
->msd_RedrawReason
= WENT_ACTIVE
;
1701 set(obj
, MUIA_Background
,
1702 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1705 //DoMethod(obj, MUIM_GoActive);
1706 set(_win(obj
), MUIA_Window_ActiveObject
, obj
);
1707 // let other objects a chance to get desactivated
1711 if (!(data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
))
1713 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1714 (IPTR
) & data
->ehn
);
1715 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
1716 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1717 (IPTR
) & data
->ehn
);
1720 text_left
= GetTextLeft(cl
, obj
);
1721 text_right
= GetTextRight(cl
, obj
);
1723 /* Check if mouseclick is inside displayed text */
1724 if ((x
>= text_left
) && (x
<= text_right
))
1726 /* Find new cursor pos. */
1727 struct TextExtent te
;
1729 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1731 newpos
= data
->DispPos
1732 + TextFit(_rp(obj
), dispstr
,
1733 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1734 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1736 if (data
->BufferPos
!= newpos
)
1738 data
->BufferPos
= newpos
;
1742 else if (x
< text_left
)
1744 /* Click on empty space at left. Set cursor to first
1746 if (data
->BufferPos
!= data
->DispPos
)
1748 data
->BufferPos
= data
->DispPos
;
1754 /* Click on empty space at right. Set cursor to last
1756 if (data
->BufferPos
!=
1757 data
->DispPos
+ data
->DispCount
)
1760 data
->DispPos
+ data
->DispCount
;
1763 } /* if (click is on text or not) */
1765 data
->MarkPos
= data
->BufferPos
;
1767 if (data
->MultiClick
== 0)
1769 if (data
->msd_Flags
& MSDF_MARKING
)
1771 data
->msd_Flags
&= ~MSDF_MARKING
;
1775 else if (data
->MultiClick
1776 && Buffer_GetMarkedRange(data
, NULL
, NULL
))
1778 data
->msd_Flags
|= MSDF_MARKING
;
1783 } /* is in object */
1784 else if (data
->is_active
1785 && !(data
->msd_Flags
& MSDF_STAYACTIVE
))
1786 /* and click not on object */
1788 data
->is_active
= FALSE
;
1789 set(obj
, MUIA_Background
,
1790 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1791 string_bg_inactive
);
1792 //DoMethod(obj, MUIM_GoInactive);
1793 // let other objects a chance to get activated
1796 } /* if (code == SELECTDOWN) */
1797 else if (code
== SELECTUP
)
1799 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
1801 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1802 (IPTR
) & data
->ehn
);
1803 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
1804 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1805 (IPTR
) & data
->ehn
);
1810 case IDCMP_MOUSEMOVE
:
1811 if (data
->is_active
)
1813 UWORD text_left
, text_right
;
1815 if (!(data
->msd_Flags
& MSDF_MARKING
))
1817 data
->msd_Flags
|= MSDF_MARKING
;
1820 text_left
= GetTextLeft(cl
, obj
);
1821 text_right
= GetTextRight(cl
, obj
);
1823 /* Check if mouseclick is inside displayed text */
1824 if ((x
>= text_left
) && (x
<= text_right
))
1826 /* Find new cursor pos. */
1827 struct TextExtent te
;
1829 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1831 newpos
= data
->DispPos
1832 + TextFit(_rp(obj
), dispstr
,
1833 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1834 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1836 if (data
->BufferPos
!= newpos
)
1838 WORD old_markstart
= 0, old_markstop
= 0;
1839 WORD markstart
= 0, markstop
= 0;
1840 BOOL was_marked
, is_marked
;
1842 was_marked
= Buffer_AnythingMarked(data
) &&
1843 Buffer_GetMarkedRange(data
, &old_markstart
,
1846 data
->BufferPos
= newpos
;
1848 is_marked
= Buffer_AnythingMarked(data
) &&
1849 Buffer_GetMarkedRange(data
, &markstart
,
1852 if ((was_marked
!= is_marked
) ||
1853 (old_markstart
!= markstart
) ||
1854 (old_markstop
!= markstop
))
1860 else if ((x
< text_left
) && (data
->BufferPos
> 0))
1864 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1866 else if ((x
> text_right
)
1867 && (data
->BufferPos
< data
->NumChars
))
1871 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1873 //kprintf(" ---- bp: %d\n", data->BufferPos);
1881 //bug("String_HandleEvent: idcmp_rawkey\n");
1883 if (!data
->is_active
)
1886 code
= ConvertKey(msg
->imsg
);
1889 switch (msg
->imsg
->Code
)
1891 case 0x64: /* LALT */
1892 case 0x65: /* RALT */
1893 case 0x64 | IECODE_UP_PREFIX
:
1894 case 0x65 | IECODE_UP_PREFIX
:
1896 Qualifier
& (IEQUALIFIER_LALT
|
1899 data
->MarkPos
= data
->BufferPos
;
1901 (MSDF_MARKING
| MSDF_KEYMARKING
);
1905 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
1915 String_HandleVanillakey(cl
, obj
, code
,
1916 msg
->imsg
->Qualifier
);
1919 retval
= MUI_EventHandlerRC_Eat
;
1929 set(obj
, MUIA_String_Contents
, data
->Buffer
); // trigger notification
1933 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1935 //D(bug("String eh return %ld\n", retval));
1941 /**************************************************************************
1942 MUIM_Export : to export an object's "contents" to a dataspace object.
1943 **************************************************************************/
1944 IPTR
String__MUIM_Export(struct IClass
*cl
, Object
*obj
,
1945 struct MUIP_Export
*msg
)
1947 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1951 if (data
->msd_useSecret
)
1952 buf
= data
->SecBuffer
;
1956 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
1959 DoMethod(msg
->dataspace
, MUIM_Dataspace_Add
,
1960 (IPTR
) buf
, data
->NumChars
+ 1, (IPTR
) id
);
1962 DoMethod(msg
->dataspace
, MUIM_Dataspace_Remove
, (IPTR
) id
);
1969 /**************************************************************************
1970 MUIM_Import : to import an object's "contents" from a dataspace object.
1971 **************************************************************************/
1972 IPTR
String__MUIM_Import(struct IClass
*cl
, Object
*obj
,
1973 struct MUIP_Import
*msg
)
1978 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
1980 if ((s
= (STRPTR
) DoMethod(msg
->dataspace
, MUIM_Dataspace_Find
,
1983 set(obj
, MUIA_String_Contents
, s
);
1990 /**************************************************************************
1992 **************************************************************************/
1993 IPTR
String__MUIM_GoActive(struct IClass
*cl
, Object
*obj
, Msg msg
)
1995 struct MUI_StringData
*data
=
1996 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1998 //D(bug("String_GoActive %p\n", obj));
1999 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2000 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
2001 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2002 data
->is_active
= TRUE
;
2003 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
2004 data
->msd_RedrawReason
= WENT_ACTIVE
;
2006 set(obj
, MUIA_Background
,
2007 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_active
);
2012 /**************************************************************************
2014 **************************************************************************/
2015 IPTR
String__MUIM_GoInactive(struct IClass
*cl
, Object
*obj
, Msg msg
)
2017 struct MUI_StringData
*data
=
2018 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2020 //D(bug("String_GoInactive %p\n", obj));
2022 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2023 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
2024 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2025 data
->is_active
= FALSE
;
2026 data
->msd_RedrawReason
= WENT_INACTIVE
;
2027 data
->MultiClick
= 0;
2030 set(obj
, MUIA_Background
,
2031 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
2036 /**************************************************************************
2037 MUIM_String_ClearSelected (BetterString)
2038 **************************************************************************/
2039 IPTR
String__MUIM_ClearSelected(struct IClass
*cl
, Object
*obj
,
2040 struct MUIP_String_ClearSelected
*msg
)
2042 struct MUI_StringData
*data
=
2043 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2045 //D(bug("String_ClearSelected %p\n", obj));
2047 if (Buffer_KillMarked(data
))
2049 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2055 /**************************************************************************
2056 MUIM_String_Insert (BetterString)
2057 **************************************************************************/
2058 IPTR
String__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
2059 struct MUIP_String_Insert
*msg
)
2061 struct MUI_StringData
*data
=
2062 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2064 ULONG old_bufferpos
;
2065 ULONG num_inserted
= 0;
2067 //D(bug("String_Insert %p\n", obj));
2069 switch ((ULONG
) msg
->pos
)
2071 case MUIV_String_Insert_StartOfString
:
2075 case MUIV_String_Insert_EndOfString
:
2076 pos
= data
->NumChars
;
2079 case MUIV_String_Insert_BufferPos
:
2080 pos
= data
->BufferPos
;
2088 if ((pos
< 0) || (pos
> data
->NumChars
))
2091 old_bufferpos
= data
->BufferPos
;
2092 data
->BufferPos
= pos
;
2094 while (msg
->text
[num_inserted
]
2095 && Buffer_AddChar(data
, msg
->text
[num_inserted
]))
2102 if (old_bufferpos
>= pos
)
2104 data
->BufferPos
= old_bufferpos
+ num_inserted
;
2108 data
->BufferPos
= old_bufferpos
;
2111 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2117 /**************************************************************************
2118 MUIM_String_FileNameStart (BetterString)
2119 **************************************************************************/
2120 IPTR
String__MUIM_FileNameStart(struct IClass
*cl
, Object
*obj
,
2121 struct MUIP_String_FileNameStart
*msg
)
2123 struct MUI_StringData
*data
=
2124 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2127 //D(bug("String_FileNameStart %p\n", obj));
2129 if (data
->msd_useSecret
)
2131 buf
= data
->SecBuffer
;
2137 // TODO: Implement String_FileNameStart correctly!
2142 BOOPSI_DISPATCHER(IPTR
, String_Dispatcher
, cl
, obj
, msg
)
2144 switch (msg
->MethodID
)
2147 return String__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
2149 return String__OM_DISPOSE(cl
, obj
, msg
);
2151 return String__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2153 return String__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2156 return String__MUIM_Setup(cl
, obj
, (APTR
) msg
);
2158 return String__MUIM_Cleanup(cl
, obj
, (APTR
) msg
);
2159 case MUIM_AskMinMax
:
2160 return String__MUIM_AskMinMax(cl
, obj
, (APTR
) msg
);
2162 return String__MUIM_Draw(cl
, obj
, (APTR
) msg
);
2164 return String__MUIM_Export(cl
, obj
, (APTR
) msg
);
2166 return String__MUIM_Import(cl
, obj
, (APTR
) msg
);
2168 return String__MUIM_GoActive(cl
, obj
, (APTR
) msg
);
2169 case MUIM_GoInactive
:
2170 return String__MUIM_GoInactive(cl
, obj
, (APTR
) msg
);
2171 case MUIM_HandleEvent
:
2172 return String__MUIM_HandleEvent(cl
, obj
, (APTR
) msg
);
2175 case MUIM_String_ClearSelected
:
2176 return String__MUIM_ClearSelected(cl
, obj
, (APTR
) msg
);
2177 case MUIM_String_Insert
:
2178 return String__MUIM_Insert(cl
, obj
, (APTR
) msg
);
2179 case MUIM_String_FileNameStart
:
2180 return String__MUIM_FileNameStart(cl
, obj
, (APTR
) msg
);
2183 return DoSuperMethodA(cl
, obj
, msg
);
2185 BOOPSI_DISPATCHER_END
2190 const struct __MUIBuiltinClass _MUI_String_desc
=
2194 sizeof(struct MUI_StringData
),
2195 (void *)String_Dispatcher