1 <?xml version="1.0"?>
\r
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
\r
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
\r
4 <html xmlns="http://www.w3.org/1999/xhtml">
\r
6 <meta name="generator" content="HTML Tidy, see www.w3.org" />
\r
7 <meta name="generator" content="SciTE" />
\r
8 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
\r
10 Scintilla Usage Notes
\r
12 <style type="text/css">
\r
14 font-family: Verdana, Arial, Helvetica;
\r
19 font-family: Verdana, Arial, Helvetica;
\r
22 font-family: Comic Sans MS, Times New Roman, Times;
\r
27 font-family: Comic Sans MS, Times New Roman, Times;
\r
32 font-family: Verdana, Arial, Helvetica;
\r
36 font-family: Verdana, Arial, Helvetica;
\r
42 font-family: Verdana, Arial, Helvetica;
\r
46 font-family: Courier New, Courier;
\r
50 font-family: Courier New, Courier;
\r
63 <body bgcolor="#FFFFFF" text="#000000">
\r
64 <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
\r
67 <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
\r
70 <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
\r
71 Usage Notes</font></a>
\r
76 Implementing Auto-Indent
\r
79 The key idea is to use the SCN_CHARADDED notification to add indentation after a newline.
\r
82 The lParam on the notification is a pointer to a SCNotification structure whose ch member
\r
83 specifies the character added. If a newline was added, the previous line can be retrieved and
\r
84 the same indentation can be added to the new line.
\r
87 Here is the relevant portion of code from SciTE: (SciTE.cxx SciTEWindow::CharAdded)
\r
89 <span class='S5'>if</span><span class='S0'> </span> <span class='S10'>(</span><span
\r
90 class='S11'>ch</span><span class='S0'> </span> <span class='S10'>==</span><span
\r
91 class='S0'> </span> <span class='S7'>'\r'</span><span class='S0'> </span> <span
\r
92 class='S10'>||</span><span class='S0'> </span> <span class='S11'>ch</span><span
\r
93 class='S0'> </span> <span class='S10'>==</span><span class='S0'> </span> <span
\r
94 class='S7'>'\n'</span><span class='S10'>)</span><span class='S0'> </span> <span
\r
95 class='S10'>{</span><span class='S0'><br />
\r
96 </span> <span class='S5'>char</span><span class='S0'> </span>
\r
97 <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
\r
98 class='S10'>];</span><span class='S0'><br />
\r
99 </span> <span class='S5'>int</span><span class='S0'> </span>
\r
100 <span class='S11'>curLine</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
101 class='S0'> </span> <span class='S11'>GetCurrentLineNumber</span><span
\r
102 class='S10'>();</span><span class='S0'><br />
\r
103 </span> <span class='S5'>int</span><span class='S0'> </span>
\r
104 <span class='S11'>lineLength</span><span class='S0'> </span> <span class='S10'>
\r
105 =</span><span class='S0'> </span> <span class='S11'>SendEditor</span><span
\r
106 class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
\r
107 class='S0'> </span> <span class='S11'>curLine</span><span class='S10'>);</span><span
\r
109 </span> <span class='S2'>
\r
110 //Platform::DebugPrintf("[CR] %d len = %d\n", curLine, lineLength);</span><span
\r
112 </span> <span class='S5'>if</span><span class='S0'> </span> <span
\r
113 class='S10'>(</span><span class='S11'>curLine</span><span class='S0'> </span> <span
\r
114 class='S10'>></span><span class='S0'> </span> <span class='S4'>0</span><span
\r
115 class='S0'> </span> <span class='S10'>&&</span><span class='S0'> </span>
\r
116 <span class='S11'>lineLength</span><span class='S0'> </span> <span class='S10'>
\r
117 <=</span><span class='S0'> </span> <span class='S4'>2</span><span
\r
118 class='S10'>)</span><span class='S0'> </span> <span class='S10'>{</span><span
\r
120 </span> <span class='S5'>int</span><span class='S0'> </span>
\r
121 <span class='S11'>prevLineLength</span><span class='S0'> </span> <span class='S10'>
\r
122 =</span><span class='S0'> </span> <span class='S11'>SendEditor</span><span
\r
123 class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
\r
124 class='S0'> </span> <span class='S11'>curLine</span><span class='S0'> </span> <span
\r
125 class='S10'>-</span><span class='S0'> </span> <span class='S4'>1</span><span
\r
126 class='S10'>);</span><span class='S0'><br />
\r
127 </span> <span class='S5'>if</span><span class='S0'> </span> <span
\r
128 class='S10'>(</span><span class='S11'>prevLineLength</span><span class='S0'> </span> <span
\r
129 class='S10'><</span><span class='S0'> </span> <span class='S5'>sizeof</span><span
\r
130 class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>))</span><span
\r
131 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
132 </span> <span class='S11'>WORD</span><span
\r
133 class='S0'> </span> <span class='S11'>buflen</span><span class='S0'> </span> <span
\r
134 class='S10'>=</span><span class='S0'> </span> <span class='S5'>sizeof</span><span
\r
135 class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>);</span><span
\r
137 </span> <span class='S11'>memcpy</span><span
\r
138 class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>,</span><span
\r
139 class='S0'> </span> <span class='S10'>&</span><span class='S11'>buflen</span><span
\r
140 class='S10'>,</span><span class='S0'> </span> <span class='S5'>sizeof</span><span
\r
141 class='S10'>(</span><span class='S11'>buflen</span><span class='S10'>));</span><span
\r
143 </span> <span class='S11'>
\r
144 SendEditor</span><span class='S10'>(</span><span class='S11'>EM_GETLINE</span><span
\r
145 class='S10'>,</span><span class='S0'> </span> <span class='S11'>curLine</span><span
\r
146 class='S0'> </span> <span class='S10'>-</span><span class='S0'> </span> <span
\r
147 class='S4'>1</span><span class='S10'>,</span><span class='S0'><br />
\r
148 </span>
\r
149 <span class='S5'>reinterpret_cast</span><span class='S10'><</span><span
\r
150 class='S11'>LPARAM</span><span class='S10'>>(</span><span class='S5'>static_cast</span><span
\r
151 class='S10'><</span><span class='S5'>char</span><span class='S0'> </span> <span
\r
152 class='S10'>*>(</span><span class='S11'>linebuf</span><span class='S10'>)));</span><span
\r
154 </span> <span class='S11'>linebuf</span><span
\r
155 class='S10'>[</span><span class='S11'>prevLineLength</span><span class='S10'>]</span><span
\r
156 class='S0'> </span> <span class='S10'>=</span><span class='S0'> </span> <span
\r
157 class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
\r
158 </span> <span class='S5'>for</span><span
\r
159 class='S0'> </span> <span class='S10'>(</span><span class='S5'>int</span><span
\r
160 class='S0'> </span> <span class='S11'>pos</span><span class='S0'> </span> <span
\r
161 class='S10'>=</span><span class='S0'> </span> <span class='S4'>0</span><span
\r
162 class='S10'>;</span><span class='S0'> </span> <span class='S11'>linebuf</span><span
\r
163 class='S10'>[</span><span class='S11'>pos</span><span class='S10'>];</span><span
\r
164 class='S0'> </span> <span class='S11'>pos</span><span class='S10'>++)</span><span
\r
165 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
166 </span> <span
\r
167 class='S5'>if</span><span class='S0'> </span> <span class='S10'>(</span><span
\r
168 class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
\r
169 class='S10'>]</span><span class='S0'> </span> <span class='S10'>!=</span><span
\r
170 class='S0'> </span> <span class='S7'>' '</span><span class='S0'> </span> <span
\r
171 class='S10'>&&</span><span class='S0'> </span> <span class='S11'>
\r
172 linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
\r
173 class='S10'>]</span><span class='S0'> </span> <span class='S10'>!=</span><span
\r
174 class='S0'> </span> <span class='S7'>'\t'</span><span class='S10'>)</span><span
\r
176 </span>
\r
177 <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
\r
178 class='S10'>]</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
179 class='S0'> </span> <span class='S7'>'\0'</span><span class='S10'>;</span><span
\r
181 </span> <span class='S10'>}</span><span
\r
183 </span> <span class='S11'>
\r
184 SendEditor</span><span class='S10'>(</span><span class='S11'>EM_REPLACESEL</span><span
\r
185 class='S10'>,</span><span class='S0'> </span> <span class='S4'>0</span><span
\r
186 class='S10'>,</span><span class='S0'> </span> <span class='S5'>
\r
187 reinterpret_cast</span><span class='S10'><</span><span class='S11'>LPARAM</span><span
\r
188 class='S10'>>(</span><span class='S5'>static_cast</span><span class='S10'><</span><span
\r
189 class='S5'>char</span><span class='S0'> </span> <span class='S10'>*>(</span><span
\r
190 class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
\r
191 </span> <span class='S10'>}</span><span class='S0'><br />
\r
192 </span> <span class='S10'>}</span><br />
\r
194 <p style="margin-bottom: 0in">
\r
195 Of course, fancier handling could be implemented. For example, if the previous line was the
\r
196 start of a control construct, the next line could be automatically indented one tab further.
\r
197 (Assuming that is your indenting style.)
\r
200 Implementing Syntax Styling
\r
203 Syntax styling is handled by the SCN_STYLENEEDED notification. Scintilla keeps track of the
\r
204 end of the styled text - this is retrieved with SCI_GETENDSTYLED. In response to the
\r
205 SCN_STYLENEEDED notification, you should apply styles to the text from ENDSTYLED to the
\r
206 position specified by the notification.
\r
209 Here is the relevant portion of code from SciTE: (SciTE.cxx)
\r
211 <span class='S5'>void</span><span class='S0'> </span> <span class='S11'>
\r
212 SciTEWindow</span><span class='S10'>::</span><span class='S11'>Notify</span><span
\r
213 class='S10'>(</span><span class='S11'>SCNotification</span><span class='S0'> </span> <span
\r
214 class='S10'>*</span><span class='S11'>notification</span><span class='S10'>)</span><span
\r
215 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
216 </span> <span class='S5'>switch</span><span class='S0'> </span>
\r
217 <span class='S10'>(</span><span class='S11'>notification</span><span
\r
218 class='S10'>-></span><span class='S11'>nmhdr.code</span><span class='S10'>)</span><span
\r
219 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
220 </span> <span class='S5'>case</span><span class='S0'> </span>
\r
221 <span class='S11'>SCN_STYLENEEDED</span><span class='S10'>:</span><span
\r
222 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
223 </span> <span
\r
224 class='S5'>if</span><span class='S0'> </span> <span class='S10'>(</span><span
\r
225 class='S11'>notification</span><span class='S10'>-></span><span
\r
226 class='S11'>nmhdr.idFrom</span><span class='S0'> </span> <span class='S10'>==</span><span
\r
227 class='S0'> </span> <span class='S11'>IDM_SRCWIN</span><span class='S10'>)</span><span
\r
228 class='S0'> </span> <span class='S10'>{</span><span class='S0'><br />
\r
229 </span>
\r
230 <span class='S5'>int</span><span class='S0'> </span> <span class='S11'>
\r
231 endStyled</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
232 class='S0'> </span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
\r
233 class='S11'>SCI_GETENDSTYLED</span><span class='S10'>);</span><span class='S0'><br />
\r
234 </span>
\r
235 <span class='S5'>int</span><span class='S0'> </span> <span class='S11'>
\r
236 lineEndStyled</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
237 class='S0'> </span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
\r
238 class='S11'>EM_LINEFROMCHAR</span><span class='S10'>,</span><span class='S0'> </span>
\r
239 <span class='S11'>endStyled</span><span class='S10'>);</span><span class='S0'><br />
\r
240 </span>
\r
241 <span class='S11'>endStyled</span><span class='S0'> </span> <span class='S10'>
\r
242 =</span><span class='S0'> </span> <span class='S11'>SendEditor</span><span
\r
243 class='S10'>(</span><span class='S11'>EM_LINEINDEX</span><span class='S10'>,</span><span
\r
244 class='S0'> </span> <span class='S11'>lineEndStyled</span><span class='S10'>);</span><span
\r
246 </span>
\r
247 <span class='S11'>Colourise</span><span class='S10'>(</span><span
\r
248 class='S11'>endStyled</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
249 class='S11'>notification</span><span class='S10'>-></span><span
\r
250 class='S11'>position</span><span class='S10'>);</span><br />
\r
253 Colourize(start, end) retrieves the specified range of text and then calls ColourizeDoc in
\r
254 keywords.cxx. It starts the process by calling:
\r
256 <span class='S11'>SendMessage</span><span class='S10'>(</span><span
\r
257 class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
258 class='S11'>SCI_STARTSTYLING</span><span class='S10'>,</span><span class='S0'> </span>
\r
259 <span class='S11'>startPos</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
260 class='S4'>31</span><span class='S10'>);</span><br />
\r
263 and then for each token of the text, calling:
\r
265 <span class='S11'>SendMessage</span><span class='S10'>(</span><span
\r
266 class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
267 class='S11'>SCI_SETSTYLING</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
268 class='S11'>length</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
269 class='S11'>style</span><span class='S10'>);</span><br />
\r
272 where style is a number from 0 to 31 whose appearance has been defined using the
\r
273 SCI_STYLESET... messages.
\r
276 Implementing Calltips
\r
279 Again, the SCN_CHARADDED notification is used to catch when an opening parenthesis is added.
\r
280 The preceding word can then be retrieved from the current line:
\r
282 <span class='S5'>char</span><span class='S0'> </span> <span
\r
283 class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
\r
284 class='S10'>];</span><span class='S0'><br />
\r
285 </span> <span class='S5'>int</span><span class='S0'> </span> <span
\r
286 class='S11'>current</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
287 class='S0'> </span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
\r
288 class='S11'>SCI_GETCURLINE</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
289 class='S5'>sizeof</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
\r
290 class='S10'>),</span><span class='S0'><br />
\r
291 </span> <span class='S5'>
\r
292 reinterpret_cast</span><span class='S10'><</span><span class='S11'>LPARAM</span><span
\r
293 class='S10'>>(</span><span class='S5'>static_cast</span><span class='S10'><</span><span
\r
294 class='S5'>char</span><span class='S0'> </span> <span class='S10'>*>(</span><span
\r
295 class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
\r
296 </span> <span class='S5'>int</span><span class='S0'> </span> <span
\r
297 class='S11'>pos</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
298 class='S0'> </span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
\r
299 class='S11'>SCI_GETCURRENTPOS</span><span class='S10'>);</span><span class='S0'><br />
\r
301 </span> <span class='S5'>int</span><span class='S0'> </span> <span
\r
302 class='S11'>startword</span><span class='S0'> </span> <span class='S10'>=</span><span
\r
303 class='S0'> </span> <span class='S11'>current</span><span class='S0'> </span> <span
\r
304 class='S10'>-</span><span class='S0'> </span> <span class='S4'>1</span><span
\r
305 class='S10'>;</span><span class='S0'><br />
\r
306 </span> <span class='S5'>while</span><span class='S0'> </span>
\r
307 <span class='S10'>(</span><span class='S11'>startword</span><span class='S0'> </span>
\r
308 <span class='S10'>></span><span class='S0'> </span> <span class='S4'>0</span><span
\r
309 class='S0'> </span> <span class='S10'>&&</span><span class='S0'> </span>
\r
310 <span class='S11'>isalpha</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
\r
311 class='S10'>[</span><span class='S11'>startword</span><span class='S0'> </span> <span
\r
312 class='S10'>-</span><span class='S0'> </span> <span class='S4'>1</span><span
\r
313 class='S10'>]))</span><span class='S0'><br />
\r
314 </span> <span class='S11'>
\r
315 startword</span><span class='S10'>--;</span><span class='S0'><br />
\r
316 </span> <span class='S11'>linebuf</span><span class='S10'>[</span><span
\r
317 class='S11'>current</span><span class='S0'> </span> <span class='S10'>-</span><span
\r
318 class='S0'> </span> <span class='S4'>1</span><span class='S10'>]</span><span
\r
319 class='S0'> </span> <span class='S10'>=</span><span class='S0'> </span> <span
\r
320 class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
\r
321 </span> <span class='S5'>char</span><span class='S10'>*</span><span
\r
322 class='S0'> </span> <span class='S11'>word</span><span class='S0'> </span> <span
\r
323 class='S10'>=</span><span class='S0'> </span> <span class='S11'>linebuf</span><span
\r
324 class='S0'> </span> <span class='S10'>+</span><span class='S0'> </span> <span
\r
325 class='S11'>startword</span><span class='S10'>;</span><br />
\r
328 Then if a calltip is available it can be displayed. The calltip appears immediately below
\r
329 the position specified. The calltip can be multiple lines separated by newlines (\n).
\r
331 <span class='S11'>pos</span><span class='S0'> </span> <span
\r
332 class='S10'>=</span><span class='S0'> </span> <span class='S11'>SendMessage</span><span
\r
333 class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
\r
334 class='S0'> </span> <span class='S11'>SCI_GETCURRENTPOS</span><span
\r
335 class='S10'>,</span><span class='S0'> </span> <span class='S4'>0</span><span
\r
336 class='S10'>,</span><span class='S0'> </span> <span class='S4'>0</span><span
\r
337 class='S10'>);</span><span class='S0'><br />
\r
338 </span> <span class='S11'>SendMessageText</span><span
\r
339 class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
\r
340 class='S0'> </span> <span class='S11'>SCI_CALLTIPSHOW</span><span
\r
341 class='S10'>,</span><span class='S0'> </span> <span class='S11'>pos</span><span
\r
342 class='S0'> </span> <span class='S10'>-</span><span class='S0'> </span> <span
\r
343 class='S11'>wordLen</span><span class='S0'> </span> <span class='S10'>-</span><span
\r
344 class='S0'> </span> <span class='S4'>1</span><span class='S10'>,</span><span
\r
345 class='S0'> </span> <span class='S11'>calltip</span><span class='S10'>);</span><br />
\r
348 The calltip can be removed when a closing parenthesis is entered:
\r
350 <span class='S5'>if</span><span class='S0'> </span> <span
\r
351 class='S10'>(</span><span class='S11'>SendMessage</span><span class='S10'>(</span><span
\r
352 class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
353 class='S11'>SCI_CALLTIPACTIVE</span><span class='S10'>,</span><span class='S0'> </span>
\r
354 <span class='S4'>0</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
355 class='S4'>0</span><span class='S10'>))</span><span class='S0'><br />
\r
356 </span> <span class='S11'>
\r
357 SendMessage</span><span class='S10'>(</span><span class='S11'>hwnd</span><span
\r
358 class='S10'>,</span><span class='S0'> </span> <span class='S11'>
\r
359 SCI_CALLTIPCANCEL</span><span class='S10'>,</span><span class='S0'> </span> <span
\r
360 class='S4'>0</span><span class='S10'>,</span><span class='S0'> </span> <span class='S4'>
\r
361 0</span><span class='S10'>);</span><br />
\r
364 Obviously, it is up the application to look after supplying the appropriate calltip text.
\r
367 SciTE goes one step further, counting the commas between arguments and highlighting the
\r
368 corresponding part of the calltip. This code is in ContinueCallTip.
\r
371 <i>Page contributed by Andrew McKinlay.</i>
\r