Scintilla gadget: Récupérer le texte sélectionné

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Marc56
Messages : 2148
Inscription : sam. 08/févr./2014 15:19

Scintilla gadget: Récupérer le texte sélectionné

Message par Marc56 »

Hello,

Dans un gadget Scintilla, je souhaite récupérer le texte sélectionné.
D'après la doc https://www.scintilla.org/ScintillaDoc. ... nformation cela se fait avec #SCI_GETSELTEXT mais en sortie j'obtiens un truc illisible (encodage)

Code : Tout sélectionner

Selected Text [捓湩楴汬䝡摡敧t         ]
J'ai mixé un exemple de la doc et un exemple de skywalk (http://forums.purebasic.com/english/vie ... 17#p342217) mais ça date de 2010.

Code : Tout sélectionner

; Récupérer le texte sélectionné dans un gadget Scintilla
; https://www.scintilla.org/ScintillaDoc.html#SelectionAndInformation
; Basé sur l'exemple de la doc PB et sur un exemple du forum (2010)
; skywalk http://forums.purebasic.com/english/viewtopic.php?p=342217#p342217


OpenWindow(0, 0, 0, 400, 90, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

If InitScintilla()
    ScintillaGadget(0, 10, 10, 390, 70, 0)
    *Texte=UTF8("Voici un simple ScintillaGadget avec du texte...")
    ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Texte)
    FreeMemory(*Texte) 
EndIf

Repeat 
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
            End
            
        Case #WM_LBUTTONUP, #WM_KEYUP
            ri = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, 0)
            Txt$ = Space(ri+1)
            ri = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, @Txt$)
            If ri     
                Debug "Selected Text [" + Txt$ + "]"
            EndIf 
    EndSelect
ForEver
End
J'ai testé quelques trucs, type UTF8(Txt$), mais j'ai alors une valeur numérique :|

Code : Tout sélectionner

Selected Text [77203552]
J'ai aussi essayé: PeekS(*Txt$, Len(*Txt$), #PB_UTF8)
et obtenu : Les types natifs ne peuvent pas etre utilisees avec des pointeurs.

Les transtypages et les pseudos-type, j'ai du mal :(
Marc56
Messages : 2148
Inscription : sam. 08/févr./2014 15:19

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par Marc56 »

