1 /***************************************************************************
3 BetterString.mcc - A better String gadget MUI Custom Class
4 Copyright (C) 1997-2000 Allan Odgaard
5 Copyright (C) 2005-2013 by BetterString.mcc Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 BetterString class Support Site: http://www.sf.net/projects/bstring-mcc/
21 ***************************************************************************/
26 #include <dos/dosextens.h>
27 #include <clib/alib_protos.h>
28 #include <proto/exec.h>
29 #include <proto/intuition.h>
30 #include <proto/utility.h>
31 #include <proto/dos.h>
33 #if defined(__amigaos4__)
34 #include <dos/obsolete.h>
38 #include <aros/config.h>
45 BOOL
OverwriteA(STRPTR text
, UWORD x
, UWORD length
, UWORD ptrn_length
, struct InstData
*data
)
51 if(length
< ptrn_length
)
53 ULONG expand
= ptrn_length
-length
;
55 if(data
->MaxLength
&& strlen(data
->Contents
)+expand
> (unsigned int)(data
->MaxLength
-1))
57 ptrn_length
-= expand
;
58 ptrn_length
+= (data
->MaxLength
-1)-strlen(data
->Contents
);
61 if(ExpandContentString(&data
->Contents
, expand
) == TRUE
)
62 memmove(data
->Contents
+x
+ptrn_length
, data
->Contents
+x
+length
, strlen(data
->Contents
+x
+length
)+1);
64 E(DBF_ALWAYS
, "content expansion by %ld bytes failed", expand
);
68 memmove(data
->Contents
+x
+ptrn_length
, data
->Contents
+x
+length
, strlen(data
->Contents
+x
+length
)+1);
70 CopyMem(text
, data
->Contents
+x
, ptrn_length
);
72 if(data
->BufferPos
>= x
)
74 data
->BufferPos
+= ptrn_length
-length
;
75 if(data
->BufferPos
< x
)
86 BOOL
Overwrite(STRPTR text
, UWORD x
, UWORD length
, struct InstData
*data
)
92 result
= OverwriteA(text
, x
, length
, strlen(text
), data
);
98 WORD
VolumeStart(STRPTR text
, WORD pos
)
100 BOOL searching
= TRUE
;
104 while(pos
> 0 && searching
)
106 switch(*(text
+pos
-1))
125 LONG
mFileNameStart(struct MUIP_BetterString_FileNameStart
*msg
)
127 STRPTR buffer
= msg
->buffer
;
132 while(pos
&& buffer
[pos
] != ':')
135 if(buffer
[pos
] == ':')
136 pos
= VolumeStart(buffer
, pos
);
138 pos
= MUIR_BetterString_FileNameStart_Volume
;
144 VOID
InsertFileName(UWORD namestart
, struct InstData
*data
)
146 struct ExAllData
*ead1
= &data
->FNCBuffer
->buffer
;
147 struct ExAllData
*ead2
;
148 struct FNCData
*fncframe
;
149 struct FNCData
*fncframe1
= data
->FNCBuffer
;
151 UWORD findnum
= data
->FileNumber
;
159 fncframe
= data
->FNCBuffer
;
160 ead2
= &fncframe
->buffer
;
163 //if(CmpStrings(ead1->ed_Name, ead2->ed_Name) > 0)
164 if(strcmp((const char *)ead1
->ed_Name
, (const char *)ead2
->ed_Name
) > 0)
167 ead2
= ead2
->ed_Next
;
168 if(ead2
== NULL
&& fncframe
->next
!= NULL
)
170 fncframe
= fncframe
->next
;
171 ead2
= &fncframe
->buffer
;
175 if(entrynum
!= findnum
)
176 ead1
= ead1
->ed_Next
;
177 if(ead1
== NULL
&& fncframe1
->next
!= NULL
)
179 fncframe1
= fncframe1
->next
;
180 ead1
= &fncframe1
->buffer
;
183 while(entrynum
!= findnum
);
185 snprintf(tmpname
, sizeof(tmpname
), "%s%s", ead1
->ed_Name
, ead1
->ed_Type
== 2 ? "/" : " ");
187 Overwrite(tmpname
, namestart
, data
->BufferPos
-namestart
, data
);
192 BOOL
FileNameComplete(Object
*obj
, BOOL backwards
, struct InstData
*data
)
198 if(data
->FNCBuffer
!= NULL
)
200 if(data
->FileEntries
== 1)
208 if(--data
->FileNumber
< 0)
209 data
->FileNumber
= data
->FileEntries
-1;
213 if(++data
->FileNumber
>= data
->FileEntries
)
214 data
->FileNumber
= 0;
217 InsertFileName(data
->FileNameStart
, data
);
222 LONG pos
= DoMethod(obj
, MUIM_BetterString_FileNameStart
, data
->Contents
, data
->BufferPos
);
226 case MUIR_BetterString_FileNameStart_Volume
:
229 STRPTR volumeName
= NULL
;
233 pos
= VolumeStart(data
->Contents
, data
->BufferPos
);
234 if((cut
= data
->BufferPos
-pos
) != 0)
236 dl
= LockDosList(LDF_READ
|LDF_DEVICES
|LDF_VOLUMES
|LDF_ASSIGNS
);
237 while((dl
= NextDosEntry(dl
, LDF_READ
|LDF_DEVICES
|LDF_VOLUMES
|LDF_ASSIGNS
)) != NULL
)
241 strlcpy(tmpBuffer
, AROS_BSTR_ADDR(dl
->dol_Name
), AROS_BSTR_strlen(dl
->dol_Name
));
243 strlcpy(tmpBuffer
, dl
->dol_Ext
.dol_AROS
.dol_DevName
, sizeof tmpBuffer
);
246 // dol_Name is a BSTR, we have to convert it to a regular C string
247 char *bstr
= BADDR(dl
->dol_Name
);
249 // a BSTR cannot exceed 255 characters, hence the buffer size of 256 is enough in any case
250 strlcpy(tmpBuffer
, &bstr
[1], (unsigned char)bstr
[0]);
253 if(Strnicmp(tmpBuffer
, data
->Contents
+pos
, cut
) == 0)
255 volumeName
= tmpBuffer
;
260 if(volumeName
!= NULL
)
262 if(OverwriteA(volumeName
, pos
, cut
, strlen(volumeName
)+1, data
))
263 data
->Contents
[data
->BufferPos
-1] = ':';
266 UnLockDosList(LDF_READ
|LDF_DEVICES
|LDF_VOLUMES
|LDF_ASSIGNS
);
273 struct FNCData
*fncbuffer
;
274 struct FNCData
*fncframe
;
275 struct ExAllControl
*control
;
278 UWORD namestart
= data
->BufferPos
;
279 char oldletter
= '\0';
280 BOOL filename
= TRUE
;
284 switch(*(data
->Contents
+namestart
-1))
297 if((data
->BufferPos
-namestart
) < 32)
299 strlcpy(pattern
, data
->Contents
+namestart
, sizeof(pattern
));
300 strlcat(pattern
, "~(#?.info)", sizeof(pattern
));
302 oldletter
= data
->Contents
[namestart
];
303 data
->Contents
[namestart
] = '\0';
305 if((fncbuffer
= (struct FNCData
*)SharedPoolAlloc(4100)) != NULL
)
307 fncbuffer
->next
= NULL
;
309 if((control
= (struct ExAllControl
*)AllocDosObject(DOS_EXALLCONTROL
, NULL
)))
311 char tokenized
[sizeof(pattern
) * 2 + 2];
313 if(ParsePatternNoCase(pattern
, tokenized
, sizeof(tokenized
)) != -1)
314 control
->eac_MatchString
= tokenized
;
316 if((dirlock
= Lock(data
->Contents
+pos
, ACCESS_READ
)))
320 fncframe
= fncbuffer
;
321 while(fncframe
&& ExAll(dirlock
, &fncframe
->buffer
, 4096, ED_TYPE
, control
))
323 entries
+= control
->eac_Entries
;
325 if((fncframe
->next
= (struct FNCData
*)SharedPoolAlloc(4100)))
326 fncframe
->next
->next
= NULL
;
328 fncframe
= fncframe
->next
;
330 control
->eac_Entries
+= entries
;
332 data
->FileNumber
= backwards
? control
->eac_Entries
-1 : 0;
333 data
->FileEntries
= control
->eac_Entries
;
334 data
->FileNameStart
= namestart
;
335 data
->FNCBuffer
= fncbuffer
;
337 if(control
->eac_Entries
)
339 data
->Contents
[namestart
] = oldletter
;
340 InsertFileName(namestart
, data
);
347 SharedPoolFree(fncbuffer
);
350 FreeDosObject(DOS_EXALLCONTROL
, (APTR
)control
);
356 data
->Contents
[namestart
] = oldletter
;