Форум программистов, компьютерный форум, киберфорум
Pure Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.60/35: Рейтинг темы: голосов - 35, средняя оценка - 4.60
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124

Работа с текстовым редактором Scintilla

16.11.2022, 21:30. Показов 8630. Ответов 99
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток ! Тружусь над небольшой программкой, в которой у меня будет редактор кода на основе "Scintilla". Столкнулся с такой задачкой: нужно, чтобы при нахождении ключевого слова, происходила его замена. По типу как в пурике - если пользователь написал ключевое слово в нижнем регистре, редактор его заменил на то, как эти ключевые слова хранятся в программе. К примеру, пользователь прописал "for" -> редактор сменил на "For". При этом, пурик, как известно, подсветку производит непосредственно как только обнаруживает ключевое слово, а замену делает при наборе следующего символа. При этом, символ должен быть либо пробел, либо скобка, либо переход на новую строку и т.п.
Выкладываю свой самый сокращенный вариант для примера. В нём зарезервировано только одно ключевое слово "For", ну этого достаточно для теста. Тут я пытаюсь добиться желаемого, но как-то некорректно это происходит. В строчках 89, 90 как раз пытаюсь прописать эту замену, но почему-то она не работает как нужно.
Подскажите, пожалуйста, в чём ошибка ? Как только не пытался экспериментировать, никак не могу добиться желаемого. Документацию по Scintilla уже раз 40 пересматривал, изучал, но там тоже не так просто разобраться. Она таким тяжелым языком написана, а более понятной и доступной нигде не найти.
В общем, вот мой пример поиска решения, дальше которого я никак не могу продвинуться. Помогите, пожалуйста, если есть кто-то компетентный.

PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
InitScintilla("Scintilla.dll")
 
; Константы для подсветки синтаксиса
Enumeration 0
  #LexerState_Space
  #LexerState_Keyword
  #LexerState_FoldKeyword
EndEnumeration
 
Global ChangeWord$ = "For" ; слово для замены
 
