I would like to capitalize the first letter of each word, but I haven’t found a way to do that.
As it is not a predefined text, would I have to create a function for this?
I only saw the UPPER and LOWER.
Any idea?
You’ll need to write a function/procedure to do this. Shouldn’t be that hard.
StringTheory does have a method Captitalze, if you already have that.
There is the CAP attribute you can put on an entry field. In the dictionary it is “Word Capitalized” on the Attributes page. It will capitalize the first word and any subsequent words after a space as you type. It doesn’t guarantee that the user won’t do something unexpected, like type in two words together and then add a space between them, but it will work 99% of the time.
Jon, also if you copy/paste something like “the quick fox jumped over the lazy sleeping dog.” into the entry field the CAP functionality doesn’t get applied.
I found this code.
UpLowText PROCEDURE (*string Txt)
Ndx long,auto
CODE
if ~Txt then return.
if SIZE(Txt)<3 | !Edit to prevent Txt[3] error,
or Txt[2] >= 'a' or Txt[3] >= 'a' then return. !<---NOTE: Do not touch if already some lowercase
Txt = lower(Txt) !Lower it all and then Upper the right letters
Txt[1] = UPPER(Txt[1]) !1st letter UPPER
loop Ndx = 2 to len(clip(txt))
Case Txt[ Ndx - 1 ]
of 'a' to 'z'
of 'A' to 'Z'
of '0' to '9'
!Prior char is Letter/Number so leave Current as lower
else
Txt[Ndx] = UPPER(Txt[Ndx]) !Prior Not letter/number so UPPER Current Char
end
end
return
You’ll have to adjust to the rules you prefer. Often only the Letter after a Space is Upper’d. This code does upper after all special characters so after apostrophe is upper e.g. O’Donnell not O’donnell
Edit:
Fixed to check for IF SIZE()<3
because Txt[3] >= 'a'
would be an illegal array subscript.
This was meant for strings longer than 3 bytes like Name and Address. Now a 2 byte size string does not get UpLow which I’m fine with.
Thanks @vitesse
I know it is not your code Carl but just be aware that this will fail if Txt is only one or two characters long.
need to either check the size(Txt) or use sub() instead.
I think Mike Hanson had a “proper case” function floating around somewhere that catered for lots of special cases. I will see if I can find it.
from a message by Mike Hanson 17 May 2003, 03:43:23
on this thread:
https://groups.google.com/g/comp.lang.clarion/c/pHcdA5kUm4Y/m/j7WwwKN-4iAJ
Here's the best of the bunch, evolved from DOS days, and now availabe
in the BoxSoft SuperStuff templates. Not only does it handle names
like McMaster and O'Henry, it will also handle McDonald's without
capitalizing the trailing "s". It's aware of international characters
too.
-=> Mike Hanson <=-
MEMBER
!==============================================================================
MAP
Proper PROCEDURE(STRING N),STRING
IsNumericChar PROCEDURE(STRING pChar),BYTE
IsAlphaChar PROCEDURE(STRING pChar),BYTE
IsLowerChar PROCEDURE(STRING pChar),BYTE
IsUpperChar PROCEDURE(STRING pChar),BYTE
ToLower PROCEDURE(STRING pChar),STRING
ToUpper PROCEDURE(STRING pChar),STRING
END!MAP
!==============================================================================
Mod:IntU STRING('ЗДЕЙЖЦЬС'),STATIC
Mod:IntL STRING('здейжцьс'),STATIC
Mod:IntLC STRING('ьйвдаезклипомжфцтыщябнуъс'),STATIC
Mod:IntUC STRING('ЬЙAДAЕЗEEEIIIЖOЦOUUYAIOUС'),STATIC
!==============================================================================
Proper PROCEDURE(STRING N)
Loc:RetVal STRING(255)
Loc:Char STRING(1),DIM(255),OVER(Loc:RetVal)
Loc:X BYTE
Loc:Start BYTE
Loc:Len BYTE
Loc:Mc BYTE(-1)
CODE
Loc:RetVal = N
IF IsLowerChar(Loc:Char[1])
Loc:Char[1] = ToUpper(Loc:Char[1])
END!IF
IF Loc:Char[1] = 'M' AND UPPER(Loc:Char[2]) = 'C'
Loc:Char[2] = 'c'
Loc:Start = 3
Loc:Mc = 1
ELSE
Loc:Start = 2
END!IF
Loc:Len = LEN(CLIP(N))
LOOP Loc:X = Loc:Start TO Loc:Len
IF IsAlphaChar(Loc:Char[Loc:X])
IF IsAlphaChar(Loc:Char[Loc:X-1])
IF Loc:Mc <> Loc:X-2
IF IsUpperChar(Loc:Char[Loc:X])
Loc:Char[Loc:X] = ToLower(Loc:Char[Loc:X])
END!IF
IF Loc:Char[Loc:X]='c' AND Loc:Char[Loc:X-1]='M'
Loc:Mc = Loc:X - 1
END!IF
ELSE
IF IsLowerChar(Loc:Char[Loc:X])
Loc:Char[Loc:X] = ToUpper(Loc:Char[Loc:X])
END!IF
END!IF
ELSIF UPPER(Loc:Char[Loc:X])='S' AND Loc:Char[Loc:X-1]=''''
IF Loc:X >= 3
IF Loc:Char[Loc:X-2] = 'O'
Loc:Char[Loc:X] = 'S'
ELSE
Loc:Char[Loc:X] = 's'
END!IF
ELSE
Loc:Char[Loc:X] = 's'
END!IF
ELSIF IsNumericChar(Loc:Char[Loc:X-1])
IF IsUpperChar(Loc:Char[Loc:X])
Loc:Char[Loc:X] = ToLower(Loc:Char[Loc:X])
END!IF
ELSIF IsLowerChar(Loc:Char[Loc:X])
Loc:Char[Loc:X] = ToUpper(Loc:Char[Loc:X])
END!IF
END!IF
END!LOOP
RETURN Loc:RetVal
!==============================================================================
IsNumericChar PROCEDURE(STRING pChar)
CODE
RETURN CHOOSE(pChar[1] >= '0' AND pChar[1] <= '9')
!==============================================================================
IsAlphaChar PROCEDURE(STRING pChar)
CODE
IF (pChar[1] >= 'A' AND pChar[1] <= 'Z') |
OR (pChar[1] >= 'a' AND pChar[1] <= 'z') |
OR INSTRING(pChar[1], Mod:IntU) |
OR INSTRING(pChar[1], Mod:IntLC)
RETURN 1
ELSE
RETURN 0
END!IF
!==============================================================================
IsLowerChar PROCEDURE(STRING pChar)
CODE
IF pChar[1] >= 'a' and pChar[1] <= 'z' |
OR INSTRING(pChar[1], Mod:IntLC)
RETURN 1
ELSE
RETURN 0
END!IF
!==============================================================================
IsUpperChar PROCEDURE(STRING pChar)
CODE
IF pChar[1] >= 'A' and pChar[1] <= 'Z' |
OR INSTRING(pChar[1], Mod:IntU, 1)
RETURN 1
ELSE
RETURN 0
END!IF
!==============================================================================
ToLower PROCEDURE(STRING pChar)
P BYTE,AUTO
CODE
IF pChar[1] < '~'
RETURN CHR(VAL(pChar)+32)
ELSE
P = INSTRING(pChar[1], Mod:IntU)
RETURN CHOOSE(~P, pChar[1], Mod:IntL[P])
END!IF
!==============================================================================
ToUpper PROCEDURE(STRING pChar)
P BYTE,AUTO
CODE
IF pChar[1] < '~'
RETURN CHR(VAL(pChar[1])-32)
ELSE
P = INSTRING(pChar[1], Mod:IntLC)
RETURN CHOOSE(~P, pChar[1], Mod:IntUC[P])
END!IF
!==============================================================================
www.boxsoft.net
also Mike did an article on a later version in Clarion Magazine:
Formatting Names Using Proper Case
by Mike Hanson
Published 2008-12-22
attached here with thanks to Dave Harms.
cmag-2008-12.pdf (793.0 KB)
v10n12proper.zip (23.9 KB)
Hi,
Capesoft’s StringTheory has a method called Capitalize that does the job (and a whole lot more)
StringTheory is the template I use the most in every app I write.
I don’t know your situation but I think USD 79.00 is a bargain for what you get.
Cheers,
René
Hello, in the SystemString Class there is the “Capitalize” method. I haven’t tried it, but it’s there.
Just look in LibSrc at SystemString.clw source which shows it does UPPER on the First and UPPER after each Space. So it assumes lower case.
SystemStringClass.ToCapitalize PROCEDURE(STRING pStr)
idx LONG,AUTO
sLength LONG,AUTO
CODE
idx = 1
sLength = LEN(pStr)
IF sLength > 0
pStr[idx] = UPPER(pStr[idx]) !1st Letter is always UPPER since idx=1
IF sLength > 1
LOOP idx = 2 to sLength !2nd Letter to Length
IF pStr[idx-1] = ' ' THEN !IF Previous Char was Space
pStr[idx] = UPPER(pStr[idx]) !then Letter is UPPER
END
END
END
END
RETURN pStr
Code could be a bit simpler. There is no need to set IDX=1. Since not using CLIP() can change LEN() to SIZE() as simpler.
CODE
sLength = SIZE(pStr)
IF sLength > 0
pStr[1] = UPPER(pStr[1]) !1st Letter is always UPPER
IF sLength > 1
... as before ...
Glad you find ST useful René - it is certainly my favourite third party tool too as I have mentioned on plenty of other threads and I have spent years working on it.
Rick mentioned it right near the top of this thread.
The reason I mentioned Mike’s versions is that they are more sophisticated and while ST does handle more than just a space as the word delimiter (and allows you to override the default delimiter character list should you wish), it would not handle something like “McDonald”. Mike’s later class in the ClarionMag article handles even more special cases. Of course the various “exceptions” could vary depending on your native language so you may need to salt to taste.
It is also worth looking at various other people’s ideas on that thread I posted earlier:
https://groups.google.com/g/comp.lang.clarion/c/pHcdA5kUm4Y/m/ULt2QV72wVsJ
(although the formatting of the indenting was all lost somewhere in the transfer from the newsgroups).