J'ai trouvé :P c'est bien-sur PeekS puisqu'il faut aller chercher ce qui a été placé dans la zone mémoire et l'afficher en UTF-8
Donc pas Txt$ mais PeekS(@Txt$, Len(Txt$), #PB_UTF8)

Code : Tout sélectionner

Debug "Selected Text [" + PeekS(@Txt$, Len(Txt$), #PB_UTF8) + "]"
Logique, pure logique 8)
Je commence à comprendre :wink:
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par nico »

Bonjour Marc56,

Il y a deux problèmes:
- Le premier, c'est que la fonction "longueur = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, 0)" retourne au minimum 1 même si aucun texte n'est sélectionné, soit le 0 de fin de caractère je suppose.

- Le second, c'est que tu travailles avec des chaines de caractères pour l'allocation en tapant space(longueur), c'est astucieux lorsqu'on travaille en ascii mais dans le cas de unicode tu vas allouer deux fois plus d'espace que nécessaire. Par conséquent, il sera préférable d'utiliser allocatememory(....) ou utilisé UTF8(Space(longueur) mais cela va créer deux chaines inutilement même si c'est temporaire.

Ce qui donne pour récupérer du texte:

Code : Tout sélectionner

                    ; La longueur va contenir le 0 de fin de chaine et donc
                    ; sera au minimum de 1 même si il n'y a pas de texte sélectionné
                    longueur = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, 0)
                    Debug longueur
                    If longueur > 1
                        *texte_utf8=AllocateMemory(longueur)
                        ; ou *texte_utf8=UTF8(Space(longueur)) ; a éviter
                        longueur_copie = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, *texte_utf8)
                        Debug longueur_copie  ; contient aussi le  0 de fin.
                        If longueur_copie = longueur ; situation attendue
                            Texte_selection.s = PeekS(*texte_utf8, longueur_copie-1, #PB_UTF8)
                            ; ou Texte_selection = PeekS(*texte_utf8, -1, #PB_UTF8)
                            FreeMemory(*texte_utf8)
                            Debug Texte_selection
                        EndIf 
                    EndIf 
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par Mesa »

ts soft a créé un petit pbi (scintillaHelper.pbi) avec toutes les fonctions les plus importantes de scintilla et qui facilite grandement utilisation de ce gadget.
https://www.purebasic.fr/german/viewtop ... illaHelper
Il n'est plus téléchargeable alors je le mets à la fin de ce fil.

Fonctionne quelque soit le format du texte, ascii, utf8 ou unicode.

Code : Tout sélectionner

OpenWindow(0, 0, 0, 400, 90, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 

If InitScintilla() 
  ScintillaGadget(0, 10, 10, 390, 70, 0) 
  *Texte=UTF8("Voici un simple ScintillaGadget avec du texte hé...") 
  ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Texte) 
  FreeMemory(*Texte)  
EndIf 

ProcedureDLL SCI_GetTextFormat(ID)
  Protected result
  Select ScintillaSendMessage(ID, #SCI_GETCODEPAGE)
    Case #SC_CP_UTF8
      result = #PB_UTF8
    Case 65001
      result = #PB_Unicode
    Default
      result = #PB_Ascii
  EndSelect
  ProcedureReturn result
EndProcedure
ProcedureDLL.s SCI_GetCurrentSelection(ID)
  Protected len, buffer.s = ""
  len = ScintillaSendMessage(ID, #SCI_GETSELECTIONEND) - ScintillaSendMessage(ID, #SCI_GETSELECTIONSTART)
  If len > 0
    buffer = Space(len)
    ScintillaSendMessage(ID, #SCI_GETSELTEXT, 0, @buffer)
    ProcedureReturn PeekS(@buffer, -1, SCI_GetTextFormat(ID))
  EndIf
EndProcedure

Repeat  
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow 
      End 
      
    Case #WM_LBUTTONUP, #WM_KEYUP 
      
      Txt$ = SCI_GetCurrentSelection(0)
      
      Debug "Selected Text [" + Txt$ + "]" 
      
  EndSelect 
ForEver 
End
Mesa
Messages : 1098
Inscription : mer. 14/sept./2011 16:59

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par Mesa »

ScintillaHelper.pbi

Code : Tout sélectionner

; EnableExplicit
; from ts soft 
; https://www.purebasic.fr/german/viewtopic.php?f=11&t=19580&hilit=ScintillaHelper

#SCI_STYLEGETFORE = 2481
#SCI_STYLEGETBACK = 2482

Enumeration; Syntax
  #SYNTAX_Text
  #SYNTAX_Keyword
  #SYNTAX_Comment
  #SYNTAX_Constant
  #SYNTAX_String
  #SYNTAX_Function
  #SYNTAX_Asm
  #SYNTAX_Operator
  #SYNTAX_Structure
  #SYNTAX_Number
  #SYNTAX_Pointer
  #SYNTAX_Separator
  #SYNTAX_Label
EndEnumeration

Prototype SyntaxHighlight(*Buffer, len, callback, asm)
Global SyntaxHighlight.SyntaxHighlight
Define SCI_start_pos, SCI_Buffer, SCI_Editor

Procedure SHCallback(pos.l, len.l, id)
  Shared SCI_start_pos, SCI_Buffer, SCI_Editor

  ScintillaSendMessage(SCI_Editor, #SCI_STARTSTYLING, (pos - SCI_Buffer) + SCI_start_pos, $1F)
  ScintillaSendMessage(SCI_Editor, #SCI_SETSTYLING, len, id)
EndProcedure

Procedure ScintillaCallBack(EditorGadget, *scinotify.SCNotification)
  Protected line_number.l
  Protected txtr.TEXTRANGE
  Protected end_pos.l
  Shared SCI_start_pos, SCI_Buffer, SCI_Editor
  SCI_Editor = EditorGadget
  
  If *scinotify\nmhdr\code = #SCN_STYLENEEDED
    line_number = ScintillaSendMessage(EditorGadget, #SCI_LINEFROMPOSITION, ScintillaSendMessage(EditorGadget, #SCI_GETENDSTYLED))
    SCI_start_pos = ScintillaSendMessage(EditorGadget, #SCI_POSITIONFROMLINE, line_number)
    end_pos     = *scinotify\Position

    txtr\chrg\cpMin = SCI_start_pos
    txtr\chrg\cpMax = end_pos
    txtr\lpstrText  = AllocateMemory(end_pos - SCI_start_pos + 1)
    SCI_Buffer      = txtr\lpstrText

    ScintillaSendMessage(EditorGadget, #SCI_GETTEXTRANGE, 0, txtr)
    SyntaxHighlight(SCI_Buffer, end_pos - SCI_start_pos, @SHCallback(), #False)

    FreeMemory(SCI_Buffer)
  EndIf
EndProcedure

Declare SCI_GetTextFormat(ID)

ProcedureDLL ScintillaGadgetPB(ID, x, y, w, h , SyntaxHilightingDLL.s)
  Protected hDLL, result
  Protected buffer.s, Font.s
  
  hDLL = OpenLibrary(#PB_Any, SyntaxHilightingDLL)
  If hDLL
    SyntaxHighlight = GetFunction(hDLL, "SyntaxHighlight")
    If SyntaxHighlight
      result = ScintillaGadget(ID, x, y, w, h, @ScintillaCallBack())
      If ID = #PB_Any
        ID = result
      EndIf
      
      OpenPreferences(GetEnvironmentVariable("APPDATA") + "\PureBasic\PureBasic.prefs")
      PreferenceGroup("Editor")
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #STYLE_DEFAULT, $000000)
      ScintillaSendMessage(ID, #SCI_STYLESETBACK, #STYLE_DEFAULT, ReadPreferenceLong("BackgroundColor", 14680063))
      Font = ReadPreferenceString("EditorFontName", "courier")
      buffer = Space(StringByteLength(Font, SCI_GetTextFormat(ID)))
      PokeS(@buffer, Font, -1, SCI_GetTextFormat(ID))
      ScintillaSendMessage(ID, #SCI_STYLESETFONT, #STYLE_DEFAULT, @buffer)
      ScintillaSendMessage(ID, #SCI_STYLESETSIZE, #STYLE_DEFAULT, ReadPreferenceLong("EditorFontSize", 10))
      ScintillaSendMessage(ID, #SCI_SETSELFORE, #STYLE_DEFAULT, ReadPreferenceLong("SelectionFrontColor", 16777215))
      ScintillaSendMessage(ID, #SCI_SETSELBACK, #STYLE_DEFAULT, ReadPreferenceLong("SelectionColor", 8388608))
      ScintillaSendMessage(ID, #SCI_STYLECLEARALL)
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Text, ReadPreferenceLong("NormalTextColor", 0))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Keyword, ReadPreferenceLong("BasicKeywordColor", 6710784))
      ScintillaSendMessage(ID, #SCI_STYLESETBOLD, #SYNTAX_Keyword, #True)
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Comment, ReadPreferenceLong("CommentColor", 11184640))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Constant, ReadPreferenceLong("ConstantColor", 7490450))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_String, ReadPreferenceLong("StringColor", 16744448))
      ScintillaSendMessage(ID, #SCI_STYLESETITALIC, #SYNTAX_String, #True)
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Function, ReadPreferenceLong("PureKeywordColor", 6710784))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Asm, ReadPreferenceLong("ASMKeywordColor", 7490450))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Operator,  ReadPreferenceLong("OperatorColor", 0))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Structure, ReadPreferenceLong("StructureColor", 0))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Number, ReadPreferenceLong("NumberColor", 8421504))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Pointer,  ReadPreferenceLong("PointerColor", 0))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Separator,  ReadPreferenceLong("SeparatorColor", $000000))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #SYNTAX_Label,  ReadPreferenceLong("LabelColor", 0))
      ScintillaSendMessage(ID, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER)
      ScintillaSendMessage(ID, #SCI_SETMARGINWIDTHN, 0, 40)
      ScintillaSendMessage(ID, #SCI_STYLESETBACK, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberBackColor", 14155775));GetSysColor_(15)))
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #STYLE_LINENUMBER, ReadPreferenceLong("LineNumberColor", 8421504))
      ScintillaSendMessage(ID, #SCI_SETMARGINWIDTHN, 1, 5)
      ClosePreferences()
      ProcedureReturn result
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

ProcedureDLL SCI_GetTextFormat(ID)
  Protected result
  Select ScintillaSendMessage(ID, #SCI_GETCODEPAGE)
    Case #SC_CP_UTF8
      result = #PB_UTF8
    Case 65001
      result = #PB_Unicode
    Default
      result = #PB_Ascii
  EndSelect
  ProcedureReturn result
EndProcedure

ProcedureDLL.s SCI_GetCurrentSelection(ID)
  Protected len, buffer.s = ""
  len = ScintillaSendMessage(ID, #SCI_GETSELECTIONEND) - ScintillaSendMessage(ID, #SCI_GETSELECTIONSTART)
  If len > 0
    buffer = Space(len)
    ScintillaSendMessage(ID, #SCI_GETSELTEXT, 0, @buffer)
    ProcedureReturn PeekS(@buffer, -1, SCI_GetTextFormat(ID))
  EndIf
EndProcedure

ProcedureDLL.s SCI_GetCurrentWord(ID)
  Protected pos, startPos, endPos, len, buffer.s
  Protected tr.TEXTRANGE
  pos = ScintillaSendMessage(ID, #SCI_GETCURRENTPOS)
  startPos = ScintillaSendMessage(ID, #SCI_WORDSTARTPOSITION, pos, #True)
  endPos = ScintillaSendMessage(ID, #SCI_WORDENDPOSITION, pos, #True)
  len = endPos - startPos
  buffer = Space(len) ; diese größe haben wir vom Scintilla ermittelt, also ist keine Umrechnung erforderlich!
  tr\chrg\cpMin = startPos
  tr\chrg\cpMax = endPos
  tr\lpstrText = @buffer
  ScintillaSendMessage(ID, #SCI_GETTEXTRANGE, 0, tr)
  ; hier wirds rausgepeeked, unter Berücksichtigung des Format,
  ; das Ergebnis ist ein String im aktuellem Compilerformat!
  ProcedureReturn PeekS(@buffer, -1, SCI_GetTextFormat(ID)) 
EndProcedure

ProcedureDLL SCI_AddGadgetItem(ID, pos, Text.s)
  Protected _pos, buffer.s
  ; eine Zeile enthält keine #CRLF$, falls doch werden die erstmal entfernt
  Text = RemoveString(Text, #LF$)
  Text = RemoveString(Text, #CR$)
  If pos = #PB_Default
    Text = #LF$ + Text
    Buffer = Space(StringByteLength(Text, SCI_GetTextFormat(ID)))
    PokeS(@Buffer, Text, -1, SCI_GetTextFormat(ID))
    ScintillaSendMessage(ID, #SCI_GOTOLINE, ScintillaSendMessage(ID, #SCI_GETLINECOUNT))
    ProcedureReturn ScintillaSendMessage(ID, #SCI_ADDTEXT, Len(text), @Buffer)
  Else
    Text + #LF$
    Buffer = Space(StringByteLength(Text, SCI_GetTextFormat(ID)))
    PokeS(@Buffer, Text, -1, SCI_GetTextFormat(ID))
    ScintillaSendMessage(ID, #SCI_GOTOLINE, pos)
    _pos = ScintillaSendMessage(ID, #SCI_GETCURRENTPOS)
    ProcedureReturn ScintillaSendMessage(ID, #SCI_INSERTTEXT, _pos, @Buffer)
  EndIf
EndProcedure

ProcedureDLL SCI_CountGadgetItems(ID)
  Protected result = 0
  If ScintillaSendMessage(ID, #SCI_GETLENGTH) ; auch ein leeres Scintilla hat eine Zeile, aber keine Länge!
    result = ScintillaSendMessage(ID, #SCI_GETLINECOUNT)
  EndIf
  ProcedureReturn result
EndProcedure

ProcedureDLL.s SCI_GetGadgetItemText(ID, pos)
  Protected length, buffer.s
  ; wie groß ist die Zeile
  length = ScintillaSendMessage(ID, #SCI_LINELENGTH, pos)
  ; buffer reservieren
  buffer = Space(length)
  ; die Zeile abfragen
  ScintillaSendMessage(ID, #SCI_GETLINE, pos, @buffer)
  ; Ergebnis aus dem Buffer peeken, unter Berücksichtigung der Scintilla Codepage!
  ProcedureReturn PeekS(@buffer, -1, SCI_GetTextFormat(ID))
EndProcedure

ProcedureDLL SCI_RemoveGadgetItem(ID, pos)
  Protected length, _pos, Buffer.s = ""
  ScintillaSendMessage(ID, #SCI_GOTOLINE, pos)
  _pos = ScintillaSendMessage(ID, #SCI_GETCURRENTPOS)
  length = ScintillaSendMessage(ID, #SCI_LINELENGTH, pos)
  ScintillaSendMessage(ID, #SCI_SETSELECTIONSTART, _pos)
  ScintillaSendMessage(ID, #SCI_SETSELECTIONEND, _pos + length)
  ProcedureReturn ScintillaSendMessage(ID, #SCI_REPLACESEL, 0, @Buffer)
EndProcedure

ProcedureDLL SCI_ClearGadgetItems(ID)
  Protected text.s = ""
  ; wichtig: Adresse zu einem leerem String übergeben! #Null o.ä. funktioniert nicht
  ProcedureReturn ScintillaSendMessage(ID, #SCI_SETTEXT, 0, @text)
EndProcedure

ProcedureDLL SCI_SetGadgetItemText(ID, pos, Text.s)
  Protected Buffer.s, length, _pos
  ; eine Zeile enthält keine #CRLF$, falls doch werden die erstmal entfernt
  Text = RemoveString(Text, #LF$)
  Text = RemoveString(Text, #CR$)
  If pos = #PB_Default
    ; wir fügen eine Zeile an, die Letzte Zeile enthält kein #CRLF$, also bauen wir es ein
    Text = #LF$ + Text
    Buffer = Space(StringByteLength(Text, SCI_GetTextFormat(ID)))
    PokeS(@Buffer, Text, -1, SCI_GetTextFormat(ID))
    ScintillaSendMessage(ID, #SCI_GOTOLINE, ScintillaSendMessage(ID, #SCI_GETLINECOUNT))
    ProcedureReturn ScintillaSendMessage(ID, #SCI_ADDTEXT, Len(text), @Buffer)
  Else
    Buffer = Space(StringByteLength(Text, SCI_GetTextFormat(ID)))
    PokeS(@Buffer, Text, -1, SCI_GetTextFormat(ID))
    ScintillaSendMessage(ID, #SCI_GOTOLINE, pos)
    _pos = ScintillaSendMessage(ID, #SCI_GETCURRENTPOS)
    length = ScintillaSendMessage(ID, #SCI_LINELENGTH, pos) - 1
    ScintillaSendMessage(ID, #SCI_SETSELECTIONSTART, _pos)
    ScintillaSendMessage(ID, #SCI_SETSELECTIONEND, _pos + length)
    ProcedureReturn ScintillaSendMessage(ID, #SCI_REPLACESEL, 0, @Buffer)
  EndIf
EndProcedure

ProcedureDLL.s SCI_GetGadgetText(ID)
  Protected length, buffer.s
  ; der Buffer muß ein Zeichen größer sein, als die tatsächliche länge
  ; hierfür ist immer in die Scintilla Documentation zu sehen. ( Manchmal hilft auch probieren ;) )
  
  ; le tampon doit avoir un caractère plus grand que la longueur réelle
  ; Cela est toujours visible dans la documentation Scintilla. (Parfois, il est utile d'essayer;))length = ScintillaSendMessage(ID, #SCI_GETLENGTH) + 1
  length = ScintillaSendMessage(ID, #SCI_GETLENGTH) + 1
  buffer = Space(length)
  ScintillaSendMessage(ID, #SCI_GETTEXT, length, @buffer)
  ProcedureReturn PeekS(@buffer, -1, SCI_GetTextFormat(ID))
EndProcedure

ProcedureDLL SCI_SetGadgetText(ID, Text.s)
  Protected Buffer.s
  ; Wir erzeugen einen Stringbuffer in der größte, wie das
  ; Scintilla in bei der momentan eingestellten Codepage benötigt!
  Buffer = Space(StringByteLength(Text, SCI_GetTextFormat(ID)))
  PokeS(@Buffer, Text, -1, SCI_GetTextFormat(ID))
  ProcedureReturn ScintillaSendMessage(ID, #SCI_SETTEXT, 0, @Buffer)
EndProcedure

ProcedureDLL SCI_GetGadgetAttribute(ID, Attribute)
  Select Attribute
    Case #PB_Editor_ReadOnly
      ProcedureReturn ScintillaSendMessage(ID, #SCI_GETREADONLY)
  EndSelect
EndProcedure

ProcedureDLL SCI_SetGadgetAttribute(ID, Attribute, Value)
  Select Attribute
    Case #PB_Editor_ReadOnly
      ProcedureReturn ScintillaSendMessage(ID, #SCI_SETREADONLY, Value)
  EndSelect 
EndProcedure

ProcedureDLL SCI_GetGadgetColor(ID, Type)
  Select Type
    Case #PB_Gadget_FrontColor
      ProcedureReturn ScintillaSendMessage(ID, #SCI_STYLEGETFORE, #STYLE_DEFAULT)
    Case #PB_Gadget_BackColor
      ProcedureReturn ScintillaSendMessage(ID, #SCI_STYLEGETBACK, #STYLE_DEFAULT)
  EndSelect
EndProcedure

ProcedureDLL SCI_SetGadgetColor(ID, Type, Color)
  Select Type
    Case #PB_Gadget_FrontColor
      ScintillaSendMessage(ID, #SCI_STYLESETFORE, #STYLE_DEFAULT, Color)
      ScintillaSendMessage(ID, #SCI_STYLECLEARALL)
    Case #PB_Gadget_BackColor
      ScintillaSendMessage(ID, #SCI_STYLESETBACK, #STYLE_DEFAULT, Color)
      ScintillaSendMessage(ID, #SCI_STYLECLEARALL)
  EndSelect
EndProcedure

ProcedureDLL SCI_SetGadgetFont(ID, FontName.s, Size)
  Protected Buffer.s
  Buffer = Space(StringByteLength(FontName, SCI_GetTextFormat(ID)))
  PokeS(@Buffer, FontName, -1, SCI_GetTextFormat(ID))  
  ScintillaSendMessage(ID, #SCI_STYLESETFONT, #STYLE_DEFAULT, @Buffer)
  ScintillaSendMessage(ID, #SCI_STYLESETSIZE, #STYLE_DEFAULT, Size)
  ScintillaSendMessage(ID, #SCI_STYLECLEARALL)
EndProcedure

ProcedureDLL SCI_LoadFile(ID, FileName.s)
  Protected FF, Format, length, *mem, Text.s
  
  FF = ReadFile(#PB_Any, FileName)
  If FF
    Select ReadStringFormat(FF)
      ; hier wird das StringFormat ermittelt und entsprechend gleich die Codepage eingestellt
      Case #PB_Unicode
        Format = #PB_Unicode
        ScintillaSendMessage(ID, #SCI_SETCODEPAGE, 65001)
      Case #PB_UTF8
        Format = #PB_UTF8
        ScintillaSendMessage(ID, #SCI_SETCODEPAGE, #SC_CP_UTF8)
      Default
        Format = #PB_Ascii
        ScintillaSendMessage(ID, #SCI_SETCODEPAGE, 0)
    EndSelect
    length = Lof(FF)
    If length
      *mem = AllocateMemory(length)
      If *mem
        ReadData(FF, *mem, length)
        Text = PeekS(*mem, length, Format)
        SCI_SetGadgetText(ID, Text.s)
        FreeMemory(*mem)
        CloseFile(FF)
        ProcedureReturn #True
      EndIf
    EndIf
    CloseFile(FF)
  EndIf
EndProcedure

ProcedureDLL SCI_SaveFile(ID, FileName.s)
  Protected length, *mem, FF
  
  FF = CreateFile(#PB_Any, FileName.s)
  
  If FF
    ; jetzt schreiben wir den BOM
    WriteStringFormat(FF, SCI_GetTextFormat(ID))
    length = ScintillaSendMessage(ID, #SCI_GETLENGTH) + 1
    *mem = AllocateMemory(length)
    ; jetzt holen wir den Text in den Speicher,
    ; wo er auch in dem Format vorliegt, das wir schreiben wollen.
    ScintillaSendMessage(ID, #SCI_GETTEXT, length, *mem)
    WriteData(FF, *mem, length - 1); der Speicher mußte ein Byte größer sein, aber schreiben wollen wir das nicht ;)
    CloseFile(FF)
    FreeMemory(*mem)
    ProcedureReturn #True
  EndIf
EndProcedure
Marc56
Messages : 2148
Inscription : sam. 08/févr./2014 15:19

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par Marc56 »

Whaou, Merci Nico et Mesa :) Je regarde tout ça de près.

Voilà (pour archive) mon petit exemple repris et modifié
Allègement au plus court tout en essayant de rester lisible.
(J'avais mis des caratères unicode dans ma chaine de test, cela fonctionne, mais ne peut être mis ici: le logiciel du forum refuse)
Erreur générale SQL ERROR [ mysqli ]
Incorrect string value: '\xF0\x9F\x98\x83 V...' for column 'post_text' at row 1 [1366]
Une erreur SQL est arrivée en chargeant cette page. Contactez l’administrateur du forum si ce problème persiste.

Pas un problème, on peut en mettre après pour vérifier que le comptage se fait bien.

Code : Tout sélectionner

; Scintilla_Select - Marc56 - 22/01/19 - PB 5.70 LTS
; Objectif: Récupérer un texte sélectionné dans un gadget Scintilla
; (À la souris ou au clavier)

; Références:
; https://www.scintilla.org/ScintillaDoc.html#SelectionAndInformation
; Exemple de skywalk http://forums.purebasic.com/english/viewtopic.php?p=342217#p342217
; Repris et modifié by myself
; Fiabilisé par Nico https://www.purebasic.fr/french/viewtopic.php?p=202705#p202705

EnableExplicit

OpenWindow(0, 0, 0, 520, 90, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

If InitScintilla()
    ScintillaGadget(0, 10, 10, 500, 70, 0)
    Define *Txt = UTF8("Voici un exemple simple ScintillaGadget© avec du texte unicode...")
    ScintillaSendMessage(0, #SCI_SETTEXT, 0, *Txt)
    FreeMemory(*Txt) 
EndIf

Repeat 
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
            End
            
        Case #WM_LBUTTONUP, #WM_KEYUP
            Define Long_Selection = ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, 0)
            If Long_Selection
                Define *Buf_Txt_UTF8 = AllocateMemory(Long_Selection)
                If ScintillaSendMessage(0, #SCI_GETSELTEXT, 0, *Buf_Txt_UTF8) = Long_Selection 
                    Define Selected_Txt$ = PeekS(*Buf_Txt_UTF8, #PB_Any, #PB_UTF8)
                    FreeMemory(*Buf_Txt_UTF8)
                    MessageRequester("", "[" + Selected_Txt$ + "]")
                EndIf
            EndIf             
            
    EndSelect
ForEver

End

Je vais mettre la partie principale dans mes modèles dans l'IDE.

:wink:
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Scintilla gadget: Récupérer le texte sélectionné

Message par nico »

Oups, j'ai commis une erreur sur Define Selected_Txt$ = PeekS(*Buf_Txt_UTF8, -1, #PB_UTF8), je reprend l'exemple de Marc56.

Il faut rajouter #PB_ByteLength comme ceci: Define Selected_Txt$ = PeekS(*Buf_Txt_UTF8, #PB_Any, #PB_UTF8 | #PB_ByteLength)
sinon la longueur est considérée comme un nombre de caractères au lieu de la mémoire occupée par la chaine UTF-8 dans notre cas.
(Vous pouvez faire un test facilement en mettant des accents par exemple)

J'ai omis #PB_ANY car même si sa valeur est -1, elle n'est pas identifiée dans l'aide pour cette fonction.
Pour rappel: UTF-8 code de 1 à 4 octets pour un caractère.
Répondre