Procedure MyLexerInit()
  ; Шрифт
  ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, @"Lucida Console")
  ; Размер шрифта
  ScintillaSendMessage(0, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 10)
  ScintillaSendMessage(0, #SCI_STYLECLEARALL)
  
  ; Цвет активной строки
  ScintillaSendMessage(0, #SCI_SETCARETLINEBACK, RGB(254, 252, 202))
  ; Разрешаем отмачать активную строку
  ScintillaSendMessage(0, #SCI_SETCARETLINEVISIBLE, #True)
  
  ; Цвета подсветки синтаксиса
  ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Keyword, 0)  ; Обычный текст
  ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_FoldKeyword, $FF) ; Ключевые слова
  
  ; Поля 
  ScintillaSendMessage(0, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) ; Поле автонумирации
  ScintillaSendMessage(0, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)  ; Поле свертки и маркеров
  ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 0, 20)               ; Ширина поля автонумирации
  ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 2, 20)               ; Ширина поля свертки и маркеров
  ScintillaSendMessage(0, #SCI_SETMARGINSENSITIVEN, 2, #True)
EndProcedure
 
Procedure SCI_EVENT(Gadget, *scinotify.SCNotification) ; Обработка событий от редактора
  code=             *scinotify.SCNotification\nmhdr\code
  pos=              *scinotify.SCNotification\Position
  ch=               *scinotify.SCNotification\ch
  modificationType= *scinotify.SCNotification\modifiers
  text=             *scinotify.SCNotification\text
  Length=           *scinotify.SCNotification\length
  linesAdded=       *scinotify.SCNotification\linesAdded
  message=          *scinotify.SCNotification\message
  wParam=           *scinotify.SCNotification\wParam
  lParam=           *scinotify.SCNotification\lParam
  line=             *scinotify.SCNotification\line
  foldLevelNow=     *scinotify.SCNotification\foldLevelNow
  foldLevelPrev=    *scinotify.SCNotification\foldLevelPrev
  margin=           *scinotify.SCNotification\margin
  listType=         *scinotify.SCNotification\listType
  x=                *scinotify.SCNotification\x
  y=                *scinotify.SCNotification\y
  
  
  Select code
    Case #SCN_STYLENEEDED
      EndPos = pos
      EndStyledPos = ScintillaSendMessage(0, #SCI_GETENDSTYLED)
      linenumber = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, EndStyledPos)
      
      ; Текуцая позиция курсора
      CurrentPos.l = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, linenumber)
      ; Подготовка к стилистической правке
      ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos)
      State = #LexerState_Space
      KeywordStartPos = CurrentPos
      keyword.s = ""
      
      While CurrentPos <= EndPos
        OldState = State
        
        Char.l = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем символ из текущей позиции 
        If Char = 10 Or Char = 13 Or Char = 9 Or Char = ' '
          State = #LexerState_Space
        Else
          State = #LexerState_Keyword
          keyword + Chr(Char)
        EndIf
        
        If OldState <> State Or CurrentPos = EndPos
          If OldState = #LexerState_Keyword
            lkeyword.s = LCase(keyword)
            If lkeyword = "for"
              LenKeyword = Len(lkeyword)
              *Kwd = AllocateMemory(LenKeyword)
              PokeS(*Kwd, ChangeWord$, LenKeyword, #PB_UTF8)
              
              ScintillaSendMessage(0, #SCI_DELETERANGE, pos - LenKeyword, LenKeyword)
              ScintillaSendMessage(0, #SCI_INSERTTEXT, -1, *Kwd)
              ScintillaSendMessage(0, #SCI_GOTOPOS, pos)
              FreeMemory(*Kwd)
              
              OldState = #LexerState_FoldKeyword
            EndIf
            keyword = ""
          EndIf
          ScintillaSendMessage(0, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState) ; Подсветка синтаксиса
          KeywordStartPos = CurrentPos
        EndIf
        CurrentPos + 1
      Wend
      
  EndSelect
EndProcedure
 
If OpenWindow(0, 450, 200, 402, 402, "Scintilla Example", #PB_Window_SystemMenu |#PB_Window_ScreenCentered)
  ScintillaGadget(0, 2, 2, 398, 398, @SCI_EVENT())
  MyLexerInit()
  
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
EndIf
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.11.2022, 21:30
Ответы с готовыми решениями:

Работа с текстовым редактором
Доброе время суток!!! Помогите! пишу текстовый редактор, на основе ActionManager использовал стандартную кнопку Undo (вернуть, назад),...

Работа с текстовым редактором
Помогите пожалуйста доделать задание. Не понимаю как дальше сделать. Только начал изучать win form

Помогите с текстовым редактором!
Пишу текстовый редактор для курсовой, почти все сделал, только препод сказал чтоб редактор был многостраничным, с использованием...

99
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
16.11.2022, 22:35
Делал подобное, но давно и уже не помню подробностей.
Если не ошибаюсь сделал через поиск/замену https://www.scintilla.org/Scin... #Searching
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
16.11.2022, 23:02  [ТС]
Я в курсе этой документации, и роюсь в ней уже довольно долгое время, но, то ли она сама так коряво объясняет назначение и принципы этих команд, то ли я такой тупой - разобраться в ней не так-то просто. Приходится фактически методом тыка всё делать. Частично, конечно, она даёт представление, но всерьёз в ней разобраться - ещё та задачка...

Добавлено через 11 минут
Просто сделать подсветку ключевых слов как есть без замены, подсветку констант, строк, заключенных в двойные кавычки и прочие подсветки - эта задача освоена и решена, а, вот не только подсветка, но ещё и замена (в данном случае ключевых слов) в моей попытке решения этого вопроса, нарушает всю корректность работы редактора.
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
17.11.2022, 01:31
Нашел исходник программы о которой писал. Участок кода заменяющий ключевые слова.
PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Procedure ZamenaSlov(Gadget, EndPos, State, PosText, RealSlovo.s, ZamenaSlovo.s)
; Замена регистра букв ключевых слов при подсветке синтаксиса
Protected Temp.s
 
 If State=0 ; Как в файле
   If RealSlovo=ZamenaSlovo
    ProcedureReturn 0
   EndIf
 ElseIf State=1 ; Перевести в верхний регистр
  Temp=UCase(ZamenaSlovo)
   If Temp=RealSlovo
    ProcedureReturn 0
   Else
    ZamenaSlovo=Temp
   EndIf
 ElseIf State=2 ; Перевести в нижний регистр
  Temp=LCase(ZamenaSlovo)
   If Temp=RealSlovo
    ProcedureReturn 0
   Else
    ZamenaSlovo=Temp
   EndIf
 Else
   ProcedureReturn 0
 EndIf
 
 
 If LCase(RealSlovo)<>LCase(ZamenaSlovo) Or EndPos=PosText
  ProcedureReturn 0
 EndIf
 
Len=Len(ZamenaSlovo)
 
ScintillaSendMessage(Gadget, #SCI_SETTARGETSTART,EndPos-Len ) ; Начало выделения (это не стандартное выделение!)
ScintillaSendMessage(Gadget, #SCI_SETTARGETEND, EndPos) ; Конец веделения (это не стандартное выделение!)
ScintillaSendMessage(Gadget, #SCI_REPLACETARGET,Len ,@ZamenaSlovo) ; Замена слова (это не стандартная замена)
 
ProcedureReturn 1
 
EndProcedure
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
17.11.2022, 02:50  [ТС]
Попробую привязать. А что здесь подразумевается под аргументом PosText ?

Добавлено через 39 минут
Просмотрел процедуру. В принципе, полностью она и не обязательна в данном случае. В ней самое нужное в 34, 35, 36 строчках. Я и так тоже уже пытался делать. Результат тот же. Вот, закомментировал свои строки, и заменил их на строки из процедуры. Результат одинаковый:

PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
InitScintilla("Scintilla.dll")
 
; Константы для подсветки синтаксиса
Enumeration 0
  #LexerState_Space
  #LexerState_Keyword
  #LexerState_FoldKeyword
EndEnumeration
 
Global ChangeWord$ = "For" ; слово для замены
 
Procedure MyLexerInit()
  ; Шрифт
  ScintillaSendMessage(0, #SCI_STYLESETFONT, #STYLE_DEFAULT, @"Lucida Console")
  ; Размер шрифта
  ScintillaSendMessage(0, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 10)
  ScintillaSendMessage(0, #SCI_STYLECLEARALL)
  ; множественный выбор
  ScintillaSendMessage(0, #SCI_SETMULTIPLESELECTION, 1)
  ; Цвет активной строки
  ScintillaSendMessage(0, #SCI_SETCARETLINEBACK, RGB(254, 252, 202))
  ; Разрешаем отмачать активную строку
  ScintillaSendMessage(0, #SCI_SETCARETLINEVISIBLE, #True)
  
  ; Цвета подсветки синтаксиса
  ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_Keyword, 0)  ; Обычный текст
  ScintillaSendMessage(0, #SCI_STYLESETFORE, #LexerState_FoldKeyword, $FF) ; Ключевые слова
  
  ; Поля 
  ScintillaSendMessage(0, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) ; Поле автонумирации
  ScintillaSendMessage(0, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS)  ; Поле свертки и маркеров
  ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 0, 20)               ; Ширина поля автонумирации
  ScintillaSendMessage(0, #SCI_SETMARGINWIDTHN, 2, 20)               ; Ширина поля свертки и маркеров
  ScintillaSendMessage(0, #SCI_SETMARGINSENSITIVEN, 2, #True)
EndProcedure
 
Procedure SCI_EVENT(Gadget, *scinotify.SCNotification) ; Обработка событий от редактора
  code=             *scinotify.SCNotification\nmhdr\code
  pos=              *scinotify.SCNotification\Position
  ch=               *scinotify.SCNotification\ch
  modificationType= *scinotify.SCNotification\modifiers
  text=             *scinotify.SCNotification\text
  Length=           *scinotify.SCNotification\length
  linesAdded=       *scinotify.SCNotification\linesAdded
  message=          *scinotify.SCNotification\message
  wParam=           *scinotify.SCNotification\wParam
  lParam=           *scinotify.SCNotification\lParam
  line=             *scinotify.SCNotification\line
  foldLevelNow=     *scinotify.SCNotification\foldLevelNow
  foldLevelPrev=    *scinotify.SCNotification\foldLevelPrev
  margin=           *scinotify.SCNotification\margin
  listType=         *scinotify.SCNotification\listType
  x=                *scinotify.SCNotification\x
  y=                *scinotify.SCNotification\y
  
  
  Select code
    Case #SCN_STYLENEEDED
      EndPos = pos
      EndStyledPos = ScintillaSendMessage(0, #SCI_GETENDSTYLED)
      linenumber = ScintillaSendMessage(0, #SCI_LINEFROMPOSITION, EndStyledPos)
      
      ; Текуцая позиция курсора
      CurrentPos.l = ScintillaSendMessage(0, #SCI_POSITIONFROMLINE, linenumber)
      ; Подготовка к стилистической правке
      ScintillaSendMessage(0, #SCI_STARTSTYLING, CurrentPos)
      State = #LexerState_Space
      KeywordStartPos = CurrentPos
      keyword.s = ""
      
      While CurrentPos <= EndPos
        OldState = State
        
        Char.l = ScintillaSendMessage(0, #SCI_GETCHARAT, CurrentPos) ; Получаем символ из текущей позиции 
        If Char = 10 Or Char = 13 Or Char = 9 Or Char = ' '
          State = #LexerState_Space
        Else
          State = #LexerState_Keyword
          keyword + Chr(Char)
        EndIf
        
        If OldState <> State Or CurrentPos = EndPos
          If OldState = #LexerState_Keyword
            lkeyword.s = LCase(keyword)
            If lkeyword = "for"
              LenKeyword = Len(lkeyword)
              *Kwd = AllocateMemory(LenKeyword)
              PokeS(*Kwd, ChangeWord$, LenKeyword, #PB_UTF8)
              
              ;ScintillaSendMessage(0, #SCI_DELETERANGE, pos - LenKeyword, LenKeyword)
              ;ScintillaSendMessage(0, #SCI_INSERTTEXT, -1, *Kwd)
              
              ScintillaSendMessage(0, #SCI_SETTARGETSTART, Pos - LenKeyword)
              ScintillaSendMessage(0, #SCI_SETTARGETEND, Pos)
              ScintillaSendMessage(0, #SCI_REPLACETARGET, LenKeyword , *Kwd)
              
              ScintillaSendMessage(0, #SCI_GOTOPOS, pos)
              
              FreeMemory(*Kwd)
              OldState = #LexerState_FoldKeyword
            EndIf
            keyword = ""
          EndIf
          ScintillaSendMessage(0, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState) ; Подсветка синтаксиса
          KeywordStartPos = CurrentPos
        EndIf
        CurrentPos + 1
      Wend
      
  EndSelect
EndProcedure
 
If OpenWindow(0, 450, 200, 402, 402, "Scintilla Example", #PB_Window_SystemMenu |#PB_Window_ScreenCentered)
  ScintillaGadget(0, 2, 2, 398, 398, @SCI_EVENT())
  MyLexerInit()
  
  Repeat
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
EndIf
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
17.11.2022, 14:29
Доработал один из давно написанных кодов. Изменяет for.
PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#DS_EDITOR_KEYWORDS = " for next if else elseif endif exit while wend goto "
#DS_EDITOR_OPENFOLD = " for while if " 
#DS_EDITOR_CLOSEFOLD = " next wend endif " 
#DS_EDITOR_ENDCONSTANT = "+=-*/%$ !<>|\/.,()"
 
Enumeration 0 
    #LexerState_Space 
    #LexerState_Comment 
    #LexerState_NonKeyword 
    #LexerState_Keyword 
    #LexerState_FoldKeyword 
    #LexerState_Constant 
    #LexerState_String 
EndEnumeration 
 
Procedure.l Scintilla(sciptr.l, p1.l, p2.l=0, p3.l=0) 
  ProcedureReturn ScintillaSendMessage(sciptr,p1,p2,p3) 
EndProcedure 
 
Procedure Highlight(sciptr.l, startpos.l, endpos.l) 
     
    If startpos = -1 
        endstyled.l = Scintilla(sciptr, #SCI_GETENDSTYLED) 
        linenumber.l = Scintilla(sciptr, #SCI_LINEFROMPOSITION, endstyled) 
    Else 
        linenumber = Scintilla(sciptr, #SCI_LINEFROMPOSITION, startpos) 
    EndIf 
    
    If linenumber = 0 
        level = #SC_FOLDLEVELBASE 
    Else 
        linenumber - 1 
        level = Scintilla(sciptr, #SCI_GETFOLDLEVEL, linenumber) & ~ #SC_FOLDLEVELHEADERFLAG 
    EndIf 
    
    thislevel.l = level 
    nextlevel.l = level 
    
    GetCursor=ScintillaSendMessage(sciptr,#SCI_GETCURRENTPOS) ; Текущее положение курсора
    
    currentpos.l = Scintilla(sciptr, #SCI_POSITIONFROMLINE, linenumber) 
    Scintilla(sciptr, #SCI_STARTSTYLING, currentpos, $1f | #INDICS_MASK) 
    state = #LexerState_Space 
    startkeyword = currentpos 
    keyword.s = "" 
    
    qpos.l = -1 ;quote pos 
    While currentpos <= endpos 
        oldstate = state 
        lastchar.l = char.l        
        char.l = Scintilla(sciptr, #SCI_GETCHARAT, currentpos) 
        If char = ';' 
            state = #LexerState_Comment 
        ElseIf char = '"' And state<>#LexerState_String 
            state = #LexerState_String 
            qpos = currentpos 
        ElseIf state = #LexerState_String 
            If (qpos<>currentpos-1 And lastchar = '"') Or char = 10 Or char = 13 
              state=#LexerState_Space 
              qpos=-1 
            EndIf          
        ElseIf char = 10 Or char = 13 
            state = #LexerState_Space 
        ElseIf state <> #LexerState_Comment 
            If state=#LexerState_Constant 
              If FindString(#DS_EDITOR_ENDCONSTANT,Chr(char)) Or char=10 Or char=13 Or char=9 
                state=#LexerState_Space 
              EndIf 
            Else              
              If char='#' 
                  state = #LexerState_Constant                
              ElseIf char = 9 Or char = ' ' Or char = '.' 
                  state = #LexerState_Space 
              Else 
                  state = #LexerState_NonKeyword 
                  keyword + Chr(char) 
              EndIf 
            EndIf 
        EndIf 
        If oldstate <> state Or currentpos = endpos 
            If oldstate = #LexerState_NonKeyword 
                lkeyword.s = LCase(keyword) 
                If FindString(#DS_EDITOR_OPENFOLD," "+LCase(keyword)+" ") 
                    thislevel | #SC_FOLDLEVELHEADERFLAG 
                    nextlevel + 1 
                ElseIf FindString(#DS_EDITOR_CLOSEFOLD," "+LCase(keyword)+" ")
                    nextlevel - 1 
                    If nextlevel < #SC_FOLDLEVELBASE 
                        nextlevel = #SC_FOLDLEVELBASE 
                    EndIf 
                EndIf 
                
                If FindString(#DS_EDITOR_KEYWORDS," "+LCase(keyword)+" ")
                  If LCase(keyword)="for"
                    keyword="For"
                  EndIf
                  *Kwd = UTF8(keyword)
                  If *Kwd
                    Debug keyword
                    Len = StringByteLength(keyword, #PB_UTF8)
                    ScintillaSendMessage(sciptr, #SCI_SETTARGETSTART, currentpos-Len)
                    ScintillaSendMessage(sciptr, #SCI_SETTARGETEND, currentpos)
                    ScintillaSendMessage(sciptr, #SCI_REPLACETARGET, Len, *Kwd)
                    
                    FreeMemory(*Kwd)
                  EndIf
                  oldstate = #LexerState_Keyword                                    
                EndIf                
                
                keyword = "" 
            EndIf 
            Scintilla(sciptr, #SCI_SETSTYLING, currentpos - startkeyword, oldstate) 
            startkeyword = currentpos-1 
        EndIf 
        
        If char = 10 Or currentpos = endpos 
            Scintilla(sciptr, #SCI_SETFOLDLEVEL, linenumber, thislevel) 
            thislevel = nextlevel 
            linenumber + 1 
        EndIf 
        
        currentpos + 1 
      Wend 
      
     ScintillaSendMessage(sciptr,#SCI_SETANCHOR,GetCursor) ; Устанавливаем курсор 
     ScintillaSendMessage(sciptr,#SCI_SETCURRENTPOS,GetCursor) ; Устанавливаем курсор 
EndProcedure 
 
Procedure ScCallBack(EditorGadget.l, *scinotify.SCNotification) 
  If *scinotify\nmhdr\code = #SCN_STYLENEEDED 
    Highlight(1, -1, *scinotify\position) 
  ElseIf *scinotify\nmhdr\code = #SCN_MARGINCLICK 
    modifiers = *scinotify\modifiers 
    position = *scinotify\position 
    margin = *scinotify\margin 
    linenumber = Scintilla(1, #SCI_LINEFROMPOSITION, position) 
    Select margin 
        Case 2 
            Scintilla(1, #SCI_TOGGLEFOLD, linenumber) 
    EndSelect 
  EndIf 
EndProcedure 
 
OpenWindow(0,0,0,600,600,"") 
 
RemoveKeyboardShortcut(0, #PB_Shortcut_Tab) 
RemoveKeyboardShortcut(0, #PB_Shortcut_Tab | #PB_Shortcut_Shift) 
 
InitScintilla("Scintilla.dll") 
CreateGadgetList(WindowID(0)) 
ScintillaGadget(1,0,0,600,500,@ScCallBack()) 
ButtonGadget(2,0,510,100,50,"GetText") 
 
; Margins 
Scintilla(1, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 10) 
Scintilla(1, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) 
Scintilla(1, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS) 
Scintilla(1, #SCI_SETMARGINWIDTHN, 0, 34) 
Scintilla(1, #SCI_SETMARGINWIDTHN, 1, 1) 
Scintilla(1, #SCI_SETMARGINWIDTHN, 2, 15) 
Scintilla(1, #SCI_SETMARGINSENSITIVEN, 2, #True) 
 
; Choose folding icons 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPEN, #SC_MARK_CIRCLEMINUS) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDER, #SC_MARK_CIRCLEPLUS) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERSUB, #SC_MARK_VLINE) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERTAIL, #SC_MARK_LCORNERCURVE) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEREND, #SC_MARK_CIRCLEPLUSCONNECTED) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDEROPENMID, #SC_MARK_CIRCLEMINUSCONNECTED) 
Scintilla(1, #SCI_MARKERDEFINE, #SC_MARKNUM_FOLDERMIDTAIL, #SC_MARK_TCORNERCURVE) 
 
; Choose folding icon colours 
Scintilla(1, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDER, $FFFFFF) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDER, 0) 
Scintilla(1, #SCI_MARKERSETFORE, #SC_MARKNUM_FOLDEROPEN, $FFFFFF) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPEN, 0) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDEROPENMID, 0) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERSUB, 0) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERTAIL, 0) 
Scintilla(1, #SCI_MARKERSETBACK, #SC_MARKNUM_FOLDERMIDTAIL, 0) 
 
;lex setup 
ScintillaSendMessage(1,#SCI_SETLEXER, #SCLEX_CONTAINER, 0); 
ScintillaSendMessage(1,#SCI_STYLESETFORE, #STYLE_DEFAULT, RGB(0,0,0)); 
ScintillaSendMessage(1,#SCI_STYLESETBACK, #STYLE_DEFAULT, RGB(255,255,255)); 
ScintillaSendMessage(1,#SCI_STYLECLEARALL); 
 
; Set caret line colour 
ScintillaSendMessage(1, #SCI_SETCARETLINEBACK, RGB(231, 245, 255)) 
ScintillaSendMessage(1, #SCI_SETCARETLINEVISIBLE, #True) 
 
; Set styles for custom lexer 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Comment, $8800) 
ScintillaSendMessage(1, #SCI_STYLESETITALIC, #LexerState_Comment, 1) 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_NonKeyword, 0) 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Keyword, RGB(38, 126, 0))
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_FoldKeyword, RGB(1, 13, 255)) 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_Constant, RGB(180,0,0)) 
ScintillaSendMessage(1, #SCI_STYLESETFORE, #LexerState_String, RGB(0,100,170)) 
 
SetGadgetText(1,";test comment"+#CRLF$+"If abc=1"+#CRLF$+"   Goto hi_there"+#CRLF$+"EndIf") 
 
Repeat 
 
 event=WaitWindowEvent() 
 
 If event=#PB_Event_Gadget 
   If EventGadget()=2 
     MessageRequester("Get",GetGadgetText(1)) 
   EndIf 
 EndIf 
 
Until event=#PB_Event_CloseWindow 
End
1
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
17.11.2022, 16:34  [ТС]
Да ! Делает так как нужно ! Сейчас сяду вникать, разбираться в чём причина некорректности моего варианта. Или, если не затруднит, можете подсказать в чём была моя недоработка ? Или хотя бы дать намёк...

Добавлено через 1 час 28 минут
Кстати, я уже рассматривал с какого-то ресурса этот вариант кода. В нём почему-то строка 201, которая должна отображаться в окне, не отображается в нём полностью, а только первый символ - точка с запятой. Это только у меня так, или нет ?
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
17.11.2022, 16:47
Код был написан давно.
Нужно заменить 201 строку на
PureBasic
1
2
3
4
5
*Text=UTF8(~"; Test comment\nIf abc=1\n   Goto hi_there\nEndIf")
If *Text
  ScintillaSendMessage(1, #SCI_SETTEXT, 0, *Text)
  FreeMemory(*Text)
EndIf
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
18.11.2022, 13:27  [ТС]
Я что-то никак не могу понять, что за позицию возвращает первое поле структуры SCNotification\position ? Когда набираешь текст в редакторе, он возвращает разные данные. По мере изменений в документе, в одном и том же месте может показывать разные значения, и я не могу понять, что за значение он возвращает ? Если бы просто позиция каретки в документе, то она в одном и том же месте была одинаковой, а тут идёт возврат разных значений. ???
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
18.11.2022, 15:54
Цитата Сообщение от antro735 Посмотреть сообщение
что за позицию возвращает первое поле структуры SCNotification\position
Зависит от сообщения https://www.scintilla.org/Scin... ifications
Sci_Position position;
/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
/* SCN_MARGINRIGHTCLICK, SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, */
/* SCN_CALLTIPCLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_AUTOCSELECTIONCHANGE */
Например вот что написано в SCN_STYLENEEDED
You are required to style the text from the line that contains the position returned by SCI_GETENDSTYLED up to the position passed in SCNotification.position.
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
18.11.2022, 17:55  [ТС]
Видимо, из-за недостатка знания других языков, к примеру, того же С++, я не могу до конца разобраться в этой документации по Scintilla. Там приводятся примеры на других языках, но мне эти примеры не совсем понятны.

То есть, после стилизации некоторых символов, значение, возвращаемое SCNotification\position каким-то образом изменяется ? Вот, конкретно в наших предыдущих кодах редактора есть такая строчка:
PureBasic
1
If OldState <> State Or CurrentPos = Pos
Чтобы прописать эту строку, нужно понимать, какое значение может быть у переменной pos. Но если не понимать как высчитывается её значение, пусть даже в зависимости от предыдущей стилизации, то невозможно осознанно написать эту часть строки: Or CurrentPos = Pos
Я и хочу разобраться, как же всё-таки понять, какое значение вернёт SCNotification\position в тот момент, когда нужно использовать это значение.

Добавлено через 19 минут
Потому что pos в наших предыдущих примерах кодов, как раз и есть значение SCNotification\position
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
18.11.2022, 18:06
Цитата Сообщение от antro735 Посмотреть сообщение
То есть, после стилизации некоторых символов, значение, возвращаемое SCNotification\position каким-то образом изменяется?
При получении сообщения #SCN_STYLENEEDED в SCNotification\position находится позиция символа до которой нужно подсвечивать синтаксис.
Для других сообщений в SCNotification\position будет другая информация.

Цитата Сообщение от antro735 Посмотреть сообщение
Чтобы прописать эту строку, нужно понимать, какое значение может быть у переменной pos.
Будет значение символа до которого нужно выполнять подсветку.

Цитата Сообщение от antro735 Посмотреть сообщение
невозможно осознанно написать эту часть строки: Or CurrentPos = Pos
В CurrentPos текущий символ. В Pos последний символ. Условие выполнится при последнем подсвечиваемом символе.
1
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
18.11.2022, 21:52  [ТС]
Благодарю, locm !!! Сейчас уже более понятно ! Теперь сяду экспериментировать на основе этой информации.

Добавлено через 3 часа 33 минуты
И всё же, правильно ли я понимаю, что после ввода какого-либо символа в редакторе, в контейнере #SCN_STYLENEEDED будет находиться значение SCNotification\position равное позиции последнего символа с тем лексером, в котором на текущий момент находится каретка ?
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
19.11.2022, 00:37
Нужно ориентироваться на документацию https://www.scintilla.org/Scin... TYLENEEDED

Проверить можно сравнивая текущую позицию со значением в SCNotification\position.
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
25.11.2022, 06:31  [ТС]
Уже почти неделю бьюсь и никак не могу понять, где ошибка. Уже какие только эксперименты и тесты не проводил, никак не могу понять, где собака зарыта... В общем, набираю я , к примеру, какое-то ключевое слово (возьмём тот же "for") все буквы в нижнем регистре, если набирать его с самого начала первой строки, как только оно будет набрано, всё нормально - оно подсветится. Дальше, допустим, я ввожу пробел (для экспериментирования пока использую пробел, доработки уже потом), в этот момент слово должно поменять вид с "for" на "For". Вид меняется, но при этом фон подсвечиваемой строки приобретает какой-то разрыв.
Следующий эксперимент - набираю сначала, допустим, 2-3 пробела, и набираю "for". Тут пока всё нормально, слово подсвечивается, но как только следом ввожу пробел или удаляю последнюю букву "r" снова возникает разрыв в подсветке активной строки. А если после только что набранного "for" попытаться перейти на следующую строку - вообще жуть.

Но самое интересное во всём этом, что если сначала набрать пробел, а перед этим пробелом набрать "for", то всё отрабатывает отлично. Оно по сути так и нужно. Если после ключевого слова стоит пробел или любой другой символ с другим лексером, то "for" тут же отобразится как "For". Как в редакторе пурика, только в пурике если набираешь "for", даже если после него есть пробел, или другой символ, не относящийся к символам слова, пока не введёшь какой-то символ после только что введённого "for", он не изменится на "For", а тут он сразу понимает, как нужно отобразить ключевое слово.

Ну, так, вот, мне непонятно, почему ? Почему после того как мы набираем "for", а затем пробел, он начинает бунтовать ? Ведь по сути, при обработке строки, он сначала обнаружит ключевое слово, а потом и введённый нами пробел, как и в вышеупомянутом случае. По алгоритму вроде бы всё верно. Хотя... есть у меня один непонятный момент. Строка 208, отвечающая за начальную подсветку обнаруженного ключевого слова, должна начать исполняться когда изменился лексер, но в момент набора символов слова лексер не изменяется. С какого перепугу он начинает подсвечивать ключевое слово, если смена лексера ещё не произошла ?

Друзья, помогите, пожалуйста, разобраться и понять, что не так, если, конечно, не затруднит ? А самое главное - почему происходит такая непонятка ? Складывается такое впечатление, что первый символ в документе не совсем первый, как будто перед ним ещё какое-то пространство как минимум в один символ. Может быть, я ошибаюсь. Пробовал отследить позицию каретки при вводе первого символа, а он выдаёт две позиции. Если отслеживать код вводимого символа, то тоже почему-то какой-то нулевой символ всегда присутствует. Я понимаю, что строки заканчиваются терминальным нулём, но если это здесь даёт такой побочный эффект, как с ним справиться ? Кстати, при появлении ключевого слова добавил, чтоб оно реагировало на курсор мыши - оно подчеркивается. Удобно для отслеживания количества символов, которые Scintilla принимает за ключевые слова. Если что-то не так, сразу будет видно какие лишние символы принимает за символы ключевого слова.

Вот сам экспериментальный код:
PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
; Ключевые слова
Key_Words.s + "ForEach,While,If,Next,Or,Wend,And,Else,ElseIf,End,EndIf,For"
AllKeys.l = CountString(Key_Words, ",")
 
Global Dim Key.s(AllKeys)
; Заполняем массив ключевыми словами
For i = 0 To AllKeys
  Key(i) = StringField(Key_Words, i + 1, ",")
Next
 
SortArray(Key(), #PB_Sort_Ascending)
 
; Константы, используемые для подсветки синтаксиса.
Enumeration 0
  #LexerState_Comment      ; (0) - Комментарии
  #LexerState_Space        ; (1) - Пробелы и другие разделители
  #LexerState_Const        ; (2) - Константы
  #LexerState_Keyword      ; (3) - Ключевые слова
  #LexerState_Word         ; (4) - Обычный текст
  #LexerState_String       ; (5) - Строки
  #LexerState_Symb         ; (6) - Одиночные символы
EndEnumeration
 
#SINGLE_SYMB = "()=^-+/\*><,."
 
#Scintilla_Gadget = 16
 
Macro Style
  ; Настройка текстового редактора Scintilla
  ;------------------------------------------
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETBACK, #STYLE_DEFAULT, RGB(209, 220, 218)) ; Цвет фона
  
  ; Шрифт
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCODEPAGE, #SC_CP_UTF8)
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFONT, #STYLE_DEFAULT, MakeUTF8Text(FontName$)) ; Имя шрифта
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETSIZE, #STYLE_DEFAULT, 10 )                     ; Размер шрифта
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLECLEARALL)                                         ; Устанавливаем стиль по умолчанию
  
  ; Цвет выделения
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSELFORE, 1, RGB(255, 255, 255)) ; Шрифт
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSELBACK, 1, RGB(52,106,220))    ; Выделенная область
  
  ; Активная строка
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCARETLINEBACK, RGB(218, 255, 231)) ; Цвет активной строки
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCARETLINEVISIBLE, #True)           ; Разрешаем отмечать активную строку
  
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINWIDTHN, 1, 0) ; Запрещаем отображать 1-вое поле маркеров
  
  ; Область свёртки
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINMASKN, 2, #SC_MASK_FOLDERS) 
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINWIDTHN, 2, 16)              ; Ширина поля свертки и маркеров
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINSENSITIVEN, 2, #True)       ; Разрешаем отображение 2-го поля, в котором будут отображаться маркеры свёртки
  ScintillaSendMessage(#Scintilla_Gadget, #SCN_MARGINCLICK, 2, #True)
  
  ; Автонумерация
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINTYPEN, 0, #SC_MARGIN_NUMBER) ; Добавляем 0-вое поле для автонумерации строк
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETMARGINWIDTHN, 0, 40)               ; Ширина поля автонумерации
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #STYLE_LINENUMBER, 0)   ; Цвет цифр автонумерации
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETBACK, #STYLE_LINENUMBER, RGB(255, 255, 255)) ; Цвет фона области автонумерации
  
  ; Курсор
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCARETFORE, RGB(2, 4, 231) ) ; Цвет курсора
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCARETPERIOD, 500)           ; Частота мерцания курсора
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCARETWIDTH, 1)              ; Ширина курсора в пикселях. Возможные значения 0-3
  
  ; Подсветка синтаксиса  
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #LexerState_Comment, RGB(19, 79, 40))    ; Цвет комментариев 
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETITALIC, #LexerState_Comment, #True)            ; Выделять комментарии курсивом: 0 - не выделять, 1 - выделять
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #LexerState_Word, 0)                     ; Цвет обычного текста
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #LexerState_String, RGB(0, 0, 255))      ; Цвет строк заключенных в двойные кавычки
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #LexerState_Keyword, RGB(33, 137, 163))  ; Цвет ключевых слов.
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETFORE, #LexerState_Symb, 0)
  
  ; Выделять комментарии наклонным шрифтом (курсивом). 0 - не выделять, 1 - выделять
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETITALIC, #LexerState_Comment, 1)
  ; Делаем ключевые слова чувствительными к действиям мыши
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETHOTSPOT, #LexerState_Keyword, 1)
  ; Выделять ключевые слова полужирным шрифтом (SCI_STYLESETWEIGHT со значением 600)
  ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETWEIGHT, #LexerState_Keyword, 600)
  ; жирным шрифтом (SCI_STYLESETBOLD со значением 1)
  ;ScintillaSendMessage(#Scintilla_Gadget, #SCI_STYLESETBOLD, #LexerState_Keyword, 1)
EndMacro
 
Procedure MakeUTF8Text(text.s)
  Static buffer.s
  buffer = Space(StringByteLength(text, #PB_UTF8))
  PokeS(@buffer, text, -1, #PB_UTF8)
  ProcedureReturn @buffer
EndProcedure
 
Procedure SCI_Callback(Gadget, *scinotify.SCNotification) 
  ; Переписываем данные из структуры в переменные 
  code             = *scinotify.SCNotification\nmhdr\code 
  pos              = *scinotify.SCNotification\Position 
  ch               = *scinotify.SCNotification\ch 
  modificationType = *scinotify.SCNotification\modifiers 
  text             = *scinotify.SCNotification\text 
  Length           = *scinotify.SCNotification\length 
  linesAdded       = *scinotify.SCNotification\linesAdded 
  message          = *scinotify.SCNotification\message 
  wParam           = *scinotify.SCNotification\wParam 
  lParam           = *scinotify.SCNotification\lParam 
  LINE             = *scinotify.SCNotification\LINE 
  foldLevelNow     = *scinotify.SCNotification\foldLevelNow 
  foldLevelPrev    = *scinotify.SCNotification\foldLevelPrev 
  margin           = *scinotify.SCNotification\margin 
  listType         = *scinotify.SCNotification\listType 
  x                = *scinotify.SCNotification\x 
  y                = *scinotify.SCNotification\y
  
  Static CheckWord.s
  
  Select code
    Case #SCN_STYLENEEDED
      ; Узнаём до какой позиции следует подсвечивать синтаксис в редакторе.
      EndStyledPos = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETENDSTYLED)
      
      ; Узнаём номер строки, до которой следует подсвечивать синтаксис.
      linenumber = ScintillaSendMessage(#Scintilla_Gadget, #SCI_LINEFROMPOSITION, EndStyledPos)
      
      CaretPos = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETCURRENTPOS)
      
      ; Узнаём позицию первого символа в строке, заданной в "linenumber".
      CurrentPos.l = ScintillaSendMessage(#Scintilla_Gadget, #SCI_POSITIONFROMLINE, linenumber)
      ; Подготовка к стилистической правке (подсветке синтаксиса). 
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK)
      
      State = #LexerState_Space
      
      KeywordStartPos = CurrentPos
      keyword.s = "" 
      
      While CurrentPos <= pos
        OldState = State 
        
        ; Получаем символ из текущей позиции курсора.
        Char.l = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETCHARAT, CurrentPos)
        
        If State <> #LexerState_Comment
          ; Находим комментарии
          If Char = ';'
            ; если это не текст между двойными кавычками
            If CountQuota = 0
              ; Отмечаем текущий текст как комментарий
              State = #LexerState_Comment
            EndIf
          ElseIf Char = '"'
            ; Считаем парность двойных кавычек
            CountQuota + 1
            If CountQuota < 2
              State = #LexerState_String
            Else
              ; сбрасываем счетчик двойных кавычек
              CountQuota = 0
            EndIf
            ; Отмечаем символы "возврата каретки" и "перевода строки" как пробелы.
          ElseIf Char = 10 Or Char = 13
            State = #LexerState_Space
            CountQuota = 0
            ; Если текущий текст НЕ комментарий, отмечаем символы
            ; "Tab" "Пробел" и "Точка" как пробелы.
          ElseIf Char = 9 Or Char = ' '
            If CountQuota = 0
              State = #LexerState_Space
            EndIf
          ElseIf FindString(#SINGLE_SYMB, Chr(Char))
            If CountQuota = 0
              state = #LexerState_Symb
            EndIf
          Else
            If CountQuota = 0
              ; Если совпадения нет, тогда отмечаем как обычный текст
              State = #LexerState_Word
              ; В переменной "keyword" сохраняется текст для поиска ключевых слов
              keyword + Chr(Char)
            EndIf
          EndIf 
        EndIf
        
        If OldState <> State Or CurrentPos = pos
          
          If State = #LexerState_Word
            StartKeyword = CurrentPos
          EndIf
          If OldState = #LexerState_Word
            EndKeyword = CurrentPos
          EndIf
          
          If CheckWord
            ; Меняем вид ключевого слова
            ;----------------------------
            ; Сохраняем адрес строки с ключевым словом
            *Kwd = UTF8(CheckWord)
            Len = StringByteLength(Key(i), #PB_UTF8)
            
            ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETSTART, EndKeyword - Len)
            ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETEND, EndKeyword)
            ScintillaSendMessage(#Scintilla_Gadget, #SCI_REPLACETARGET, Len, *Kwd)
            
            ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETANCHOR, CaretPos) ; Устанавливаем каретку
            ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCURRENTPOS, CaretPos) ; Устанавливаем каретку
            
            FreeMemory(*Kwd)
            OldState = #LexerState_Keyword
            CheckWord = ""
          EndIf
          
          If OldState = #LexerState_Word
            ; Сравниваем текущее слово с ключевыми словами из массива Key()
            For i = 0 To ArraySize(Key())
              ; если в нижних регистрах слова одинаковы
              If LCase(keyword) = LCase(Key(i))
                ; подготавливаем к подсветке как ключевое слово
                oldstate = #LexerState_Keyword
                ; а если в разных регистрах при этом отличаются
                If keyword <> Key(i)
                  CheckWord = Key(i)
                EndIf
                Break
              EndIf
            Next
            keyword = ""
          EndIf
          ; Подсветка ключевых слов
          ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState)
          
          KeywordStartPos = CurrentPos
        EndIf 
        
        CurrentPos + 1
      Wend
      ;ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETANCHOR, CaretPos) ; Устанавливаем каретку
      ;ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCURRENTPOS, CaretPos) ; Устанавливаем каретку
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSAVEPOINT)
  EndSelect
EndProcedure
 
OpenWindow(1, 0, 0, 500, 350, "Редактор", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
InitScintilla()
ScintillaGadget(#Scintilla_Gadget, 5, 1, 490, 318, @SCI_Callback())
SetActiveGadget(#Scintilla_Gadget)
Style
 
Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_Event_CloseWindow
0
62 / 60 / 3
Регистрация: 06.11.2010
Сообщений: 185
Записей в блоге: 1
25.11.2022, 08:18
antro735, на всякий случай справка по Scintilla на русском переведённая в гугле и обработанная скриптами, чтобы была подсветка и функции являлись ссылками. Пытался осмысленно переводить но забросил. Понять не сложно, никакой там не другой язык, там вообще нет привязки к языку. Есть функция, в скобках перечислены параметры, стрелка после скобок показывает в каком формате будет возвращено, например "int" и таких там большинство, то есть целое число. Параметры в скобках тоже имеют тип и назначение, например "position length" тип "position" то есть положительное число, и длинна или например "char *text", char это тип символы, *text это указатель. Причём по контексту везде написано если не указана длина строки, то строка нуль-терминированная, то есть движок будет искать 00 что будет определять конец строки, если же указана длина, что строка будет не нуль-терминированная. Где-то сказано что надо добавить 1 байт к длине строки чтобы движок завершил текст нулём, который определяет конец строки. В большинстве случаев везде тип int. Также в начале справки идёт описание типов, таблица с 11 типов bool, int, position, line и т.д.
Но я делал 3 года назад, может что-либо обновилось уже, так что можно заглядывать в англоязычную для уточнения. И в комплекте скрипт для обработки, можно скачать новую и выполнить обработку.
Вложения
Тип файла: zip Scintilla_Help_Ru_Google.zip (205.2 Кб, 17 просмотров)
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
25.11.2022, 09:53  [ТС]
AZJIO, У меня эти все документации по Scintilla есть давно. Кроме них фактически другой документации и нет никакой. Ну, хорошо, 3 года назад ты пытался работать с Scintilla, а каков результат ? Сделал что нужно было ? Выложи свою наработку. Отправить читать литературу большого ума не надо. Так и я всем могу помогать и подсказывать: "Вот книжки - возьми почитай".
Если ты о том, чтобы просто разукрасить текст - с этим я в общем-то разобрался, а, вот, с заменой в нужном месте - тут немного сложно для меня оказалось. Может быть, я совсем деревянный, но документацию вдоль и поперёк уже жую насколько понятия моего хватает. Да, огромным багажом знаний и опыта не похвастаюсь, к тому же, там примеры приводятся в основном на, если не ошибаюсь, С++. Я этот язык ещё не осваивал, и мне не так просто понять те примеры, которые там приводятся, поэтому и обращаюсь сюда за помощью на форум. Я нуждаюсь в помощи и подсказках более опытных ребят. И, самое главное - разобрать причину моих неудачных попыток добиться желаемого результата. Что я неправильно делаю. Я и справ, и слева, и спереди, и сзади, и сверху, и снизу экспериментирую не без помощи той же документации, найти нужное решение. Что-то уже освоено, достигнуто и сделано, а сейчас топчусь на одном месте как головой пО столу, ну, хоть ты тресни, не могу въехать что не так я делаю. Кроме как к более опытным парням больше не знаю к кому обратиться. Нет, можно, конечно, ещё неделю - две - месяц, а то и пол-года потратить на поиски, эксперименты, изучение дополнительной литературы, ЯП, и т.д. Время - самый дорогой ресурс. Всё можно вернуть, а время - нет. Так почему не обратиться к старшим товарищам, увидеть и узнать более грамотные и более профессиональные пути решения, научиться у них чему-то за более короткое время ?

Добавлено через 21 минуту
Мне ведь нужно даже не то, чтобы мне прислали готовое решение, а просто понять, в чём моя ошибка. Если я пойму и разберусь, я сам всё допишу и сделаю. Главное - понять причину кривого результата. В принципе, я близко подобрался к достижению желаемого. Возможно, тут какая-то мелочь, которую я никак не могу разглядеть или понять. Нуждаюсь просто в доступном объяснении, подсказке, намёке хотя бы.

Добавлено через 8 минут
Пусть, допустим, ты уже нашёл причину и решение, и у тебя всё работает, просто, помоги понять что у меня не так. Может быть, там совсем мелочь, а я её не вижу, или не знаю о ней.
0
62 / 60 / 3
Регистрация: 06.11.2010
Сообщений: 185
Записей в блоге: 1
25.11.2022, 10:01
antro735, если я только умею разукрасить текст, а ты уже наизусть документацию выучил, то получается ты больше меня знаешь и не я, а ты должен меня учить.
0
1 / 1 / 0
Регистрация: 28.07.2018
Сообщений: 124
25.11.2022, 10:04  [ТС]
AZJIO, я выше писал, что я не всё понимаю в этой документации. Если бы я там всё понимал, и выучил наизусть, как ты считаешь, я бы сюда не написал, и не просил помочь.
0
Эксперт по электронике
6574 / 3201 / 335
Регистрация: 28.10.2011
Сообщений: 12,482
Записей в блоге: 7
25.11.2022, 14:11
antro735, почему замена регистра ключевого слова выполняется в следующем вызове процедуры когда все позиции отличаются?
Нашли ключевое слово и сразу заменяйте его.
PureBasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Procedure SCI_Callback(Gadget, *scinotify.SCNotification) 
  ; Переписываем данные из структуры в переменные 
  code             = *scinotify.SCNotification\nmhdr\code 
  pos              = *scinotify.SCNotification\Position 
  ch               = *scinotify.SCNotification\ch 
  modificationType = *scinotify.SCNotification\modifiers 
  text             = *scinotify.SCNotification\text 
  Length           = *scinotify.SCNotification\length 
  linesAdded       = *scinotify.SCNotification\linesAdded 
  message          = *scinotify.SCNotification\message 
  wParam           = *scinotify.SCNotification\wParam 
  lParam           = *scinotify.SCNotification\lParam 
  LINE             = *scinotify.SCNotification\LINE 
  foldLevelNow     = *scinotify.SCNotification\foldLevelNow 
  foldLevelPrev    = *scinotify.SCNotification\foldLevelPrev 
  margin           = *scinotify.SCNotification\margin 
  listType         = *scinotify.SCNotification\listType 
  x                = *scinotify.SCNotification\x 
  y                = *scinotify.SCNotification\y
  
  Static CheckWord.s
  
  Select code
    Case #SCN_STYLENEEDED
      ; Узнаём до какой позиции следует подсвечивать синтаксис в редакторе.
      EndStyledPos = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETENDSTYLED)
      
      ; Узнаём номер строки, до которой следует подсвечивать синтаксис.
      linenumber = ScintillaSendMessage(#Scintilla_Gadget, #SCI_LINEFROMPOSITION, EndStyledPos)
      
      CaretPos = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETCURRENTPOS)
      
      ; Узнаём позицию первого символа в строке, заданной в "linenumber".
      CurrentPos.l = ScintillaSendMessage(#Scintilla_Gadget, #SCI_POSITIONFROMLINE, linenumber)
      ; Подготовка к стилистической правке (подсветке синтаксиса). 
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_STARTSTYLING, CurrentPos, $1F | #INDICS_MASK)
      
      State = #LexerState_Space
      
      KeywordStartPos = CurrentPos
      keyword.s = "" 
      
      While CurrentPos <= pos
        OldState = State 
        
        ; Получаем символ из текущей позиции курсора.
        Char.l = ScintillaSendMessage(#Scintilla_Gadget, #SCI_GETCHARAT, CurrentPos)
        
        If State <> #LexerState_Comment
          ; Находим комментарии
          If Char = ';'
            ; если это не текст между двойными кавычками
            If CountQuota = 0
              ; Отмечаем текущий текст как комментарий
              State = #LexerState_Comment
            EndIf
          ElseIf Char = '"'
            ; Считаем парность двойных кавычек
            CountQuota + 1
            If CountQuota < 2
              State = #LexerState_String
            Else
              ; сбрасываем счетчик двойных кавычек
              CountQuota = 0
            EndIf
            ; Отмечаем символы "возврата каретки" и "перевода строки" как пробелы.
          ElseIf Char = 10 Or Char = 13
            State = #LexerState_Space
            CountQuota = 0
            ; Если текущий текст НЕ комментарий, отмечаем символы
            ; "Tab" "Пробел" и "Точка" как пробелы.
          ElseIf Char = 9 Or Char = ' '
            If CountQuota = 0
              State = #LexerState_Space
            EndIf
          ElseIf FindString(#SINGLE_SYMB, Chr(Char))
            If CountQuota = 0
              state = #LexerState_Symb
            EndIf
          Else
            If CountQuota = 0
              ; Если совпадения нет, тогда отмечаем как обычный текст
              State = #LexerState_Word
              ; В переменной "keyword" сохраняется текст для поиска ключевых слов
              keyword + Chr(Char)
            EndIf
          EndIf 
        EndIf
        
        If OldState <> State Or CurrentPos = pos
          
          If State = #LexerState_Word
            StartKeyword = CurrentPos
          EndIf
          If OldState = #LexerState_Word
            EndKeyword = CurrentPos
          EndIf
          
;           If CheckWord
;             ; Меняем вид ключевого слова
;             ;----------------------------
;             ; Сохраняем адрес строки с ключевым словом
;             *Kwd = UTF8(CheckWord)
;             Len = StringByteLength(CheckWord, #PB_UTF8)
;             
;             ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETSTART, EndKeyword - Len)
;             ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETEND, EndKeyword)
;             ScintillaSendMessage(#Scintilla_Gadget, #SCI_REPLACETARGET, Len, *Kwd)
;             
;             ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETANCHOR, CaretPos) ; Устанавливаем каретку
;             ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCURRENTPOS, CaretPos) ; Устанавливаем каретку
;             
;             FreeMemory(*Kwd)
;             OldState = #LexerState_Keyword
;             CheckWord = ""
;           EndIf
          
          If OldState = #LexerState_Word
            ; Сравниваем текущее слово с ключевыми словами из массива Key()
            For i = 0 To ArraySize(Key())
              ; если в нижних регистрах слова одинаковы
              If LCase(keyword) = LCase(Key(i))
                ; подготавливаем к подсветке как ключевое слово
                oldstate = #LexerState_Keyword
                ; а если в разных регистрах при этом отличаются
                If keyword <> Key(i)
                  CheckWord = Key(i)
                  
                  *Kwd = UTF8(CheckWord)
                  If *Kwd
                    Len = StringByteLength(CheckWord, #PB_UTF8)
                    ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETSTART, EndKeyword - Len)
                    ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETTARGETEND, EndKeyword)
                    ScintillaSendMessage(#Scintilla_Gadget, #SCI_REPLACETARGET, Len, *Kwd)
                    FreeMemory(*Kwd)
                  EndIf
                  
                EndIf
                Break
              EndIf
            Next
            keyword = ""
          EndIf
          ; Подсветка ключевых слов
          ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSTYLING, CurrentPos - KeywordStartPos, OldState)
          
          KeywordStartPos = CurrentPos
        EndIf 
        
        CurrentPos + 1
      Wend
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETANCHOR, CaretPos) ; Устанавливаем каретку
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETCURRENTPOS, CaretPos) ; Устанавливаем каретку
      ScintillaSendMessage(#Scintilla_Gadget, #SCI_SETSAVEPOINT)
  EndSelect
EndProcedure
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.11.2022, 14:11
Помогаю со студенческими работами здесь

С текстовым редактором C++ Builder
Всем привет, нужна ваша помощь. Делаю текстовый редактор, окно сохранить, открыть файл уже готовы. Вопрос следующий. Как сделать так,...

Помощь с текстовым редактором
ребят нужна помощь!) нужно в текстовом редакторе сделать правописание жи-ши , т.е. пишим ЖЫ или Шы он должен подчекнуть и исправить по...

Ввод и вывод массива с текстовым редактором
Ребят помогите срочно нужно сделать так чтобы считывался массив с in.txt и отправлялся полученный результат в out.txt {$R+} uses crt; ...

Обработка больших файлов текстовым редактором
У меня задание написать текстовый редактор, в целом всё ясно, за исключение пункта: &quot;возможность обработки больших файлов&quot;. Я не...

Сценарий PowerShell для работы с текстовым редактором
Доброго времени суток!!! Очень нуждаюсь в вашей помощи! Начали изучать в университете новый предмет, лекции читают про то как работают ОС,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru