Page 1 of 1

Scintilla not changeable text area

Posted: Fri Nov 07, 2014 3:23 pm
by rmenezes
Hey

So I needed Scintilla to let me insert a read-only section at the start of text and lock it in place. This area would be filled later, progammatically. Maybe I could use this in a self-documenting feature or something. Or not.

Anyway, I took a peek at the #SCI_STYLESETCHANGEABLE message. In ScintillaDocs it is said that it is an "experimental and incompletely implemented style attribute". Caveat emptor. Ok, I understand that. But maybe it could still be usefull as it is. So I wrote this simple tester code:

Code: Select all

EnableExplicit
InitScintilla()

#STYLE_PROTECTED = 30
Define sciFont.s, hdr$, hdrLen, memBuffer

Procedure MakeUTF8Text(text.s)
  Static buffer.s
  buffer = Space(StringByteLength(text, #PB_UTF8))
  PokeS(@buffer, text, -1, #PB_UTF8)
  ProcedureReturn @buffer
EndProcedure

Procedure DoSciEvent()
  Shared hdrLen
  Protected posNow
  If EventType() = #PB_EventType_RightClick
    posNow = ScintillaSendMessage(0, #SCI_GETCURRENTPOS)
    If ScintillaSendMessage(0, #SCI_GETSTYLEAT, posNow) = #STYLE_PROTECTED
      ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
      MessageRequester("WARNING!", "Restricted area. Trespassers will be shot.")
    EndIf
  EndIf
EndProcedure

hdr$ = ""
hdr$ + "----------------------------------------" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----    This is a protected area    ----" + #CR$
hdr$ + "----        (ma non troppo)         ----" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----------------------------------------" + #CR$
hdrLen = StringByteLength(hdr$,#PB_UTF8)
sciFont = "Courier New"
memBuffer = AllocateMemory(Len(sciFont) + 1)
PokeS(memBuffer, sciFont, -1, #PB_Ascii)

OpenWindow(0, 0, 0, 600, 700, "Block me lines!", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScintillaGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), 0)
ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, memBuffer)
ScintillaSendMessage(0, #SCI_SETWRAPMODE, #SC_WRAP_WHITESPACE)
ScintillaSendMessage(0, #SCI_SETCODEPAGE, #SC_CP_UTF8)
ScintillaSendMessage(0, #SCI_STYLESETBACK, #STYLE_PROTECTED, RGB($EE, $EE, $EE))
ScintillaSendMessage(0, #SCI_STYLESETCHANGEABLE, #STYLE_PROTECTED, 0)
ScintillaSendMessage(0, #SCI_SETTEXT, 0, MakeUTF8Text(hdr$))
ScintillaSendMessage(0, #SCI_STARTSTYLING, 0, $1F)
ScintillaSendMessage(0, #SCI_SETSTYLING, hdrLen, #STYLE_PROTECTED)
ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
SetActiveGadget(0)
BindGadgetEvent(0, @DoSciEvent())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
End
I my test machine it worked pretty good, actually: I could not position the caret within the styled area neither using the cursos keys nor with mouse leftclick. But oh, the rightclick... There was the caret, smack in the middle of the text, and Scintilla let me insert text normally. So I trapped the rightclick event (as per netmaestro, in another post): if it happened within the protected area, I would just move the caret to the first editable position past it. Success! That is, if you didn't rightclick and held it that way. Then you could insert text again. Allright, I guess I can live with that. I mean, if you really want to mess it up...

But the caret could still be positioned right before the protected area (either by arrow keys, as it jumped past it, or by leftclicking there) and then I was able to insert text again, pushing the following text forward. Not cool. Not cool at all. My protected area must remain there, at the start of the text, always. Then I realized I was out of beer. And ideas.

Any thoughts?

Ricardo

Re: Scintilla not changeable text area

Posted: Fri Nov 07, 2014 3:35 pm
by IdeasVacuum
Why not use a separate gadget (StringGadget) and make that read only?

Re: Scintilla not changeable text area

Posted: Fri Nov 07, 2014 3:39 pm
by Tenaja
If you trap the Scintilla notification (Case #SCN_CHARADDED), you can remove the new character if it is in an invalid location.


See srod's GOSCI for an example of a callback that traps those notifications, in proc GOSCI_ScintillaCallBackXXX.

Re: Scintilla not changeable text area

Posted: Fri Nov 07, 2014 6:18 pm
by rmenezes
@vacuumm

That's true. That can be done. But what about the challenge? Ultimately, this is an exercise on pushing the prosaic "envelope". And an excuse to go for more beer :)

@tenaja

Good call. That 'll be my next attempt. I don't know how to remove the CHARADDED character once it is in (couldn't find it in the SciDocs). Lemme look at them GoSCI code. Maybe I'll find my answer there.


To be continued.

Ricardo

Re: Scintilla not changeable text area

Posted: Fri Nov 07, 2014 7:20 pm
by rmenezes
Oh, yeah.

Be it known to one and all that in Scintilla we don't delete chars. We replace them! So, with a big thank you to srod for his GoSCI and tenaja for his suggestion to look it up, here's a revised version of the previous code:

Code: Select all


EnableExplicit
InitScintilla()

#STYLE_PROTECTED = 30
Define sciFont.s, hdr$, hdrLen, memBuffer

Procedure MakeUTF8Text(text.s)
  Static buffer.s
  buffer = Space(StringByteLength(text, #PB_UTF8))
  PokeS(@buffer, text, -1, #PB_UTF8)
  ProcedureReturn @buffer
EndProcedure

Procedure DoSciCallback(i, *scinotify.SCNotification)
  Shared hdrLen
  Protected posNow
  Select *scinotify\nmhdr\code
    Case #SCN_CHARADDED
      posNow = ScintillaSendMessage(i, #SCI_GETCURRENTPOS)
      If posNow < hdrLen
        ; delete this sucker
        ScintillaSendMessage(i, #SCI_SETTARGETSTART, 0)
        ScintillaSendMessage(i, #SCI_SETTARGETEND, posNow)
        ScintillaSendMessage(i, #SCI_REPLACETARGET, -1, @"")
        ScintillaSendMessage(i, #SCI_GOTOPOS, hdrLen)
    EndIf
  EndSelect
EndProcedure

Procedure DoSciEvent()
  Shared hdrLen
  Protected posNow
  If EventType() = #PB_EventType_RightClick
    posNow = ScintillaSendMessage(0, #SCI_GETCURRENTPOS)
    If posNow < hdrLen
      ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
      MessageRequester("WARNING!", "Restricted area. Trespassers will be shot.")
    EndIf
  EndIf
EndProcedure

hdr$ = ""
hdr$ + "----------------------------------------" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----    This is a protected area    ----" + #CR$
hdr$ + "----        (ma non troppo)         ----" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----------------------------------------" + #CR$
hdrLen = StringByteLength(hdr$,#PB_UTF8)
sciFont = "Courier New"
memBuffer = AllocateMemory(Len(sciFont) + 1)
PokeS(memBuffer, sciFont, -1, #PB_Ascii)

OpenWindow(0, 0, 0, 600, 700, "Block me lines!", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScintillaGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), @DoSciCallback())
ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, memBuffer)
ScintillaSendMessage(0, #SCI_SETWRAPMODE, #SC_WRAP_WHITESPACE)
ScintillaSendMessage(0, #SCI_SETCODEPAGE, #SC_CP_UTF8)
ScintillaSendMessage(0, #SCI_STYLESETBACK, #STYLE_PROTECTED, RGB($EE, $EE, $EE))
ScintillaSendMessage(0, #SCI_STYLESETCHANGEABLE, #STYLE_PROTECTED, 0)
ScintillaSendMessage(0, #SCI_SETTEXT, 0, MakeUTF8Text(hdr$))
ScintillaSendMessage(0, #SCI_STARTSTYLING, 0, $1F)
ScintillaSendMessage(0, #SCI_SETSTYLING, hdrLen, #STYLE_PROTECTED)
ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
SetActiveGadget(0)
BindGadgetEvent(0, @DoSciEvent())

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
End
Now I light up my cigar (can't wait to find more chars to delete - I mean, replace).

Ricardo

Re: Scintilla not changeable text area

Posted: Fri Nov 07, 2014 10:15 pm
by eddy
using scintilla UI notification

Code: Select all

EnableExplicit
InitScintilla()

#STYLE_PROTECTED=30
Define sciFont.s, hdr$, hdrLen, memBuffer

Procedure MakeUTF8Text(text.s)
   Static buffer.s
   buffer=Space(StringByteLength(text, #PB_UTF8))
   PokeS(@buffer, text, -1, #PB_UTF8)
   ProcedureReturn @buffer
EndProcedure

ProcedureDLL LockScintillaCB(Gadget, *scinotify.SCNotification)
   Shared hdrLen
   With *scinotify
      If \nmhdr\code=#SCN_UPDATEUI
         If \updated & #SC_UPDATE_CONTENT
            ;typing text
         EndIf
         If \updated & #SC_UPDATE_H_SCROLL
            ;scrolling
         EndIf
         If \updated & #SC_UPDATE_V_SCROLL
            ;scrolling
         EndIf
         If \updated & #SC_UPDATE_SELECTION
            ;selection changed
            Protected posNow=ScintillaSendMessage(0, #SCI_GETCURRENTPOS)
            If ScintillaSendMessage(0, #SCI_GETSTYLEAT, posNow)=#STYLE_PROTECTED
               ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
               MessageRequester("WARNING!", "Restricted area. Trespassers will be shot.")
            EndIf
         EndIf
      EndIf
   EndWith
EndProcedure

hdr$=""
hdr$ + "----------------------------------------" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----    This is a protected area    ----" + #CR$
hdr$ + "----        (ma non troppo)         ----" + #CR$
hdr$ + "----                                ----" + #CR$
hdr$ + "----------------------------------------" + #CR$
hdrLen=StringByteLength(hdr$, #PB_UTF8)
sciFont="Courier New"
memBuffer=AllocateMemory(Len(sciFont) + 1)
PokeS(memBuffer, sciFont, -1, #PB_Ascii)

OpenWindow(0, 0, 0, 600, 700, "Block me lines!", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ScintillaGadget(0, 0, 0, WindowWidth(0), WindowHeight(0), @LockScintillaCB())
ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, memBuffer)
ScintillaSendMessage(0, #SCI_SETWRAPMODE, #SC_WRAP_WHITESPACE)
ScintillaSendMessage(0, #SCI_SETCODEPAGE, #SC_CP_UTF8)
ScintillaSendMessage(0, #SCI_STYLESETBACK, #STYLE_PROTECTED, RGB($EE, $EE, $EE))
ScintillaSendMessage(0, #SCI_STYLESETCHANGEABLE, #STYLE_PROTECTED, 0)
ScintillaSendMessage(0, #SCI_SETTEXT, 0, MakeUTF8Text(hdr$))
ScintillaSendMessage(0, #SCI_STARTSTYLING, 0, $1F)
ScintillaSendMessage(0, #SCI_SETSTYLING, hdrLen, #STYLE_PROTECTED)
ScintillaSendMessage(0, #SCI_GOTOPOS, hdrLen)
SetActiveGadget(0)

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
End

Re: Scintilla not changeable text area

Posted: Sat Nov 08, 2014 11:00 pm
by Vera
Hi rmenezes,

with a double-click on the block (will mark a line) and twice on any key ... your block is gone for good. :mrgreen:
... and anything one likes to write thereafter vanishes into the mist 8)

Tested on Linux ... so you might not mind ~ cheers Vera

Re: Scintilla not changeable text area

Posted: Sat Nov 08, 2014 11:21 pm
by davido
Oddly, the right-click is not recognised on OSX. :?

Re: Scintilla not changeable text area

Posted: Sun Nov 09, 2014 2:08 pm
by rmenezes
Eddy's solution worked fine in 64w7. Will try on UX next.

BTW, @vera, generally it's the other way around in my case: it has to work on Linux first and then on Windows :)

Thanks guys. The next round's on me.

Ricardo

Re: Scintilla not changeable text area

Posted: Wed Dec 10, 2014 10:07 pm
by eddy

Code: Select all

[/b]
- Remark : \updated property is bit flag

Here is the correct way to test its value:
[code]         If \updated & #SC_UPDATE_CONTENT
            ;typing text
         EndIf
         If\updated & #SC_UPDATE_H_SCROLL
            ;scrolling 
         EndIf
         If\updated & #SC_UPDATE_V_SCROLL
            ;scrolling 
         EndIf
         If \updated & #SC_UPDATE_SELECTION
            ;selection changes
         EndIf