Uppercase every word in a string (and more)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Uppercase every word in a string (and more)

Post by Fangbeast »

Not quite sure how to do this.

As the user types a string, it is grabbed during a change event and:

Any # entered manually are removed.
All first letters in the string are uppercased
All spaces are then removed.
The # symbol is replaced at the start.
Then the string is placed back into the string box.

Not quite working though, only the first word is uppercased, the # is never replaced after the first time.

Not sure how to fix this so that it all works in the correct sequence.

This "#run program setup"
Should always be this "#RunProgramSetup

Could someone please edumfacate me??? (heheheh)

(I may be getting older but I ain't finished!)

Code: Select all

; First letter uppercase in a string box. srod!

Procedure StringFirstLetterUpperCase(Gadget.i)

  Protected Parent.i, StringOut.s, StringIn.s, Temporary.s, Position.i, StartSelection.i, EndSelection.i

  StringIn.s  = GetGadgetText(Gadget.i)
  
  ; My addition to remove manually entered hash key
  
  StringIn.s  = RemoveString(StringIn.s,  "#", #PB_String_NoCase)
  
  If StringIn.s = #Empty$
    ProcedureReturn
  EndIf

  WordFlag.i = 1

  SendMessage_(GadgetID(Gadget.i), #EM_GETSEL, @StartSelection, @EndSelection)  ; Get the Position of the caret.

  If StartSelection.i <> EndSelection.i
    ProcedureReturn
  EndIf

  Repeat
    Position.i + 1
    StringOut.s = Mid(StringIn.s, Position.i, 1)
    If WordFlag.i
      Temporary.s + UCase(StringOut.s)
    Else
      Temporary.s + StringOut.s
    EndIf
    If StringOut.s = " "
      WordFlag.i = 1
    Else
      WordFlag.i = 0
    EndIf
  Until Position.i = Len(StringIn.s)
  
  ; My addition to remove spaces in the string
  
  Temporary.s  = ReplaceString(Temporary.s, " ", #Empty$, #PB_String_NoCase)

  SetGadgetText(Gadget.i, Temporary.s)

  ; Return the caret to it's original Position

  SendMessage_(GadgetID(Gadget.i), #EM_SETSEL, EndSelection.i, EndSelection.i)

EndProcedure

Amateur Radio, D-STAR/VK3HAF
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Uppercase every word in a string (and more)

Post by Dude »

Real-time changing can get difficult, because the user can type (and paste!) so many different things. I'd suggest just cleaning the entry after the user finishes typing and they move out of the StringGadget to something else, like clicking a "Process" button:

Code: Select all

#SOC=SizeOf(character)

Procedure.s TitleCase(text$)
  *i.Character=@text$
  newWord=1
  While *i\c
    If newWord
      *i\c=Asc(UCase(Chr(*i\c)))
      newWord=0
    Else
      *i\c=Asc(LCase(Chr(*i\c)))
    EndIf
    If *i\c=' ' Or *i\c='.' Or *i\c='!' Or *i\c='?' Or *i\c=#CR Or *i\c=#LF
      newWord=1
    EndIf   
    *i+#SOC
  Wend
  ProcedureReturn text$
EndProcedure

OpenWindow(0,200,200,200,100,"test",#PB_Window_SystemMenu)

StringGadget(0,10,10,180,22,"")
ButtonGadget(1,10,40,180,22,"Process")
SetActiveGadget(0)

Repeat
  
  ev=WaitWindowEvent()
  
  If ev=#PB_Event_Gadget
    
    If EventGadget()=0
      If EventType()=#PB_EventType_LostFocus
        t$=GetGadgetText(0)    
        t$=TitleCase(t$)
        t$=RemoveString(t$," ")
        t$=RemoveString(t$,"#")
        SetGadgetText(0,"#"+t$)
      EndIf
    EndIf
    
  EndIf
  
Until ev=#PB_Event_CloseWindow
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Uppercase every word in a string (and more)

Post by Trond »

How about using a live preview text gadget below?

Code: Select all

Procedure.s ProcessString(S.s)
  Result.s = "#"
  S.s = RemoveString(S, "#")
  FieldCount = CountString(S, " ")+1
  For I = 1 To FieldCount
    Field.s = StringField(S, I, " ")
    Field = UCase(Left(Field, 1)) + Mid(Field, 2)
    Result.s + Field
  Next 
  ProcedureReturn Result
EndProcedure

H = 350
W = 500

OpenWindow(0, 200, 300, W, H, "", #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
StringGadget(0,10,10,180,22,"")
TextGadget(1, 10, 50, 180, 22, "")

Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0:
          NewString.s = ProcessString(GetGadgetText(0))
          SetGadgetText(1, "Preview: " + NewString)
      EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Uppercase every word in a string (and more)

Post by Dude »

Good to see you again, Trond. :)
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Uppercase every word in a string (and more)

Post by TI-994A »

Fangbeast wrote:As the user types a string, it is grabbed during a change event and:

Any # entered manually are removed.
All first letters in the string are uppercased
All spaces are then removed.
The # symbol is replaced at the start.
Then the string is placed back into the string box.

This "#run program setup"
Should always be this "#RunProgramSetup
Modified this numeric-filter routine from an earlier post just for you: :D

Code: Select all

;====================================================================
;   Custom StringGadget() filter/handler  ->  for Fangbeast
;
;   cross-platform masking routines by Keya & Shardik - Thank you!
;   filter routine modified as per custom requirements, by TI-994A
;   original posted code available in the following forum thread:
;
;====================================================================
; http://forums.purebasic.com/english/viewtopic.php?t=67986&p=503517
;====================================================================
;   
;   tested & working on Win10 running PureBasic v5.62 (x64)
;   and Mac OS-X High Sierra running PureBasic v5.60 (x64)
;
;   by TI-994A - free to use, improve, share...
;
;   20th May 2018
;====================================================================

;==================
; masking routines 
;==================

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
  CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
    ImportC ""
      GetControlData(ControlRef.L, ControlPartCode.L, TagName.L, BufferSize.L, *Buffer, *ActualSize)
      SetControlData(ControlRef.L, ControlPartCode.L, TagName.L, BufferSize.L, *Buffer)
    EndImport   
    #kControlEditTextPart = 5
    #kControlEditTextSelectionTag = $73656C65 ;'sele'   
    Structure ControlEditTextSelectionRec
      SelStart.W
      SelEnd.W
    EndStructure
  CompilerElse
    Global NSRangeZero.NSRange
    Procedure.i TextEditor(Gadget.i)
      Protected TextField.i = GadgetID(Gadget)
      Protected Window.i = CocoaMessage(0, TextField, "window")
      ProcedureReturn CocoaMessage(0, Window, "fieldEditor:", #YES, "forObject:", TextField)
    EndProcedure
  CompilerEndIf
CompilerEndIf

Procedure SetStringGadgetSelection(GadgetID.i, Start.i, Length.i=0)
  SetActiveGadget(gadgetid)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      SendMessage_(GadgetID(GadgetID), #EM_SETSEL, Start-1, Start-1)
    CompilerCase #PB_OS_Linux
      gtk_editable_select_region_(GadgetID(gadgetid), Start-1, Start-1)
    CompilerCase #PB_OS_MacOS
      CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
        Protected TextSelection.ControlEditTextSelectionRec
        TextSelection\selStart = Start - 1
        TextSelection\selEnd = Start -1 
        SetControlData(GadgetID(GadgetID), #kControlEditTextPart, 
                       #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection)
      CompilerElse
        Protected Range.NSRange\location = Start - 1 : Range\length = 0
        CocoaMessage(0, TextEditor(GadgetID), "setSelectedRange:@", @Range)
      CompilerEndIf
  CompilerEndSelect
EndProcedure

Procedure.i GetCaretPosition(GadgetID.i)
  Protected Start.i = 0
  Protected Stop.i = 0
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      SendMessage_(GadgetID(GadgetID.i), #EM_GETSEL, @Start.i, @Stop.i)
      ProcedureReturn Stop + 1
    CompilerCase #PB_OS_Linux
      Stop = gtk_editable_get_position_(GadgetID(gadgetid))
      ProcedureReturn Stop + 1
    CompilerCase #PB_OS_MacOS
      CompilerIf #PB_Compiler_Version < 470 Or (#PB_Compiler_Version >= 500 And Subsystem("Carbon"))
        Protected TextSelection.ControlEditTextSelectionRec
        GetControlData(GadgetID(GadgetID), #kControlEditTextPart, #kControlEditTextSelectionTag, 
                       SizeOf(ControlEditTextSelectionRec), @TextSelection.ControlEditTextSelectionRec, 0)
        ProcedureReturn TextSelection\End + 1
      CompilerElse
        Protected Range.NSRange
        CocoaMessage(@Range, TextEditor(GadgetID), "selectedRange")        
        ProcedureReturn Range\location + Range\length + 1
      CompilerEndIf
  CompilerEndSelect
EndProcedure

Procedure RestrictChars(*pchr.Ascii, slen)
  Static newWord = 1
  If slen
    *pout.Ascii = *pchr
    For i = 1 To slen
      Select *pchr\a
        Case '0' To '9', 'a' To 'z', 'A' To 'Z'             
          If newWord
            changed = i
            newWord = 0
          EndIf          
          *pchr+SizeOf(Character): *pout+SizeOf(Character)
        Case '#':
          hexcnt+1
          If hexcnt=1 And i = 1
            *pchr+SizeOf(Character): *pout+SizeOf(Character)
          Else
            Goto BadChar
          EndIf  
        Case ' ':  
          newWord = 1
          Goto BadChar
        Default:
          BadChar:
          *pchr+SizeOf(Character): changed = -1
      EndSelect 
      *pout\a = *pchr\a
    Next
  Else
    newWord = 1
  EndIf
  ProcedureReturn changed
EndProcedure

Procedure StringFilter()
  Static Changing
  gadget = EventGadget()
  If Not Changing
    Changing=1
    sTxt$ = GetGadgetText(gadget)
    lastcaretpos = GetCaretPosition(gadget)  
    currentCharPos = RestrictChars(@sTxt$, Len(sTxt$))
    If currentCharPos = -1
      SetGadgetText(gadget, sTxt$)
      SetStringGadgetSelection(gadget, lastcaretpos-1)
    ElseIf currentCharPos > 0
      If currentCharPos = 1 
        prefix$ = "#"
      EndIf
      sTxt$ = prefix$ + Left(sTxt$, Len(sTxt$) - 1) + UCase(Right(sTxt$, 1))
      SetGadgetText(gadget, sTxt$)
      SetStringGadgetSelection(gadget, lastcaretpos + 1)
    EndIf
    Changing = 0
  EndIf 
EndProcedure

;===============
; usage example
;===============

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
mainWindow = OpenWindow(#PB_Any, 0, 0, 350, 100, "Custom StringGadget()", wFlags)
customStringGadget = StringGadget(#PB_Any, 50, 30, 250, 30, "")
BindGadgetEvent(customStringGadget, @StringFilter(), #PB_EventType_Change)

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
As indicated in the code header, the original masking routines are courtesy of Keya & Shardik. A little long, but cross-platform, and easily tucked away into an include toolbox for future use.

The modifications conform to your requirements, of prefixing a hex (#), capitalising every first letter, and stripping all inline spaces. It currently accepts all alpha-numeric characters, and would capitalise characters which follow a tap on the space bar.

Hope it helps. :wink:
Last edited by TI-994A on Sun May 20, 2018 5:20 pm, edited 1 time in total.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Otrebor
Enthusiast
Enthusiast
Posts: 201
Joined: Mon Mar 17, 2014 1:42 pm
Location: São Paulo, Brasil
Contact:

Re: Uppercase every word in a string (and more)

Post by Otrebor »

This code helped me with similar situation:
http://www.purebasic.fr/english/viewtop ... t=FilterIt
:)
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Uppercase every word in a string (and more)

Post by Fangbeast »

Dude wrote:Real-time changing can get difficult, because the user can type (and paste!) so many different things. I'd suggest just cleaning the entry after the user finishes typing and they move out of the StringGadget to something else, like clicking a "Process" button:
True, years ago, Netmaestro made me what he called a 'fangleized currency gadget' to covere a live formatted currency gadget and he covered just about every contingency that I could think of but oh boy, it worked well.
Amateur Radio, D-STAR/VK3HAF
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Uppercase every word in a string (and more)

Post by Fangbeast »

Trond wrote:How about using a live preview text gadget below?
Interesting approach Trond, might simplify things for other ideas I have. Thanks.
Amateur Radio, D-STAR/VK3HAF
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Uppercase every word in a string (and more)

Post by Fangbeast »

Modified this numeric-filter routine from an earlier post just for you: :D

Code: Select all

As indicated in the code header, the original masking routines are courtesy of Keya & Shardik. A little long, but [b]cross-platform,[/b] and easily tucked away into an include toolbox for future use. 

The modifications conform to your requirements, of prefixing a hex (#), capitalising every first letter, and stripping all inline spaces. It currently accepts all alpha-numeric characters, and would capitalise characters which follow a tap on the space bar.

Hope it helps.    :wink:
[/quote]

Oh Shucks, and it's not even my birthday yet (heheheheh). Thanks Syed.

I am writing a subprogram that will help create my next program. I add to it all section headings, keyboard shortcuts, long and short key texts and it will generate formatted includes for any program for whom I would normally have to manually type thousands of lines.

This is all helpful stuff.
Amateur Radio, D-STAR/VK3HAF
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Uppercase every word in a string (and more)

Post by Fangbeast »

Otrebor wrote:This code helped me with similar situation:
http://www.purebasic.fr/english/viewtop ... t=FilterIt
:)
Thanks, will check that out.
Amateur Radio, D-STAR/VK3HAF
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Uppercase every word in a string (and more)

Post by Trond »

Dude wrote:Good to see you again, Trond. :)
Thanks. :)
Post Reply