Scintilla Tk

Check-in [e150c20c60]
Login
Tcl 2015 Conference, Manassas/VA, US, Oct 19-23
Send your abstracts to tclconference@googlegroups.com by Aug 24.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial commit of ScintillaTk The code here includes Scintilla 3.3.0
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | descendants | trunk
Files: files | file ages | folders
SHA1:e150c20c6070c71cdf577a0fcd86ded04589262d
User & Date: devnull@localhost 2013-06-27 02:24:49
Context
2013-09-16
01:56
Initial check-in is version 0.26 check-in: f646ef686b user: briang42@easystreet.net tags: trunk
2013-06-27
02:24
Initial commit of ScintillaTk The code here includes Scintilla 3.3.0 check-in: e150c20c60 user: devnull@localhost tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace

Added License.txt.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
License for Scintilla and SciTE

Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>

All Rights Reserved 

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that 
both that copyright notice and this permission notice appear in 
supporting documentation. 

NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY 
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 
OR PERFORMANCE OF THIS SOFTWARE. 

Added README.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
README for building of Scintilla and SciTE

Scintilla can be built by itself.
To build SciTE, Scintilla must first be built.


*** GTK+/Linux version ***

You must first have GTK+ 2.0 or later and GCC (4.1 or better) installed.
GTK+ 1.x will not work.
Other C++ compilers may work but may require tweaking the make file.

To build Scintilla, use the makefile located in the scintilla/gtk directory
	cd scintilla/gtk
	make
	cd ../..

To build and install SciTE, use the makefile located in the scite/gtk directory
	cd scite/gtk
	make
	make install

This installs SciTE into $prefix/bin. The value of $prefix is determined from
the location of Gnome if it is installed. This is usually /usr if installed
with Linux or /usr/local if built from source. If Gnome is not installed
/usr/bin is used as the prefix. The prefix can be overridden on the command
line like "make prefix=/opt" but the same value should be used for both make
and make install as this location is compiled into the executable. The global
properties file is installed at $prefix/share/scite/SciTEGlobal.properties.
The language specific properties files are also installed into this directory.

To remove SciTE
	make uninstall

To clean the object files which may be needed to change $prefix
	make clean

The current make file only supports static linking between SciTE and Scintilla.


*** Windows version ***

A C++ compiler is required. Visual Studio .NET 2010 is the development system
used for most development although TDM Mingw32 4.4.1 is also supported.

To build Scintilla, make in the scintilla/win32 directory
		cd scintilla\win32
GCC:		mingw32-make
VS .NET:	nmake -f scintilla.mak
		cd ..\..

To build SciTE, use the makefiles located in the scite/win32 directory
		cd scite\win32
GCC:		mingw32-make
VS .NET: 	nmake -f scite.mak

An executable SciTE will now be in scite\bin.

The Visual C++ 6.0 project (.dsp) and make files are no longer supported but are left
in the download for people that are prepared to update them.

*** GTK+/Windows version ***

Mingw32 is known to work. Other compilers will probably not work.

Only Scintilla will build with GTK+ on Windows. SciTE will not work.

To build Scintilla, make in the scintilla/gtk directory
	cd scintilla\gtk
	mingw32-make

Added cocoa/Framework.mk.















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
### start defines ###
include common.mk

INST_NAME=-install_name \
	@executable_path/../Frameworks/Sci.framework/Versions/A/Sci

LD=gcc $(ARCH) -dynamiclib -framework Cocoa $(INST_NAME)

LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))

SCI_LEXERS=$(LEXOBJS) \
	LexerBase.o LexerModule.o LexerSimple.o Accessor.o

SCI_OBJ=AutoComplete.o CallTip.o CellBuffer.o CharClassify.o \
	ContractionState.o Decoration.o Document.o Editor.o \
	ExternalLexer.o Indicator.o KeyMap.o LineMarker.o PerLine.o \
	PositionCache.o PropSetSimple.o RESearch.o RunStyles.o ScintillaBase.o Style.o \
	StyleContext.o UniConversion.o ViewStyle.o XPM.o WordList.o \
	Selection.o CharacterSet.o Catalogue.o $(SCI_LEXERS)

WAH_OBJ=DocumentAccessor.o KeyWords.o WindowAccessor.o

COC_OBJ=PlatCocoa.o ScintillaCocoa.o ScintillaView.o InfoBar.o

OBJ=$(SCI_OBJ) $(UNUSED_OBJ) $(COC_OBJ)
OBJS=$(addprefix $(FRM_BLD)/,$(OBJ))

TARG=$(APP)/Versions/A/Sci
APP=$(FRM_BLD)/Sci.framework
### end defines ###

### start targets ###

all: $(FRM_BLD) $(TARG)

cleanfrm:
	-rm -rf $(FRM_BLD)

$(APP): $(FRM_BLD)
	-rm -rf $(APP)
	-mkdir $(APP)
	-mkdir $(APP)/Versions
	-mkdir $(APP)/Versions/A
	-mkdir $(APP)/Versions/A/Headers
	-mkdir $(APP)/Versions/A/Resources
	-ln -sf `pwd`/$(APP)/Versions/A `pwd`/$(APP)/Versions/Current
	-ln -sf `pwd`/$(APP)/Versions/A/Headers `pwd`/$(APP)/Headers
	-ln -sf `pwd`/$(APP)/Versions/A/Resources `pwd`/$(APP)/Resources
	-cp *.h $(APP)/Headers/
	-cp ../src/*.h $(APP)/Headers/
	-cp ../include/*.h $(APP)/Headers/
	-cp -R ScintillaFramework/English.lproj $(APP)/Resources
	-cp res/*.png $(APP)/Resources
	-cp ScintillaFramework/Info.plist $(APP)/Resources

$(TARG) : $(OBJS) $(APP)
	$(LD) $(OBJS) $(gDEFs) -o $(TARG) -lstdc++
	-ln `pwd`/$(TARG) `pwd`/$(APP)/Sci

$(FRM_BLD):
	-mkdir $(BLD)
	-mkdir $(FRM_BLD)

### get around to filling out the real dependencies later ###
#$(FRM_BLD)/AutoComplete.o : ../src/AutoComplete.cxx ../src/AutoComplete.h \
#	../include/Platform.h

#$(FRM_BLD)/CallTip.o : ../src/CallTip.cxx ../src/CallTip.h \
#	../include/Platform.h

### end targets ###

Added cocoa/InfoBar.h.















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

/**
 * Scintilla source code edit control
 * InfoBar.h - Implements special info bar with zoom info, caret position etc. to be used with
 *             ScintillaView.
 *
 * Mike Lischke <mlischke@sun.com>
 *
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <Cocoa/Cocoa.h>
#import "InfoBarCommunicator.h"

/**
 * Extended text cell for vertically aligned text.
 */
@interface VerticallyCenteredTextFieldCell : NSTextFieldCell
{
	BOOL mIsEditingOrSelecting;
}

@end

@interface InfoBar : NSView <InfoBarCommunicator>
{
@private
  NSImage* mBackground;
  IBDisplay mDisplayMask;
  
  float mScaleFactor;
  NSPopUpButton* mZoomPopup;
  
  int mCurrentCaretX;
  int mCurrentCaretY;
  NSTextField* mCaretPositionLabel;
  NSTextField* mStatusTextLabel;
  
  id <InfoBarCommunicator> mCallback;
}

- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
          value: (float) value;
- (void) setCallback: (id <InfoBarCommunicator>) callback;

- (void) createItems;
- (void) positionSubViews;
- (void) setDisplay: (IBDisplay) display;
- (void) zoomItemAction: (id) sender;
- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag;
- (void) setCaretPosition: (NSPoint) position;
- (void) sizeToFit;

@end

Added cocoa/InfoBar.mm.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448

/**
 * Scintilla source code edit control
 * InfoBar.mm - Implements special info bar with zoom info, caret position etc. to be used with
 *              ScintillaView.
 *
 * Mike Lischke <mlischke@sun.com>
 *
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import "InfoBar.h"

//--------------------------------------------------------------------------------------------------

@implementation VerticallyCenteredTextFieldCell

// Inspired by code from Daniel Jalkut, Red Sweater Software.

- (NSRect) drawingRectForBounds: (NSRect) theRect
{
	// Get the parent's idea of where we should draw
	NSRect newRect = [super drawingRectForBounds: theRect];
  
	// When the text field is being edited or selected, we have to turn off the magic because it
  // screws up the configuration of the field editor. We sneak around this by intercepting
  // selectWithFrame and editWithFrame and sneaking a reduced, centered rect in at the last minute.
	if (mIsEditingOrSelecting == NO)
	{
		// Get our ideal size for current text
		NSSize textSize = [self cellSizeForBounds: theRect];
    
		// Center that in the proposed rect
		float heightDelta = newRect.size.height - textSize.height;	
		if (heightDelta > 0)
		{
			newRect.size.height -= heightDelta;
			newRect.origin.y += ceil(heightDelta / 2);
		}
	}
	
	return newRect;
}

//--------------------------------------------------------------------------------------------------

- (void) selectWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj 
                delegate:(id) anObject start: (NSInteger) selStart length: (NSInteger) selLength
{
	aRect = [self drawingRectForBounds: aRect];
	mIsEditingOrSelecting = YES;	
	[super selectWithFrame: aRect
                  inView: controlView
                  editor: textObj
                delegate: anObject
                   start: selStart
                  length: selLength];
	mIsEditingOrSelecting = NO;
}

//--------------------------------------------------------------------------------------------------

- (void) editWithFrame: (NSRect) aRect inView: (NSView*) controlView editor: (NSText*) textObj
              delegate: (id) anObject event: (NSEvent*) theEvent
{	
	aRect = [self drawingRectForBounds: aRect];
	mIsEditingOrSelecting = YES;
	[super editWithFrame: aRect
                inView: controlView
                editor: textObj
              delegate: anObject
                 event: theEvent];
	mIsEditingOrSelecting = NO;
}

@end

//--------------------------------------------------------------------------------------------------

@implementation InfoBar

- (id) initWithFrame: (NSRect) frame
{
  self = [super initWithFrame: frame];
  if (self)
  {
    NSBundle* bundle = [NSBundle bundleForClass: [InfoBar class]];
    
    NSString* path = [bundle pathForResource: @"info_bar_bg" ofType: @"png" inDirectory: nil];
    mBackground = [[NSImage alloc] initWithContentsOfFile: path];
    if (![mBackground isValid])
      NSLog(@"Background image for info bar is invalid.");

    mScaleFactor = 1.0;
    mCurrentCaretX = 0;
    mCurrentCaretY = 0;
    [self createItems];
  }
  return self;
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by a connected compontent (usually the info bar) if something changed there.
 *
 * @param type The type of the notification.
 * @param message Carries the new status message if the type is a status message change.
 * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type.
 * @param location Carries the new zoom value if the type is a zoom change.
 */
- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
  value: (float) value
{
  switch (type)
  {
    case IBNZoomChanged:
      [self setScaleFactor: value adjustPopup: YES];
      break;
    case IBNCaretChanged:
      [self setCaretPosition: location];
      break;
    case IBNStatusChanged:
      [mStatusTextLabel setStringValue: message];
      break;
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to set a protocol object we can use to send change notifications to.
 */
- (void) setCallback: (id <InfoBarCommunicator>) callback
{
  mCallback = callback;
}

//--------------------------------------------------------------------------------------------------

static NSString *DefaultScaleMenuLabels[] = {
  @"20%", @"30%", @"50%", @"75%", @"100%", @"130%", @"160%", @"200%", @"250%", @"300%"
};
static float DefaultScaleMenuFactors[] = {
  0.2, 0.3, 0.5, 0.75, 1.0, 1.3, 1.6, 2.0, 2.5, 3.0
};
static unsigned DefaultScaleMenuSelectedItemIndex = 4;
static float BarFontSize = 10.0;

- (void) createItems
{
  // 1) The zoom popup.
  unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuLabels) / sizeof(NSString *);
  
  // Create the popup button.
  mZoomPopup = [[NSPopUpButton allocWithZone:[self zone]] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0) pullsDown: NO];
  
  // No border or background please.
  [[mZoomPopup cell] setBordered: NO];
  [[mZoomPopup cell] setArrowPosition: NSPopUpArrowAtBottom];
  
  // Fill it.
  for (unsigned count = 0; count < numberOfDefaultItems; count++)
  {
    [mZoomPopup addItemWithTitle: NSLocalizedStringFromTable(DefaultScaleMenuLabels[count], @"ZoomValues", nil)];
    id currentItem = [mZoomPopup itemAtIndex: count];
    if (DefaultScaleMenuFactors[count] != 0.0)
      [currentItem setRepresentedObject: [NSNumber numberWithFloat: DefaultScaleMenuFactors[count]]];
  }
  [mZoomPopup selectItemAtIndex: DefaultScaleMenuSelectedItemIndex];
  
  // Hook it up.
  [mZoomPopup setTarget: self];
  [mZoomPopup setAction: @selector(zoomItemAction:)];
  
  // Set a suitable font.
  [mZoomPopup setFont: [NSFont menuBarFontOfSize: BarFontSize]];
  
  // Make sure the popup is big enough to fit the cells.
  [mZoomPopup sizeToFit];
  
  // Don't let it become first responder
  [mZoomPopup setRefusesFirstResponder: YES];
  
  // put it in the scrollview.
  [self addSubview: mZoomPopup];
  [mZoomPopup release];
  
  // 2) The caret position label.
  Class oldCellClass = [NSTextField cellClass];
  [NSTextField setCellClass: [VerticallyCenteredTextFieldCell class]];
  
  mCaretPositionLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 50.0, 1.0)];
  [mCaretPositionLabel setBezeled: NO];
  [mCaretPositionLabel setBordered: NO];
  [mCaretPositionLabel setEditable: NO];
  [mCaretPositionLabel setSelectable: NO];
  [mCaretPositionLabel setDrawsBackground: NO];
  [mCaretPositionLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]];

  NSTextFieldCell* cell = [mCaretPositionLabel cell];
  [cell setPlaceholderString: @"0:0"];
  [cell setAlignment: NSCenterTextAlignment];

  [self addSubview: mCaretPositionLabel];
  [mCaretPositionLabel release];
  
  // 3) The status text.
  mStatusTextLabel = [[NSTextField alloc] initWithFrame: NSMakeRect(0.0, 0.0, 1.0, 1.0)];
  [mStatusTextLabel setBezeled: NO];
  [mStatusTextLabel setBordered: NO];
  [mStatusTextLabel setEditable: NO];
  [mStatusTextLabel setSelectable: NO];
  [mStatusTextLabel setDrawsBackground: NO];
  [mStatusTextLabel setFont: [NSFont menuBarFontOfSize: BarFontSize]];

  cell = [mStatusTextLabel cell];
  [cell setPlaceholderString: @""];

  [self addSubview: mStatusTextLabel];
  [mStatusTextLabel release];
  
  // Restore original cell class so that everything else doesn't get broken
  [NSTextField setCellClass: oldCellClass];
}

//--------------------------------------------------------------------------------------------------

- (void) dealloc
{
  [mBackground release];
  [super dealloc];
}

//--------------------------------------------------------------------------------------------------

/**
 * Fill the background.
 */
- (void) drawRect: (NSRect) rect
{
  // Since the background is seamless, we don't need to take care for the proper offset.
  // Simply tile the background over the invalid rectangle.
  NSPoint target = {rect.origin.x, 0};
  while (target.x < rect.origin.x + rect.size.width)
  {
    [mBackground drawAtPoint: target fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1];
    target.x += mBackground.size.width;
  }
  
  // Draw separator lines between items.
  NSRect verticalLineRect;
  float component = 190.0 / 255.0;
  NSColor* lineColor = [NSColor colorWithDeviceRed: component green: component blue: component alpha: 1];
  
  if (mDisplayMask & IBShowZoom)
  {
    verticalLineRect = [mZoomPopup frame];
    verticalLineRect.origin.x += verticalLineRect.size.width + 1.0;
    verticalLineRect.size.width = 1.0;
    if (NSIntersectsRect(rect, verticalLineRect))
    {
      [lineColor set];
      NSRectFill(verticalLineRect);
    }
  }
  
  if (mDisplayMask & IBShowCaretPosition)
  {
    verticalLineRect = [mCaretPositionLabel frame];
    verticalLineRect.origin.x += verticalLineRect.size.width + 1.0;
    verticalLineRect.size.width = 1.0;
    if (NSIntersectsRect(rect, verticalLineRect))
    {
      [lineColor set];
      NSRectFill(verticalLineRect);
    }
  }
}

//--------------------------------------------------------------------------------------------------

- (BOOL) isOpaque
{
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to reposition our content depending on the size of the view.
 */
- (void) setFrame: (NSRect) newFrame
{
  [super setFrame: newFrame];
  [self positionSubViews];
}

//--------------------------------------------------------------------------------------------------

- (void) positionSubViews
{
  NSRect currentBounds = {0, 0, 0, [self frame].size.height};
  if (mDisplayMask & IBShowZoom)
  {
    [mZoomPopup setHidden: NO];
    currentBounds.size.width = [mZoomPopup frame].size.width;
    [mZoomPopup setFrame: currentBounds];
    currentBounds.origin.x += currentBounds.size.width + 1; // Add 1 for the separator.
  }
  else
    [mZoomPopup setHidden: YES];

  if (mDisplayMask & IBShowCaretPosition)
  {
    [mCaretPositionLabel setHidden: NO];
    currentBounds.size.width = [mCaretPositionLabel frame].size.width;
    [mCaretPositionLabel setFrame: currentBounds];
    currentBounds.origin.x += currentBounds.size.width + 1;
  }
  else
    [mCaretPositionLabel setHidden: YES];

  if (mDisplayMask & IBShowStatusText)
  {
    // The status text always takes the rest of the available space.
    [mStatusTextLabel setHidden: NO];
    currentBounds.size.width = [self frame].size.width - currentBounds.origin.x;
    [mStatusTextLabel setFrame: currentBounds];
  }
  else
    [mStatusTextLabel setHidden: YES];
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to switch the visible parts of the info bar.
 *
 * @param display Bitwise ORed IBDisplay values which determine what to show on the bar.
 */
- (void) setDisplay: (IBDisplay) display
{
  if (mDisplayMask != display)
  {
    mDisplayMask = display;
    [self positionSubViews];
    [self needsDisplay];
  }  
}

//--------------------------------------------------------------------------------------------------

/**
 * Handler for selection changes in the zoom menu.
 */
- (void) zoomItemAction: (id) sender
{
  NSNumber* selectedFactorObject = [[sender selectedCell] representedObject];
  
  if (selectedFactorObject == nil)
  {
    NSLog(@"Scale popup action: setting arbitrary zoom factors is not yet supported.");
    return;
  }
  else
  {
    [self setScaleFactor: [selectedFactorObject floatValue] adjustPopup: NO];
  }
}
    
//--------------------------------------------------------------------------------------------------
    
- (void) setScaleFactor: (float) newScaleFactor adjustPopup: (BOOL) flag
{
  if (mScaleFactor != newScaleFactor)
  {
    mScaleFactor = newScaleFactor;
    if (flag)
    {
      unsigned count = 0;
      unsigned numberOfDefaultItems = sizeof(DefaultScaleMenuFactors) / sizeof(float);
      
      // We only work with some preset zoom values. If the given value does not correspond
      // to one then show no selection.
      while (count < numberOfDefaultItems && (fabs(newScaleFactor - DefaultScaleMenuFactors[count]) > 0.07))
        count++;
      if (count == numberOfDefaultItems)
        [mZoomPopup selectItemAtIndex: -1];
      else
      {
        [mZoomPopup selectItemAtIndex: count];
        
        // Set scale factor to found preset value if it comes close.
        mScaleFactor = DefaultScaleMenuFactors[count];
      }
    }
    else
    {
      // Internally set. Notify owner.
      [mCallback notify: IBNZoomChanged message: nil location: NSZeroPoint value: newScaleFactor];
    }    
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Called from the notification method to update the caret position display.
 */
- (void) setCaretPosition: (NSPoint) position
{
  // Make the position one-based.
  int newX = (int) position.x + 1;
  int newY = (int) position.y + 1;
  
  if (mCurrentCaretX != newX || mCurrentCaretY != newY)
  {
    mCurrentCaretX = newX;
    mCurrentCaretY = newY;
    
    [mCaretPositionLabel setStringValue: [NSString stringWithFormat: @"%d:%d", newX, newY]];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Makes the bar resize to the smallest width that can accomodate the currently enabled items.
 */
- (void) sizeToFit
{
  NSRect frame = [self frame];
  frame.size.width = 0;
  if (mDisplayMask & IBShowZoom)
    frame.size.width += [mZoomPopup frame].size.width;
  
  if (mDisplayMask & IBShowCaretPosition)
    frame.size.width += [mCaretPositionLabel frame].size.width;
  
  if (mDisplayMask & IBShowStatusText)
    frame.size.width += [mStatusTextLabel frame].size.width;
  
  [self setFrame: frame];
}

@end

Added cocoa/InfoBarCommunicator.h.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * InfoBarCommunicator.h - Definitions of a communication protocol and other data types used for
 *                         the info bar implementation.
 *
 * Mike Lischke <mlischke@sun.com>
 *
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

enum IBDisplay {
  IBShowZoom          = 0x01,
  IBShowCaretPosition = 0x02,
  IBShowStatusText    = 0x04,
  IBShowAll           = 0xFF
};

/**
 * The info bar communicator protocol is used for communication between ScintillaView and its
 * information bar component. Using this protocol decouples any potential info target from the main
 * ScintillaView implementation. The protocol is used two-way.
 */

enum NotificationType {
  IBNZoomChanged,    // The user selected another zoom value.
  IBNCaretChanged,   // The caret in the editor changed.
  IBNStatusChanged,  // The application set a new status message.
};

@protocol InfoBarCommunicator
- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
          value: (float) value;
- (void) setCallback: (id <InfoBarCommunicator>) callback;
@end

Added cocoa/PlatCocoa.h.























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

/**
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#ifndef PLATCOCOA_H
#define PLATCOCOA_H

#include <cstring>
#include <cstdio>
#include <cstdlib>

#include <assert.h>

#include <sys/time.h>

#include <Cocoa/Cocoa.h>
#include "QuartzTextLayout.h"

#include "Platform.h"
#include "Scintilla.h"

NSRect PRectangleToNSRect(Scintilla::PRectangle& rc);
Scintilla::PRectangle NSRectToPRectangle(NSRect& rc);
CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet);

@interface ScintillaContextMenu : NSMenu
{
  Scintilla::ScintillaCocoa* owner;
}
- (void) handleCommand: (NSMenuItem*) sender;
- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner;

@end

namespace Scintilla {

// A class to do the actual text rendering for us using Quartz 2D.
class SurfaceImpl : public Surface
{
private:
  bool unicodeMode;
  float x;
  float y;

  CGContextRef gc;

  /** The text layout instance */
  QuartzTextLayout*	textLayout;
  int codePage;
  int verticalDeviceResolution;
	
  /** If the surface is a bitmap context, contains a reference to the bitmap data. */
  uint8_t* bitmapData;
  /** If the surface is a bitmap context, stores the dimensions of the bitmap. */
  int bitmapWidth;
  int bitmapHeight;

  /** Set the CGContext's fill colour to the specified desired colour. */
  void FillColour( const ColourDesired& back );


  // 24-bit RGB+A bitmap data constants
  static const int BITS_PER_COMPONENT = 8;
  static const int BITS_PER_PIXEL = BITS_PER_COMPONENT * 4;
  static const int BYTES_PER_PIXEL = BITS_PER_PIXEL / 8;
public:
  SurfaceImpl();
  ~SurfaceImpl();

  void Init(WindowID wid);
  void Init(SurfaceID sid, WindowID wid);
  void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
  CGContextRef GetContext() { return gc; }

  void Release();
  bool Initialised();
  void PenColour(ColourDesired fore);

  /** Returns a CGImageRef that represents the surface. Returns NULL if this is not possible. */
  CGImageRef GetImage();
  void CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect);

  int LogPixelsY();
  int DeviceHeightFont(int points);
  void MoveTo(int x_, int y_);
  void LineTo(int x_, int y_);
  void Polygon(Scintilla::Point *pts, int npts, ColourDesired fore, ColourDesired back);
  void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back);
  void FillRectangle(PRectangle rc, ColourDesired back);
  void FillRectangle(PRectangle rc, Surface &surfacePattern);
  void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back);
  void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
                     ColourDesired outline, int alphaOutline, int flags);
  void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
  void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back);
  void Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource);
  void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore,
                     ColourDesired back);
  void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, 
                      ColourDesired back);
  void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
  void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
  XYPOSITION WidthText(Font &font_, const char *s, int len);
  XYPOSITION WidthChar(Font &font_, char ch);
  XYPOSITION Ascent(Font &font_);
  XYPOSITION Descent(Font &font_);
  XYPOSITION InternalLeading(Font &font_);
  XYPOSITION ExternalLeading(Font &font_);
  XYPOSITION Height(Font &font_);
  XYPOSITION AverageCharWidth(Font &font_);

  void SetClip(PRectangle rc);
  void FlushCachedState();

  void SetUnicodeMode(bool unicodeMode_);
  void SetDBCSMode(int codePage_);
}; // SurfaceImpl class
  
} // Scintilla namespace

#endif

Added cocoa/PlatCocoa.mm.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
/**
 * Scintilla source code edit control
 * PlatCocoa.mm - implementation of platform facilities on MacOS X/Cocoa
 *
 * Written by Mike Lischke
 * Based on PlatMacOSX.cxx
 * Based on work by Evan Jones (c) 2002 <ejones@uwaterloo.ca>
 * Based on PlatGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed.
 *
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <ScintillaView.h>

#include "PlatCocoa.h"

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <assert.h>
#include <sys/time.h>
#include <stdexcept>
#include <map>

#include "XPM.h"

#import <Foundation/NSGeometry.h>

using namespace Scintilla;

extern sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam);

//--------------------------------------------------------------------------------------------------

/**
 * Converts a PRectangle as used by Scintilla to standard Obj-C NSRect structure .
 */
NSRect PRectangleToNSRect(PRectangle& rc)
{
  return NSMakeRect(rc.left, rc.top, rc.Width(), rc.Height());
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts an NSRect as used by the system to a native Scintilla rectangle.
 */
PRectangle NSRectToPRectangle(NSRect& rc)
{
  return PRectangle(rc.origin.x, rc.origin.y, rc.size.width + rc.origin.x, rc.size.height + rc.origin.y);
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts a PRctangle as used by Scintilla to a Quartz-style rectangle.
 */
inline CGRect PRectangleToCGRect(PRectangle& rc)
{
  return CGRectMake(rc.left, rc.top, rc.Width(), rc.Height());
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts a Quartz-style rectangle to a PRectangle structure as used by Scintilla.
 */
inline PRectangle CGRectToPRectangle(const CGRect& rect)
{
  PRectangle rc;
  rc.left = (int)(rect.origin.x + 0.5);
  rc.top = (int)(rect.origin.y + 0.5);
  rc.right = (int)(rect.origin.x + rect.size.width + 0.5);
  rc.bottom = (int)(rect.origin.y + rect.size.height + 0.5);
  return rc;
}

//----------------- Point --------------------------------------------------------------------------

/**
 * Converts a point given as a long into a native Point structure.
 */
Scintilla::Point Scintilla::Point::FromLong(long lpoint)
{
  return Scintilla::Point(
                          Platform::LowShortFromLong(lpoint),
                          Platform::HighShortFromLong(lpoint)
                          );
}

//----------------- Font ---------------------------------------------------------------------------

Font::Font(): fid(0)
{
}

//--------------------------------------------------------------------------------------------------

Font::~Font()
{
  Release();
}

//--------------------------------------------------------------------------------------------------

static int FontCharacterSet(Font &f) {
	return reinterpret_cast<QuartzTextStyle *>(f.GetID())->getCharacterSet();
}

/**
 * Creates a CTFontRef with the given properties.
 */
void Font::Create(const FontParameters &fp)
{
	Release();

	QuartzTextStyle* style = new QuartzTextStyle();
	fid = style;

	// Create the font with attributes
	QuartzFont font(fp.faceName, strlen(fp.faceName), fp.size, fp.weight, fp.italic);
	CTFontRef fontRef = font.getFontID();
	style->setFontRef(fontRef, fp.characterSet);
}

//--------------------------------------------------------------------------------------------------

void Font::Release()
{
  if (fid)
    delete reinterpret_cast<QuartzTextStyle*>( fid );
  fid = 0;
}

//----------------- SurfaceImpl --------------------------------------------------------------------

SurfaceImpl::SurfaceImpl()
{
  unicodeMode = true;
  x = 0;
  y = 0;
  gc = NULL;

  textLayout = new QuartzTextLayout(NULL);
  codePage = 0;
  verticalDeviceResolution = 0;

  bitmapData = NULL; // Release will try and delete bitmapData if != NULL
  bitmapWidth = 0;
  bitmapHeight = 0;

  Release();
}

//--------------------------------------------------------------------------------------------------

SurfaceImpl::~SurfaceImpl()
{
  Release();
  delete textLayout;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::Release()
{
  textLayout->setContext (NULL);
  if ( bitmapData != NULL )
  {
    delete[] bitmapData;
    // We only "own" the graphics context if we are a bitmap context
    if (gc != NULL)
      CGContextRelease(gc);
  }
  bitmapData = NULL;
  gc = NULL;
  
  bitmapWidth = 0;
  bitmapHeight = 0;
  x = 0;
  y = 0;
}

//--------------------------------------------------------------------------------------------------

bool SurfaceImpl::Initialised()
{
  // We are initalised if the graphics context is not null
  return gc != NULL;// || port != NULL;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::Init(WindowID)
{
  // To be able to draw, the surface must get a CGContext handle.  We save the graphics port,
  // then aquire/release the context on an as-need basis (see above).
  // XXX Docs on QDBeginCGContext are light, a better way to do this would be good.
  // AFAIK we should not hold onto a context retrieved this way, thus the need for
  // aquire/release of the context.
  
  Release();
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::Init(SurfaceID sid, WindowID)
{
  Release();
  gc = reinterpret_cast<CGContextRef>(sid);
  CGContextSetLineWidth(gc, 1.0);
  textLayout->setContext(gc);
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::InitPixMap(int width, int height, Surface* /* surface_ */, WindowID /* wid */)
{
  Release();
  
  // Create a new bitmap context, along with the RAM for the bitmap itself
  bitmapWidth = width;
  bitmapHeight = height;
  
  const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL);
  const int bitmapByteCount = (bitmapBytesPerRow * height);
  
  // Create an RGB color space.
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  if (colorSpace == NULL)
    return;
  
  // Create the bitmap.
  bitmapData = new uint8_t[bitmapByteCount];
  if (bitmapData != NULL)
  {
    // create the context
    gc = CGBitmapContextCreate(bitmapData,
                               width,
                               height,
                               BITS_PER_COMPONENT,
                               bitmapBytesPerRow,
                               colorSpace,
                               kCGImageAlphaPremultipliedLast);
    
    if (gc == NULL)
    {
      // the context couldn't be created for some reason,
      // and we have no use for the bitmap without the context
      delete[] bitmapData;
      bitmapData = NULL;
    }
    textLayout->setContext (gc);
  }
  
  // the context retains the color space, so we can release it
  CGColorSpaceRelease(colorSpace);
  
  if (gc != NULL && bitmapData != NULL)
  {
    // "Erase" to white.
    CGContextClearRect( gc, CGRectMake( 0, 0, width, height ) );
    CGContextSetRGBFillColor( gc, 1.0, 1.0, 1.0, 1.0 );
    CGContextFillRect( gc, CGRectMake( 0, 0, width, height ) );
  }
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::PenColour(ColourDesired fore)
{
  if (gc)
  {
    ColourDesired colour(fore.AsLong());
    
    // Set the Stroke color to match
    CGContextSetRGBStrokeColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, 
                               colour.GetBlue() / 255.0, 1.0 );
  }
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::FillColour(const ColourDesired& back)
{
  if (gc)
  {
    ColourDesired colour(back.AsLong());
    
    // Set the Fill color to match
    CGContextSetRGBFillColor(gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, 
                             colour.GetBlue() / 255.0, 1.0 );
  }
}

//--------------------------------------------------------------------------------------------------

CGImageRef SurfaceImpl::GetImage()
{
  // For now, assume that GetImage can only be called on PixMap surfaces.
  if (bitmapData == NULL)
    return NULL;
  
  CGContextFlush(gc);
  
  // Create an RGB color space.
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  if( colorSpace == NULL )
    return NULL;
  
  const int bitmapBytesPerRow = ((int) bitmapWidth * BYTES_PER_PIXEL);
  const int bitmapByteCount = (bitmapBytesPerRow * (int) bitmapHeight);
  
  // Make a copy of the bitmap data for the image creation and divorce it
  // From the SurfaceImpl lifetime
  CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bitmapData, bitmapByteCount);

  // Create a data provider.
  CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataRef);

  CGImageRef image = NULL;
  if (dataProvider != NULL)
  {
    // Create the CGImage.
    image = CGImageCreate(bitmapWidth,
                          bitmapHeight,
                          BITS_PER_COMPONENT,
                          BITS_PER_PIXEL,
                          bitmapBytesPerRow,
                          colorSpace,
                          kCGImageAlphaPremultipliedLast,
                          dataProvider,
                          NULL,
                          0,
                          kCGRenderingIntentDefault);
  }
  
  // The image retains the color space, so we can release it.
  CGColorSpaceRelease(colorSpace);
  colorSpace = NULL;
  
  // Done with the data provider.
  CGDataProviderRelease(dataProvider);
  dataProvider = NULL;
  
  // Done with the data provider.
  CFRelease(dataRef);
    
  return image;
}

//--------------------------------------------------------------------------------------------------

/**
 * Returns the vertical logical device resolution of the main monitor.
 * This is no longer called.
 * For Cocoa, all screens are treated as 72 DPI, even retina displays.
 */
int SurfaceImpl::LogPixelsY()
{
  return 72;
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts the logical font height in points into a device height.
 * For Cocoa, points are always used for the result even on retina displays.
 */
int SurfaceImpl::DeviceHeightFont(int points)
{
  return points;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::MoveTo(int x_, int y_)
{
  x = x_;
  y = y_;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::LineTo(int x_, int y_)
{
  CGContextBeginPath( gc );
  
  // Because Quartz is based on floating point, lines are drawn with half their colour
  // on each side of the line. Integer coordinates specify the INTERSECTION of the pixel
  // divison lines. If you specify exact pixel values, you get a line that
  // is twice as thick but half as intense. To get pixel aligned rendering,
  // we render the "middle" of the pixels by adding 0.5 to the coordinates.
  CGContextMoveToPoint( gc, x + 0.5, y + 0.5 );
  CGContextAddLineToPoint( gc, x_ + 0.5, y_ + 0.5 );
  CGContextStrokePath( gc );
  x = x_;
  y = y_;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::Polygon(Scintilla::Point *pts, int npts, ColourDesired fore,
                          ColourDesired back)
{
  // Allocate memory for the array of points.
  CGPoint *points = new CGPoint[npts];
  
  for (int i = 0;i < npts;i++)
  {
    // Quartz floating point issues: plot the MIDDLE of the pixels
    points[i].x = pts[i].x + 0.5;
    points[i].y = pts[i].y + 0.5;
  }
  
  CGContextBeginPath(gc);
  
  // Set colours
  FillColour(back);
  PenColour(fore);
  
  // Draw the polygon
  CGContextAddLines(gc, points, npts);
  
  // Explicitly close the path, so it is closed for stroking AND filling (implicit close = filling only)
  CGContextClosePath( gc );
  CGContextDrawPath( gc, kCGPathFillStroke );
  
  // Deallocate memory.
  delete points;
  points = NULL;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)
{
  if (gc)
  {
    CGContextBeginPath( gc );
    FillColour(back);
    PenColour(fore);
    
    // Quartz integer -> float point conversion fun (see comment in SurfaceImpl::LineTo)
    // We subtract 1 from the Width() and Height() so that all our drawing is within the area defined
    // by the PRectangle. Otherwise, we draw one pixel too far to the right and bottom.
    CGContextAddRect( gc, CGRectMake( rc.left + 0.5, rc.top + 0.5, rc.Width() - 1, rc.Height() - 1 ) );
    CGContextDrawPath( gc, kCGPathFillStroke );
  }
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back)
{
  if (gc)
  {
    FillColour(back);
    // Snap rectangle boundaries to nearest int
    rc.left = lround(rc.left);
    rc.right = lround(rc.right);
    CGRect rect = PRectangleToCGRect(rc);
    CGContextFillRect(gc, rect);
  }
}

//--------------------------------------------------------------------------------------------------

void drawImageRefCallback(CGImageRef pattern, CGContextRef gc)
{
  CGContextDrawImage(gc, CGRectMake(0, 0, CGImageGetWidth(pattern), CGImageGetHeight(pattern)), pattern);
}

//--------------------------------------------------------------------------------------------------

void releaseImageRefCallback(CGImageRef pattern)
{
  CGImageRelease(pattern);
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern)
{
  SurfaceImpl& patternSurface = static_cast<SurfaceImpl &>(surfacePattern);
  
  // For now, assume that copy can only be called on PixMap surfaces. Shows up black.
  CGImageRef image = patternSurface.GetImage();
  if (image == NULL)
  {
    FillRectangle(rc, ColourDesired(0));
    return;
  }
  
  const CGPatternCallbacks drawImageCallbacks = { 0,
    reinterpret_cast<CGPatternDrawPatternCallback>(drawImageRefCallback),
    reinterpret_cast<CGPatternReleaseInfoCallback>(releaseImageRefCallback) };
  
  CGPatternRef pattern = CGPatternCreate(image,
                                         CGRectMake(0, 0, patternSurface.bitmapWidth, patternSurface.bitmapHeight),
                                         CGAffineTransformIdentity,
                                         patternSurface.bitmapWidth,
                                         patternSurface.bitmapHeight,
                                         kCGPatternTilingNoDistortion,
                                         true,
                                         &drawImageCallbacks
                                        );
  if (pattern != NULL)
  {
    // Create a pattern color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern( NULL );
    if( colorSpace != NULL ) {
      
      CGContextSaveGState( gc );
      CGContextSetFillColorSpace( gc, colorSpace );
      
      // Unlike the documentation, you MUST pass in a "components" parameter:
      // For coloured patterns it is the alpha value.
      const CGFloat alpha = 1.0;
      CGContextSetFillPattern( gc, pattern, &alpha );
      CGContextFillRect( gc, PRectangleToCGRect( rc ) );
      CGContextRestoreGState( gc );
      // Free the color space, the pattern and image
      CGColorSpaceRelease( colorSpace );
    } /* colorSpace != NULL */
    colorSpace = NULL;
    CGPatternRelease( pattern );
    pattern = NULL;
  } /* pattern != NULL */
}

void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) {
  // This is only called from the margin marker drawing code for SC_MARK_ROUNDRECT
  // The Win32 version does
  //  ::RoundRect(hdc, rc.left + 1, rc.top, rc.right - 1, rc.bottom, 8, 8 );
  // which is a rectangle with rounded corners each having a radius of 4 pixels.
  // It would be almost as good just cutting off the corners with lines at
  // 45 degrees as is done on GTK+.
  
  // Create a rectangle with semicircles at the corners
  const int MAX_RADIUS = 4;
  int radius = Platform::Minimum( MAX_RADIUS, rc.Height()/2 );
  radius = Platform::Minimum( radius, rc.Width()/2 );
  
  // Points go clockwise, starting from just below the top left
  // Corners are kept together, so we can easily create arcs to connect them
  CGPoint corners[4][3] =
  {
    {
      { rc.left, rc.top + radius },
      { rc.left, rc.top },
      { rc.left + radius, rc.top },
    },
    {
      { rc.right - radius - 1, rc.top },
      { rc.right - 1, rc.top },
      { rc.right - 1, rc.top + radius },
    },
    {
      { rc.right - 1, rc.bottom - radius - 1 },
      { rc.right - 1, rc.bottom - 1 },
      { rc.right - radius - 1, rc.bottom - 1 },
    },
    {
      { rc.left + radius, rc.bottom - 1 },
      { rc.left, rc.bottom - 1 },
      { rc.left, rc.bottom - radius - 1 },
    },
  };
  
  // Align the points in the middle of the pixels
  for( int i = 0; i < 4; ++ i )
  {
    for( int j = 0; j < 3; ++ j )
    {
      corners[i][j].x += 0.5;
      corners[i][j].y += 0.5;
    }
  }
  
  PenColour( fore );
  FillColour( back );
  
  // Move to the last point to begin the path
  CGContextBeginPath( gc );
  CGContextMoveToPoint( gc, corners[3][2].x, corners[3][2].y );
  
  for ( int i = 0; i < 4; ++ i )
  {
    CGContextAddLineToPoint( gc, corners[i][0].x, corners[i][0].y );
    CGContextAddArcToPoint( gc, corners[i][1].x, corners[i][1].y, corners[i][2].x, corners[i][2].y, radius );
  }
  
  // Close the path to enclose it for stroking and for filling, then draw it
  CGContextClosePath( gc );
  CGContextDrawPath( gc, kCGPathFillStroke );
}

void Scintilla::SurfaceImpl::AlphaRectangle(PRectangle rc, int /*cornerSize*/, ColourDesired fill, int alphaFill,
                                            ColourDesired /*outline*/, int /*alphaOutline*/, int /*flags*/)
{
  if ( gc ) {
    ColourDesired colour( fill.AsLong() );
 
    // Snap rectangle boundaries to nearest int
    rc.left = lround(rc.left);
    rc.right = lround(rc.right);
    // Set the Fill color to match
    CGContextSetRGBFillColor( gc, colour.GetRed() / 255.0, colour.GetGreen() / 255.0, colour.GetBlue() / 255.0, alphaFill / 255.0 );
    CGRect rect = PRectangleToCGRect( rc );
    CGContextFillRect( gc, rect );
  }
}

static void ProviderReleaseData(void *, const void *data, size_t) {
	const unsigned char *pixels = reinterpret_cast<const unsigned char *>(data);
	delete []pixels;
}

static CGImageRef ImageCreateFromRGBA(int width, int height, const unsigned char *pixelsImage, bool invert) {
	CGImageRef image = 0;

	// Create an RGB color space.
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
	if (colorSpace) {
		const int bitmapBytesPerRow = ((int) width * 4);
		const int bitmapByteCount = (bitmapBytesPerRow * (int) height);
		
		// Create a data provider.
		CGDataProviderRef dataProvider = 0;
		if (invert) {
			unsigned char *pixelsUpsideDown = new unsigned char[bitmapByteCount];
		
			for (int y=0; y<height; y++) {
				int yInverse = height - y - 1;
				memcpy(pixelsUpsideDown + y * bitmapBytesPerRow,
				       pixelsImage + yInverse * bitmapBytesPerRow,
				       bitmapBytesPerRow);
			}
			
			dataProvider = CGDataProviderCreateWithData(
								NULL, pixelsUpsideDown, bitmapByteCount, ProviderReleaseData);
		} else {
			dataProvider = CGDataProviderCreateWithData(
								NULL, pixelsImage, bitmapByteCount, NULL);
			
		}
		if (dataProvider) {
			// Create the CGImage.
			image = CGImageCreate(width,
							 height,
							 8,
							 8 * 4,
							 bitmapBytesPerRow,
							 colorSpace,
							 kCGImageAlphaLast,
							 dataProvider,
							 NULL,
							 0,
							 kCGRenderingIntentDefault);

			CGDataProviderRelease(dataProvider);
		}
		
		// The image retains the color space, so we can release it.
		CGColorSpaceRelease(colorSpace);
	}
	return image;
}

void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
	CGImageRef image = ImageCreateFromRGBA(width, height, pixelsImage, true);
	if (image) {
		CGRect drawRect = CGRectMake(rc.left, rc.top, rc.Width(), rc.Height());
		CGContextDrawImage(gc, drawRect, image);
		CGImageRelease(image);
	}
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {
  // Drawing an ellipse with bezier curves. Code modified from:
  // http://www.codeguru.com/gdi/ellipse.shtml
  // MAGICAL CONSTANT to map ellipse to beziers 2/3*(sqrt(2)-1)
  const double EToBConst = 0.2761423749154;
  
  CGSize offset = CGSizeMake((int)(rc.Width() * EToBConst), (int)(rc.Height() * EToBConst));
  CGPoint centre = CGPointMake((rc.left + rc.right) / 2, (rc.top + rc.bottom) / 2);
  
  // The control point array
  CGPoint cCtlPt[13];
  
  // Assign values to all the control points
  cCtlPt[0].x  =
  cCtlPt[1].x  =
  cCtlPt[11].x =
  cCtlPt[12].x = rc.left + 0.5;
  cCtlPt[5].x  =
  cCtlPt[6].x  =
  cCtlPt[7].x  = rc.right - 0.5;
  cCtlPt[2].x  =
  cCtlPt[10].x = centre.x - offset.width + 0.5;
  cCtlPt[4].x  =
  cCtlPt[8].x  = centre.x + offset.width + 0.5;
  cCtlPt[3].x  =
  cCtlPt[9].x  = centre.x + 0.5;
  
  cCtlPt[2].y  =
  cCtlPt[3].y  =
  cCtlPt[4].y  = rc.top + 0.5;
  cCtlPt[8].y  =
  cCtlPt[9].y  =
  cCtlPt[10].y = rc.bottom - 0.5;
  cCtlPt[7].y  =
  cCtlPt[11].y = centre.y + offset.height + 0.5;
  cCtlPt[1].y =
  cCtlPt[5].y  = centre.y - offset.height + 0.5;
  cCtlPt[0].y =
  cCtlPt[12].y =
  cCtlPt[6].y  = centre.y + 0.5;
  
  FillColour(back);
  PenColour(fore);
  
  CGContextBeginPath( gc );
  CGContextMoveToPoint( gc, cCtlPt[0].x, cCtlPt[0].y );
  
  for ( int i = 1; i < 13; i += 3 )
  {
    CGContextAddCurveToPoint( gc, cCtlPt[i].x, cCtlPt[i].y, cCtlPt[i+1].x, cCtlPt[i+1].y, cCtlPt[i+2].x, cCtlPt[i+2].y );
  }
  
  // Close the path to enclose it for stroking and for filling, then draw it
  CGContextClosePath( gc );
  CGContextDrawPath( gc, kCGPathFillStroke );
}

void SurfaceImpl::CopyImageRectangle(Surface &surfaceSource, PRectangle srcRect, PRectangle dstRect)
{
  SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
  CGImageRef image = source.GetImage();
  
  CGRect src = PRectangleToCGRect(srcRect);
  CGRect dst = PRectangleToCGRect(dstRect);
  
  /* source from QuickDrawToQuartz2D.pdf on developer.apple.com */
  float w = (float) CGImageGetWidth(image);
  float h = (float) CGImageGetHeight(image);
  CGRect drawRect = CGRectMake (0, 0, w, h);
  if (!CGRectEqualToRect (src, dst))
  {
    float sx = CGRectGetWidth(dst) / CGRectGetWidth(src);
    float sy = CGRectGetHeight(dst) / CGRectGetHeight(src);
    float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx);
    float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy);
    drawRect = CGRectMake (dx, dy, w*sx, h*sy);
  }
  CGContextSaveGState (gc);
  CGContextClipToRect (gc, dst);
  CGContextDrawImage (gc, drawRect, image);
  CGContextRestoreGState (gc);
  CGImageRelease(image);
}

void SurfaceImpl::Copy(PRectangle rc, Scintilla::Point from, Surface &surfaceSource) {
  // Maybe we have to make the Surface two contexts:
  // a bitmap context which we do all the drawing on, and then a "real" context
  // which we copy the output to when we call "Synchronize". Ugh! Gross and slow!
  
  // For now, assume that copy can only be called on PixMap surfaces
  SurfaceImpl& source = static_cast<SurfaceImpl &>(surfaceSource);
  
  // Get the CGImageRef
  CGImageRef image = source.GetImage();
  // If we could not get an image reference, fill the rectangle black
  if ( image == NULL )
  {
    FillRectangle( rc, ColourDesired( 0 ) );
    return;
  }
  
  // Now draw the image on the surface
  
  // Some fancy clipping work is required here: draw only inside of rc
  CGContextSaveGState( gc );
  CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
  
  //Platform::DebugPrintf(stderr, "Copy: CGContextDrawImage: (%d, %d) - (%d X %d)\n", rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight );
  CGContextDrawImage( gc, CGRectMake( rc.left - from.x, rc.top - from.y, source.bitmapWidth, source.bitmapHeight ), image );
  
  // Undo the clipping fun
  CGContextRestoreGState( gc );
  
  // Done with the image
  CGImageRelease( image );
  image = NULL;
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                 ColourDesired fore, ColourDesired back)
{
  FillRectangle(rc, back);
  DrawTextTransparent(rc, font_, ybase, s, len, fore);
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                  ColourDesired fore, ColourDesired back)
{
  CGContextSaveGState(gc);
  CGContextClipToRect(gc, PRectangleToCGRect(rc));
  DrawTextNoClip(rc, font_, ybase, s, len, fore, back);
  CGContextRestoreGState(gc);
}

//--------------------------------------------------------------------------------------------------

CFStringEncoding EncodingFromCharacterSet(bool unicode, int characterSet)
{
  if (unicode)
    return kCFStringEncodingUTF8;

  // Unsupported -> Latin1 as reasonably safe
  enum { notSupported = kCFStringEncodingISOLatin1};

  switch (characterSet)
  {
  case SC_CHARSET_ANSI:
    return kCFStringEncodingISOLatin1;
  case SC_CHARSET_DEFAULT:
    return kCFStringEncodingISOLatin1;
  case SC_CHARSET_BALTIC:
    return kCFStringEncodingWindowsBalticRim;
  case SC_CHARSET_CHINESEBIG5:
    return kCFStringEncodingBig5;
  case SC_CHARSET_EASTEUROPE:
    return kCFStringEncodingWindowsLatin2;
  case SC_CHARSET_GB2312:
    return kCFStringEncodingGB_18030_2000;
  case SC_CHARSET_GREEK:
    return kCFStringEncodingWindowsGreek;
  case SC_CHARSET_HANGUL:
    return kCFStringEncodingEUC_KR;
  case SC_CHARSET_MAC:
    return kCFStringEncodingMacRoman;
  case SC_CHARSET_OEM:
    return kCFStringEncodingISOLatin1;
  case SC_CHARSET_RUSSIAN:
    return kCFStringEncodingKOI8_R;
  case SC_CHARSET_CYRILLIC:
    return kCFStringEncodingWindowsCyrillic;
  case SC_CHARSET_SHIFTJIS:
    return kCFStringEncodingShiftJIS;
  case SC_CHARSET_SYMBOL:
    return kCFStringEncodingMacSymbol;
  case SC_CHARSET_TURKISH:
    return kCFStringEncodingWindowsLatin5;
  case SC_CHARSET_JOHAB:
    return kCFStringEncodingWindowsKoreanJohab;
  case SC_CHARSET_HEBREW:
    return kCFStringEncodingWindowsHebrew;
  case SC_CHARSET_ARABIC:
    return kCFStringEncodingWindowsArabic;
  case SC_CHARSET_VIETNAMESE:
    return kCFStringEncodingWindowsVietnamese;
  case SC_CHARSET_THAI:
    return kCFStringEncodingISOLatinThai;
  case SC_CHARSET_8859_15:
    return kCFStringEncodingISOLatin1;
  default:
    return notSupported;
  }
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, 
                                      ColourDesired fore)
{
	CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
	ColourDesired colour(fore.AsLong());
	CGColorRef color = CGColorCreateGenericRGB(colour.GetRed()/255.0,colour.GetGreen()/255.0,colour.GetBlue()/255.0,1.0);

	QuartzTextStyle* style = reinterpret_cast<QuartzTextStyle*>(font_.GetID());
	style->setCTStyleColor(color);
	
	CGColorRelease(color);

	textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
	textLayout->draw(rc.left, ybase);
}

static size_t utf8LengthFromLead(unsigned char uch) {
	if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
		return 4;
	} else if (uch >= (0x80 + 0x40 + 0x20)) {
		return 3;
	} else if (uch >= (0x80)) {
		return 2;
	} else {
		return 1;
	}
}

//--------------------------------------------------------------------------------------------------

void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)
{
	CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
	textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
	
	CTLineRef mLine = textLayout->getCTLine();
	assert(mLine != NULL);
	
	if (unicodeMode) {
		// Map the widths given for UTF-16 characters back onto the UTF-8 input string
		CFIndex fit = textLayout->getStringLength();
		int ui=0;
		const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
		int i=0;
		while (ui<fit) {
			size_t lenChar = utf8LengthFromLead(us[i]);
			size_t codeUnits = (lenChar < 4) ? 1 : 2;
			CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = xPosition;
			}
			ui += codeUnits;
		}
		int lastPos = 0;
		if (i > 0)
			lastPos = positions[i-1];
		while (i<len) {
			positions[i++] = lastPos;
		}
	} else if (codePage) {
		int ui = 0;
		for (int i=0;i<len;) {
			size_t lenChar = Platform::IsDBCSLeadByte(codePage, s[i]) ? 2 : 1;
			CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, ui+1, NULL);
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = xPosition;
			}
			ui++;
		}
	} else {	// Single byte encoding
		for (int i=0;i<len;i++) {
			CGFloat xPosition = CTLineGetOffsetForStringIndex(mLine, i+1, NULL);
			positions[i] = xPosition;
		}
	}

}

XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
  if (font_.GetID())
  {
    CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
    textLayout->setText (reinterpret_cast<const UInt8*>(s), len, encoding, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
    
	return textLayout->MeasureStringWidth();
  }
  return 1;
}

XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) {
  char str[2] = { ch, '\0' };
  if (font_.GetID())
  {
    CFStringEncoding encoding = EncodingFromCharacterSet(unicodeMode, FontCharacterSet(font_));
    textLayout->setText (reinterpret_cast<const UInt8*>(str), 1, encoding, *reinterpret_cast<QuartzTextStyle*>(font_.GetID()));
    
    return textLayout->MeasureStringWidth();
  }
  else
    return 1;
}

// This string contains a good range of characters to test for size.
const char sizeString[] = "`~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

XYPOSITION SurfaceImpl::Ascent(Font &font_) {
  if (!font_.GetID())
    return 1;
  
	float ascent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getAscent();
	return ascent + 0.5;

}

XYPOSITION SurfaceImpl::Descent(Font &font_) {
  if (!font_.GetID())
    return 1;
  
	float descent = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getDescent();
	return descent + 0.5;

}

XYPOSITION SurfaceImpl::InternalLeading(Font &) {
  return 0;
}

XYPOSITION SurfaceImpl::ExternalLeading(Font &font_) {
  if (!font_.GetID())
    return 1;
  
	float leading = reinterpret_cast<QuartzTextStyle*>( font_.GetID() )->getLeading();
	return leading + 0.5;

}

XYPOSITION SurfaceImpl::Height(Font &font_) {

	int ht = Ascent(font_) + Descent(font_);
	return ht;
}

XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) {
  
  if (!font_.GetID())
    return 1;
  
  const int sizeStringLength = (sizeof( sizeString ) / sizeof( sizeString[0] ) - 1);
  int width = WidthText( font_, sizeString, sizeStringLength  );
  
  return (int) ((width / (float) sizeStringLength) + 0.5);
}

void SurfaceImpl::SetClip(PRectangle rc) {
  CGContextClipToRect( gc, PRectangleToCGRect( rc ) );
}

void SurfaceImpl::FlushCachedState() {
  CGContextSynchronize( gc );
}

void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
  unicodeMode = unicodeMode_;
}

void SurfaceImpl::SetDBCSMode(int codePage_) {
  if (codePage_ && (codePage_ != SC_CP_UTF8))
    codePage = codePage_;
}

Surface *Surface::Allocate(int)
{
  return new SurfaceImpl();
}

//----------------- Window -------------------------------------------------------------------------

// Cocoa uses different types for windows and views, so a Window may
// be either an NSWindow or NSView and the code will check the type
// before performing an action.

Window::~Window()
{
}

//--------------------------------------------------------------------------------------------------

void Window::Destroy()
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isKindOfClass: [NSWindow class]])
    {
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      [win release];
    }
  }
  wid = 0;
}

//--------------------------------------------------------------------------------------------------

bool Window::HasFocus()
{
  NSView* container = reinterpret_cast<NSView*>(wid);
  return [[container window] firstResponder] == container;
}

//--------------------------------------------------------------------------------------------------

static int ScreenMax(NSWindow* win)
{
  NSScreen* screen = [win screen];
  NSRect frame = [screen frame];
  return frame.origin.y + frame.size.height;
}

PRectangle Window::GetPosition()
{
  if (wid)
  {
    NSRect rect;
    id idWin = reinterpret_cast<id>(wid);
    NSWindow* win;
    if ([idWin isKindOfClass: [NSView class]])
    {
      // NSView
      NSView* view = reinterpret_cast<NSView*>(idWin);
      win = [view window];
      rect = [view convertRect: [view bounds] toView: nil];
      rect.origin = [win convertBaseToScreen:rect.origin];
    }
    else
    {
      // NSWindow
      win = reinterpret_cast<NSWindow*>(idWin);
      rect = [win frame];
    }
    int screenHeight = ScreenMax(win);
    // Invert screen positions to match Scintilla
    return PRectangle(
        NSMinX(rect), screenHeight - NSMaxY(rect),
        NSMaxX(rect), screenHeight - NSMinY(rect));
  }
  else
  {
    return PRectangle(0, 0, 1, 1);
  }
}

//--------------------------------------------------------------------------------------------------

void Window::SetPosition(PRectangle rc)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isKindOfClass: [NSView class]])
    {
      // NSView
      // Moves this view inside the parent view
      NSRect nsrc = NSMakeRect(rc.left, rc.bottom, rc.Width(), rc.Height());
      NSView* view = reinterpret_cast<NSView*>(idWin);
      nsrc.origin = [[view window] convertScreenToBase:nsrc.origin];
      [view setFrame: nsrc];
    }
    else
    {
      // NSWindow
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      int screenHeight = ScreenMax(win);
      NSRect nsrc = NSMakeRect(rc.left, screenHeight - rc.bottom,
          rc.Width(), rc.Height());
      [win setFrame: nsrc display:YES];
    }
  }
}

//--------------------------------------------------------------------------------------------------

void Window::SetPositionRelative(PRectangle rc, Window window)
{
  PRectangle rcOther = window.GetPosition();
  rc.left += rcOther.left;
  rc.right += rcOther.left;
  rc.top += rcOther.top;
  rc.bottom += rcOther.top;
  SetPosition(rc);
}

//--------------------------------------------------------------------------------------------------

PRectangle Window::GetClientPosition()
{
  // This means, in MacOS X terms, get the "frame bounds". Call GetPosition, just like on Win32.
  return GetPosition();
}

//--------------------------------------------------------------------------------------------------

void Window::Show(bool show)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isKindOfClass: [NSWindow class]])
    {
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      if (show)
      {
        [win orderFront:nil];
      }
      else
      {
        [win orderOut:nil];
      }
    }
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Invalidates the entire window or view so it is completely redrawn.
 */
void Window::InvalidateAll()
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    NSView* container;
    if ([idWin isKindOfClass: [NSView class]])
    {
      container = reinterpret_cast<NSView*>(idWin);
    }
    else
    {
      // NSWindow
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      container = reinterpret_cast<NSView*>([win contentView]);
      container.needsDisplay = YES;
    }
    container.needsDisplay = YES;
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Invalidates part of the window or view so only this part redrawn.
 */
void Window::InvalidateRectangle(PRectangle rc)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    NSView* container;
    if ([idWin isKindOfClass: [NSView class]])
    {
      container = reinterpret_cast<NSView*>(idWin);
    }
    else
    {
      // NSWindow
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      container = reinterpret_cast<NSView*>([win contentView]);
    }
    [container setNeedsDisplayInRect: PRectangleToNSRect(rc)];
  }
}

//--------------------------------------------------------------------------------------------------

void Window::SetFont(Font&)
{
  // Implemented on list subclass on Cocoa.
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts the Scintilla cursor enum into an NSCursor and stores it in the associated NSView,
 * which then will take care to set up a new mouse tracking rectangle.
 */
void Window::SetCursor(Cursor curs)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isMemberOfClass: [InnerView class]])
    {
      InnerView* container = reinterpret_cast<InnerView*>(idWin);
      [container setCursor: curs];
    }
  }
}

//--------------------------------------------------------------------------------------------------

void Window::SetTitle(const char* s)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isKindOfClass: [NSWindow class]])
    {
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      NSString* sTitle = [NSString stringWithUTF8String:s];
      [win setTitle:sTitle];
    }
  }
}

//--------------------------------------------------------------------------------------------------

PRectangle Window::GetMonitorRect(Point)
{
  if (wid)
  {
    id idWin = reinterpret_cast<id>(wid);
    if ([idWin isKindOfClass: [NSWindow class]])
    {
      NSWindow* win = reinterpret_cast<NSWindow*>(idWin);
      NSScreen* screen = [win screen];
      NSRect rect = [screen frame];
      int screenHeight = rect.origin.y + rect.size.height;
      // Invert screen positions to match Scintilla
      return PRectangle(
          NSMinX(rect), screenHeight - NSMaxY(rect),
          NSMaxX(rect), screenHeight - NSMinY(rect));
    }
  }
  return PRectangle();
}

//----------------- ImageFromXPM -------------------------------------------------------------------

// Convert an XPM image into an NSImage for use with Cocoa

static NSImage* ImageFromXPM(XPM* pxpm)
{
  NSImage* img = nil;
  if (pxpm)
  {
    const int width = pxpm->GetWidth();
    const int height = pxpm->GetHeight();
    PRectangle rcxpm(0, 0, width, height);
    Surface* surfaceXPM = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
    if (surfaceXPM)
    {
      surfaceXPM->InitPixMap(width, height, NULL, NULL);
      SurfaceImpl* surfaceIXPM = static_cast<SurfaceImpl*>(surfaceXPM);
      CGContextClearRect(surfaceIXPM->GetContext(), CGRectMake(0, 0, width, height));
      pxpm->Draw(surfaceXPM, rcxpm);
      img = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
      CGImageRef imageRef = surfaceIXPM->GetImage();
      NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef];
      [img addRepresentation: bitmapRep];
      [bitmapRep release];
      CGImageRelease(imageRef);
      delete surfaceXPM;
    }
  }
  return img;
}

//----------------- ListBox and related classes ----------------------------------------------------

namespace {

// unnamed namespace hides IListBox interface

class IListBox {
public:
  virtual int Rows() = 0;
  virtual NSImage* ImageForRow(NSInteger row) = 0;
  virtual NSString* TextForRow(NSInteger row) = 0;
  virtual void DoubleClick() = 0;
};

} // unnamed namespace

//----------------- AutoCompletionDataSource -------------------------------------------------------

@interface AutoCompletionDataSource :
NSObject
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
<NSTableViewDataSource>
#endif
{
  IListBox* box;
}

@property IListBox* box;

@end

@implementation AutoCompletionDataSource

@synthesize box;

- (void) doubleClick: (id) sender
{
#pragma unused(sender)
	if (box)
	{
		box->DoubleClick();
	}
}

- (id)tableView: (NSTableView*)aTableView objectValueForTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex
{
#pragma unused(aTableView)
	if (!box)
		return nil;
	if ([(NSString*)[aTableColumn identifier] isEqualToString: @"icon"])
	{
		return box->ImageForRow(rowIndex);
	}
	else {
		return box->TextForRow(rowIndex);
	}
}

- (void)tableView: (NSTableView*)aTableView setObjectValue: anObject forTableColumn: (NSTableColumn*)aTableColumn row: (NSInteger)rowIndex
{
#pragma unused(aTableView)
#pragma unused(anObject)
#pragma unused(aTableColumn)
#pragma unused(rowIndex)
}

- (NSInteger)numberOfRowsInTableView: (NSTableView*)aTableView
{
#pragma unused(aTableView)
	if (!box)
		return 0;
	return box->Rows();
}

@end

//----------------- ListBoxImpl --------------------------------------------------------------------

namespace {	// unnamed namespace hides ListBoxImpl and associated classes

struct RowData
{
  int type;
  std::string text;
  RowData(int type_, const char* text_) :
    type(type_), text(text_)
  {
  }
};

class LinesData
{
  std::vector<RowData> lines;
public:
  LinesData()
  {
  }
  ~LinesData()
  {
  }
  int Length() const
  {
    return static_cast<int>(lines.size());
  }
  void Clear()
  {
    lines.clear();
  }
  void Add(int /* index */, int type, char* str)
  {
    lines.push_back(RowData(type, str));
  }
  int GetType(size_t index) const
  {
    if (index < lines.size())
    {
      return lines[index].type;
    }
    else
    {
      return 0;
    }
  }
  const char* GetString(size_t index) const
  {
    if (index < lines.size())
    {
      return lines[index].text.c_str();
    }
    else
    {
      return 0;
    }
  }
};

// Map from icon type to an NSImage*
typedef std::map<NSInteger, NSImage*> ImageMap;

class ListBoxImpl : public ListBox, IListBox
{
private:
  ImageMap images;
  int lineHeight;
  bool unicodeMode;
  int desiredVisibleRows;
  unsigned int maxItemWidth;
  unsigned int aveCharWidth;
  unsigned int maxIconWidth;
  Font font;
  int maxWidth;

  NSTableView* table;
  NSScrollView* scroller;
  NSTableColumn* colIcon;
  NSTableColumn* colText;
  AutoCompletionDataSource* ds;
	
  LinesData ld;
  CallBackAction doubleClickAction;
  void* doubleClickActionData;

public:
  ListBoxImpl() : lineHeight(10), unicodeMode(false),
    desiredVisibleRows(5), maxItemWidth(0), aveCharWidth(8), maxIconWidth(0),
    doubleClickAction(NULL), doubleClickActionData(NULL)
  {
  }
  ~ListBoxImpl() {}

  // ListBox methods
  void SetFont(Font& font);
  void Create(Window& parent, int ctrlID, Scintilla::Point pt, int lineHeight_, bool unicodeMode_, int technology_);
  void SetAverageCharWidth(int width);
  void SetVisibleRows(int rows);
  int GetVisibleRows() const;
  PRectangle GetDesiredRect();
  int CaretFromEdge();
  void Clear();
  void Append(char* s, int type = -1);
  int Length();
  void Select(int n);
  int GetSelection();
  int Find(const char* prefix);
  void GetValue(int n, char* value, int len);
  void RegisterImage(int type, const char* xpm_data);
  void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
  void ClearRegisteredImages();
  void SetDoubleClickAction(CallBackAction action, void* data)
  {
    doubleClickAction = action;
    doubleClickActionData = data;
  }
  void SetList(const char* list, char separator, char typesep);

  // For access from AutoCompletionDataSource implement IListBox
  int Rows();
  NSImage* ImageForRow(NSInteger row);
  NSString* TextForRow(NSInteger row);
  void DoubleClick();
};

void ListBoxImpl::Create(Window& /*parent*/, int /*ctrlID*/, Scintilla::Point pt,
    int lineHeight_, bool unicodeMode_, int)
{
  lineHeight = lineHeight_;
  unicodeMode = unicodeMode_;
  maxWidth = 2000;

  NSRect lbRect = NSMakeRect(pt.x,pt.y, 120, lineHeight * desiredVisibleRows);
  NSWindow* winLB = [[NSWindow alloc] initWithContentRect: lbRect
    styleMask: NSBorderlessWindowMask
    backing: NSBackingStoreBuffered
    defer: NO];
  [winLB setLevel:NSFloatingWindowLevel];
  [winLB setHasShadow:YES];
  scroller = [NSScrollView alloc];
  NSRect scRect = NSMakeRect(0, 0, lbRect.size.width, lbRect.size.height);
  [scroller initWithFrame: scRect];
  [scroller setHasVerticalScroller:YES];
  table = [[NSTableView alloc] initWithFrame: scRect];
  [table setHeaderView:nil];
  [scroller setDocumentView: table];
  colIcon = [[NSTableColumn alloc] initWithIdentifier:@"icon"];
  [colIcon setWidth: 20];
  [colIcon setEditable:NO];
  [colIcon setHidden:YES];
  NSImageCell* imCell = [[[NSImageCell alloc] init] autorelease];
  [colIcon setDataCell:imCell];
  [table addTableColumn:colIcon];
  colText = [[NSTableColumn alloc] initWithIdentifier:@"name"];
  [colText setResizingMask:NSTableColumnAutoresizingMask];
  [colText setEditable:NO];
  [table addTableColumn:colText];
  ds = [[AutoCompletionDataSource alloc] init];
  [ds setBox:this];
  [table setDataSource: ds];	// Weak reference
  [scroller setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
  [[winLB contentView] addSubview: scroller];

  [table setTarget:ds];
  [table setDoubleAction:@selector(doubleClick:)];
  wid = winLB;
}

void ListBoxImpl::SetFont(Font& font_)
{
  // NSCell setFont takes an NSFont* rather than a CTFontRef but they
  // are the same thing toll-free bridged.
  QuartzTextStyle* style = reinterpret_cast<QuartzTextStyle*>(font_.GetID());
  font.Release();
  font.SetID(new QuartzTextStyle(*style));
  NSFont *pfont = (NSFont *)style->getFontRef();
  [[colText dataCell] setFont: pfont];
  CGFloat itemHeight = ceil([pfont boundingRectForFont].size.height);
  [table setRowHeight:itemHeight];
}

void ListBoxImpl::SetAverageCharWidth(int width)
{
  aveCharWidth = width;
}

void ListBoxImpl::SetVisibleRows(int rows)
{
  desiredVisibleRows = rows;
}

int ListBoxImpl::GetVisibleRows() const
{
  return desiredVisibleRows;
}

PRectangle ListBoxImpl::GetDesiredRect()
{
  PRectangle rcDesired;
  rcDesired = GetPosition();

  // There appears to be an extra pixel above and below the row contents
  int itemHeight = [table rowHeight] + 2;

  int rows = Length();
  if ((rows == 0) || (rows > desiredVisibleRows))
    rows = desiredVisibleRows;

  rcDesired.bottom = rcDesired.top + itemHeight * rows;
  rcDesired.right = rcDesired.left + maxItemWidth + aveCharWidth;

  if (Length() > rows)
  {
    [scroller setHasVerticalScroller:YES];
    rcDesired.right += [NSScroller scrollerWidth];
  }
  else
  {
    [scroller setHasVerticalScroller:NO];
  }
  rcDesired.right += maxIconWidth;
  rcDesired.right += 6;

  return rcDesired;
}

int ListBoxImpl::CaretFromEdge()
{
  if ([colIcon isHidden])
    return 3;
  else
    return 6 + [colIcon width];
}

void ListBoxImpl::Clear()
{
  maxItemWidth = 0;
  maxIconWidth = 0;
  ld.Clear();
}

void ListBoxImpl::Append(char* s, int type)
{
  int count = Length();
  ld.Add(count, type, s);

  Scintilla::SurfaceImpl surface;
  unsigned int width = surface.WidthText(font, s, static_cast<int>(strlen(s)));
  if (width > maxItemWidth)
  {
    maxItemWidth = width;
    [colText setWidth: maxItemWidth];
  }
  ImageMap::iterator it = images.find(type);
  if (it != images.end())
  {
    NSImage* img = it->second;
    if (img)
    {
      unsigned int widthIcon = img.size.width;
      if (widthIcon > maxIconWidth)
      {
        [colIcon setHidden: NO];
        maxIconWidth = widthIcon;
        [colIcon setWidth: maxIconWidth];
      }
    }
  }
}

void ListBoxImpl::SetList(const char* list, char separator, char typesep)
{
  Clear();
  size_t count = strlen(list) + 1;
  char* words = new char[count];
  if (words)
  {
    memcpy(words, list, count);
    char* startword = words;
    char* numword = NULL;
    int i = 0;
    for (; words[i]; i++)
    {
      if (words[i] == separator)
      {
        words[i] = '\0';
        if (numword)
          *numword = '\0';
        Append(startword, numword?atoi(numword + 1):-1);
        startword = words + i + 1;
        numword = NULL;
      }
      else if (words[i] == typesep)
      {
        numword = words + i;
      }
    }
    if (startword)
    {
      if (numword)
        *numword = '\0';
      Append(startword, numword?atoi(numword + 1):-1);
    }
    delete []words;
  }
  [table reloadData];
}

int ListBoxImpl::Length()
{
  return ld.Length();
}

void ListBoxImpl::Select(int n)
{
  [table selectRowIndexes:[NSIndexSet indexSetWithIndex:n] byExtendingSelection:NO];
  [table scrollRowToVisible:n];
}

int ListBoxImpl::GetSelection()
{
  return static_cast<int>([table selectedRow]);
}

int ListBoxImpl::Find(const char* prefix)
{
  int count = Length();
  for (int i = 0; i < count; i++)
  {
    const char* s = ld.GetString(i);
    if (s && (s[0] != '\0') && (0 == strncmp(prefix, s, strlen(prefix))))
    {
      return i;
    }
  }
  return - 1;
}

void ListBoxImpl::GetValue(int n, char* value, int len)
{
  const char* textString = ld.GetString(n);
  if (textString == NULL)
  {
    value[0] = '\0';
    return;
  }
  strncpy(value, textString, len);
  value[len - 1] = '\0';
}

void ListBoxImpl::RegisterImage(int type, const char* xpm_data)
{
  XPM xpm(xpm_data);
  NSImage* img = ImageFromXPM(&xpm);
  [img retain];
  ImageMap::iterator it=images.find(type);
  if (it == images.end())
  {
    images[type] = img;
  }
  else
  {
    [it->second release];
    it->second = img;
  }
}

void ListBoxImpl::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
	CGImageRef imageRef = ImageCreateFromRGBA(width, height, pixelsImage, false);
	NSSize sz = {static_cast<CGFloat>(width), static_cast<CGFloat>(height)};
	NSImage *img = [[[NSImage alloc] initWithSize: sz] autorelease];
	NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef];
	[img addRepresentation: bitmapRep];
	[bitmapRep release];
	CGImageRelease(imageRef);
	[img retain];
	ImageMap::iterator it=images.find(type);
	if (it == images.end())
	{
		images[type] = img;
	}
	else
	{
		[it->second release];
		it->second = img;
	}
}

void ListBoxImpl::ClearRegisteredImages()
{
  for (ImageMap::iterator it=images.begin();
      it != images.end(); ++it)
  {
    [it->second release];
    it->second = nil;
  }
  images.clear();
}

int ListBoxImpl::Rows()
{
  return ld.Length();
}

NSImage* ListBoxImpl::ImageForRow(NSInteger row)
{
  ImageMap::iterator it = images.find(ld.GetType(row));
  if (it != images.end())
  {
    NSImage* img = it->second;
    return img;
  }
  else
  {
    return nil;
  }
}

NSString* ListBoxImpl::TextForRow(NSInteger row)
{
  const char* textString = ld.GetString(row);
  NSString* sTitle;
  if (unicodeMode)
    sTitle = [NSString stringWithUTF8String:textString];
  else
    sTitle = [NSString stringWithCString:textString encoding:NSWindowsCP1252StringEncoding];
  return sTitle;
}

void ListBoxImpl::DoubleClick()
{
  if (doubleClickAction)
  {
    doubleClickAction(doubleClickActionData);
  }
}

} // unnamed namespace

//----------------- ListBox ------------------------------------------------------------------------

ListBox::ListBox()
{
}

ListBox::~ListBox()
{
}

ListBox* ListBox::Allocate()
{
	ListBoxImpl* lb = new ListBoxImpl();
	return lb;
}

//----------------- ScintillaContextMenu -----------------------------------------------------------

@implementation ScintillaContextMenu : NSMenu

// This NSMenu subclass serves also as target for menu commands and forwards them as
// notfication messages to the front end.

- (void) handleCommand: (NSMenuItem*) sender
{
  owner->HandleCommand([sender tag]);
}

//--------------------------------------------------------------------------------------------------

- (void) setOwner: (Scintilla::ScintillaCocoa*) newOwner
{
  owner = newOwner;
}

@end

//----------------- Menu ---------------------------------------------------------------------------

Menu::Menu()
  : mid(0)
{
}

//--------------------------------------------------------------------------------------------------

void Menu::CreatePopUp()
{
  Destroy();
  mid = [[ScintillaContextMenu alloc] initWithTitle: @""];
}

//--------------------------------------------------------------------------------------------------

void Menu::Destroy()
{
  ScintillaContextMenu* menu = reinterpret_cast<ScintillaContextMenu*>(mid);
  [menu release];
  mid = NULL;
}

//--------------------------------------------------------------------------------------------------

void Menu::Show(Point, Window &)
{
  // Cocoa menus are handled a bit differently. We only create the menu. The framework
  // takes care to show it properly.
}

//----------------- ElapsedTime --------------------------------------------------------------------

// ElapsedTime is used for precise performance measurements during development
// and not for anything a user sees.

ElapsedTime::ElapsedTime() {
  struct timeval curTime;
  gettimeofday( &curTime, NULL );
  
  bigBit = curTime.tv_sec;
  littleBit = curTime.tv_usec;
}

double ElapsedTime::Duration(bool reset) {
  struct timeval curTime;
  gettimeofday( &curTime, NULL );
  long endBigBit = curTime.tv_sec;
  long endLittleBit = curTime.tv_usec;
  double result = 1000000.0 * (endBigBit - bigBit);
  result += endLittleBit - littleBit;
  result /= 1000000.0;
  if (reset) {
    bigBit = endBigBit;
    littleBit = endLittleBit;
  }
  return result;
}

//----------------- Platform -----------------------------------------------------------------------

ColourDesired Platform::Chrome()
{
  return ColourDesired(0xE0, 0xE0, 0xE0);
}

//--------------------------------------------------------------------------------------------------

ColourDesired Platform::ChromeHighlight()
{
  return ColourDesired(0xFF, 0xFF, 0xFF);
}

//--------------------------------------------------------------------------------------------------

/**
 * Returns the currently set system font for the user.
 */
const char *Platform::DefaultFont()
{
  NSString* name = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSFixedPitchFont"];
  return [name UTF8String];
}

//--------------------------------------------------------------------------------------------------

/**
 * Returns the currently set system font size for the user.
 */
int Platform::DefaultFontSize()
{
  return static_cast<int>([[NSUserDefaults standardUserDefaults]
			   integerForKey: @"NSFixedPitchFontSize"]);
}

//--------------------------------------------------------------------------------------------------

/**
 * Returns the time span in which two consequtive mouse clicks must occur to be considered as
 * double click.
 *
 * @return
 */
unsigned int Platform::DoubleClickTime()
{
  float threshold = [[NSUserDefaults standardUserDefaults] floatForKey: 
                     @"com.apple.mouse.doubleClickThreshold"];
  if (threshold == 0)
    threshold = 0.5;
  return static_cast<unsigned int>(threshold * 1000.0);
}

//--------------------------------------------------------------------------------------------------

bool Platform::MouseButtonBounce()
{
  return false;
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper method for the backend to reach through to the scintilla window.
 */
long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) 
{
  return scintilla_send_message(w, msg, wParam, lParam);
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper method for the backend to reach through to the scintilla window.
 */
long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam)
{
  return scintilla_send_message(w, msg, wParam, (long) lParam);
}

//--------------------------------------------------------------------------------------------------

bool Platform::IsDBCSLeadByte(int codePage, char ch)
{
  // Byte ranges found in Wikipedia articles with relevant search strings in each case
  unsigned char uch = static_cast<unsigned char>(ch);
  switch (codePage)
  {
  case 932:
    // Shift_jis
    return ((uch >= 0x81) && (uch <= 0x9F)) ||
        ((uch >= 0xE0) && (uch <= 0xFC));
        // Lead bytes F0 to FC may be a Microsoft addition. 
  case 936:
    // GBK
    return (uch >= 0x81) && (uch <= 0xFE);
  case 949:
    // Korean Wansung KS C-5601-1987
    return (uch >= 0x81) && (uch <= 0xFE);
  case 950:
    // Big5
    return (uch >= 0x81) && (uch <= 0xFE);
  case 1361:
    // Korean Johab KS C-5601-1992
    return
      ((uch >= 0x84) && (uch <= 0xD3)) ||
      ((uch >= 0xD8) && (uch <= 0xDE)) ||
      ((uch >= 0xE0) && (uch <= 0xF9));
  }
  return false;
}

//--------------------------------------------------------------------------------------------------

int Platform::DBCSCharLength(int /* codePage */, const char* /* s */)
{
  // DBCS no longer uses this.
  return 1;
}

//--------------------------------------------------------------------------------------------------

int Platform::DBCSCharMaxLength()
{
  return 2;
}

//--------------------------------------------------------------------------------------------------

int Platform::Minimum(int a, int b)
{
  return (a < b) ? a : b;
}

//--------------------------------------------------------------------------------------------------

int Platform::Maximum(int a, int b) {
  return (a > b) ? a : b;
}

//--------------------------------------------------------------------------------------------------

//#define TRACE
#ifdef TRACE

void Platform::DebugDisplay(const char *s)
{
  fprintf( stderr, "%s", s );
}

//--------------------------------------------------------------------------------------------------

void Platform::DebugPrintf(const char *format, ...)
{
  const int BUF_SIZE = 2000;
  char buffer[BUF_SIZE];
  
  va_list pArguments;
  va_start(pArguments, format);
  vsnprintf(buffer, BUF_SIZE, format, pArguments);
  va_end(pArguments);
  Platform::DebugDisplay(buffer);
}

#else

void Platform::DebugDisplay(const char *) {}

void Platform::DebugPrintf(const char *, ...) {}

#endif

//--------------------------------------------------------------------------------------------------

static bool assertionPopUps = true;

bool Platform::ShowAssertionPopUps(bool assertionPopUps_)
{
  bool ret = assertionPopUps;
  assertionPopUps = assertionPopUps_;
  return ret;
}

//--------------------------------------------------------------------------------------------------

void Platform::Assert(const char *c, const char *file, int line)
{
  char buffer[2000];
  sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
  strcat(buffer, "\r\n");
  Platform::DebugDisplay(buffer);
#ifdef DEBUG 
  // Jump into debugger in assert on Mac (CL269835)
  ::Debugger();
#endif
}

//--------------------------------------------------------------------------------------------------

int Platform::Clamp(int val, int minVal, int maxVal)
{
  if (val > maxVal)
    val = maxVal;
  if (val < minVal)
    val = minVal;
  return val;
}

//----------------- DynamicLibrary -----------------------------------------------------------------

/**
 * Implements the platform specific part of library loading.
 * 
 * @param modulePath The path to the module to load.
 * @return A library instance or NULL if the module could not be found or another problem occured.
 */
DynamicLibrary* DynamicLibrary::Load(const char* /* modulePath */)
{
  // Not implemented.
  return NULL;
}

//--------------------------------------------------------------------------------------------------

Added cocoa/QuartzTextLayout.h.































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 *  QuartzTextLayout.h
 *
 *  Original Code by Evan Jones on Wed Oct 02 2002.
 *  Contributors:
 *  Shane Caraveo, ActiveState
 *  Bernd Paradies, Adobe
 *
 */

#ifndef _QUARTZ_TEXT_LAYOUT_H
#define _QUARTZ_TEXT_LAYOUT_H

#include <Cocoa/Cocoa.h>

#include "QuartzTextStyle.h"


class QuartzTextLayout
{
public:
    /** Create a text layout for drawing on the specified context. */
    QuartzTextLayout( CGContextRef context )
    {
		mString = NULL;
		mLine = NULL;
		stringLength = 0;
        setContext(context);
    }

    ~QuartzTextLayout()
    {
		if ( mString != NULL )
		{
			CFRelease(mString);
			mString = NULL;
		}
		if ( mLine != NULL )
		{
			CFRelease(mLine);
			mLine = NULL;
		}	
    }

    inline void setText( const UInt8* buffer, size_t byteLength, CFStringEncoding encoding, const QuartzTextStyle& r )
    {
		CFStringRef str = CFStringCreateWithBytes( NULL, buffer, byteLength, encoding, false );
        if (!str)
            return;
		
	        stringLength = CFStringGetLength(str);

		CFMutableDictionaryRef stringAttribs = r.getCTStyle();
		
		if (mString != NULL)
			CFRelease(mString);
		mString = ::CFAttributedStringCreate(NULL, str, stringAttribs);
		
		if (mLine != NULL)
			CFRelease(mLine);
		mLine = ::CTLineCreateWithAttributedString(mString);
		
		CFRelease( str );
    }

    /** Draw the text layout into the current CGContext at the specified position.
    * @param x The x axis position to draw the baseline in the current CGContext.
    * @param y The y axis position to draw the baseline in the current CGContext. */
    void draw( float x, float y )
    {
		if (mLine == NULL)
			return;
		
		::CGContextSetTextMatrix(gc, CGAffineTransformMakeScale(1.0, -1.0));
		
		// Set the text drawing position.
		::CGContextSetTextPosition(gc, x, y);
		
		// And finally, draw!
		::CTLineDraw(mLine, gc);
    }
	
	float MeasureStringWidth()
	{		
		if (mLine == NULL)
			return 0.0f;
		
		return ::CTLineGetTypographicBounds(mLine, NULL, NULL, NULL);
	}
	
    CTLineRef getCTLine() {
        return mLine;
    }
	
    CFIndex getStringLength() {
	    return stringLength;
    }

    inline void setContext (CGContextRef context)
    {
        gc = context;
    }

private:
    CGContextRef gc;
	CFAttributedStringRef mString;
	CTLineRef mLine;
	CFIndex stringLength;
};

#endif

Added cocoa/QuartzTextStyle.h.



























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 *  QuartzTextStyle.h
 *
 *  Created by Evan Jones on Wed Oct 02 2002.
 *
 */

#ifndef _QUARTZ_TEXT_STYLE_H
#define _QUARTZ_TEXT_STYLE_H

#include "QuartzTextStyleAttribute.h"

class QuartzTextStyle
{
public:
	QuartzTextStyle()
	{
		fontRef = NULL;
		styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2,
		        &kCFTypeDictionaryKeyCallBacks,
		        &kCFTypeDictionaryValueCallBacks);

		characterSet = 0;
	}

	QuartzTextStyle(const QuartzTextStyle &other)
	{
		// Does not copy font colour attribute
		fontRef = static_cast<CTFontRef>(CFRetain(other.fontRef));
		styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2,
		        &kCFTypeDictionaryKeyCallBacks,
		        &kCFTypeDictionaryValueCallBacks);
		CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef);
		characterSet = other.characterSet;
	}

	~QuartzTextStyle()
	{
		if (styleDict != NULL)
		{
			CFRelease(styleDict);
			styleDict = NULL;
		}

		if (fontRef)
		{
			CFRelease(fontRef);
			fontRef = NULL;
		}
	}

	CFMutableDictionaryRef getCTStyle() const
	{
		return styleDict;
	}

	void setCTStyleColor(CGColor *inColor)
	{
		CFDictionarySetValue(styleDict, kCTForegroundColorAttributeName, inColor);
	}

	float getAscent() const
	{
		return ::CTFontGetAscent(fontRef);
	}

	float getDescent() const
	{
		return ::CTFontGetDescent(fontRef);
	}

	float getLeading() const
	{
		return ::CTFontGetLeading(fontRef);
	}

	void setFontRef(CTFontRef inRef, int characterSet_)
	{
		fontRef = inRef;
		characterSet = characterSet_;

		if (styleDict != NULL)
			CFRelease(styleDict);

		styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2,
		        &kCFTypeDictionaryKeyCallBacks,
		        &kCFTypeDictionaryValueCallBacks);

		CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef);
	}

	CTFontRef getFontRef()
	{
		return fontRef;
	}

	int getCharacterSet()
	{
		return characterSet;
	}

private:
	CFMutableDictionaryRef styleDict;
	CTFontRef fontRef;
	int characterSet;
};

#endif

Added cocoa/QuartzTextStyleAttribute.h.





































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/**
 *  QuartzTextStyleAttribute.h
 *
 *  Original Code by Evan Jones on Wed Oct 02 2002.
 *  Contributors:
 *  Shane Caraveo, ActiveState
 *  Bernd Paradies, Adobe
 *
 */


#ifndef _QUARTZ_TEXT_STYLE_ATTRIBUTE_H
#define _QUARTZ_TEXT_STYLE_ATTRIBUTE_H

class QuartzFont
{
public:
    /** Create a font style from a name. */
	QuartzFont( const char* name, size_t length, float size, int weight, bool italic )
    {
        assert( name != NULL && length > 0 && name[length] == '\0' );

		CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
		assert(fontName != NULL);
	        bool bold = weight > SC_WEIGHT_NORMAL;

		if (bold || italic)
		{
			CTFontSymbolicTraits desiredTrait = 0;
			CTFontSymbolicTraits traitMask = 0;

			// if bold was specified, add the trait
			if (bold) {
				desiredTrait |= kCTFontBoldTrait;
				traitMask |= kCTFontBoldTrait;
			}

			// if italic was specified, add the trait
			if (italic) {
				desiredTrait |= kCTFontItalicTrait;
				traitMask |= kCTFontItalicTrait;
			}

			// create a font and then a copy of it with the sym traits
			CTFontRef iFont = ::CTFontCreateWithName(fontName, size, NULL);
			fontid = ::CTFontCreateCopyWithSymbolicTraits(iFont, size, NULL, desiredTrait, traitMask);
			if (fontid)
			{
				CFRelease(iFont);
			}
			else
			{
				// Traits failed so use base font
				fontid = iFont;
			}
		}
		else
		{
			// create the font, no traits
			fontid = ::CTFontCreateWithName(fontName, size, NULL);
		}

		if (!fontid)
		{
			// Failed to create requested font so use font always present
			fontid = ::CTFontCreateWithName((CFStringRef)@"Monaco", size, NULL);
		}

		CFRelease(fontName);
    }

	CTFontRef getFontID()
    {
        return fontid;
    }

private:
	CTFontRef fontid;
};

#endif

Added cocoa/SciTest.mk.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
### start defines ###
include common.mk

NAME=Demo

LD=gcc $(ARCH) -framework Cocoa

TARG=$(APP)/Contents/MacOS/$(NAME)
APP=$(APP_BLD)/$(NAME).app

all: $(APP_BLD) $(TARG)

$(APP):
	-rm -rf $(APP)
	-mkdir $(APP)
	-mkdir $(APP)/Contents/
	-mkdir $(APP)/Contents/Frameworks/
	-mkdir $(APP)/Contents/MacOS/
	-mkdir $(APP)/Contents/Resources/
	-cp ScintillaTest/Info.plist $(APP)/Contents/Info.plist.bak
	-sed "s/\$${EXECUTABLE_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak > $(APP)/Contents/Info.plist.bak2
	-sed "s/\$${PRODUCT_NAME}/$(NAME)/g" < $(APP)/Contents/Info.plist.bak2 > $(APP)/Contents/Info.plist
	-rm $(APP)/Contents/Info.plist.bak $(APP)/Contents/Info.plist.bak2
	-cp -r ScintillaTest/English.lproj $(APP)/Contents/Resources/
	/Developer/usr/bin/ibtool --errors --warnings --notices --output-format human-readable-text \
	--compile $(APP)/Contents/Resources/English.lproj/MainMenu.nib ScintillaTest/English.lproj/MainMenu.xib
	-cp ScintillaTest/TestData.sql $(APP)/Contents/Resources/
	-make -f Framework.mk all

$(TARG) : $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP)
	-cp -R $(FRM_BLD)/Sci.framework $(APP)/Contents/Frameworks/
	$(LD) $(APP_BLD)/main.o $(APP_BLD)/AppController.o $(APP)/Contents/Frameworks/Sci.framework/Sci -o $(TARG) -lstdc++

$(APP_BLD) :
	-mkdir $(BLD)
	-mkdir $(APP_BLD)

Added cocoa/ScintillaCocoa.h.

































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * ScintillaCocoa.h
 *
 * Mike Lischke <mlischke@sun.com>
 *
 * Based on ScintillaMacOSX.h
 * Original code by Evan Jones on Sun Sep 01 2002.
 *  Contributors:
 *  Shane Caraveo, ActiveState
 *  Bernd Paradies, Adobe
 *
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#include <stdlib.h>
#include <string>
#include <stdio.h>
#include <ctype.h>
#include <time.h>

#include <vector>
#include <map>

#include "ILexer.h"

#ifdef SCI_LEXER
#include "SciLexer.h"
#include "PropSetSimple.h"
#endif

#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"

#include "ScintillaBase.h"

extern "C" NSString* ScintillaRecPboardType;

@class InnerView;
@class MarginView;
@class ScintillaView;

@class FindHighlightLayer;

/**
 * Helper class to be used as timer target (NSTimer).
 */
@interface TimerTarget : NSObject
{
  void* mTarget;
  NSNotificationQueue* notificationQueue;
}
- (id) init: (void*) target;
- (void) timerFired: (NSTimer*) timer;
- (void) idleTimerFired: (NSTimer*) timer;
- (void) idleTriggered: (NSNotification*) notification;
@end

namespace Scintilla {

/**
 * On the Mac, there is no WM_COMMAND or WM_NOTIFY message that can be sent
 * back to the parent. Therefore, there must be a callback handler that acts
 * like a Windows WndProc, where Scintilla can send notifications to. Use
 * ScintillaCocoa::RegisterNotifyHandler() to register such a handler.
 * Message format is:
 * <br>
 * WM_COMMAND: HIWORD (wParam) = notification code, LOWORD (wParam) = 0 (no control ID), lParam = ScintillaCocoa*
 * <br>
 * WM_NOTIFY: wParam = 0 (no control ID), lParam = ptr to SCNotification structure, with hwndFrom set to ScintillaCocoa*
 */
typedef void(*SciNotifyFunc) (intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam);

/**
 * Scintilla sends these two messages to the nofity handler. Please refer
 * to the Windows API doc for details about the message format.
 */
#define	WM_COMMAND	1001
#define WM_NOTIFY	1002

/**
 * Main scintilla class, implemented for OS X (Cocoa).
 */
class ScintillaCocoa : public ScintillaBase
{
private:
  TimerTarget* timerTarget;
  NSEvent* lastMouseEvent;
  
  SciNotifyFunc	notifyProc;
  intptr_t notifyObj;

  bool capturedMouse;

  bool enteredSetScrollingSize;

  // Private so ScintillaCocoa objects can not be copied
  ScintillaCocoa(const ScintillaCocoa &) : ScintillaBase() {}
  ScintillaCocoa &operator=(const ScintillaCocoa &) { return * this; }

  bool GetPasteboardData(NSPasteboard* board, SelectionText* selectedText);
  void SetPasteboardData(NSPasteboard* board, const SelectionText& selectedText);
  
  int scrollSpeed;
  int scrollTicks;
  NSTimer* tickTimer;
  NSTimer* idleTimer;
  CFRunLoopObserverRef observer;
	
  FindHighlightLayer *layerFindIndicator;

protected:
  Point GetVisibleOriginInMain();
  PRectangle GetClientRectangle();
  Point ConvertPoint(NSPoint point);
  
  virtual void Initialise();
  virtual void Finalise();
  virtual CaseFolder *CaseFolderForEncoding();
  virtual std::string CaseMapString(const std::string &s, int caseMapping);
  virtual void CancelModes();

public:
  ScintillaCocoa(InnerView* view, MarginView* viewMargin);
  virtual ~ScintillaCocoa();

  void RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback);
  sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

  ScintillaView* TopContainer();
  NSScrollView* ScrollContainer();
  InnerView* ContentView();

  bool SyncPaint(void* gc, PRectangle rc);
  bool Draw(NSRect rect, CGContextRef gc);
  void PaintMargin(NSRect aRect);

  virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
  void SetTicking(bool on);
  bool SetIdle(bool on);
  void SetMouseCapture(bool on);
  bool HaveMouseCapture();
  void ScrollText(int linesToMove);
  void SetVerticalScrollPos();
  void SetHorizontalScrollPos();
  bool ModifyScrollBars(int nMax, int nPage);
  bool SetScrollingSize(void);
  void Resize();
  void UpdateForScroll();

  // Notifications for the owner.
  void NotifyChange();
  void NotifyFocus(bool focus);
  void NotifyParent(SCNotification scn);
  void NotifyURIDropped(const char *uri);

  bool HasSelection();
  bool CanUndo();
  bool CanRedo();
  virtual void CopyToClipboard(const SelectionText &selectedText);
  virtual void Copy();
  virtual bool CanPaste();
  virtual void Paste();
  virtual void Paste(bool rectangular);
  void CTPaint(void* gc, NSRect rc);
  void CallTipMouseDown(NSPoint pt);
  virtual void CreateCallTipWindow(PRectangle rc);
  virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
  virtual void ClaimSelection();

  NSPoint GetCaretPosition();
  
  static sptr_t DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam);

  void TimerFired(NSTimer* timer);
  void IdleTimerFired();
  static void UpdateObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *sci);
  void ObserverAdd();
  void ObserverRemove();
  virtual void IdleWork();
  virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo);
  int InsertText(NSString* input);
  
  bool KeyboardInput(NSEvent* event);
  void MouseDown(NSEvent* event);
  void MouseMove(NSEvent* event);
  void MouseUp(NSEvent* event);
  void MouseEntered(NSEvent* event);
  void MouseExited(NSEvent* event);
  void MouseWheel(NSEvent* event);

  // Drag and drop
  void StartDrag();
  bool GetDragData(id <NSDraggingInfo> info, NSPasteboard &pasteBoard, SelectionText* selectedText);
  NSDragOperation DraggingEntered(id <NSDraggingInfo> info);
  NSDragOperation DraggingUpdated(id <NSDraggingInfo> info);
  void DraggingExited(id <NSDraggingInfo> info);
  bool PerformDragOperation(id <NSDraggingInfo> info);
  void DragScroll();
  
  // Promote some methods needed for NSResponder actions.
  virtual void SelectAll();
  void DeleteBackward();
  virtual void Cut();
  virtual void Undo();
  virtual void Redo();
  
  virtual NSMenu* CreateContextMenu(NSEvent* event);
  void HandleCommand(NSInteger command);

  virtual void ActiveStateChanged(bool isActive);

  // Find indicator
  void ShowFindIndicatorForRange(NSRange charRange, BOOL retaining);
  void MoveFindIndicatorWithBounce(BOOL bounce);
  void HideFindIndicator();
};


}


Added cocoa/ScintillaCocoa.mm.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148

/**
 * Scintilla source code edit control
 * ScintillaCocoa.mm - Cocoa subclass of ScintillaBase
 * 
 * Written by Mike Lischke <mlischke@sun.com>
 *
 * Loosely based on ScintillaMacOSX.cxx.
 * Copyright 2003 by Evan Jones <ejones@uwaterloo.ca>
 * Based on ScintillaGTK.cxx Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed.
  *
 * Copyright (c) 2009, 2010 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <Cocoa/Cocoa.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
#import <QuartzCore/CAGradientLayer.h>
#endif
#import <QuartzCore/CAAnimation.h>
#import <QuartzCore/CATransaction.h>

#include "ScintillaView.h"
#include "PlatCocoa.h"

using namespace Scintilla;

#ifndef WM_UNICHAR
#define WM_UNICHAR 0x0109
#endif

NSString* ScintillaRecPboardType = @"com.scintilla.utf16-plain-text.rectangular";

//--------------------------------------------------------------------------------------------------

// Define keyboard shortcuts (equivalents) the Mac way.
#define SCI_CMD ( SCI_CTRL)
#define SCI_SCMD ( SCI_CMD | SCI_SHIFT)
#define SCI_SMETA ( SCI_META | SCI_SHIFT)

static const KeyToCommand macMapDefault[] =
{
  // OS X specific
  {SCK_DOWN,      SCI_CTRL,   SCI_DOCUMENTEND},
  {SCK_DOWN,      SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
  {SCK_UP,        SCI_CTRL,   SCI_DOCUMENTSTART},
  {SCK_UP,        SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
  {SCK_LEFT,      SCI_CTRL,   SCI_VCHOME},
  {SCK_LEFT,      SCI_CSHIFT, SCI_VCHOMEEXTEND},
  {SCK_RIGHT,     SCI_CTRL,   SCI_LINEEND},
  {SCK_RIGHT,     SCI_CSHIFT, SCI_LINEENDEXTEND},

  // Similar to Windows and GTK+
  // Where equivalent clashes with OS X standard, use Meta instead
  {SCK_DOWN,      SCI_NORM,   SCI_LINEDOWN},
  {SCK_DOWN,      SCI_SHIFT,  SCI_LINEDOWNEXTEND},
  {SCK_DOWN,      SCI_META,   SCI_LINESCROLLDOWN},
  {SCK_DOWN,      SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
  {SCK_UP,        SCI_NORM,   SCI_LINEUP},
  {SCK_UP,        SCI_SHIFT,  SCI_LINEUPEXTEND},
  {SCK_UP,        SCI_META,   SCI_LINESCROLLUP},
  {SCK_UP,        SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
  {'[',           SCI_CTRL,   SCI_PARAUP},
  {'[',           SCI_CSHIFT, SCI_PARAUPEXTEND},
  {']',           SCI_CTRL,   SCI_PARADOWN},
  {']',           SCI_CSHIFT, SCI_PARADOWNEXTEND},
  {SCK_LEFT,      SCI_NORM,   SCI_CHARLEFT},
  {SCK_LEFT,      SCI_SHIFT,  SCI_CHARLEFTEXTEND},
  {SCK_LEFT,      SCI_ALT,    SCI_WORDLEFT},
  {SCK_LEFT,      SCI_META,   SCI_WORDLEFT},
  {SCK_LEFT,      SCI_SMETA,  SCI_WORDLEFTEXTEND},
  {SCK_LEFT,      SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND},
  {SCK_RIGHT,     SCI_NORM,   SCI_CHARRIGHT},
  {SCK_RIGHT,     SCI_SHIFT,  SCI_CHARRIGHTEXTEND},
  {SCK_RIGHT,     SCI_ALT,    SCI_WORDRIGHT},
  {SCK_RIGHT,     SCI_META,   SCI_WORDRIGHT},
  {SCK_RIGHT,     SCI_SMETA,  SCI_WORDRIGHTEXTEND},
  {SCK_RIGHT,     SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND},
  {'/',           SCI_CTRL,   SCI_WORDPARTLEFT},
  {'/',           SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
  {'\\',          SCI_CTRL,   SCI_WORDPARTRIGHT},
  {'\\',          SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
  {SCK_HOME,      SCI_NORM,   SCI_VCHOME},
  {SCK_HOME,      SCI_SHIFT,  SCI_VCHOMEEXTEND},
  {SCK_HOME,      SCI_CTRL,   SCI_DOCUMENTSTART},
  {SCK_HOME,      SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
  {SCK_HOME,      SCI_ALT,    SCI_HOMEDISPLAY},
  {SCK_HOME,      SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
  {SCK_END,       SCI_NORM,   SCI_LINEEND},
  {SCK_END,       SCI_SHIFT,  SCI_LINEENDEXTEND},
  {SCK_END,       SCI_CTRL,   SCI_DOCUMENTEND},
  {SCK_END,       SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
  {SCK_END,       SCI_ALT,    SCI_LINEENDDISPLAY},
  {SCK_END,       SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
  {SCK_PRIOR,     SCI_NORM,   SCI_PAGEUP},
  {SCK_PRIOR,     SCI_SHIFT,  SCI_PAGEUPEXTEND},
  {SCK_PRIOR,     SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
  {SCK_NEXT,      SCI_NORM,   SCI_PAGEDOWN},
  {SCK_NEXT,      SCI_SHIFT,  SCI_PAGEDOWNEXTEND},
  {SCK_NEXT,      SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
  {SCK_DELETE,    SCI_NORM,   SCI_CLEAR},
  {SCK_DELETE,    SCI_SHIFT,  SCI_CUT},
  {SCK_DELETE,    SCI_CTRL,   SCI_DELWORDRIGHT},
  {SCK_DELETE,    SCI_CSHIFT, SCI_DELLINERIGHT},
  {SCK_INSERT,    SCI_NORM,   SCI_EDITTOGGLEOVERTYPE},
  {SCK_INSERT,    SCI_SHIFT,  SCI_PASTE},
  {SCK_INSERT,    SCI_CTRL,   SCI_COPY},
  {SCK_ESCAPE,    SCI_NORM,   SCI_CANCEL},
  {SCK_BACK,      SCI_NORM,   SCI_DELETEBACK},
  {SCK_BACK,      SCI_SHIFT,  SCI_DELETEBACK},
  {SCK_BACK,      SCI_CTRL,   SCI_DELWORDLEFT},
  {SCK_BACK,      SCI_ALT,    SCI_DELWORDLEFT},
  {SCK_BACK,      SCI_CSHIFT, SCI_DELLINELEFT},
  {'z',           SCI_CMD,    SCI_UNDO},
  {'z',           SCI_SCMD,   SCI_REDO},
  {'x',           SCI_CMD,    SCI_CUT},
  {'c',           SCI_CMD,    SCI_COPY},
  {'v',           SCI_CMD,    SCI_PASTE},
  {'a',           SCI_CMD,    SCI_SELECTALL},
  {SCK_TAB,       SCI_NORM,   SCI_TAB},
  {SCK_TAB,       SCI_SHIFT,  SCI_BACKTAB},
  {SCK_RETURN,    SCI_NORM,   SCI_NEWLINE},
  {SCK_RETURN,    SCI_SHIFT,  SCI_NEWLINE},
  {SCK_ADD,       SCI_CMD,    SCI_ZOOMIN},
  {SCK_SUBTRACT,  SCI_CMD,    SCI_ZOOMOUT},
  {SCK_DIVIDE,    SCI_CMD,    SCI_SETZOOM},
  {'l',           SCI_CMD,    SCI_LINECUT},
  {'l',           SCI_CSHIFT, SCI_LINEDELETE},
  {'t',           SCI_CSHIFT, SCI_LINECOPY},
  {'t',           SCI_CTRL,   SCI_LINETRANSPOSE},
  {'d',           SCI_CTRL,   SCI_SELECTIONDUPLICATE},
  {'u',           SCI_CTRL,   SCI_LOWERCASE},
  {'u',           SCI_CSHIFT, SCI_UPPERCASE},
  {0, 0, 0},
};

//--------------------------------------------------------------------------------------------------

#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5

// Only implement FindHighlightLayer on OS X 10.6+

/**
 * Class to display the animated gold roundrect used on OS X for matches.
 */
@interface FindHighlightLayer : CAGradientLayer
{
@private
	NSString *sFind;
	int positionFind;
	BOOL retaining;
	CGFloat widthText;
	CGFloat heightLine;
	NSString *sFont;
	CGFloat fontSize;
}

@property (copy) NSString *sFind;
@property (assign) int positionFind;
@property (assign) BOOL retaining;
@property (assign) CGFloat widthText;
@property (assign) CGFloat heightLine;
@property (copy) NSString *sFont;
@property (assign) CGFloat fontSize;

- (void) animateMatch: (CGPoint)ptText bounce:(BOOL)bounce;
- (void) hideMatch;

@end

//--------------------------------------------------------------------------------------------------

@implementation FindHighlightLayer

@synthesize sFind, positionFind, retaining, widthText, heightLine, sFont, fontSize;

-(id) init {
	if (self = [super init]) {
		[self setNeedsDisplayOnBoundsChange: YES];
		// A gold to slightly redder gradient to match other applications
		CGColorRef colGold = CGColorCreateGenericRGB(1.0, 1.0, 0, 1.0);
		CGColorRef colGoldRed = CGColorCreateGenericRGB(1.0, 0.8, 0, 1.0);
		self.colors = [NSArray arrayWithObjects:(id)colGoldRed, (id)colGold, nil];
		CGColorRelease(colGoldRed);
		CGColorRelease(colGold);

		CGColorRef colGreyBorder = CGColorCreateGenericGray(0.756f, 0.5f);
		self.borderColor = colGreyBorder;
		CGColorRelease(colGreyBorder);

		self.borderWidth = 1.0;
		self.cornerRadius = 5.0f;
		self.shadowRadius = 1.0f;
		self.shadowOpacity = 0.9f;
		self.shadowOffset = CGSizeMake(0.0f, -2.0f);
		self.anchorPoint = CGPointMake(0.5, 0.5);
	}
	return self;
	
}

const CGFloat paddingHighlightX = 4;
const CGFloat paddingHighlightY = 2;

-(void) drawInContext:(CGContextRef)context {
	if (!sFind || !sFont)
		return;
	
	CFStringRef str = CFStringRef(sFind);
	
	CFMutableDictionaryRef styleDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2,
								     &kCFTypeDictionaryKeyCallBacks, 
								     &kCFTypeDictionaryValueCallBacks);
	CGColorRef color = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0);
	CFDictionarySetValue(styleDict, kCTForegroundColorAttributeName, color);
	CTFontRef fontRef = ::CTFontCreateWithName((CFStringRef)sFont, fontSize, NULL);
	CFDictionaryAddValue(styleDict, kCTFontAttributeName, fontRef);
	
	CFAttributedStringRef attrString = ::CFAttributedStringCreate(NULL, str, styleDict);
	CTLineRef textLine = ::CTLineCreateWithAttributedString(attrString);
	// Indent from corner of bounds
	CGContextSetTextPosition(context, paddingHighlightX, 3 + paddingHighlightY);
	CTLineDraw(textLine, context);
	
	CFRelease(textLine);
	CFRelease(attrString);
	CFRelease(fontRef);
	CGColorRelease(color);
	CFRelease(styleDict);
}

- (void) animateMatch: (CGPoint)ptText bounce:(BOOL)bounce {
	if (!self.sFind || ![self.sFind length]) {
		[self hideMatch];
		return;
	}

	CGFloat width = self.widthText + paddingHighlightX * 2;
	CGFloat height = self.heightLine + paddingHighlightY * 2;

	CGFloat flipper = self.geometryFlipped ? -1.0 : 1.0;

	// Adjust for padding
	ptText.x -= paddingHighlightX;
	ptText.y += flipper * paddingHighlightY;

	// Shift point to centre as expanding about centre
	ptText.x += width / 2.0;
	ptText.y -= flipper * height / 2.0;

	[CATransaction begin];
	[CATransaction setValue:[NSNumber numberWithFloat:0.0] forKey:kCATransactionAnimationDuration];
	self.bounds = CGRectMake(0,0, width, height);
	self.position = ptText;
	if (bounce) {
		// Do not reset visibility when just moving
		self.hidden = NO;
		self.opacity = 1.0;
	}
	[self setNeedsDisplay];
	[CATransaction commit];
	
	if (bounce) {
		CABasicAnimation *animBounce = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
		animBounce.duration = 0.15;
		animBounce.autoreverses = YES;
		animBounce.removedOnCompletion = NO;
		animBounce.fromValue = [NSNumber numberWithFloat: 1.0];
		animBounce.toValue = [NSNumber numberWithFloat: 1.25];
		
		if (self.retaining) {
			
			[self addAnimation: animBounce forKey:@"animateFound"];
			
		} else {
			
			CABasicAnimation *animFade = [CABasicAnimation animationWithKeyPath:@"opacity"];
			animFade.duration = 0.1;
			animFade.beginTime = 0.4;
			animFade.removedOnCompletion = NO;
			animFade.fromValue = [NSNumber numberWithFloat: 1.0];
			animFade.toValue = [NSNumber numberWithFloat: 0.0];
			
			CAAnimationGroup *group = [CAAnimationGroup animation];
			[group setDuration:0.5];
			group.removedOnCompletion = NO;
			group.fillMode = kCAFillModeForwards;
			[group setAnimations:[NSArray arrayWithObjects:animBounce, animFade, nil]];
			
			[self addAnimation:group forKey:@"animateFound"];
		}
	}
}

- (void) hideMatch {
	self.sFind = @"";
	self.positionFind = INVALID_POSITION;
	self.hidden = YES;
}

@end

#endif

//--------------------------------------------------------------------------------------------------

@implementation TimerTarget

- (id) init: (void*) target
{
  self = [super init];
  if (self != nil)
  {
    mTarget = target;

    // Get the default notification queue for the thread which created the instance (usually the
    // main thread). We need that later for idle event processing.
    NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; 
    notificationQueue = [[NSNotificationQueue alloc] initWithNotificationCenter: center];
    [center addObserver: self selector: @selector(idleTriggered:) name: @"Idle" object: nil]; 
  }
  return self;
}

//--------------------------------------------------------------------------------------------------

- (void) dealloc
{
  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
  [center removeObserver:self];
  [notificationQueue release];
  [super dealloc];
}

//--------------------------------------------------------------------------------------------------

/**
 * Method called by a timer installed by ScintillaCocoa. This two step approach is needed because
 * a native Obj-C class is required as target for the timer.
 */
- (void) timerFired: (NSTimer*) timer
{
  reinterpret_cast<ScintillaCocoa*>(mTarget)->TimerFired(timer);
}

//--------------------------------------------------------------------------------------------------

/**
 * Another timer callback for the idle timer.
 */
- (void) idleTimerFired: (NSTimer*) timer
{
#pragma unused(timer)
  // Idle timer event.
  // Post a new idle notification, which gets executed when the run loop is idle.
  // Since we are coalescing on name and sender there will always be only one actual notification
  // even for multiple requests.
  NSNotification *notification = [NSNotification notificationWithName: @"Idle" object: self]; 
  [notificationQueue enqueueNotification: notification
                            postingStyle: NSPostWhenIdle
                            coalesceMask: (NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender)
                                forModes: nil]; 
}

//--------------------------------------------------------------------------------------------------

/**
 * Another step for idle events. The timer (for idle events) simply requests a notification on
 * idle time. Only when this notification is send we actually call back the editor.
 */
- (void) idleTriggered: (NSNotification*) notification
{
#pragma unused(notification)
  reinterpret_cast<ScintillaCocoa*>(mTarget)->IdleTimerFired();
}

@end

//----------------- ScintillaCocoa -----------------------------------------------------------------

ScintillaCocoa::ScintillaCocoa(InnerView* view, MarginView* viewMargin)
{
  vs.marginInside = false;
  wMain = view; // Don't retain since we're owned by view, which would cause a cycle
  wMargin = viewMargin;
  timerTarget = [[TimerTarget alloc] init: this];
  lastMouseEvent = NULL;
  notifyObj = NULL;
  notifyProc = NULL;
  capturedMouse = false;
  enteredSetScrollingSize = false;
  scrollSpeed = 1;
  scrollTicks = 2000;
  tickTimer = NULL;
  idleTimer = NULL;
  observer = NULL;
  layerFindIndicator = NULL;
  Initialise();
}

//--------------------------------------------------------------------------------------------------

ScintillaCocoa::~ScintillaCocoa()
{
  SetTicking(false);
  [timerTarget release];
}

//--------------------------------------------------------------------------------------------------

/**
 * Core initialization of the control. Everything that needs to be set up happens here.
 */
void ScintillaCocoa::Initialise() 
{
  Scintilla_LinkLexers();
  
  // Tell Scintilla not to buffer: Quartz buffers drawing for us.
  WndProc(SCI_SETBUFFEREDDRAW, 0, 0);
  
  // We are working with Unicode exclusively.
  WndProc(SCI_SETCODEPAGE, SC_CP_UTF8, 0);

  // Add Mac specific key bindings.
  for (int i = 0; macMapDefault[i].key; i++) 
    kmap.AssignCmdKey(macMapDefault[i].key, macMapDefault[i].modifiers, macMapDefault[i].msg);
  
}

//--------------------------------------------------------------------------------------------------

/**
 * We need some clean up. Do it here.
 */
void ScintillaCocoa::Finalise()
{
  ObserverRemove();
  SetTicking(false);
  ScintillaBase::Finalise();
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::UpdateObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
  ScintillaCocoa* sci = reinterpret_cast<ScintillaCocoa*>(info);
  sci->IdleWork();
}

//--------------------------------------------------------------------------------------------------

/**
 * Add an observer to the run loop to perform styling as high-priority idle task.
 */

void ScintillaCocoa::ObserverAdd() {
  if (!observer) {
    CFRunLoopObserverContext context;
    context.version = 0;
    context.info = this;
    context.retain = NULL;
    context.release = NULL;
    context.copyDescription = NULL;

    CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
    observer = CFRunLoopObserverCreate(NULL, kCFRunLoopEntry | kCFRunLoopBeforeWaiting,
      true, 0, UpdateObserver, &context);
    CFRunLoopAddObserver(mainRunLoop, observer, kCFRunLoopCommonModes);
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Remove the run loop observer.
 */
void ScintillaCocoa::ObserverRemove() {
  if (observer) {
    CFRunLoopRef mainRunLoop = CFRunLoopGetMain();
    CFRunLoopRemoveObserver(mainRunLoop, observer, kCFRunLoopCommonModes);
    CFRelease(observer);
  }
  observer = NULL;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::IdleWork() {
  Editor::IdleWork();
  ObserverRemove();
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
  Editor::QueueIdleWork(items, upTo);
  ObserverAdd();
}

//--------------------------------------------------------------------------------------------------

/**
 * Convert a core foundation string into an array of bytes in a particular encoding
 */

static char *EncodedBytes(CFStringRef cfsRef, CFStringEncoding encoding) {
    CFRange rangeAll = {0, CFStringGetLength(cfsRef)};
    CFIndex usedLen = 0;
    CFStringGetBytes(cfsRef, rangeAll, encoding, '?',
                     false, NULL, 0, &usedLen);
    
    char *buffer = new char[usedLen+1];
    CFStringGetBytes(cfsRef, rangeAll, encoding, '?',
                     false, (UInt8 *)buffer,usedLen, NULL);
    buffer[usedLen] = '\0';
    return buffer;
}

//--------------------------------------------------------------------------------------------------

/**
 * Case folders.
 */

class CaseFolderUTF8 : public CaseFolderTable {
public:
	CaseFolderUTF8() {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
            CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
                                                         reinterpret_cast<const UInt8 *>(mixed), 
                                                         lenMixed, kCFStringEncodingUTF8, false);

            NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch
                                                            locale:[NSLocale currentLocale]];

            const char *cpMapped = [sMapped UTF8String];
			size_t lenMapped = cpMapped ? strlen(cpMapped) : 0;
			if (lenMapped < sizeFolded) {
				memcpy(folded, cpMapped,  lenMapped);
			} else {
				lenMapped = 0;
			}
			if (cfsVal)
				CFRelease(cfsVal);
			return lenMapped;
		}
	}
};

class CaseFolderDBCS : public CaseFolderTable {
	CFStringEncoding encoding;
public:
	CaseFolderDBCS(CFStringEncoding encoding_) : encoding(encoding_) {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
            CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
                                                         reinterpret_cast<const UInt8 *>(mixed), 
                                                         lenMixed, encoding, false);

            NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch
                                                                        locale:[NSLocale currentLocale]];
            
            char *encoded = EncodedBytes((CFStringRef)sMapped, encoding);

			size_t lenMapped = strlen(encoded);
            if (lenMapped < sizeFolded) {
                memcpy(folded, encoded,  lenMapped);
            } else {
                folded[0] = '\0';
                lenMapped = 1;
            }
            delete []encoded;
            CFRelease(cfsVal);
			return lenMapped;
		}
		// Something failed so return a single NUL byte
		folded[0] = '\0';
		return 1;
	}
};

CaseFolder *ScintillaCocoa::CaseFolderForEncoding() {
	if (pdoc->dbcsCodePage == SC_CP_UTF8) {
		return new CaseFolderUTF8();
	} else {
        CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
                                                             vs.styles[STYLE_DEFAULT].characterSet);
        if (pdoc->dbcsCodePage == 0) {
            CaseFolderTable *pcf = new CaseFolderTable();
            pcf->StandardASCII();
            // Only for single byte encodings
            for (int i=0x80; i<0x100; i++) {
                char sCharacter[2] = "A";
                sCharacter[0] = i;
                CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
                                                             reinterpret_cast<const UInt8 *>(sCharacter), 
                                                             1, encoding, false);
                
                NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch
                                                                            locale:[NSLocale currentLocale]];
                
                char *encoded = EncodedBytes((CFStringRef)sMapped, encoding);
                
                if (strlen(encoded) == 1) {
                    pcf->SetTranslation(sCharacter[0], encoded[0]);
                }
                
                delete []encoded;
                CFRelease(cfsVal);
            }
            return pcf;
        } else {
            return new CaseFolderDBCS(encoding);
        }
		return 0;
	}
}


//--------------------------------------------------------------------------------------------------

/**
 * Case-fold the given string depending on the specified case mapping type.
 */
std::string ScintillaCocoa::CaseMapString(const std::string &s, int caseMapping)
{
  CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
                                                       vs.styles[STYLE_DEFAULT].characterSet);
  CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
                                               reinterpret_cast<const UInt8 *>(s.c_str()), 
                                               s.length(), encoding, false);

  NSString *sMapped;
  switch (caseMapping)
  {
    case cmUpper:
      sMapped = [(NSString *)cfsVal uppercaseString];
      break;
    case cmLower:
      sMapped = [(NSString *)cfsVal lowercaseString];
      break;
    default:
      sMapped = (NSString *)cfsVal;
  }

  // Back to encoding
  char *encoded = EncodedBytes((CFStringRef)sMapped, encoding);
  std::string result(encoded);
  delete []encoded;
  CFRelease(cfsVal);
  return result;
}

//--------------------------------------------------------------------------------------------------

/**
 * Cancel all modes, both for base class and any find indicator.
 */
void ScintillaCocoa::CancelModes() {
  ScintillaBase::CancelModes();
  HideFindIndicator();
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper function to get the outer container which represents the Scintilla editor on application side.
 */
ScintillaView* ScintillaCocoa::TopContainer()
{
  NSView* container = static_cast<NSView*>(wMain.GetID());
  return static_cast<ScintillaView*>([[[container superview] superview] superview]);
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper function to get the scrolling view.
 */
NSScrollView* ScintillaCocoa::ScrollContainer() {
  NSView* container = static_cast<NSView*>(wMain.GetID());
  return static_cast<NSScrollView*>([[container superview] superview]);
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper function to get the inner container which represents the actual "canvas" we work with.
 */
InnerView* ScintillaCocoa::ContentView()
{
  return static_cast<InnerView*>(wMain.GetID());
}

//--------------------------------------------------------------------------------------------------

/**
 * Return the top left visible point relative to the origin point of the whole document.
 */
Scintilla::Point ScintillaCocoa::GetVisibleOriginInMain()
{
  NSScrollView *scrollView = ScrollContainer();
  NSRect contentRect = [[scrollView contentView] bounds];
  return Point(contentRect.origin.x, contentRect.origin.y);
}

//--------------------------------------------------------------------------------------------------

/**
 * Instead of returning the size of the inner view we have to return the visible part of it
 * in order to make scrolling working properly.
 * The returned value is in document coordinates.
 */
PRectangle ScintillaCocoa::GetClientRectangle()
{
  NSView* host = ContentView();
  NSSize size = [[host superview] frame].size;
  Point origin = GetVisibleOriginInMain();
  return PRectangle(origin.x, origin.y, origin.x+size.width, origin.y + size.height);
}

//--------------------------------------------------------------------------------------------------

/**
 * Converts the given point from base coordinates to local coordinates and at the same time into
 * a native Point structure. Base coordinates are used for the top window used in the view hierarchy.
 * Returned value is in view coordinates. 
 */
Scintilla::Point ScintillaCocoa::ConvertPoint(NSPoint point)
{
  NSView* container = ContentView();
  NSPoint result = [container convertPoint: point fromView: nil];
  Scintilla::Point ptOrigin = GetVisibleOriginInMain();
  return Point(result.x - ptOrigin.x, result.y - ptOrigin.y);
}

//--------------------------------------------------------------------------------------------------

/**
 * A function to directly execute code that would usually go the long way via window messages.
 * However this is a Windows metapher and not used here, hence we just call our fake
 * window proc. The given parameters directly reflect the message parameters used on Windows.
 *
 * @param sciThis The target which is to be called.
 * @param iMessage A code that indicates which message was sent.
 * @param wParam One of the two free parameters for the message. Traditionally a word sized parameter 
 *               (hence the w prefix).
 * @param lParam The other of the two free parameters. A signed long.
 */
sptr_t ScintillaCocoa::DirectFunction(ScintillaCocoa *sciThis, unsigned int iMessage, uptr_t wParam, 
                                      sptr_t lParam)
{
  return sciThis->WndProc(iMessage, wParam, lParam);
}

//--------------------------------------------------------------------------------------------------

/**
 * This method is very similar to DirectFunction. On Windows it sends a message (not in the Obj-C sense)
 * to the target window. Here we simply call our fake window proc.
 */
sptr_t scintilla_send_message(void* sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam)
{
  ScintillaView *control = reinterpret_cast<ScintillaView*>(sci);
  ScintillaCocoa* scintilla = [control backend];
  return scintilla->WndProc(iMessage, wParam, lParam);
}

//--------------------------------------------------------------------------------------------------

/**
 * That's our fake window procedure. On Windows each window has a dedicated procedure to handle
 * commands (also used to synchronize UI and background threads), which is not the case in Cocoa.
 *
 * Messages handled here are almost solely for special commands of the backend. Everything which
 * would be sytem messages on Windows (e.g. for key down, mouse move etc.) are handled by
 * directly calling appropriate handlers.
 */
sptr_t ScintillaCocoa::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam)
{
  switch (iMessage)
  {
    case SCI_GETDIRECTFUNCTION:
      return reinterpret_cast<sptr_t>(DirectFunction);
      
    case SCI_GETDIRECTPOINTER:
      return reinterpret_cast<sptr_t>(this);
      
    case SCI_GRABFOCUS:
      [[ContentView() window] makeFirstResponder:ContentView()];
      break;
      
    case SCI_SETBUFFEREDDRAW:
      // Buffered drawing not supported on Cocoa
      bufferedDraw = false;
      break;
      
    case SCI_FINDINDICATORSHOW:
      ShowFindIndicatorForRange(NSMakeRange(wParam, lParam-wParam), YES);
      return 0;
      
    case SCI_FINDINDICATORFLASH:
      ShowFindIndicatorForRange(NSMakeRange(wParam, lParam-wParam), NO);
      return 0;
      
    case SCI_FINDINDICATORHIDE:
      HideFindIndicator();
      return 0;
      
    case WM_UNICHAR:
      // Special case not used normally. Characters passed in this way will be inserted
      // regardless of their value or modifier states. That means no command interpretation is
      // performed.
      if (IsUnicodeMode())
      {
        NSString* input = [NSString stringWithCharacters: (const unichar*) &wParam length: 1];
        const char* utf8 = [input UTF8String];
        AddCharUTF((char*) utf8, static_cast<unsigned int>(strlen(utf8)), false);
        return 1;
      }
      return 0;
      
    default:
      sptr_t r = ScintillaBase::WndProc(iMessage, wParam, lParam);
      
      return r;
  }
  return 0l;
}

//--------------------------------------------------------------------------------------------------

/**
 * In Windows lingo this is the handler which handles anything that wasn't handled in the normal 
 * window proc which would usually send the message back to generic window proc that Windows uses.
 */
sptr_t ScintillaCocoa::DefWndProc(unsigned int, uptr_t, sptr_t)
{
  return 0;
}

//--------------------------------------------------------------------------------------------------

/**
 * Enables or disables a timer that can trigger background processing at a regular interval, like
 * drag scrolling or caret blinking.
 */
void ScintillaCocoa::SetTicking(bool on)
{
  if (timer.ticking != on)
  {
    timer.ticking = on;
    if (timer.ticking)
    {
      // Scintilla ticks = milliseconds
      tickTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0
						   target: timerTarget
						 selector: @selector(timerFired:)
						 userInfo: nil
						  repeats: YES];
      timer.tickerID = reinterpret_cast<TickerID>(tickTimer);
    }
    else
      if (timer.tickerID != NULL)
      {
        [reinterpret_cast<NSTimer*>(timer.tickerID) invalidate];
        timer.tickerID = 0;
      }
  }
  timer.ticksToWait = caret.period;
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::SetIdle(bool on)
{
  if (idler.state != on)
  {
    idler.state = on;
    if (idler.state)
    {
      // Scintilla ticks = milliseconds
      idleTimer = [NSTimer scheduledTimerWithTimeInterval: timer.tickSize / 1000.0
						   target: timerTarget
						 selector: @selector(idleTimerFired:)
						 userInfo: nil
						  repeats: YES];
      idler.idlerID = reinterpret_cast<IdlerID>(idleTimer);
    }
    else
      if (idler.idlerID != NULL)
      {
        [reinterpret_cast<NSTimer*>(idler.idlerID) invalidate];
        idler.idlerID = 0;
      }
  }
  return true;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::CopyToClipboard(const SelectionText &selectedText)
{
  SetPasteboardData([NSPasteboard generalPasteboard], selectedText);
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::Copy()
{
  if (!sel.Empty())
  {
    SelectionText selectedText;
    CopySelectionRange(&selectedText);
    CopyToClipboard(selectedText);
  }
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::CanPaste()
{
  if (!Editor::CanPaste())
    return false;
  
  return GetPasteboardData([NSPasteboard generalPasteboard], NULL);
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::Paste()
{
  Paste(false);
}

//--------------------------------------------------------------------------------------------------

/**
 * Pastes data from the paste board into the editor.
 */
void ScintillaCocoa::Paste(bool forceRectangular)
{
  SelectionText selectedText;
  bool ok = GetPasteboardData([NSPasteboard generalPasteboard], &selectedText);
  if (forceRectangular)
    selectedText.rectangular = forceRectangular;
  
  if (!ok || !selectedText.s)
    // No data or no flavor we support.
    return;
  
  pdoc->BeginUndoAction();
  ClearSelection(false);
  int length = selectedText.len - 1; // One less to avoid inserting the terminating 0 character.
  if (selectedText.rectangular)
  {
    SelectionPosition selStart = sel.RangeMain().Start();
    PasteRectangular(selStart, selectedText.s, length);
  }
  else 
    if (pdoc->InsertString(sel.RangeMain().caret.Position(), selectedText.s, length))
      SetEmptySelection(sel.RangeMain().caret.Position() + length);
  
  pdoc->EndUndoAction();
  
  Redraw();
  EnsureCaretVisible();
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::CTPaint(void* gc, NSRect rc) {
#pragma unused(rc)
    Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
    if (surfaceWindow) {
        surfaceWindow->Init(gc, wMain.GetID());
        surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ct.codePage);
        surfaceWindow->SetDBCSMode(ct.codePage);
        ct.PaintCT(surfaceWindow);
        surfaceWindow->Release();
        delete surfaceWindow;
    }
}

@interface CallTipView : NSControl {
    ScintillaCocoa *sci;
}

@end

@implementation CallTipView

- (NSView*) initWithFrame: (NSRect) frame {
	self = [super initWithFrame: frame];

	if (self) {
        sci = NULL;
	}
	
	return self;
}

- (void) dealloc {
	[super dealloc];
}

- (BOOL) isFlipped {
	return YES;
}

- (void) setSci: (ScintillaCocoa *) sci_ {
    sci = sci_;
}

- (void) drawRect: (NSRect) needsDisplayInRect {
    if (sci) {
        CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
        sci->CTPaint(context, needsDisplayInRect);
    }
}

- (void) mouseDown: (NSEvent *) event {
    if (sci) {
        sci->CallTipMouseDown([event locationInWindow]);
    }
}

// On OS X, only the key view should modify the cursor so the calltip can't.
// This view does not become key so resetCursorRects never called.
- (void) resetCursorRects {
    //[super resetCursorRects];
    //[self addCursorRect: [self bounds] cursor: [NSCursor arrowCursor]];
}

@end

void ScintillaCocoa::CallTipMouseDown(NSPoint pt) {
    NSRect rectBounds = [(NSView *)(ct.wDraw.GetID()) bounds];
    Point location(pt.x, rectBounds.size.height - pt.y);
    ct.MouseClick(location);
    CallTipClick();
}

void ScintillaCocoa::CreateCallTipWindow(PRectangle rc) {
    if (!ct.wCallTip.Created()) {
        NSRect ctRect = NSMakeRect(rc.top,rc.bottom, rc.Width(), rc.Height());
        NSWindow *callTip = [[NSWindow alloc] initWithContentRect: ctRect 
                                                        styleMask: NSBorderlessWindowMask
                                                          backing: NSBackingStoreBuffered
                                                            defer: NO];
        [callTip setLevel:NSFloatingWindowLevel];
        [callTip setHasShadow:YES];
        NSRect ctContent = NSMakeRect(0,0, rc.Width(), rc.Height());
        CallTipView *caption = [[CallTipView alloc] initWithFrame: ctContent];
        [caption setAutoresizingMask: NSViewWidthSizable | NSViewMaxYMargin];
        [caption setSci: this];
        [[callTip contentView] addSubview: caption];
        [callTip orderFront:caption];
        ct.wCallTip = callTip;
        ct.wDraw = caption;
    }
}

void ScintillaCocoa::AddToPopUp(const char *label, int cmd, bool enabled)
{
  NSMenuItem* item;
  ScintillaContextMenu *menu= reinterpret_cast<ScintillaContextMenu*>(popup.GetID());
  [menu setOwner: this];
  [menu setAutoenablesItems: NO];
  
  if (cmd == 0) {
    item = [NSMenuItem separatorItem];
  } else {
    item = [[[NSMenuItem alloc] init] autorelease];
    [item setTitle: [NSString stringWithUTF8String: label]];
  }
  [item setTarget: menu];
  [item setAction: @selector(handleCommand:)];
  [item setTag: cmd];
  [item setEnabled: enabled];
  
  [menu addItem: item];
}

// -------------------------------------------------------------------------------------------------

void ScintillaCocoa::ClaimSelection()
{
  // Mac OS X does not have a primary selection.
}

// -------------------------------------------------------------------------------------------------

/**
 * Returns the current caret position (which is tracked as an offset into the entire text string)
 * as a row:column pair. The result is zero-based.
 */
NSPoint ScintillaCocoa::GetCaretPosition()
{
  NSPoint result;

  result.y = pdoc->LineFromPosition(sel.RangeMain().caret.Position());
  result.x = sel.RangeMain().caret.Position() - pdoc->LineStart(result.y);
  return result;
}

// -------------------------------------------------------------------------------------------------

#pragma mark Drag

/**
 * Triggered by the tick timer on a regular basis to scroll the content during a drag operation.
 */
void ScintillaCocoa::DragScroll()
{
  if (!posDrag.IsValid())
  {
    scrollSpeed = 1;
    scrollTicks = 2000;
    return;
  }

  // TODO: does not work for wrapped lines, fix it.
  int line = pdoc->LineFromPosition(posDrag.Position());
  int currentVisibleLine = cs.DisplayFromDoc(line);
  int lastVisibleLine = Platform::Minimum(topLine + LinesOnScreen(), cs.LinesDisplayed()) - 2;
    
  if (currentVisibleLine <= topLine && topLine > 0)
    ScrollTo(topLine - scrollSpeed);
  else
    if (currentVisibleLine >= lastVisibleLine)
      ScrollTo(topLine + scrollSpeed);
    else
    {
      scrollSpeed = 1;
      scrollTicks = 2000;
      return;
    }
  
  // TODO: also handle horizontal scrolling.
  
  if (scrollSpeed == 1)
  {
    scrollTicks -= timer.tickSize;
    if (scrollTicks <= 0)
    {
      scrollSpeed = 5;
      scrollTicks = 2000;
    }
  }
  
}

//--------------------------------------------------------------------------------------------------

/**
 * Called when a drag operation was initiated from within Scintilla.
 */
void ScintillaCocoa::StartDrag()
{
  if (sel.Empty())
    return;

  // Put the data to be dragged on the drag pasteboard.
  SelectionText selectedText;
  NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName: NSDragPboard];
  CopySelectionRange(&selectedText);
  SetPasteboardData(pasteboard, selectedText);
  
  // calculate the bounds of the selection
  PRectangle client = GetTextRectangle();
  int selStart = sel.RangeMain().Start().Position();
  int selEnd = sel.RangeMain().End().Position();
  int startLine = pdoc->LineFromPosition(selStart);
  int endLine = pdoc->LineFromPosition(selEnd);
  Point pt;
  long startPos, endPos, ep;
  Rect rcSel;
  
  if (startLine==endLine && WndProc(SCI_GETWRAPMODE, 0, 0) != SC_WRAP_NONE) {
    // Komodo bug http://bugs.activestate.com/show_bug.cgi?id=87571
    // Scintilla bug https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3040200&group_id=2439
    // If the width on a wrapped-line selection is negative,
    // find a better bounding rectangle.
    
    Point ptStart, ptEnd;
    startPos = WndProc(SCI_GETLINESELSTARTPOSITION, startLine, 0);
    endPos =   WndProc(SCI_GETLINESELENDPOSITION,   startLine, 0);
    // step back a position if we're counting the newline
    ep =       WndProc(SCI_GETLINEENDPOSITION,      startLine, 0);
    if (endPos > ep) endPos = ep;
    ptStart = LocationFromPosition(static_cast<int>(startPos));
    ptEnd =   LocationFromPosition(static_cast<int>(endPos));
    if (ptStart.y == ptEnd.y) {
      // We're just selecting part of one visible line
      rcSel.left = ptStart.x;
      rcSel.right = ptEnd.x < client.right ? ptEnd.x : client.right;
    } else {
      // Find the bounding box.
      startPos = WndProc(SCI_POSITIONFROMLINE, startLine, 0);
      rcSel.left = LocationFromPosition(static_cast<int>(startPos)).x;
      rcSel.right = client.right;
    }
    rcSel.top = ptStart.y;
    rcSel.bottom = ptEnd.y + vs.lineHeight;
    if (rcSel.bottom > client.bottom) {
      rcSel.bottom = client.bottom;
    }
  } else {
    rcSel.top = rcSel.bottom = rcSel.right = rcSel.left = -1;
    for (int l = startLine; l <= endLine; l++) {
      startPos = WndProc(SCI_GETLINESELSTARTPOSITION, l, 0);
      endPos = WndProc(SCI_GETLINESELENDPOSITION, l, 0);
      if (endPos == startPos) continue;
      // step back a position if we're counting the newline
      ep = WndProc(SCI_GETLINEENDPOSITION, l, 0);
      if (endPos > ep) endPos = ep;
      pt = LocationFromPosition(static_cast<int>(startPos)); // top left of line selection
      if (pt.x < rcSel.left || rcSel.left < 0) rcSel.left = pt.x;
      if (pt.y < rcSel.top || rcSel.top < 0) rcSel.top = pt.y;
      pt = LocationFromPosition(static_cast<int>(endPos)); // top right of line selection
      pt.y += vs.lineHeight; // get to the bottom of the line
      if (pt.x > rcSel.right || rcSel.right < 0) {
        if (pt.x > client.right)
          rcSel.right = client.right;
        else
          rcSel.right = pt.x;
      }
      if (pt.y > rcSel.bottom || rcSel.bottom < 0) {
        if (pt.y > client.bottom)
          rcSel.bottom = client.bottom;
        else
          rcSel.bottom = pt.y;
      }
    }
  }
  // must convert to global coordinates for drag regions, but also save the
  // image rectangle for further calculations and copy operations
  PRectangle localRectangle = PRectangle(rcSel.left, rcSel.top, rcSel.right, rcSel.bottom);
    
  // Prepare drag image.
  NSRect selectionRectangle = PRectangleToNSRect(localRectangle);
  
  NSView* content = ContentView();
    
#if 1

  // To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface.
  SurfaceImpl *sw = new SurfaceImpl();
  SurfaceImpl *pixmap = NULL;
  
  bool lastHideSelection = hideSelection;
  hideSelection = true;
  if (sw)
  {
    pixmap = new SurfaceImpl();
    if (pixmap)
    {
      PRectangle imageRect = NSRectToPRectangle(selectionRectangle);
      paintState = painting;
      sw->InitPixMap(client.Width(), client.Height(), NULL, NULL);
      paintingAllText = true;
      // Have to create a new context and make current as text drawing goes 
      // to the current context, not a passed context.
      CGContextRef gcsw = sw->GetContext(); 
      NSGraphicsContext *nsgc = [NSGraphicsContext graphicsContextWithGraphicsPort: gcsw 
                                                                           flipped: YES];
      [NSGraphicsContext setCurrentContext:nsgc];
      Paint(sw, client);
      paintState = notPainting;
      
      pixmap->InitPixMap(imageRect.Width(), imageRect.Height(), NULL, NULL);
      
      CGContextRef gc = pixmap->GetContext(); 
      // To make Paint() work on a bitmap, we have to flip our coordinates and translate the origin
      CGContextTranslateCTM(gc, 0, imageRect.Height());
      CGContextScaleCTM(gc, 1.0, -1.0);
      
      pixmap->CopyImageRectangle(*sw, imageRect, PRectangle(0, 0, imageRect.Width(), imageRect.Height()));
      // XXX TODO: overwrite any part of the image that is not part of the
      //           selection to make it transparent.  right now we just use
      //           the full rectangle which may include non-selected text.
    }
    sw->Release();
    delete sw;
  }
  hideSelection = lastHideSelection;
  
  NSBitmapImageRep* bitmap = NULL;
  if (pixmap)
  {
    CGImageRef imagePixmap = pixmap->GetImage();
    bitmap = [[[NSBitmapImageRep alloc] initWithCGImage: imagePixmap] autorelease];
    CGImageRelease(imagePixmap);
    pixmap->Release();
    delete pixmap;
  }
#else
  
  // Poor man's drag image: take a snapshot of the content view.
  [content lockFocus];
  NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: selectionRectangle] autorelease];
  [bitmap setColorSpaceName: NSDeviceRGBColorSpace];
  [content unlockFocus];
  
#endif
  
  NSImage* image = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease];
  [image addRepresentation: bitmap];
  
  NSImage* dragImage = [[[NSImage alloc] initWithSize: selectionRectangle.size] autorelease];
  [dragImage setBackgroundColor: [NSColor clearColor]];
  [dragImage lockFocus];
  [image dissolveToPoint: NSMakePoint(0.0, 0.0) fraction: 0.5];
  [dragImage unlockFocus];
  
  NSPoint startPoint;
  startPoint.x = selectionRectangle.origin.x;
  startPoint.y = selectionRectangle.origin.y + selectionRectangle.size.height;
  [content dragImage: dragImage 
                  at: startPoint
              offset: NSZeroSize
               event: lastMouseEvent // Set in MouseMove.
          pasteboard: pasteboard
              source: content
           slideBack: YES];
}

//--------------------------------------------------------------------------------------------------

/**
 * Called when a drag operation reaches the control which was initiated outside.
 */
NSDragOperation ScintillaCocoa::DraggingEntered(id <NSDraggingInfo> info)
{
  inDragDrop = ddDragging;
  return DraggingUpdated(info);
}

//--------------------------------------------------------------------------------------------------

/**
 * Called frequently during a drag operation if we are the target. Keep telling the caller
 * what drag operation we accept and update the drop caret position to indicate the
 * potential insertion point of the dragged data.
 */
NSDragOperation ScintillaCocoa::DraggingUpdated(id <NSDraggingInfo> info)
{
  // Convert the drag location from window coordinates to view coordinates and 
  // from there to a text position to finally set the drag position.
  Point location = ConvertPoint([info draggingLocation]);
  SetDragPosition(SPositionFromLocation(location));
  
  NSDragOperation sourceDragMask = [info draggingSourceOperationMask];
  if (sourceDragMask == NSDragOperationNone)
    return sourceDragMask;
  
  NSPasteboard* pasteboard = [info draggingPasteboard];
  
  // Return what type of operation we will perform. Prefer move over copy.
  if ([[pasteboard types] containsObject: NSStringPboardType] ||
      [[pasteboard types] containsObject: ScintillaRecPboardType])
    return (sourceDragMask & NSDragOperationMove) ? NSDragOperationMove : NSDragOperationCopy;
  
  if ([[pasteboard types] containsObject: NSFilenamesPboardType])
    return (sourceDragMask & NSDragOperationGeneric);
  return NSDragOperationNone;
}

//--------------------------------------------------------------------------------------------------

/**
 * Resets the current drag position as we are no longer the drag target.
 */
void ScintillaCocoa::DraggingExited(id <NSDraggingInfo> info)
{
#pragma unused(info)
  SetDragPosition(SelectionPosition(invalidPosition));
  inDragDrop = ddNone;
}

//--------------------------------------------------------------------------------------------------

/**
 * Here is where the real work is done. Insert the text from the pasteboard.
 */
bool ScintillaCocoa::PerformDragOperation(id <NSDraggingInfo> info)
{
  NSPasteboard* pasteboard = [info draggingPasteboard];
  
  if ([[pasteboard types] containsObject: NSFilenamesPboardType])
  {
    NSArray* files = [pasteboard propertyListForType: NSFilenamesPboardType];
    for (NSString* uri in files)
      NotifyURIDropped([uri UTF8String]);
  }
  else
  {
    SelectionText text;
    GetPasteboardData(pasteboard, &text);
    
    if (text.len > 0)
    {
      NSDragOperation operation = [info draggingSourceOperationMask];
      bool moving = (operation & NSDragOperationMove) != 0;
      
      DropAt(posDrag, text.s, moving, text.rectangular);
    };
  }

  return true;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::SetPasteboardData(NSPasteboard* board, const SelectionText &selectedText)
{
  if (selectedText.len == 0)
    return;

  CFStringEncoding encoding = EncodingFromCharacterSet(selectedText.codePage == SC_CP_UTF8,
                                                       selectedText.characterSet);
  CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
                                               reinterpret_cast<const UInt8 *>(selectedText.s), 
                                               selectedText.len-1, encoding, false);

  NSArray *pbTypes = selectedText.rectangular ?
    [NSArray arrayWithObjects: NSStringPboardType, ScintillaRecPboardType, nil] :
    [NSArray arrayWithObjects: NSStringPboardType, nil];
  [board declareTypes:pbTypes owner:nil];
  
  if (selectedText.rectangular)
  {
    // This is specific to scintilla, allows us to drag rectangular selections around the document.
    [board setString: (NSString *)cfsVal forType: ScintillaRecPboardType];
  }
  
  [board setString: (NSString *)cfsVal forType: NSStringPboardType];

  if (cfsVal)
    CFRelease(cfsVal);
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper method to retrieve the best fitting alternative from the general pasteboard.
 */
bool ScintillaCocoa::GetPasteboardData(NSPasteboard* board, SelectionText* selectedText)
{
  NSArray* supportedTypes = [NSArray arrayWithObjects: ScintillaRecPboardType, 
                             NSStringPboardType, 
                             nil];
  NSString *bestType = [board availableTypeFromArray: supportedTypes];
  NSString* data = [board stringForType: bestType];
  
  if (data != nil)
  {
    if (selectedText != nil)
    {
      CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
                                                           vs.styles[STYLE_DEFAULT].characterSet);
      CFRange rangeAll = {0, static_cast<CFIndex>([data length])};
      CFIndex usedLen = 0;
      CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?',
                       false, NULL, 0, &usedLen);

      UInt8 *buffer = new UInt8[usedLen];
    
      CFStringGetBytes((CFStringRef)data, rangeAll, encoding, '?',
                       false, buffer,usedLen, NULL);

      bool rectangular = bestType == ScintillaRecPboardType;

      int len = static_cast<int>(usedLen);
      char *dest = Document::TransformLineEnds(&len, (char *)buffer, len, pdoc->eolMode);

      selectedText->Set(dest, len+1, pdoc->dbcsCodePage, 
                         vs.styles[STYLE_DEFAULT].characterSet , rectangular, false);
      delete []buffer;
    }
    return true;
  }
  
  return false;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::SetMouseCapture(bool on)
{
  capturedMouse = on;
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::HaveMouseCapture()
{
  return capturedMouse;
}

//--------------------------------------------------------------------------------------------------

/**
 * Synchronously paint a rectangle of the window.
 */
bool ScintillaCocoa::SyncPaint(void* gc, PRectangle rc)
{
  paintState = painting;
  rcPaint = rc;
  PRectangle rcText = GetTextRectangle();
  paintingAllText = rcPaint.Contains(rcText);
  bool succeeded = true;
  Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
  if (sw)
  {
    sw->Init(gc, wMain.GetID());
    Paint(sw, rc);
    succeeded = paintState != paintAbandoned;
    sw->Release();
    delete sw;
  }
  paintState = notPainting;
  if (!succeeded)
  {
    NSView *marginView = static_cast<NSView*>(wMargin.GetID());
    [marginView setNeedsDisplay:YES];
  }
  return succeeded;
}

//--------------------------------------------------------------------------------------------------

/**
 * Paint the margin into the MarginView space.
 */
void ScintillaCocoa::PaintMargin(NSRect aRect)
{
  CGContextRef gc = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];

  PRectangle rc = NSRectToPRectangle(aRect);
  rcPaint = rc;
  Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
  if (sw)
  {
    sw->Init(gc, wMargin.GetID());
    PaintSelMargin(sw, rc);
    sw->Release();
    delete sw;
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * ScrollText is empty because scrolling is handled by the NSScrollView.
 */
void ScintillaCocoa::ScrollText(int linesToMove)
{
}

//--------------------------------------------------------------------------------------------------

/**
 * Modifies the vertical scroll position to make the current top line show up as such.
 */
void ScintillaCocoa::SetVerticalScrollPos()
{
  NSScrollView *scrollView = ScrollContainer();
  if (scrollView) {
    NSClipView *clipView = [scrollView contentView];
    NSRect contentRect = [clipView bounds];
    [clipView scrollToPoint: NSMakePoint(contentRect.origin.x, topLine * vs.lineHeight)];
    [scrollView reflectScrolledClipView:clipView];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Modifies the horizontal scroll position to match xOffset.
 */
void ScintillaCocoa::SetHorizontalScrollPos()
{
  PRectangle textRect = GetTextRectangle();

  int maxXOffset = scrollWidth - textRect.Width();
  if (maxXOffset < 0)
    maxXOffset = 0;
  if (xOffset > maxXOffset)
    xOffset = maxXOffset;
  NSScrollView *scrollView = ScrollContainer();
  if (scrollView) {
    NSClipView * clipView = [scrollView contentView];
    NSRect contentRect = [clipView bounds];
    [clipView scrollToPoint: NSMakePoint(xOffset, contentRect.origin.y)];
    [scrollView reflectScrolledClipView:clipView];
  }
  MoveFindIndicatorWithBounce(NO);
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to adjust both scrollers to reflect the current scroll range and position in the editor.
 * Arguments no longer used as NSScrollView handles details of scroll bar sizes.
 *
 * @param nMax Number of lines in the editor.
 * @param nPage Number of lines per scroll page.
 * @return True if there was a change, otherwise false.
 */
bool ScintillaCocoa::ModifyScrollBars(int nMax, int nPage)
{
#pragma unused(nMax, nPage)
  return SetScrollingSize();
}

bool ScintillaCocoa::SetScrollingSize(void) {
	bool changes = false;
	InnerView *inner = ContentView();
	if (!enteredSetScrollingSize) {
		enteredSetScrollingSize = true;
		NSScrollView *scrollView = ScrollContainer();
		NSClipView *clipView = [ScrollContainer() contentView];
		NSRect clipRect = [clipView bounds];
		int docHeight = (cs.LinesDisplayed()+1) * vs.lineHeight;
		if (!endAtLastLine)
			docHeight += (int([scrollView bounds].size.height / vs.lineHeight)-3) * vs.lineHeight;
		// Allow extra space so that last scroll position places whole line at top
		int clipExtra = int(clipRect.size.height) % vs.lineHeight;
		docHeight += clipExtra;
		// Ensure all of clipRect covered by Scintilla drawing
		if (docHeight < clipRect.size.height)
			docHeight = clipRect.size.height;
		int docWidth = scrollWidth;
		bool showHorizontalScroll = horizontalScrollBarVisible &&
			(wrapState == eWrapNone);
		if (!showHorizontalScroll)
			docWidth = clipRect.size.width;
		NSRect contentRect = {0, 0, docWidth, docHeight};
		NSRect contentRectNow = [inner frame];
		changes = (contentRect.size.width != contentRectNow.size.width) ||
			(contentRect.size.height != contentRectNow.size.height);
		if (changes) {
			[inner setFrame: contentRect];
		}
		[scrollView setHasVerticalScroller: verticalScrollBarVisible];
		[scrollView setHasHorizontalScroller: showHorizontalScroll];
		SetVerticalScrollPos();
		enteredSetScrollingSize = false;
	}
	[inner.owner setMarginWidth: vs.fixedColumnWidth];
	return changes;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::Resize()
{
  SetScrollingSize();
  ChangeSize();
}

//--------------------------------------------------------------------------------------------------

/**
 * Update fields to match scroll position after receiving a notification that the user has scrolled.
 */
void ScintillaCocoa::UpdateForScroll() {
  Point ptOrigin = GetVisibleOriginInMain();
  xOffset = ptOrigin.x;
  int newTop = Platform::Minimum(ptOrigin.y / vs.lineHeight, MaxScrollPos());
  SetTopLine(newTop);
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to register a callback function for a given window. This is used to emulate the way
 * Windows notfies other controls (mainly up in the view hierarchy) about certain events.
 *
 * @param windowid A handle to a window. That value is generic and can be anything. It is passed
 *                 through to the callback.
 * @param callback The callback function to be used for future notifications. If NULL then no
 *                 notifications will be sent anymore.
 */
void ScintillaCocoa::RegisterNotifyCallback(intptr_t windowid, SciNotifyFunc callback)
{
  notifyObj = windowid;
  notifyProc = callback;
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::NotifyChange()
{
  if (notifyProc != NULL)
    notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE),
	       (uintptr_t) this);
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::NotifyFocus(bool focus)
{
  if (notifyProc != NULL)
    notifyProc(notifyObj, WM_COMMAND, Platform::LongFromTwoShorts(GetCtrlID(), (focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS)),
	       (uintptr_t) this);
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to send a notification (as WM_NOTIFY call) to the procedure, which has been set by the call
 * to RegisterNotifyCallback (so it is not necessarily the parent window).
 *
 * @param scn The notification to send.
 */
void ScintillaCocoa::NotifyParent(SCNotification scn)
{ 
  if (notifyProc != NULL)
  {
    scn.nmhdr.hwndFrom = (void*) this;
    scn.nmhdr.idFrom = GetCtrlID();
    notifyProc(notifyObj, WM_NOTIFY, (uintptr_t) 0, (uintptr_t) &scn);
  }
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::NotifyURIDropped(const char *uri)
{
  SCNotification scn;
  scn.nmhdr.code = SCN_URIDROPPED;
  scn.text = uri;
  
  NotifyParent(scn);
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::HasSelection()
{
  return !sel.Empty();
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::CanUndo()
{
  return pdoc->CanUndo();
}

//--------------------------------------------------------------------------------------------------

bool ScintillaCocoa::CanRedo()
{
  return pdoc->CanRedo();
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::TimerFired(NSTimer* timer)
{
#pragma unused(timer)
  Tick();
  DragScroll();
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::IdleTimerFired()
{
  bool more = Idle();
  if (!more)
    SetIdle(false);
}

//--------------------------------------------------------------------------------------------------

/**
 * Main entry point for drawing the control.
 *
 * @param rect The area to paint, given in the sender's coordinate system.
 * @param gc The context we can use to paint.
 */
bool ScintillaCocoa::Draw(NSRect rect, CGContextRef gc)
{
  return SyncPaint(gc, NSRectToPRectangle(rect));
}

//--------------------------------------------------------------------------------------------------
    
/**
 * Helper function to translate OS X key codes to Scintilla key codes.
 */
static inline UniChar KeyTranslate(UniChar unicodeChar)
{
  switch (unicodeChar)
  {
    case NSDownArrowFunctionKey:
      return SCK_DOWN;
    case NSUpArrowFunctionKey:
      return SCK_UP;
    case NSLeftArrowFunctionKey:
      return SCK_LEFT;
    case NSRightArrowFunctionKey:
      return SCK_RIGHT;
    case NSHomeFunctionKey:
      return SCK_HOME;
    case NSEndFunctionKey:
      return SCK_END;
    case NSPageUpFunctionKey:
      return SCK_PRIOR;
    case NSPageDownFunctionKey:
      return SCK_NEXT;
    case NSDeleteFunctionKey:
      return SCK_DELETE;
    case NSInsertFunctionKey:
      return SCK_INSERT;
    case '\n':
    case 3:
      return SCK_RETURN;
    case 27:
      return SCK_ESCAPE;
    case 127:
      return SCK_BACK;
    case '\t':
    case 25: // Shift tab, return to unmodified tab and handle that via modifiers.
      return SCK_TAB;
    default:
      return unicodeChar;
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Main keyboard input handling method. It is called for any key down event, including function keys,
 * numeric keypad input and whatnot. 
 *
 * @param event The event instance associated with the key down event.
 * @return True if the input was handled, false otherwise.
 */
bool ScintillaCocoa::KeyboardInput(NSEvent* event)
{
  // For now filter out function keys.
  NSUInteger modifiers = [event modifierFlags];
  
  NSString* input = [event characters];
  
  bool control = (modifiers & NSControlKeyMask) != 0;
  bool shift = (modifiers & NSShiftKeyMask) != 0;
  bool command = (modifiers & NSCommandKeyMask) != 0;
  bool alt = (modifiers & NSAlternateKeyMask) != 0;
  
  bool handled = false;
  
  // Handle each entry individually. Usually we only have one entry anway.
  for (size_t i = 0; i < input.length; i++)
  {
    const UniChar originalKey = [input characterAtIndex: i];
    UniChar key = KeyTranslate(originalKey);
    
    bool consumed = false; // Consumed as command?
    
    // Signal Control as SCMOD_META
    int modifierKeys = 
	  (shift ? SCI_SHIFT : 0) | 
	  (command ? SCI_CTRL : 0) |
	  (alt ? SCI_ALT : 0) |
	  (control ? SCI_META : 0);
    if (KeyDownWithModifiers(key, modifierKeys, &consumed))
      handled = true;
    if (consumed)
      handled = true;
  }
  
  return handled;
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to insert already processed text provided by the Cocoa text input system.
 */
int ScintillaCocoa::InsertText(NSString* input)
{
  CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
                                                         vs.styles[STYLE_DEFAULT].characterSet);
  CFRange rangeAll = {0, static_cast<CFIndex>([input length])};
  CFIndex usedLen = 0;
  CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?',
                   false, NULL, 0, &usedLen);
    
  UInt8 *buffer = new UInt8[usedLen];
    
  CFStringGetBytes((CFStringRef)input, rangeAll, encoding, '?',
                     false, buffer,usedLen, NULL);
    
  AddCharUTF((char*) buffer, static_cast<unsigned int>(usedLen), false);
  delete []buffer;
  return static_cast<int>(usedLen);
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by the owning view when the mouse pointer enters the control.
 */
void ScintillaCocoa::MouseEntered(NSEvent* event)
{
  if (!HaveMouseCapture())
  {
    WndProc(SCI_SETCURSOR, (long int)SC_CURSORNORMAL, 0);
    
    // Mouse location is given in screen coordinates and might also be outside of our bounds.
    Point location = ConvertPoint([event locationInWindow]);
    ButtonMove(location);
  }
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::MouseExited(NSEvent* /* event */)
{
  // Nothing to do here.
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::MouseDown(NSEvent* event)
{
  Point location = ConvertPoint([event locationInWindow]);
  NSTimeInterval time = [event timestamp];
  bool command = ([event modifierFlags] & NSCommandKeyMask) != 0;
  bool shift = ([event modifierFlags] & NSShiftKeyMask) != 0;
  bool alt = ([event modifierFlags] & NSAlternateKeyMask) != 0;
    
  ButtonDown(Point(location.x, location.y), (int) (time * 1000), shift, command, alt);
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::MouseMove(NSEvent* event)
{
  lastMouseEvent = event;

  ButtonMove(ConvertPoint([event locationInWindow]));
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::MouseUp(NSEvent* event)
{
  NSTimeInterval time = [event timestamp];
  bool control = ([event modifierFlags] & NSControlKeyMask) != 0;

  ButtonUp(ConvertPoint([event locationInWindow]), (int) (time * 1000), control);
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::MouseWheel(NSEvent* event)
{
  bool command = ([event modifierFlags] & NSCommandKeyMask) != 0;
  int dY = 0;

    // In order to make scrolling with larger offset smoother we scroll less lines the larger the 
    // delta value is.
    if ([event deltaY] < 0)
    dY = -(int) sqrt(-10.0 * [event deltaY]);
    else
    dY = (int) sqrt(10.0 * [event deltaY]);
  
  if (command)
  {
    // Zoom! We play with the font sizes in the styles.
    // Number of steps/line is ignored, we just care if sizing up or down.
    if (dY > 0.5)
      KeyCommand(SCI_ZOOMIN);
    else if (dY < -0.5)
      KeyCommand(SCI_ZOOMOUT);
  }
  else
  {
  }
}

//--------------------------------------------------------------------------------------------------

// Helper methods for NSResponder actions.

void ScintillaCocoa::SelectAll()
{
  Editor::SelectAll();
}

void ScintillaCocoa::DeleteBackward()
{
  KeyDown(SCK_BACK, false, false, false, nil);
}

void ScintillaCocoa::Cut()
{
  Editor::Cut();
}

void ScintillaCocoa::Undo()
{
  Editor::Undo();
}

void ScintillaCocoa::Redo()
{
  Editor::Redo();
}

//--------------------------------------------------------------------------------------------------

/**
 * Creates and returns a popup menu, which is then displayed by the Cocoa framework.
 */
NSMenu* ScintillaCocoa::CreateContextMenu(NSEvent* /* event */)
{
  // Call ScintillaBase to create the context menu.
  ContextMenu(Point(0, 0));
  
  return reinterpret_cast<NSMenu*>(popup.GetID());
}

//--------------------------------------------------------------------------------------------------

/**
 * An intermediate function to forward context menu commands from the menu action handler to
 * scintilla.
 */
void ScintillaCocoa::HandleCommand(NSInteger command)
{
  Command(static_cast<int>(command));
}

//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::ActiveStateChanged(bool isActive)
{
  // If the window is being deactivated, lose the focus and turn off the ticking
  if (!isActive) {
    DropCaret();
    //SetFocusState( false );
    SetTicking( false );
  } else {
    ShowCaretAtCurrentPosition();
  }
}


//--------------------------------------------------------------------------------------------------

void ScintillaCocoa::ShowFindIndicatorForRange(NSRange charRange, BOOL retaining)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
  NSView *content = ContentView();
  if (!layerFindIndicator)
  {
    layerFindIndicator = [[FindHighlightLayer alloc] init];
    [content setWantsLayer: YES];
    layerFindIndicator.geometryFlipped = content.layer.geometryFlipped;
    [[content layer] addSublayer:layerFindIndicator];
  }
  [layerFindIndicator removeAnimationForKey:@"animateFound"];
  
  if (charRange.length)
  {
    CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
							 vs.styles[STYLE_DEFAULT].characterSet);
    std::vector<char> buffer(charRange.length);
    pdoc->GetCharRange(&buffer[0], charRange.location, charRange.length);
    
    CFStringRef cfsFind = CFStringCreateWithBytes(kCFAllocatorDefault,
						  reinterpret_cast<const UInt8 *>(&buffer[0]), 
						  charRange.length, encoding, false);
    layerFindIndicator.sFind = (NSString *)cfsFind;
    if (cfsFind)
        CFRelease(cfsFind);
    layerFindIndicator.retaining = retaining;
    layerFindIndicator.positionFind = charRange.location;
    int style = WndProc(SCI_GETSTYLEAT, charRange.location, 0);
    std::vector<char> bufferFontName(WndProc(SCI_STYLEGETFONT, style, 0) + 1);
    WndProc(SCI_STYLEGETFONT, style, (sptr_t)&bufferFontName[0]);
    layerFindIndicator.sFont = [NSString stringWithUTF8String: &bufferFontName[0]];
    
    layerFindIndicator.fontSize = WndProc(SCI_STYLEGETSIZEFRACTIONAL, style, 0) / 
      (float)SC_FONT_SIZE_MULTIPLIER;
    layerFindIndicator.widthText = WndProc(SCI_POINTXFROMPOSITION, 0, charRange.location + charRange.length) -
      WndProc(SCI_POINTXFROMPOSITION, 0, charRange.location);
    layerFindIndicator.heightLine = WndProc(SCI_TEXTHEIGHT, 0, 0);
    MoveFindIndicatorWithBounce(YES);
  }
  else
  {
    [layerFindIndicator hideMatch];
  }
#endif
}

void ScintillaCocoa::MoveFindIndicatorWithBounce(BOOL bounce)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
  if (layerFindIndicator)
  {
    CGPoint ptText = CGPointMake(
      WndProc(SCI_POINTXFROMPOSITION, 0, layerFindIndicator.positionFind),
      WndProc(SCI_POINTYFROMPOSITION, 0, layerFindIndicator.positionFind));
    ptText.x = ptText.x - vs.fixedColumnWidth + xOffset;
    ptText.y += topLine * vs.lineHeight;
    if (!layerFindIndicator.geometryFlipped)
    {
      NSView *content = ContentView();
      ptText.y = content.bounds.size.height - ptText.y;
    }
    [layerFindIndicator animateMatch:ptText bounce:bounce];
  }
#endif
}

void ScintillaCocoa::HideFindIndicator()
{
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
  if (layerFindIndicator)
  {
    [layerFindIndicator hideMatch];
  }
#endif
}


Added cocoa/ScintillaFramework/English.lproj/InfoPlist.strings.





>
>
1
2
/* Localized versions of Info.plist keys */

Added cocoa/ScintillaFramework/Info.plist.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>com.sun.${PRODUCT_NAME:identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
	<key>NSPrincipalClass</key>
	<string></string>
</dict>
</plist>

Added cocoa/ScintillaFramework/ScintillaFramework.xcodeproj/project.pbxproj.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		1102C31C169FB49300DC16AB /* LexLaTeX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 1102C31B169FB49300DC16AB /* LexLaTeX.cxx */; };
		11126B8214CD3A6200803C49 /* LexAVS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11126B8114CD3A6200803C49 /* LexAVS.cxx */; };
		1114D6CB1602A951001DC345 /* LexPO.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 1114D6CA1602A951001DC345 /* LexPO.cxx */; };
		114B6F0D11FA7526004FB6AB /* LexAbaqus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EBE11FA7526004FB6AB /* LexAbaqus.cxx */; };
		114B6F0E11FA7526004FB6AB /* LexAda.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EBF11FA7526004FB6AB /* LexAda.cxx */; };
		114B6F0F11FA7526004FB6AB /* LexAPDL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC011FA7526004FB6AB /* LexAPDL.cxx */; };
		114B6F1011FA7526004FB6AB /* LexAsm.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC111FA7526004FB6AB /* LexAsm.cxx */; };
		114B6F1111FA7526004FB6AB /* LexAsn1.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC211FA7526004FB6AB /* LexAsn1.cxx */; };
		114B6F1211FA7526004FB6AB /* LexASY.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC311FA7526004FB6AB /* LexASY.cxx */; };
		114B6F1311FA7526004FB6AB /* LexAU3.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC411FA7526004FB6AB /* LexAU3.cxx */; };
		114B6F1411FA7526004FB6AB /* LexAVE.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC511FA7526004FB6AB /* LexAVE.cxx */; };
		114B6F1511FA7526004FB6AB /* LexBaan.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC611FA7526004FB6AB /* LexBaan.cxx */; };
		114B6F1611FA7526004FB6AB /* LexBash.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC711FA7526004FB6AB /* LexBash.cxx */; };
		114B6F1711FA7526004FB6AB /* LexBasic.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC811FA7526004FB6AB /* LexBasic.cxx */; };
		114B6F1811FA7526004FB6AB /* LexBullant.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EC911FA7526004FB6AB /* LexBullant.cxx */; };
		114B6F1911FA7526004FB6AB /* LexCaml.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECA11FA7526004FB6AB /* LexCaml.cxx */; };
		114B6F1A11FA7526004FB6AB /* LexCLW.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECB11FA7526004FB6AB /* LexCLW.cxx */; };
		114B6F1B11FA7526004FB6AB /* LexCmake.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECC11FA7526004FB6AB /* LexCmake.cxx */; };
		114B6F1C11FA7526004FB6AB /* LexCOBOL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECD11FA7526004FB6AB /* LexCOBOL.cxx */; };
		114B6F1D11FA7526004FB6AB /* LexConf.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECE11FA7526004FB6AB /* LexConf.cxx */; };
		114B6F1E11FA7526004FB6AB /* LexCPP.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ECF11FA7526004FB6AB /* LexCPP.cxx */; };
		114B6F1F11FA7526004FB6AB /* LexCrontab.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED011FA7526004FB6AB /* LexCrontab.cxx */; };
		114B6F2011FA7526004FB6AB /* LexCsound.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED111FA7526004FB6AB /* LexCsound.cxx */; };
		114B6F2111FA7526004FB6AB /* LexCSS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED211FA7526004FB6AB /* LexCSS.cxx */; };
		114B6F2211FA7526004FB6AB /* LexD.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED311FA7526004FB6AB /* LexD.cxx */; };
		114B6F2311FA7526004FB6AB /* LexEiffel.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED411FA7526004FB6AB /* LexEiffel.cxx */; };
		114B6F2411FA7526004FB6AB /* LexErlang.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED511FA7526004FB6AB /* LexErlang.cxx */; };
		114B6F2511FA7526004FB6AB /* LexEScript.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED611FA7526004FB6AB /* LexEScript.cxx */; };
		114B6F2611FA7526004FB6AB /* LexFlagship.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED711FA7526004FB6AB /* LexFlagship.cxx */; };
		114B6F2711FA7526004FB6AB /* LexForth.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED811FA7526004FB6AB /* LexForth.cxx */; };
		114B6F2811FA7526004FB6AB /* LexFortran.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6ED911FA7526004FB6AB /* LexFortran.cxx */; };
		114B6F2911FA7526004FB6AB /* LexGAP.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDA11FA7526004FB6AB /* LexGAP.cxx */; };
		114B6F2A11FA7526004FB6AB /* LexGui4Cli.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDB11FA7526004FB6AB /* LexGui4Cli.cxx */; };
		114B6F2B11FA7526004FB6AB /* LexHaskell.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDC11FA7526004FB6AB /* LexHaskell.cxx */; };
		114B6F2C11FA7526004FB6AB /* LexHTML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDD11FA7526004FB6AB /* LexHTML.cxx */; };
		114B6F2D11FA7526004FB6AB /* LexInno.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDE11FA7526004FB6AB /* LexInno.cxx */; };
		114B6F2E11FA7526004FB6AB /* LexKix.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EDF11FA7526004FB6AB /* LexKix.cxx */; };
		114B6F2F11FA7526004FB6AB /* LexLisp.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE011FA7526004FB6AB /* LexLisp.cxx */; };
		114B6F3011FA7526004FB6AB /* LexLout.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE111FA7526004FB6AB /* LexLout.cxx */; };
		114B6F3111FA7526004FB6AB /* LexLua.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE211FA7526004FB6AB /* LexLua.cxx */; };
		114B6F3211FA7526004FB6AB /* LexMagik.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE311FA7526004FB6AB /* LexMagik.cxx */; };
		114B6F3311FA7526004FB6AB /* LexMarkdown.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE411FA7526004FB6AB /* LexMarkdown.cxx */; };
		114B6F3411FA7526004FB6AB /* LexMatlab.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE511FA7526004FB6AB /* LexMatlab.cxx */; };
		114B6F3511FA7526004FB6AB /* LexMetapost.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE611FA7526004FB6AB /* LexMetapost.cxx */; };
		114B6F3611FA7526004FB6AB /* LexMMIXAL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE711FA7526004FB6AB /* LexMMIXAL.cxx */; };
		114B6F3711FA7526004FB6AB /* LexMPT.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE811FA7526004FB6AB /* LexMPT.cxx */; };
		114B6F3811FA7526004FB6AB /* LexMSSQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EE911FA7526004FB6AB /* LexMSSQL.cxx */; };
		114B6F3911FA7526004FB6AB /* LexMySQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EEA11FA7526004FB6AB /* LexMySQL.cxx */; };
		114B6F3A11FA7526004FB6AB /* LexNimrod.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EEB11FA7526004FB6AB /* LexNimrod.cxx */; };
		114B6F3B11FA7526004FB6AB /* LexNsis.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EEC11FA7526004FB6AB /* LexNsis.cxx */; };
		114B6F3C11FA7526004FB6AB /* LexOpal.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EED11FA7526004FB6AB /* LexOpal.cxx */; };
		114B6F3D11FA7526004FB6AB /* LexOthers.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EEE11FA7526004FB6AB /* LexOthers.cxx */; };
		114B6F3E11FA7526004FB6AB /* LexPascal.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EEF11FA7526004FB6AB /* LexPascal.cxx */; };
		114B6F3F11FA7526004FB6AB /* LexPB.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF011FA7526004FB6AB /* LexPB.cxx */; };
		114B6F4011FA7526004FB6AB /* LexPerl.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF111FA7526004FB6AB /* LexPerl.cxx */; };
		114B6F4111FA7526004FB6AB /* LexPLM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF211FA7526004FB6AB /* LexPLM.cxx */; };
		114B6F4211FA7526004FB6AB /* LexPOV.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF311FA7526004FB6AB /* LexPOV.cxx */; };
		114B6F4311FA7526004FB6AB /* LexPowerPro.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF411FA7526004FB6AB /* LexPowerPro.cxx */; };
		114B6F4411FA7526004FB6AB /* LexPowerShell.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF511FA7526004FB6AB /* LexPowerShell.cxx */; };
		114B6F4511FA7526004FB6AB /* LexProgress.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF611FA7526004FB6AB /* LexProgress.cxx */; };
		114B6F4611FA7526004FB6AB /* LexPS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF711FA7526004FB6AB /* LexPS.cxx */; };
		114B6F4711FA7526004FB6AB /* LexPython.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF811FA7526004FB6AB /* LexPython.cxx */; };
		114B6F4811FA7526004FB6AB /* LexR.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EF911FA7526004FB6AB /* LexR.cxx */; };
		114B6F4911FA7526004FB6AB /* LexRebol.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFA11FA7526004FB6AB /* LexRebol.cxx */; };
		114B6F4A11FA7526004FB6AB /* LexRuby.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFB11FA7526004FB6AB /* LexRuby.cxx */; };
		114B6F4B11FA7526004FB6AB /* LexScriptol.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFC11FA7526004FB6AB /* LexScriptol.cxx */; };
		114B6F4C11FA7526004FB6AB /* LexSmalltalk.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFD11FA7526004FB6AB /* LexSmalltalk.cxx */; };
		114B6F4D11FA7526004FB6AB /* LexSML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFE11FA7526004FB6AB /* LexSML.cxx */; };
		114B6F4E11FA7526004FB6AB /* LexSorcus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6EFF11FA7526004FB6AB /* LexSorcus.cxx */; };
		114B6F4F11FA7526004FB6AB /* LexSpecman.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0011FA7526004FB6AB /* LexSpecman.cxx */; };
		114B6F5011FA7526004FB6AB /* LexSpice.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0111FA7526004FB6AB /* LexSpice.cxx */; };
		114B6F5111FA7526004FB6AB /* LexSQL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0211FA7526004FB6AB /* LexSQL.cxx */; };
		114B6F5211FA7526004FB6AB /* LexTACL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0311FA7526004FB6AB /* LexTACL.cxx */; };
		114B6F5311FA7526004FB6AB /* LexTADS3.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0411FA7526004FB6AB /* LexTADS3.cxx */; };
		114B6F5411FA7526004FB6AB /* LexTAL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0511FA7526004FB6AB /* LexTAL.cxx */; };
		114B6F5511FA7526004FB6AB /* LexTCL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0611FA7526004FB6AB /* LexTCL.cxx */; };
		114B6F5611FA7526004FB6AB /* LexTeX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0711FA7526004FB6AB /* LexTeX.cxx */; };
		114B6F5711FA7526004FB6AB /* LexTxt2tags.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0811FA7526004FB6AB /* LexTxt2tags.cxx */; };
		114B6F5811FA7526004FB6AB /* LexVB.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0911FA7526004FB6AB /* LexVB.cxx */; };
		114B6F5911FA7526004FB6AB /* LexVerilog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0A11FA7526004FB6AB /* LexVerilog.cxx */; };
		114B6F5A11FA7526004FB6AB /* LexVHDL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0B11FA7526004FB6AB /* LexVHDL.cxx */; };
		114B6F5B11FA7526004FB6AB /* LexYAML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F0C11FA7526004FB6AB /* LexYAML.cxx */; };
		114B6F7711FA7598004FB6AB /* AutoComplete.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6011FA7597004FB6AB /* AutoComplete.cxx */; };
		114B6F7811FA7598004FB6AB /* CallTip.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6111FA7597004FB6AB /* CallTip.cxx */; };
		114B6F7911FA7598004FB6AB /* Catalogue.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6211FA7597004FB6AB /* Catalogue.cxx */; };
		114B6F7A11FA7598004FB6AB /* CellBuffer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6311FA7597004FB6AB /* CellBuffer.cxx */; };
		114B6F7B11FA7598004FB6AB /* CharClassify.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6411FA7597004FB6AB /* CharClassify.cxx */; };
		114B6F7C11FA7598004FB6AB /* ContractionState.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6511FA7597004FB6AB /* ContractionState.cxx */; };
		114B6F7D11FA7598004FB6AB /* Decoration.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6611FA7597004FB6AB /* Decoration.cxx */; };
		114B6F7E11FA7598004FB6AB /* Document.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6711FA7597004FB6AB /* Document.cxx */; };
		114B6F7F11FA7598004FB6AB /* Editor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6811FA7597004FB6AB /* Editor.cxx */; };
		114B6F8011FA7598004FB6AB /* ExternalLexer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6911FA7598004FB6AB /* ExternalLexer.cxx */; };
		114B6F8111FA7598004FB6AB /* Indicator.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6A11FA7598004FB6AB /* Indicator.cxx */; };
		114B6F8211FA7598004FB6AB /* KeyMap.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6B11FA7598004FB6AB /* KeyMap.cxx */; };
		114B6F8311FA7598004FB6AB /* LineMarker.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6C11FA7598004FB6AB /* LineMarker.cxx */; };
		114B6F8411FA7598004FB6AB /* PerLine.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6D11FA7598004FB6AB /* PerLine.cxx */; };
		114B6F8511FA7598004FB6AB /* PositionCache.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6E11FA7598004FB6AB /* PositionCache.cxx */; };
		114B6F8611FA7598004FB6AB /* RESearch.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F6F11FA7598004FB6AB /* RESearch.cxx */; };
		114B6F8711FA7598004FB6AB /* RunStyles.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7011FA7598004FB6AB /* RunStyles.cxx */; };
		114B6F8811FA7598004FB6AB /* ScintillaBase.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7111FA7598004FB6AB /* ScintillaBase.cxx */; };
		114B6F8911FA7598004FB6AB /* Selection.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7211FA7598004FB6AB /* Selection.cxx */; };
		114B6F8A11FA7598004FB6AB /* Style.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7311FA7598004FB6AB /* Style.cxx */; };
		114B6F8B11FA7598004FB6AB /* UniConversion.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7411FA7598004FB6AB /* UniConversion.cxx */; };
		114B6F8C11FA7598004FB6AB /* ViewStyle.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7511FA7598004FB6AB /* ViewStyle.cxx */; };
		114B6F8D11FA7598004FB6AB /* XPM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F7611FA7598004FB6AB /* XPM.cxx */; };
		114B6F9711FA75BE004FB6AB /* Accessor.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F8E11FA75BE004FB6AB /* Accessor.cxx */; };
		114B6F9811FA75BE004FB6AB /* CharacterSet.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F8F11FA75BE004FB6AB /* CharacterSet.cxx */; };
		114B6F9911FA75BE004FB6AB /* LexerBase.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9011FA75BE004FB6AB /* LexerBase.cxx */; };
		114B6F9A11FA75BE004FB6AB /* LexerModule.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9111FA75BE004FB6AB /* LexerModule.cxx */; };
		114B6F9B11FA75BE004FB6AB /* LexerNoExceptions.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9211FA75BE004FB6AB /* LexerNoExceptions.cxx */; };
		114B6F9C11FA75BE004FB6AB /* LexerSimple.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9311FA75BE004FB6AB /* LexerSimple.cxx */; };
		114B6F9D11FA75BE004FB6AB /* PropSetSimple.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9411FA75BE004FB6AB /* PropSetSimple.cxx */; };
		114B6F9E11FA75BE004FB6AB /* StyleContext.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9511FA75BE004FB6AB /* StyleContext.cxx */; };
		114B6F9F11FA75BE004FB6AB /* WordList.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 114B6F9611FA75BE004FB6AB /* WordList.cxx */; };
		114B6FA111FA75DB004FB6AB /* ILexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA011FA75DB004FB6AB /* ILexer.h */; };
		114B6FBD11FA7623004FB6AB /* AutoComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA211FA7623004FB6AB /* AutoComplete.h */; };
		114B6FBE11FA7623004FB6AB /* CallTip.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA311FA7623004FB6AB /* CallTip.h */; };
		114B6FBF11FA7623004FB6AB /* Catalogue.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA411FA7623004FB6AB /* Catalogue.h */; };
		114B6FC011FA7623004FB6AB /* CellBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA511FA7623004FB6AB /* CellBuffer.h */; };
		114B6FC111FA7623004FB6AB /* CharClassify.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA611FA7623004FB6AB /* CharClassify.h */; };
		114B6FC211FA7623004FB6AB /* ContractionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA711FA7623004FB6AB /* ContractionState.h */; };
		114B6FC311FA7623004FB6AB /* Decoration.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA811FA7623004FB6AB /* Decoration.h */; };
		114B6FC411FA7623004FB6AB /* Document.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FA911FA7623004FB6AB /* Document.h */; };
		114B6FC511FA7623004FB6AB /* Editor.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAA11FA7623004FB6AB /* Editor.h */; };
		114B6FC611FA7623004FB6AB /* ExternalLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAB11FA7623004FB6AB /* ExternalLexer.h */; };
		114B6FC711FA7623004FB6AB /* FontQuality.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAC11FA7623004FB6AB /* FontQuality.h */; };
		114B6FC811FA7623004FB6AB /* Indicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAD11FA7623004FB6AB /* Indicator.h */; };
		114B6FC911FA7623004FB6AB /* KeyMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAE11FA7623004FB6AB /* KeyMap.h */; };
		114B6FCA11FA7623004FB6AB /* LineMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FAF11FA7623004FB6AB /* LineMarker.h */; };
		114B6FCB11FA7623004FB6AB /* Partitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB011FA7623004FB6AB /* Partitioning.h */; };
		114B6FCC11FA7623004FB6AB /* PerLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB111FA7623004FB6AB /* PerLine.h */; };
		114B6FCD11FA7623004FB6AB /* PositionCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB211FA7623004FB6AB /* PositionCache.h */; };
		114B6FCE11FA7623004FB6AB /* RESearch.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB311FA7623004FB6AB /* RESearch.h */; };
		114B6FCF11FA7623004FB6AB /* RunStyles.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB411FA7623004FB6AB /* RunStyles.h */; };
		114B6FD011FA7623004FB6AB /* ScintillaBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB511FA7623004FB6AB /* ScintillaBase.h */; };
		114B6FD111FA7623004FB6AB /* Selection.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB611FA7623004FB6AB /* Selection.h */; };
		114B6FD211FA7623004FB6AB /* SplitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB711FA7623004FB6AB /* SplitVector.h */; };
		114B6FD311FA7623004FB6AB /* Style.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB811FA7623004FB6AB /* Style.h */; };
		114B6FD411FA7623004FB6AB /* SVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FB911FA7623004FB6AB /* SVector.h */; };
		114B6FD511FA7623004FB6AB /* UniConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FBA11FA7623004FB6AB /* UniConversion.h */; };
		114B6FD611FA7623004FB6AB /* ViewStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FBB11FA7623004FB6AB /* ViewStyle.h */; };
		114B6FD711FA7623004FB6AB /* XPM.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FBC11FA7623004FB6AB /* XPM.h */; };
		114B6FE311FA7645004FB6AB /* Accessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FD811FA7645004FB6AB /* Accessor.h */; };
		114B6FE411FA7645004FB6AB /* CharacterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FD911FA7645004FB6AB /* CharacterSet.h */; };
		114B6FE511FA7645004FB6AB /* LexAccessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDA11FA7645004FB6AB /* LexAccessor.h */; };
		114B6FE611FA7645004FB6AB /* LexerBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDB11FA7645004FB6AB /* LexerBase.h */; };
		114B6FE711FA7645004FB6AB /* LexerModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDC11FA7645004FB6AB /* LexerModule.h */; };
		114B6FE811FA7645004FB6AB /* LexerNoExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDD11FA7645004FB6AB /* LexerNoExceptions.h */; };
		114B6FE911FA7645004FB6AB /* LexerSimple.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDE11FA7645004FB6AB /* LexerSimple.h */; };
		114B6FEA11FA7645004FB6AB /* OptionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FDF11FA7645004FB6AB /* OptionSet.h */; };
		114B6FEB11FA7645004FB6AB /* PropSetSimple.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FE011FA7645004FB6AB /* PropSetSimple.h */; };
		114B6FEC11FA7645004FB6AB /* StyleContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FE111FA7645004FB6AB /* StyleContext.h */; };
		114B6FED11FA7645004FB6AB /* WordList.h in Headers */ = {isa = PBXBuildFile; fileRef = 114B6FE211FA7645004FB6AB /* WordList.h */; };
		1152A77315313E58000D4E1A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1152A77215313E58000D4E1A /* QuartzCore.framework */; };
		11594BE9155B91DF0099E1FA /* LexOScript.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11594BE7155B91DF0099E1FA /* LexOScript.cxx */; };
		11594BEA155B91DF0099E1FA /* LexVisualProlog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11594BE8155B91DF0099E1FA /* LexVisualProlog.cxx */; };
		117ACE9114A29A1E002876F9 /* LexTCMD.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 117ACE9014A29A1E002876F9 /* LexTCMD.cxx */; };
		119FF1BF13C9D1820007CE42 /* QuartzTextStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 119FF1BE13C9D1820007CE42 /* QuartzTextStyle.h */; };
		11A0A8A1148602DF0018D143 /* LexCoffeeScript.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11A0A8A0148602DF0018D143 /* LexCoffeeScript.cxx */; };
		11BB124D12FF9C1300F6BCF7 /* LexModula.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11BB124C12FF9C1300F6BCF7 /* LexModula.cxx */; };
		11BEB6A214EF189600BDE92A /* LexECL.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11BEB6A114EF189600BDE92A /* LexECL.cxx */; };
		11F35FDB12AEFAF100F0236D /* LexA68k.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 11F35FDA12AEFAF100F0236D /* LexA68k.cxx */; };
		2744E5A40FC168A100E85C33 /* InfoBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59D0FC168A100E85C33 /* InfoBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2744E5AA0FC168A100E85C33 /* ScintillaView.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A30FC168A100E85C33 /* ScintillaView.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2744E5AC0FC168B200E85C33 /* InfoBarCommunicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2744E5B20FC168C500E85C33 /* InfoBar.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5AD0FC168C500E85C33 /* InfoBar.mm */; };
		2744E5B30FC168C500E85C33 /* PlatCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */; };
		2744E5B50FC168C500E85C33 /* ScintillaCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */; };
		2744E5B60FC168C500E85C33 /* ScintillaView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744E5B10FC168C500E85C33 /* ScintillaView.mm */; };
		2791F3C60FC19F71009DBCF9 /* PlatCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59E0FC168A100E85C33 /* PlatCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3C70FC19F71009DBCF9 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4850FC1678600E85C33 /* Platform.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3C80FC19F71009DBCF9 /* SciLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4870FC1678600E85C33 /* SciLexer.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3C90FC19F71009DBCF9 /* Scintilla.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E4880FC1678600E85C33 /* Scintilla.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3E00FC1A390009DBCF9 /* ScintillaCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3E30FC1A3AE009DBCF9 /* QuartzTextLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
		2791F3E40FC1A3AE009DBCF9 /* QuartzTextStyleAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; };
		27FEF4540FC1B413005E115A /* info_bar_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4510FC1B413005E115A /* info_bar_bg.png */; };
		27FEF4550FC1B413005E115A /* mac_cursor_busy.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4520FC1B413005E115A /* mac_cursor_busy.png */; };
		27FEF4560FC1B413005E115A /* mac_cursor_flipped.png in Resources */ = {isa = PBXBuildFile; fileRef = 27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */; };
		8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
		0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
		089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
		1102C31B169FB49300DC16AB /* LexLaTeX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLaTeX.cxx; path = ../../lexers/LexLaTeX.cxx; sourceTree = "<group>"; };
		11126B8114CD3A6200803C49 /* LexAVS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAVS.cxx; path = ../../lexers/LexAVS.cxx; sourceTree = "<group>"; };
		1114D6CA1602A951001DC345 /* LexPO.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPO.cxx; path = ../../lexers/LexPO.cxx; sourceTree = "<group>"; };
		114B6EBE11FA7526004FB6AB /* LexAbaqus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAbaqus.cxx; path = ../../lexers/LexAbaqus.cxx; sourceTree = SOURCE_ROOT; };
		114B6EBF11FA7526004FB6AB /* LexAda.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAda.cxx; path = ../../lexers/LexAda.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC011FA7526004FB6AB /* LexAPDL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAPDL.cxx; path = ../../lexers/LexAPDL.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC111FA7526004FB6AB /* LexAsm.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAsm.cxx; path = ../../lexers/LexAsm.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC211FA7526004FB6AB /* LexAsn1.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAsn1.cxx; path = ../../lexers/LexAsn1.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC311FA7526004FB6AB /* LexASY.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexASY.cxx; path = ../../lexers/LexASY.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC411FA7526004FB6AB /* LexAU3.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAU3.cxx; path = ../../lexers/LexAU3.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC511FA7526004FB6AB /* LexAVE.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexAVE.cxx; path = ../../lexers/LexAVE.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC611FA7526004FB6AB /* LexBaan.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBaan.cxx; path = ../../lexers/LexBaan.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC711FA7526004FB6AB /* LexBash.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBash.cxx; path = ../../lexers/LexBash.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC811FA7526004FB6AB /* LexBasic.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBasic.cxx; path = ../../lexers/LexBasic.cxx; sourceTree = SOURCE_ROOT; };
		114B6EC911FA7526004FB6AB /* LexBullant.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexBullant.cxx; path = ../../lexers/LexBullant.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECA11FA7526004FB6AB /* LexCaml.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCaml.cxx; path = ../../lexers/LexCaml.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECB11FA7526004FB6AB /* LexCLW.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCLW.cxx; path = ../../lexers/LexCLW.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECC11FA7526004FB6AB /* LexCmake.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCmake.cxx; path = ../../lexers/LexCmake.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECD11FA7526004FB6AB /* LexCOBOL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCOBOL.cxx; path = ../../lexers/LexCOBOL.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECE11FA7526004FB6AB /* LexConf.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexConf.cxx; path = ../../lexers/LexConf.cxx; sourceTree = SOURCE_ROOT; };
		114B6ECF11FA7526004FB6AB /* LexCPP.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCPP.cxx; path = ../../lexers/LexCPP.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED011FA7526004FB6AB /* LexCrontab.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCrontab.cxx; path = ../../lexers/LexCrontab.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED111FA7526004FB6AB /* LexCsound.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCsound.cxx; path = ../../lexers/LexCsound.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED211FA7526004FB6AB /* LexCSS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCSS.cxx; path = ../../lexers/LexCSS.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED311FA7526004FB6AB /* LexD.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexD.cxx; path = ../../lexers/LexD.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED411FA7526004FB6AB /* LexEiffel.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexEiffel.cxx; path = ../../lexers/LexEiffel.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED511FA7526004FB6AB /* LexErlang.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexErlang.cxx; path = ../../lexers/LexErlang.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED611FA7526004FB6AB /* LexEScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexEScript.cxx; path = ../../lexers/LexEScript.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED711FA7526004FB6AB /* LexFlagship.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexFlagship.cxx; path = ../../lexers/LexFlagship.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED811FA7526004FB6AB /* LexForth.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexForth.cxx; path = ../../lexers/LexForth.cxx; sourceTree = SOURCE_ROOT; };
		114B6ED911FA7526004FB6AB /* LexFortran.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexFortran.cxx; path = ../../lexers/LexFortran.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDA11FA7526004FB6AB /* LexGAP.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexGAP.cxx; path = ../../lexers/LexGAP.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDB11FA7526004FB6AB /* LexGui4Cli.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexGui4Cli.cxx; path = ../../lexers/LexGui4Cli.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDC11FA7526004FB6AB /* LexHaskell.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexHaskell.cxx; path = ../../lexers/LexHaskell.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDD11FA7526004FB6AB /* LexHTML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexHTML.cxx; path = ../../lexers/LexHTML.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDE11FA7526004FB6AB /* LexInno.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexInno.cxx; path = ../../lexers/LexInno.cxx; sourceTree = SOURCE_ROOT; };
		114B6EDF11FA7526004FB6AB /* LexKix.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexKix.cxx; path = ../../lexers/LexKix.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE011FA7526004FB6AB /* LexLisp.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLisp.cxx; path = ../../lexers/LexLisp.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE111FA7526004FB6AB /* LexLout.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLout.cxx; path = ../../lexers/LexLout.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE211FA7526004FB6AB /* LexLua.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexLua.cxx; path = ../../lexers/LexLua.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE311FA7526004FB6AB /* LexMagik.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMagik.cxx; path = ../../lexers/LexMagik.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE411FA7526004FB6AB /* LexMarkdown.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMarkdown.cxx; path = ../../lexers/LexMarkdown.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE511FA7526004FB6AB /* LexMatlab.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMatlab.cxx; path = ../../lexers/LexMatlab.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE611FA7526004FB6AB /* LexMetapost.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMetapost.cxx; path = ../../lexers/LexMetapost.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE711FA7526004FB6AB /* LexMMIXAL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMMIXAL.cxx; path = ../../lexers/LexMMIXAL.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE811FA7526004FB6AB /* LexMPT.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMPT.cxx; path = ../../lexers/LexMPT.cxx; sourceTree = SOURCE_ROOT; };
		114B6EE911FA7526004FB6AB /* LexMSSQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMSSQL.cxx; path = ../../lexers/LexMSSQL.cxx; sourceTree = SOURCE_ROOT; };
		114B6EEA11FA7526004FB6AB /* LexMySQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexMySQL.cxx; path = ../../lexers/LexMySQL.cxx; sourceTree = SOURCE_ROOT; };
		114B6EEB11FA7526004FB6AB /* LexNimrod.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNimrod.cxx; path = ../../lexers/LexNimrod.cxx; sourceTree = SOURCE_ROOT; };
		114B6EEC11FA7526004FB6AB /* LexNsis.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexNsis.cxx; path = ../../lexers/LexNsis.cxx; sourceTree = SOURCE_ROOT; };
		114B6EED11FA7526004FB6AB /* LexOpal.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexOpal.cxx; path = ../../lexers/LexOpal.cxx; sourceTree = SOURCE_ROOT; };
		114B6EEE11FA7526004FB6AB /* LexOthers.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexOthers.cxx; path = ../../lexers/LexOthers.cxx; sourceTree = SOURCE_ROOT; };
		114B6EEF11FA7526004FB6AB /* LexPascal.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPascal.cxx; path = ../../lexers/LexPascal.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF011FA7526004FB6AB /* LexPB.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPB.cxx; path = ../../lexers/LexPB.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF111FA7526004FB6AB /* LexPerl.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPerl.cxx; path = ../../lexers/LexPerl.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF211FA7526004FB6AB /* LexPLM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPLM.cxx; path = ../../lexers/LexPLM.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF311FA7526004FB6AB /* LexPOV.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPOV.cxx; path = ../../lexers/LexPOV.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF411FA7526004FB6AB /* LexPowerPro.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPowerPro.cxx; path = ../../lexers/LexPowerPro.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF511FA7526004FB6AB /* LexPowerShell.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPowerShell.cxx; path = ../../lexers/LexPowerShell.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF611FA7526004FB6AB /* LexProgress.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexProgress.cxx; path = ../../lexers/LexProgress.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF711FA7526004FB6AB /* LexPS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPS.cxx; path = ../../lexers/LexPS.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF811FA7526004FB6AB /* LexPython.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexPython.cxx; path = ../../lexers/LexPython.cxx; sourceTree = SOURCE_ROOT; };
		114B6EF911FA7526004FB6AB /* LexR.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexR.cxx; path = ../../lexers/LexR.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFA11FA7526004FB6AB /* LexRebol.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexRebol.cxx; path = ../../lexers/LexRebol.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFB11FA7526004FB6AB /* LexRuby.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexRuby.cxx; path = ../../lexers/LexRuby.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFC11FA7526004FB6AB /* LexScriptol.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexScriptol.cxx; path = ../../lexers/LexScriptol.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFD11FA7526004FB6AB /* LexSmalltalk.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSmalltalk.cxx; path = ../../lexers/LexSmalltalk.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFE11FA7526004FB6AB /* LexSML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSML.cxx; path = ../../lexers/LexSML.cxx; sourceTree = SOURCE_ROOT; };
		114B6EFF11FA7526004FB6AB /* LexSorcus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSorcus.cxx; path = ../../lexers/LexSorcus.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0011FA7526004FB6AB /* LexSpecman.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSpecman.cxx; path = ../../lexers/LexSpecman.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0111FA7526004FB6AB /* LexSpice.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSpice.cxx; path = ../../lexers/LexSpice.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0211FA7526004FB6AB /* LexSQL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexSQL.cxx; path = ../../lexers/LexSQL.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0311FA7526004FB6AB /* LexTACL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTACL.cxx; path = ../../lexers/LexTACL.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0411FA7526004FB6AB /* LexTADS3.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTADS3.cxx; path = ../../lexers/LexTADS3.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0511FA7526004FB6AB /* LexTAL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTAL.cxx; path = ../../lexers/LexTAL.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0611FA7526004FB6AB /* LexTCL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTCL.cxx; path = ../../lexers/LexTCL.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0711FA7526004FB6AB /* LexTeX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTeX.cxx; path = ../../lexers/LexTeX.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0811FA7526004FB6AB /* LexTxt2tags.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTxt2tags.cxx; path = ../../lexers/LexTxt2tags.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0911FA7526004FB6AB /* LexVB.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVB.cxx; path = ../../lexers/LexVB.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0A11FA7526004FB6AB /* LexVerilog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVerilog.cxx; path = ../../lexers/LexVerilog.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0B11FA7526004FB6AB /* LexVHDL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVHDL.cxx; path = ../../lexers/LexVHDL.cxx; sourceTree = SOURCE_ROOT; };
		114B6F0C11FA7526004FB6AB /* LexYAML.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexYAML.cxx; path = ../../lexers/LexYAML.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6011FA7597004FB6AB /* AutoComplete.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AutoComplete.cxx; path = ../../src/AutoComplete.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6111FA7597004FB6AB /* CallTip.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CallTip.cxx; path = ../../src/CallTip.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6211FA7597004FB6AB /* Catalogue.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Catalogue.cxx; path = ../../src/Catalogue.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6311FA7597004FB6AB /* CellBuffer.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CellBuffer.cxx; path = ../../src/CellBuffer.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6411FA7597004FB6AB /* CharClassify.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CharClassify.cxx; path = ../../src/CharClassify.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6511FA7597004FB6AB /* ContractionState.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContractionState.cxx; path = ../../src/ContractionState.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6611FA7597004FB6AB /* Decoration.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Decoration.cxx; path = ../../src/Decoration.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6711FA7597004FB6AB /* Document.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Document.cxx; path = ../../src/Document.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6811FA7597004FB6AB /* Editor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Editor.cxx; path = ../../src/Editor.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6911FA7598004FB6AB /* ExternalLexer.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExternalLexer.cxx; path = ../../src/ExternalLexer.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6A11FA7598004FB6AB /* Indicator.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Indicator.cxx; path = ../../src/Indicator.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6B11FA7598004FB6AB /* KeyMap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KeyMap.cxx; path = ../../src/KeyMap.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6C11FA7598004FB6AB /* LineMarker.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LineMarker.cxx; path = ../../src/LineMarker.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6D11FA7598004FB6AB /* PerLine.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PerLine.cxx; path = ../../src/PerLine.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6E11FA7598004FB6AB /* PositionCache.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PositionCache.cxx; path = ../../src/PositionCache.cxx; sourceTree = SOURCE_ROOT; };
		114B6F6F11FA7598004FB6AB /* RESearch.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RESearch.cxx; path = ../../src/RESearch.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7011FA7598004FB6AB /* RunStyles.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RunStyles.cxx; path = ../../src/RunStyles.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7111FA7598004FB6AB /* ScintillaBase.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScintillaBase.cxx; path = ../../src/ScintillaBase.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7211FA7598004FB6AB /* Selection.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Selection.cxx; path = ../../src/Selection.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7311FA7598004FB6AB /* Style.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Style.cxx; path = ../../src/Style.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7411FA7598004FB6AB /* UniConversion.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UniConversion.cxx; path = ../../src/UniConversion.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7511FA7598004FB6AB /* ViewStyle.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ViewStyle.cxx; path = ../../src/ViewStyle.cxx; sourceTree = SOURCE_ROOT; };
		114B6F7611FA7598004FB6AB /* XPM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XPM.cxx; path = ../../src/XPM.cxx; sourceTree = SOURCE_ROOT; };
		114B6F8E11FA75BE004FB6AB /* Accessor.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Accessor.cxx; path = ../../lexlib/Accessor.cxx; sourceTree = SOURCE_ROOT; };
		114B6F8F11FA75BE004FB6AB /* CharacterSet.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CharacterSet.cxx; path = ../../lexlib/CharacterSet.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9011FA75BE004FB6AB /* LexerBase.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexerBase.cxx; path = ../../lexlib/LexerBase.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9111FA75BE004FB6AB /* LexerModule.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexerModule.cxx; path = ../../lexlib/LexerModule.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9211FA75BE004FB6AB /* LexerNoExceptions.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexerNoExceptions.cxx; path = ../../lexlib/LexerNoExceptions.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9311FA75BE004FB6AB /* LexerSimple.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexerSimple.cxx; path = ../../lexlib/LexerSimple.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9411FA75BE004FB6AB /* PropSetSimple.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PropSetSimple.cxx; path = ../../lexlib/PropSetSimple.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9511FA75BE004FB6AB /* StyleContext.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StyleContext.cxx; path = ../../lexlib/StyleContext.cxx; sourceTree = SOURCE_ROOT; };
		114B6F9611FA75BE004FB6AB /* WordList.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WordList.cxx; path = ../../lexlib/WordList.cxx; sourceTree = SOURCE_ROOT; };
		114B6FA011FA75DB004FB6AB /* ILexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ILexer.h; path = ../../include/ILexer.h; sourceTree = SOURCE_ROOT; };
		114B6FA211FA7623004FB6AB /* AutoComplete.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AutoComplete.h; path = ../../src/AutoComplete.h; sourceTree = SOURCE_ROOT; };
		114B6FA311FA7623004FB6AB /* CallTip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallTip.h; path = ../../src/CallTip.h; sourceTree = SOURCE_ROOT; };
		114B6FA411FA7623004FB6AB /* Catalogue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Catalogue.h; path = ../../src/Catalogue.h; sourceTree = SOURCE_ROOT; };
		114B6FA511FA7623004FB6AB /* CellBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CellBuffer.h; path = ../../src/CellBuffer.h; sourceTree = SOURCE_ROOT; };
		114B6FA611FA7623004FB6AB /* CharClassify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CharClassify.h; path = ../../src/CharClassify.h; sourceTree = SOURCE_ROOT; };
		114B6FA711FA7623004FB6AB /* ContractionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContractionState.h; path = ../../src/ContractionState.h; sourceTree = SOURCE_ROOT; };
		114B6FA811FA7623004FB6AB /* Decoration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Decoration.h; path = ../../src/Decoration.h; sourceTree = SOURCE_ROOT; };
		114B6FA911FA7623004FB6AB /* Document.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Document.h; path = ../../src/Document.h; sourceTree = SOURCE_ROOT; };
		114B6FAA11FA7623004FB6AB /* Editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Editor.h; path = ../../src/Editor.h; sourceTree = SOURCE_ROOT; };
		114B6FAB11FA7623004FB6AB /* ExternalLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalLexer.h; path = ../../src/ExternalLexer.h; sourceTree = SOURCE_ROOT; };
		114B6FAC11FA7623004FB6AB /* FontQuality.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FontQuality.h; path = ../../src/FontQuality.h; sourceTree = SOURCE_ROOT; };
		114B6FAD11FA7623004FB6AB /* Indicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Indicator.h; path = ../../src/Indicator.h; sourceTree = SOURCE_ROOT; };
		114B6FAE11FA7623004FB6AB /* KeyMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KeyMap.h; path = ../../src/KeyMap.h; sourceTree = SOURCE_ROOT; };
		114B6FAF11FA7623004FB6AB /* LineMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineMarker.h; path = ../../src/LineMarker.h; sourceTree = SOURCE_ROOT; };
		114B6FB011FA7623004FB6AB /* Partitioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Partitioning.h; path = ../../src/Partitioning.h; sourceTree = SOURCE_ROOT; };
		114B6FB111FA7623004FB6AB /* PerLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PerLine.h; path = ../../src/PerLine.h; sourceTree = SOURCE_ROOT; };
		114B6FB211FA7623004FB6AB /* PositionCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PositionCache.h; path = ../../src/PositionCache.h; sourceTree = SOURCE_ROOT; };
		114B6FB311FA7623004FB6AB /* RESearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RESearch.h; path = ../../src/RESearch.h; sourceTree = SOURCE_ROOT; };
		114B6FB411FA7623004FB6AB /* RunStyles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RunStyles.h; path = ../../src/RunStyles.h; sourceTree = SOURCE_ROOT; };
		114B6FB511FA7623004FB6AB /* ScintillaBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaBase.h; path = ../../src/ScintillaBase.h; sourceTree = SOURCE_ROOT; };
		114B6FB611FA7623004FB6AB /* Selection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Selection.h; path = ../../src/Selection.h; sourceTree = SOURCE_ROOT; };
		114B6FB711FA7623004FB6AB /* SplitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SplitVector.h; path = ../../src/SplitVector.h; sourceTree = SOURCE_ROOT; };
		114B6FB811FA7623004FB6AB /* Style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Style.h; path = ../../src/Style.h; sourceTree = SOURCE_ROOT; };
		114B6FB911FA7623004FB6AB /* SVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SVector.h; path = ../../src/SVector.h; sourceTree = SOURCE_ROOT; };
		114B6FBA11FA7623004FB6AB /* UniConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UniConversion.h; path = ../../src/UniConversion.h; sourceTree = SOURCE_ROOT; };
		114B6FBB11FA7623004FB6AB /* ViewStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewStyle.h; path = ../../src/ViewStyle.h; sourceTree = SOURCE_ROOT; };
		114B6FBC11FA7623004FB6AB /* XPM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XPM.h; path = ../../src/XPM.h; sourceTree = SOURCE_ROOT; };
		114B6FD811FA7645004FB6AB /* Accessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Accessor.h; path = ../../lexlib/Accessor.h; sourceTree = SOURCE_ROOT; };
		114B6FD911FA7645004FB6AB /* CharacterSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CharacterSet.h; path = ../../lexlib/CharacterSet.h; sourceTree = SOURCE_ROOT; };
		114B6FDA11FA7645004FB6AB /* LexAccessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LexAccessor.h; path = ../../lexlib/LexAccessor.h; sourceTree = SOURCE_ROOT; };
		114B6FDB11FA7645004FB6AB /* LexerBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LexerBase.h; path = ../../lexlib/LexerBase.h; sourceTree = SOURCE_ROOT; };
		114B6FDC11FA7645004FB6AB /* LexerModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LexerModule.h; path = ../../lexlib/LexerModule.h; sourceTree = SOURCE_ROOT; };
		114B6FDD11FA7645004FB6AB /* LexerNoExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LexerNoExceptions.h; path = ../../lexlib/LexerNoExceptions.h; sourceTree = SOURCE_ROOT; };
		114B6FDE11FA7645004FB6AB /* LexerSimple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LexerSimple.h; path = ../../lexlib/LexerSimple.h; sourceTree = SOURCE_ROOT; };
		114B6FDF11FA7645004FB6AB /* OptionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionSet.h; path = ../../lexlib/OptionSet.h; sourceTree = SOURCE_ROOT; };
		114B6FE011FA7645004FB6AB /* PropSetSimple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PropSetSimple.h; path = ../../lexlib/PropSetSimple.h; sourceTree = SOURCE_ROOT; };
		114B6FE111FA7645004FB6AB /* StyleContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StyleContext.h; path = ../../lexlib/StyleContext.h; sourceTree = SOURCE_ROOT; };
		114B6FE211FA7645004FB6AB /* WordList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WordList.h; path = ../../lexlib/WordList.h; sourceTree = SOURCE_ROOT; };
		1152A77215313E58000D4E1A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = ../../../../../../../../System/Library/Frameworks/QuartzCore.framework; sourceTree = "<group>"; };
		11594BE7155B91DF0099E1FA /* LexOScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexOScript.cxx; path = ../../lexers/LexOScript.cxx; sourceTree = "<group>"; };
		11594BE8155B91DF0099E1FA /* LexVisualProlog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexVisualProlog.cxx; path = ../../lexers/LexVisualProlog.cxx; sourceTree = "<group>"; };
		117ACE9014A29A1E002876F9 /* LexTCMD.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexTCMD.cxx; path = ../../lexers/LexTCMD.cxx; sourceTree = "<group>"; };
		119FF1BE13C9D1820007CE42 /* QuartzTextStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuartzTextStyle.h; path = ../QuartzTextStyle.h; sourceTree = "<group>"; };
		11A0A8A0148602DF0018D143 /* LexCoffeeScript.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexCoffeeScript.cxx; path = ../../lexers/LexCoffeeScript.cxx; sourceTree = "<group>"; };
		11BB124C12FF9C1300F6BCF7 /* LexModula.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexModula.cxx; path = ../../lexers/LexModula.cxx; sourceTree = SOURCE_ROOT; };
		11BEB6A114EF189600BDE92A /* LexECL.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexECL.cxx; path = ../../lexers/LexECL.cxx; sourceTree = "<group>"; };
		11F35FDA12AEFAF100F0236D /* LexA68k.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LexA68k.cxx; path = ../../lexers/LexA68k.cxx; sourceTree = SOURCE_ROOT; };
		2744E4850FC1678600E85C33 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = ../../include/Platform.h; sourceTree = SOURCE_ROOT; };
		2744E4870FC1678600E85C33 /* SciLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SciLexer.h; path = ../../include/SciLexer.h; sourceTree = SOURCE_ROOT; };
		2744E4880FC1678600E85C33 /* Scintilla.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scintilla.h; path = ../../include/Scintilla.h; sourceTree = SOURCE_ROOT; };
		2744E59D0FC168A100E85C33 /* InfoBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InfoBar.h; path = ../InfoBar.h; sourceTree = SOURCE_ROOT; };
		2744E59E0FC168A100E85C33 /* PlatCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatCocoa.h; path = ../PlatCocoa.h; sourceTree = SOURCE_ROOT; };
		2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuartzTextLayout.h; path = ../QuartzTextLayout.h; sourceTree = SOURCE_ROOT; };
		2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuartzTextStyleAttribute.h; path = ../QuartzTextStyleAttribute.h; sourceTree = SOURCE_ROOT; };
		2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaCocoa.h; path = ../ScintillaCocoa.h; sourceTree = "<group>"; };
		2744E5A30FC168A100E85C33 /* ScintillaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScintillaView.h; path = ../ScintillaView.h; sourceTree = "<group>"; };
		2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InfoBarCommunicator.h; path = ../InfoBarCommunicator.h; sourceTree = SOURCE_ROOT; };
		2744E5AD0FC168C500E85C33 /* InfoBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InfoBar.mm; path = ../InfoBar.mm; sourceTree = SOURCE_ROOT; };
		2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PlatCocoa.mm; path = ../PlatCocoa.mm; sourceTree = SOURCE_ROOT; };
		2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScintillaCocoa.mm; path = ../ScintillaCocoa.mm; sourceTree = "<group>"; };
		2744E5B10FC168C500E85C33 /* ScintillaView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScintillaView.mm; path = ../ScintillaView.mm; sourceTree = "<group>"; };
		27FEF4510FC1B413005E115A /* info_bar_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = info_bar_bg.png; sourceTree = "<group>"; };
		27FEF4520FC1B413005E115A /* mac_cursor_busy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mac_cursor_busy.png; sourceTree = "<group>"; };
		27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mac_cursor_flipped.png; sourceTree = "<group>"; };
		32DBCF5E0370ADEE00C91783 /* Scintilla_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scintilla_Prefix.pch; sourceTree = "<group>"; };
		8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		8DC2EF5B0486A6940098B216 /* Scintilla.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Scintilla.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		8DC2EF560486A6940098B216 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
				1152A77315313E58000D4E1A /* QuartzCore.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		034768DFFF38A50411DB9C8B /* Products */ = {
			isa = PBXGroup;
			children = (
				8DC2EF5B0486A6940098B216 /* Scintilla.framework */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		0867D691FE84028FC02AAC07 /* Scintilla */ = {
			isa = PBXGroup;
			children = (
				2744E47D0FC1674E00E85C33 /* Lexers */,
				2744E47C0FC1674100E85C33 /* Backend */,
				08FB77AEFE84172EC02AAC07 /* Classes */,
				32C88DFF0371C24200C91783 /* Other Sources */,
				089C1665FE841158C02AAC07 /* Resources */,
				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
				034768DFFF38A50411DB9C8B /* Products */,
			);
			name = Scintilla;
			sourceTree = "<group>";
		};
		0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
			isa = PBXGroup;
			children = (
				1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
				1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
			);
			name = "External Frameworks and Libraries";
			sourceTree = "<group>";
		};
		089C1665FE841158C02AAC07 /* Resources */ = {
			isa = PBXGroup;
			children = (
				27FEF4500FC1B413005E115A /* res */,
				8DC2EF5A0486A6940098B216 /* Info.plist */,
				089C1666FE841158C02AAC07 /* InfoPlist.strings */,
			);
			name = Resources;
			sourceTree = "<group>";
		};
		08FB77AEFE84172EC02AAC07 /* Classes */ = {
			isa = PBXGroup;
			children = (
				2744E4980FC167ED00E85C33 /* Source Files */,
				2744E4970FC167E400E85C33 /* Header Files */,
			);
			name = Classes;
			sourceTree = "<group>";
		};
		1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
			isa = PBXGroup;
			children = (
				1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
			);
			name = "Linked Frameworks";
			sourceTree = "<group>";
		};
		1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
			isa = PBXGroup;
			children = (
				1152A77215313E58000D4E1A /* QuartzCore.framework */,
				0867D6A5FE840307C02AAC07 /* AppKit.framework */,
				D2F7E79907B2D74100F64583 /* CoreData.framework */,
				0867D69BFE84028FC02AAC07 /* Foundation.framework */,
			);
			name = "Other Frameworks";
			sourceTree = "<group>";
		};
		2744E47C0FC1674100E85C33 /* Backend */ = {
			isa = PBXGroup;
			children = (
				2744E47F0FC1676400E85C33 /* Source Files */,
				2744E47E0FC1675800E85C33 /* Header Files */,
			);
			name = Backend;
			sourceTree = "<group>";
		};
		2744E47D0FC1674E00E85C33 /* Lexers */ = {
			isa = PBXGroup;
			children = (
				11126B8114CD3A6200803C49 /* LexAVS.cxx */,
				11F35FDA12AEFAF100F0236D /* LexA68k.cxx */,
				114B6EBE11FA7526004FB6AB /* LexAbaqus.cxx */,
				114B6EBF11FA7526004FB6AB /* LexAda.cxx */,
				114B6EC011FA7526004FB6AB /* LexAPDL.cxx */,
				114B6EC111FA7526004FB6AB /* LexAsm.cxx */,
				114B6EC211FA7526004FB6AB /* LexAsn1.cxx */,
				114B6EC311FA7526004FB6AB /* LexASY.cxx */,
				114B6EC411FA7526004FB6AB /* LexAU3.cxx */,
				114B6EC511FA7526004FB6AB /* LexAVE.cxx */,
				114B6EC611FA7526004FB6AB /* LexBaan.cxx */,
				114B6EC711FA7526004FB6AB /* LexBash.cxx */,
				114B6EC811FA7526004FB6AB /* LexBasic.cxx */,
				114B6EC911FA7526004FB6AB /* LexBullant.cxx */,
				114B6ECA11FA7526004FB6AB /* LexCaml.cxx */,
				114B6ECB11FA7526004FB6AB /* LexCLW.cxx */,
				114B6ECC11FA7526004FB6AB /* LexCmake.cxx */,
				114B6ECD11FA7526004FB6AB /* LexCOBOL.cxx */,
				11A0A8A0148602DF0018D143 /* LexCoffeeScript.cxx */,
				114B6ECE11FA7526004FB6AB /* LexConf.cxx */,
				114B6ECF11FA7526004FB6AB /* LexCPP.cxx */,
				114B6ED011FA7526004FB6AB /* LexCrontab.cxx */,
				114B6ED111FA7526004FB6AB /* LexCsound.cxx */,
				114B6ED211FA7526004FB6AB /* LexCSS.cxx */,
				114B6ED311FA7526004FB6AB /* LexD.cxx */,
				11BEB6A114EF189600BDE92A /* LexECL.cxx */,
				114B6ED411FA7526004FB6AB /* LexEiffel.cxx */,
				114B6ED511FA7526004FB6AB /* LexErlang.cxx */,
				114B6ED611FA7526004FB6AB /* LexEScript.cxx */,
				114B6ED711FA7526004FB6AB /* LexFlagship.cxx */,
				114B6ED811FA7526004FB6AB /* LexForth.cxx */,
				114B6ED911FA7526004FB6AB /* LexFortran.cxx */,
				114B6EDA11FA7526004FB6AB /* LexGAP.cxx */,
				114B6EDB11FA7526004FB6AB /* LexGui4Cli.cxx */,
				114B6EDC11FA7526004FB6AB /* LexHaskell.cxx */,
				114B6EDD11FA7526004FB6AB /* LexHTML.cxx */,
				114B6EDE11FA7526004FB6AB /* LexInno.cxx */,
				114B6EDF11FA7526004FB6AB /* LexKix.cxx */,
				1102C31B169FB49300DC16AB /* LexLaTeX.cxx */,
				114B6EE011FA7526004FB6AB /* LexLisp.cxx */,
				114B6EE111FA7526004FB6AB /* LexLout.cxx */,
				114B6EE211FA7526004FB6AB /* LexLua.cxx */,
				114B6EE311FA7526004FB6AB /* LexMagik.cxx */,
				114B6EE411FA7526004FB6AB /* LexMarkdown.cxx */,
				114B6EE511FA7526004FB6AB /* LexMatlab.cxx */,
				114B6EE611FA7526004FB6AB /* LexMetapost.cxx */,
				114B6EE711FA7526004FB6AB /* LexMMIXAL.cxx */,
				11BB124C12FF9C1300F6BCF7 /* LexModula.cxx */,
				114B6EE811FA7526004FB6AB /* LexMPT.cxx */,
				114B6EE911FA7526004FB6AB /* LexMSSQL.cxx */,
				114B6EEA11FA7526004FB6AB /* LexMySQL.cxx */,
				114B6EEB11FA7526004FB6AB /* LexNimrod.cxx */,
				114B6EEC11FA7526004FB6AB /* LexNsis.cxx */,
				114B6EED11FA7526004FB6AB /* LexOpal.cxx */,
				11594BE7155B91DF0099E1FA /* LexOScript.cxx */,
				114B6EEE11FA7526004FB6AB /* LexOthers.cxx */,
				114B6EEF11FA7526004FB6AB /* LexPascal.cxx */,
				114B6EF011FA7526004FB6AB /* LexPB.cxx */,
				114B6EF111FA7526004FB6AB /* LexPerl.cxx */,
				114B6EF211FA7526004FB6AB /* LexPLM.cxx */,
				1114D6CA1602A951001DC345 /* LexPO.cxx */,
				114B6EF311FA7526004FB6AB /* LexPOV.cxx */,
				114B6EF411FA7526004FB6AB /* LexPowerPro.cxx */,
				114B6EF511FA7526004FB6AB /* LexPowerShell.cxx */,
				114B6EF611FA7526004FB6AB /* LexProgress.cxx */,
				114B6EF711FA7526004FB6AB /* LexPS.cxx */,
				114B6EF811FA7526004FB6AB /* LexPython.cxx */,
				114B6EF911FA7526004FB6AB /* LexR.cxx */,
				114B6EFA11FA7526004FB6AB /* LexRebol.cxx */,
				114B6EFB11FA7526004FB6AB /* LexRuby.cxx */,
				114B6EFC11FA7526004FB6AB /* LexScriptol.cxx */,
				114B6EFD11FA7526004FB6AB /* LexSmalltalk.cxx */,
				114B6EFE11FA7526004FB6AB /* LexSML.cxx */,
				114B6EFF11FA7526004FB6AB /* LexSorcus.cxx */,
				114B6F0011FA7526004FB6AB /* LexSpecman.cxx */,
				114B6F0111FA7526004FB6AB /* LexSpice.cxx */,
				114B6F0211FA7526004FB6AB /* LexSQL.cxx */,
				114B6F0311FA7526004FB6AB /* LexTACL.cxx */,
				114B6F0411FA7526004FB6AB /* LexTADS3.cxx */,
				114B6F0511FA7526004FB6AB /* LexTAL.cxx */,
				114B6F0611FA7526004FB6AB /* LexTCL.cxx */,
				117ACE9014A29A1E002876F9 /* LexTCMD.cxx */,
				114B6F0711FA7526004FB6AB /* LexTeX.cxx */,
				114B6F0811FA7526004FB6AB /* LexTxt2tags.cxx */,
				114B6F0911FA7526004FB6AB /* LexVB.cxx */,
				114B6F0A11FA7526004FB6AB /* LexVerilog.cxx */,
				114B6F0B11FA7526004FB6AB /* LexVHDL.cxx */,
				11594BE8155B91DF0099E1FA /* LexVisualProlog.cxx */,
				114B6F0C11FA7526004FB6AB /* LexYAML.cxx */,
			);
			name = Lexers;
			sourceTree = "<group>";
		};
		2744E47E0FC1675800E85C33 /* Header Files */ = {
			isa = PBXGroup;
			children = (
				114B6FD811FA7645004FB6AB /* Accessor.h */,
				114B6FD911FA7645004FB6AB /* CharacterSet.h */,
				114B6FDA11FA7645004FB6AB /* LexAccessor.h */,
				114B6FDB11FA7645004FB6AB /* LexerBase.h */,
				114B6FDC11FA7645004FB6AB /* LexerModule.h */,
				114B6FDD11FA7645004FB6AB /* LexerNoExceptions.h */,
				114B6FDE11FA7645004FB6AB /* LexerSimple.h */,
				114B6FDF11FA7645004FB6AB /* OptionSet.h */,
				114B6FE011FA7645004FB6AB /* PropSetSimple.h */,
				114B6FE111FA7645004FB6AB /* StyleContext.h */,
				114B6FE211FA7645004FB6AB /* WordList.h */,
				114B6FA211FA7623004FB6AB /* AutoComplete.h */,
				114B6FA311FA7623004FB6AB /* CallTip.h */,
				114B6FA411FA7623004FB6AB /* Catalogue.h */,
				114B6FA511FA7623004FB6AB /* CellBuffer.h */,
				114B6FA611FA7623004FB6AB /* CharClassify.h */,
				114B6FA711FA7623004FB6AB /* ContractionState.h */,
				114B6FA811FA7623004FB6AB /* Decoration.h */,
				114B6FA911FA7623004FB6AB /* Document.h */,
				114B6FAA11FA7623004FB6AB /* Editor.h */,
				114B6FAB11FA7623004FB6AB /* ExternalLexer.h */,
				114B6FAC11FA7623004FB6AB /* FontQuality.h */,
				114B6FAD11FA7623004FB6AB /* Indicator.h */,
				114B6FAE11FA7623004FB6AB /* KeyMap.h */,
				114B6FAF11FA7623004FB6AB /* LineMarker.h */,
				114B6FB011FA7623004FB6AB /* Partitioning.h */,
				114B6FB111FA7623004FB6AB /* PerLine.h */,
				114B6FB211FA7623004FB6AB /* PositionCache.h */,
				114B6FB311FA7623004FB6AB /* RESearch.h */,
				114B6FB411FA7623004FB6AB /* RunStyles.h */,
				114B6FB511FA7623004FB6AB /* ScintillaBase.h */,
				114B6FB611FA7623004FB6AB /* Selection.h */,
				114B6FB711FA7623004FB6AB /* SplitVector.h */,
				114B6FB811FA7623004FB6AB /* Style.h */,
				114B6FB911FA7623004FB6AB /* SVector.h */,
				114B6FBA11FA7623004FB6AB /* UniConversion.h */,
				114B6FBB11FA7623004FB6AB /* ViewStyle.h */,
				114B6FBC11FA7623004FB6AB /* XPM.h */,
				114B6FA011FA75DB004FB6AB /* ILexer.h */,
			);
			name = "Header Files";
			sourceTree = "<group>";
		};
		2744E47F0FC1676400E85C33 /* Source Files */ = {
			isa = PBXGroup;
			children = (
				114B6F8E11FA75BE004FB6AB /* Accessor.cxx */,
				114B6F8F11FA75BE004FB6AB /* CharacterSet.cxx */,
				114B6F9011FA75BE004FB6AB /* LexerBase.cxx */,
				114B6F9111FA75BE004FB6AB /* LexerModule.cxx */,
				114B6F9211FA75BE004FB6AB /* LexerNoExceptions.cxx */,
				114B6F9311FA75BE004FB6AB /* LexerSimple.cxx */,
				114B6F9411FA75BE004FB6AB /* PropSetSimple.cxx */,
				114B6F9511FA75BE004FB6AB /* StyleContext.cxx */,
				114B6F9611FA75BE004FB6AB /* WordList.cxx */,
				114B6F6011FA7597004FB6AB /* AutoComplete.cxx */,
				114B6F6111FA7597004FB6AB /* CallTip.cxx */,
				114B6F6211FA7597004FB6AB /* Catalogue.cxx */,
				114B6F6311FA7597004FB6AB /* CellBuffer.cxx */,
				114B6F6411FA7597004FB6AB /* CharClassify.cxx */,
				114B6F6511FA7597004FB6AB /* ContractionState.cxx */,
				114B6F6611FA7597004FB6AB /* Decoration.cxx */,
				114B6F6711FA7597004FB6AB /* Document.cxx */,
				114B6F6811FA7597004FB6AB /* Editor.cxx */,
				114B6F6911FA7598004FB6AB /* ExternalLexer.cxx */,
				114B6F6A11FA7598004FB6AB /* Indicator.cxx */,
				114B6F6B11FA7598004FB6AB /* KeyMap.cxx */,
				114B6F6C11FA7598004FB6AB /* LineMarker.cxx */,
				114B6F6D11FA7598004FB6AB /* PerLine.cxx */,
				114B6F6E11FA7598004FB6AB /* PositionCache.cxx */,
				114B6F6F11FA7598004FB6AB /* RESearch.cxx */,
				114B6F7011FA7598004FB6AB /* RunStyles.cxx */,
				114B6F7111FA7598004FB6AB /* ScintillaBase.cxx */,
				114B6F7211FA7598004FB6AB /* Selection.cxx */,
				114B6F7311FA7598004FB6AB /* Style.cxx */,
				114B6F7411FA7598004FB6AB /* UniConversion.cxx */,
				114B6F7511FA7598004FB6AB /* ViewStyle.cxx */,
				114B6F7611FA7598004FB6AB /* XPM.cxx */,
			);
			name = "Source Files";
			sourceTree = "<group>";
		};
		2744E4970FC167E400E85C33 /* Header Files */ = {
			isa = PBXGroup;
			children = (
				2744E59D0FC168A100E85C33 /* InfoBar.h */,
				2744E5AB0FC168B200E85C33 /* InfoBarCommunicator.h */,
				2744E59E0FC168A100E85C33 /* PlatCocoa.h */,
				2744E4850FC1678600E85C33 /* Platform.h */,
				2744E59F0FC168A100E85C33 /* QuartzTextLayout.h */,
				119FF1BE13C9D1820007CE42 /* QuartzTextStyle.h */,
				2744E5A00FC168A100E85C33 /* QuartzTextStyleAttribute.h */,
				2744E4870FC1678600E85C33 /* SciLexer.h */,
				2744E4880FC1678600E85C33 /* Scintilla.h */,
				2744E5A20FC168A100E85C33 /* ScintillaCocoa.h */,
				2744E5A30FC168A100E85C33 /* ScintillaView.h */,
			);
			name = "Header Files";
			sourceTree = "<group>";
		};
		2744E4980FC167ED00E85C33 /* Source Files */ = {
			isa = PBXGroup;
			children = (
				2744E5AD0FC168C500E85C33 /* InfoBar.mm */,
				2744E5AE0FC168C500E85C33 /* PlatCocoa.mm */,
				2744E5B00FC168C500E85C33 /* ScintillaCocoa.mm */,
				2744E5B10FC168C500E85C33 /* ScintillaView.mm */,
			);
			name = "Source Files";
			sourceTree = "<group>";
		};
		27FEF4500FC1B413005E115A /* res */ = {
			isa = PBXGroup;
			children = (
				27FEF4510FC1B413005E115A /* info_bar_bg.png */,
				27FEF4520FC1B413005E115A /* mac_cursor_busy.png */,
				27FEF4530FC1B413005E115A /* mac_cursor_flipped.png */,
			);
			name = res;
			path = ../res;
			sourceTree = SOURCE_ROOT;
		};
		32C88DFF0371C24200C91783 /* Other Sources */ = {
			isa = PBXGroup;
			children = (
				32DBCF5E0370ADEE00C91783 /* Scintilla_Prefix.pch */,
			);
			name = "Other Sources";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
		8DC2EF500486A6940098B216 /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
				2744E5A40FC168A100E85C33 /* InfoBar.h in Headers */,
				2744E5AC0FC168B200E85C33 /* InfoBarCommunicator.h in Headers */,
				2791F3C60FC19F71009DBCF9 /* PlatCocoa.h in Headers */,
				2791F3E30FC1A3AE009DBCF9 /* QuartzTextLayout.h in Headers */,
				2791F3E40FC1A3AE009DBCF9 /* QuartzTextStyleAttribute.h in Headers */,
				2791F3E00FC1A390009DBCF9 /* ScintillaCocoa.h in Headers */,
				2744E5AA0FC168A100E85C33 /* ScintillaView.h in Headers */,
				2791F3C70FC19F71009DBCF9 /* Platform.h in Headers */,
				2791F3C80FC19F71009DBCF9 /* SciLexer.h in Headers */,
				2791F3C90FC19F71009DBCF9 /* Scintilla.h in Headers */,
				114B6FA111FA75DB004FB6AB /* ILexer.h in Headers */,
				114B6FBD11FA7623004FB6AB /* AutoComplete.h in Headers */,
				114B6FBE11FA7623004FB6AB /* CallTip.h in Headers */,
				114B6FBF11FA7623004FB6AB /* Catalogue.h in Headers */,
				114B6FC011FA7623004FB6AB /* CellBuffer.h in Headers */,
				114B6FC111FA7623004FB6AB /* CharClassify.h in Headers */,
				114B6FC211FA7623004FB6AB /* ContractionState.h in Headers */,
				114B6FC311FA7623004FB6AB /* Decoration.h in Headers */,
				114B6FC411FA7623004FB6AB /* Document.h in Headers */,
				114B6FC511FA7623004FB6AB /* Editor.h in Headers */,
				114B6FC611FA7623004FB6AB /* ExternalLexer.h in Headers */,
				114B6FC711FA7623004FB6AB /* FontQuality.h in Headers */,
				114B6FC811FA7623004FB6AB /* Indicator.h in Headers */,
				114B6FC911FA7623004FB6AB /* KeyMap.h in Headers */,
				114B6FCA11FA7623004FB6AB /* LineMarker.h in Headers */,
				114B6FCB11FA7623004FB6AB /* Partitioning.h in Headers */,
				114B6FCC11FA7623004FB6AB /* PerLine.h in Headers */,
				114B6FCD11FA7623004FB6AB /* PositionCache.h in Headers */,
				114B6FCE11FA7623004FB6AB /* RESearch.h in Headers */,
				114B6FCF11FA7623004FB6AB /* RunStyles.h in Headers */,
				114B6FD011FA7623004FB6AB /* ScintillaBase.h in Headers */,
				114B6FD111FA7623004FB6AB /* Selection.h in Headers */,
				114B6FD211FA7623004FB6AB /* SplitVector.h in Headers */,
				114B6FD311FA7623004FB6AB /* Style.h in Headers */,
				114B6FD411FA7623004FB6AB /* SVector.h in Headers */,
				114B6FD511FA7623004FB6AB /* UniConversion.h in Headers */,
				114B6FD611FA7623004FB6AB /* ViewStyle.h in Headers */,
				114B6FD711FA7623004FB6AB /* XPM.h in Headers */,
				114B6FE311FA7645004FB6AB /* Accessor.h in Headers */,
				114B6FE411FA7645004FB6AB /* CharacterSet.h in Headers */,
				114B6FE511FA7645004FB6AB /* LexAccessor.h in Headers */,
				114B6FE611FA7645004FB6AB /* LexerBase.h in Headers */,
				114B6FE711FA7645004FB6AB /* LexerModule.h in Headers */,
				114B6FE811FA7645004FB6AB /* LexerNoExceptions.h in Headers */,
				114B6FE911FA7645004FB6AB /* LexerSimple.h in Headers */,
				114B6FEA11FA7645004FB6AB /* OptionSet.h in Headers */,
				114B6FEB11FA7645004FB6AB /* PropSetSimple.h in Headers */,
				114B6FEC11FA7645004FB6AB /* StyleContext.h in Headers */,
				114B6FED11FA7645004FB6AB /* WordList.h in Headers */,
				119FF1BF13C9D1820007CE42 /* QuartzTextStyle.h in Headers */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXHeadersBuildPhase section */

/* Begin PBXNativeTarget section */
		8DC2EF4F0486A6940098B216 /* Scintilla */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Scintilla" */;
			buildPhases = (
				8DC2EF500486A6940098B216 /* Headers */,
				8DC2EF520486A6940098B216 /* Resources */,
				8DC2EF540486A6940098B216 /* Sources */,
				8DC2EF560486A6940098B216 /* Frameworks */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Scintilla;
			productInstallPath = "$(HOME)/Library/Frameworks";
			productName = Scintilla;
			productReference = 8DC2EF5B0486A6940098B216 /* Scintilla.framework */;
			productType = "com.apple.product-type.framework";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		0867D690FE84028FC02AAC07 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0460;
			};
			buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ScintillaFramework" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 1;
			knownRegions = (
				English,
				Japanese,
				French,
				German,
			);
			mainGroup = 0867D691FE84028FC02AAC07 /* Scintilla */;
			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				8DC2EF4F0486A6940098B216 /* Scintilla */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		8DC2EF520486A6940098B216 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
				27FEF4540FC1B413005E115A /* info_bar_bg.png in Resources */,
				27FEF4550FC1B413005E115A /* mac_cursor_busy.png in Resources */,
				27FEF4560FC1B413005E115A /* mac_cursor_flipped.png in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8DC2EF540486A6940098B216 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				2744E5B20FC168C500E85C33 /* InfoBar.mm in Sources */,
				2744E5B30FC168C500E85C33 /* PlatCocoa.mm in Sources */,
				2744E5B50FC168C500E85C33 /* ScintillaCocoa.mm in Sources */,
				2744E5B60FC168C500E85C33 /* ScintillaView.mm in Sources */,
				114B6F0D11FA7526004FB6AB /* LexAbaqus.cxx in Sources */,
				114B6F0E11FA7526004FB6AB /* LexAda.cxx in Sources */,
				114B6F0F11FA7526004FB6AB /* LexAPDL.cxx in Sources */,
				114B6F1011FA7526004FB6AB /* LexAsm.cxx in Sources */,
				114B6F1111FA7526004FB6AB /* LexAsn1.cxx in Sources */,
				114B6F1211FA7526004FB6AB /* LexASY.cxx in Sources */,
				114B6F1311FA7526004FB6AB /* LexAU3.cxx in Sources */,
				114B6F1411FA7526004FB6AB /* LexAVE.cxx in Sources */,
				114B6F1511FA7526004FB6AB /* LexBaan.cxx in Sources */,
				114B6F1611FA7526004FB6AB /* LexBash.cxx in Sources */,
				114B6F1711FA7526004FB6AB /* LexBasic.cxx in Sources */,
				114B6F1811FA7526004FB6AB /* LexBullant.cxx in Sources */,
				114B6F1911FA7526004FB6AB /* LexCaml.cxx in Sources */,
				114B6F1A11FA7526004FB6AB /* LexCLW.cxx in Sources */,
				114B6F1B11FA7526004FB6AB /* LexCmake.cxx in Sources */,
				114B6F1C11FA7526004FB6AB /* LexCOBOL.cxx in Sources */,
				114B6F1D11FA7526004FB6AB /* LexConf.cxx in Sources */,
				114B6F1E11FA7526004FB6AB /* LexCPP.cxx in Sources */,
				114B6F1F11FA7526004FB6AB /* LexCrontab.cxx in Sources */,
				114B6F2011FA7526004FB6AB /* LexCsound.cxx in Sources */,
				114B6F2111FA7526004FB6AB /* LexCSS.cxx in Sources */,
				114B6F2211FA7526004FB6AB /* LexD.cxx in Sources */,
				114B6F2311FA7526004FB6AB /* LexEiffel.cxx in Sources */,
				114B6F2411FA7526004FB6AB /* LexErlang.cxx in Sources */,
				114B6F2511FA7526004FB6AB /* LexEScript.cxx in Sources */,
				114B6F2611FA7526004FB6AB /* LexFlagship.cxx in Sources */,
				114B6F2711FA7526004FB6AB /* LexForth.cxx in Sources */,
				114B6F2811FA7526004FB6AB /* LexFortran.cxx in Sources */,
				114B6F2911FA7526004FB6AB /* LexGAP.cxx in Sources */,
				114B6F2A11FA7526004FB6AB /* LexGui4Cli.cxx in Sources */,
				114B6F2B11FA7526004FB6AB /* LexHaskell.cxx in Sources */,
				114B6F2C11FA7526004FB6AB /* LexHTML.cxx in Sources */,
				114B6F2D11FA7526004FB6AB /* LexInno.cxx in Sources */,
				114B6F2E11FA7526004FB6AB /* LexKix.cxx in Sources */,
				114B6F2F11FA7526004FB6AB /* LexLisp.cxx in Sources */,
				114B6F3011FA7526004FB6AB /* LexLout.cxx in Sources */,
				114B6F3111FA7526004FB6AB /* LexLua.cxx in Sources */,
				114B6F3211FA7526004FB6AB /* LexMagik.cxx in Sources */,
				114B6F3311FA7526004FB6AB /* LexMarkdown.cxx in Sources */,
				114B6F3411FA7526004FB6AB /* LexMatlab.cxx in Sources */,
				114B6F3511FA7526004FB6AB /* LexMetapost.cxx in Sources */,
				114B6F3611FA7526004FB6AB /* LexMMIXAL.cxx in Sources */,
				114B6F3711FA7526004FB6AB /* LexMPT.cxx in Sources */,
				114B6F3811FA7526004FB6AB /* LexMSSQL.cxx in Sources */,
				114B6F3911FA7526004FB6AB /* LexMySQL.cxx in Sources */,
				114B6F3A11FA7526004FB6AB /* LexNimrod.cxx in Sources */,
				114B6F3B11FA7526004FB6AB /* LexNsis.cxx in Sources */,
				114B6F3C11FA7526004FB6AB /* LexOpal.cxx in Sources */,
				114B6F3D11FA7526004FB6AB /* LexOthers.cxx in Sources */,
				114B6F3E11FA7526004FB6AB /* LexPascal.cxx in Sources */,
				114B6F3F11FA7526004FB6AB /* LexPB.cxx in Sources */,
				114B6F4011FA7526004FB6AB /* LexPerl.cxx in Sources */,
				114B6F4111FA7526004FB6AB /* LexPLM.cxx in Sources */,
				114B6F4211FA7526004FB6AB /* LexPOV.cxx in Sources */,
				114B6F4311FA7526004FB6AB /* LexPowerPro.cxx in Sources */,
				114B6F4411FA7526004FB6AB /* LexPowerShell.cxx in Sources */,
				114B6F4511FA7526004FB6AB /* LexProgress.cxx in Sources */,
				114B6F4611FA7526004FB6AB /* LexPS.cxx in Sources */,
				114B6F4711FA7526004FB6AB /* LexPython.cxx in Sources */,
				114B6F4811FA7526004FB6AB /* LexR.cxx in Sources */,
				114B6F4911FA7526004FB6AB /* LexRebol.cxx in Sources */,
				114B6F4A11FA7526004FB6AB /* LexRuby.cxx in Sources */,
				114B6F4B11FA7526004FB6AB /* LexScriptol.cxx in Sources */,
				114B6F4C11FA7526004FB6AB /* LexSmalltalk.cxx in Sources */,
				114B6F4D11FA7526004FB6AB /* LexSML.cxx in Sources */,
				114B6F4E11FA7526004FB6AB /* LexSorcus.cxx in Sources */,
				114B6F4F11FA7526004FB6AB /* LexSpecman.cxx in Sources */,
				114B6F5011FA7526004FB6AB /* LexSpice.cxx in Sources */,
				114B6F5111FA7526004FB6AB /* LexSQL.cxx in Sources */,
				114B6F5211FA7526004FB6AB /* LexTACL.cxx in Sources */,
				114B6F5311FA7526004FB6AB /* LexTADS3.cxx in Sources */,
				114B6F5411FA7526004FB6AB /* LexTAL.cxx in Sources */,
				114B6F5511FA7526004FB6AB /* LexTCL.cxx in Sources */,
				114B6F5611FA7526004FB6AB /* LexTeX.cxx in Sources */,
				114B6F5711FA7526004FB6AB /* LexTxt2tags.cxx in Sources */,
				114B6F5811FA7526004FB6AB /* LexVB.cxx in Sources */,
				114B6F5911FA7526004FB6AB /* LexVerilog.cxx in Sources */,
				114B6F5A11FA7526004FB6AB /* LexVHDL.cxx in Sources */,
				114B6F5B11FA7526004FB6AB /* LexYAML.cxx in Sources */,
				114B6F7711FA7598004FB6AB /* AutoComplete.cxx in Sources */,
				114B6F7811FA7598004FB6AB /* CallTip.cxx in Sources */,
				114B6F7911FA7598004FB6AB /* Catalogue.cxx in Sources */,
				114B6F7A11FA7598004FB6AB /* CellBuffer.cxx in Sources */,
				114B6F7B11FA7598004FB6AB /* CharClassify.cxx in Sources */,
				114B6F7C11FA7598004FB6AB /* ContractionState.cxx in Sources */,
				114B6F7D11FA7598004FB6AB /* Decoration.cxx in Sources */,
				114B6F7E11FA7598004FB6AB /* Document.cxx in Sources */,
				114B6F7F11FA7598004FB6AB /* Editor.cxx in Sources */,
				114B6F8011FA7598004FB6AB /* ExternalLexer.cxx in Sources */,
				114B6F8111FA7598004FB6AB /* Indicator.cxx in Sources */,
				114B6F8211FA7598004FB6AB /* KeyMap.cxx in Sources */,
				114B6F8311FA7598004FB6AB /* LineMarker.cxx in Sources */,
				114B6F8411FA7598004FB6AB /* PerLine.cxx in Sources */,
				114B6F8511FA7598004FB6AB /* PositionCache.cxx in Sources */,
				114B6F8611FA7598004FB6AB /* RESearch.cxx in Sources */,
				114B6F8711FA7598004FB6AB /* RunStyles.cxx in Sources */,
				114B6F8811FA7598004FB6AB /* ScintillaBase.cxx in Sources */,
				114B6F8911FA7598004FB6AB /* Selection.cxx in Sources */,
				114B6F8A11FA7598004FB6AB /* Style.cxx in Sources */,
				114B6F8B11FA7598004FB6AB /* UniConversion.cxx in Sources */,
				114B6F8C11FA7598004FB6AB /* ViewStyle.cxx in Sources */,
				114B6F8D11FA7598004FB6AB /* XPM.cxx in Sources */,
				114B6F9711FA75BE004FB6AB /* Accessor.cxx in Sources */,
				114B6F9811FA75BE004FB6AB /* CharacterSet.cxx in Sources */,
				114B6F9911FA75BE004FB6AB /* LexerBase.cxx in Sources */,
				114B6F9A11FA75BE004FB6AB /* LexerModule.cxx in Sources */,
				114B6F9B11FA75BE004FB6AB /* LexerNoExceptions.cxx in Sources */,
				114B6F9C11FA75BE004FB6AB /* LexerSimple.cxx in Sources */,
				114B6F9D11FA75BE004FB6AB /* PropSetSimple.cxx in Sources */,
				114B6F9E11FA75BE004FB6AB /* StyleContext.cxx in Sources */,
				114B6F9F11FA75BE004FB6AB /* WordList.cxx in Sources */,
				11F35FDB12AEFAF100F0236D /* LexA68k.cxx in Sources */,
				11BB124D12FF9C1300F6BCF7 /* LexModula.cxx in Sources */,
				11A0A8A1148602DF0018D143 /* LexCoffeeScript.cxx in Sources */,
				117ACE9114A29A1E002876F9 /* LexTCMD.cxx in Sources */,
				11126B8214CD3A6200803C49 /* LexAVS.cxx in Sources */,
				11BEB6A214EF189600BDE92A /* LexECL.cxx in Sources */,
				11594BE9155B91DF0099E1FA /* LexOScript.cxx in Sources */,
				11594BEA155B91DF0099E1FA /* LexVisualProlog.cxx in Sources */,
				1114D6CB1602A951001DC345 /* LexPO.cxx in Sources */,
				1102C31C169FB49300DC16AB /* LexLaTeX.cxx in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				089C1667FE841158C02AAC07 /* English */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		1DEB91AE08733DA50010E9CD /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				COPY_PHASE_STRIP = NO;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				EXCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = ".bzr *.nib *.lproj *.framework *.gch (*) CVS .svn *.xcodeproj *.xcode *.pbproj *.pbxproj";
				FRAMEWORK_VERSION = A;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_MODEL_TUNING = G5;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = Scintilla_Prefix.pch;
				GCC_PREPROCESSOR_DEFINITIONS = (
					SCI_NAMESPACE,
					SCI_LEXER,
				);
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				GCC_WARN_UNINITIALIZED_AUTOS = NO;
				GCC_WARN_UNKNOWN_PRAGMAS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_LABEL = YES;
				INFOPLIST_FILE = Info.plist;
				INSTALL_PATH = "@executable_path/../Frameworks";
				PRODUCT_NAME = Scintilla;
				SDKROOT = macosx10.7;
				WRAPPER_EXTENSION = framework;
			};
			name = Debug;
		};
		1DEB91AF08733DA50010E9CD /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				FRAMEWORK_VERSION = A;
				GCC_MODEL_TUNING = G5;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = Scintilla_Prefix.pch;
				GCC_PREPROCESSOR_DEFINITIONS = (
					SCI_NAMESPACE,
					SCI_LEXER,
				);
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				GCC_WARN_UNINITIALIZED_AUTOS = NO;
				GCC_WARN_UNKNOWN_PRAGMAS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_LABEL = YES;
				INFOPLIST_FILE = Info.plist;
				INSTALL_PATH = "@executable_path/../Frameworks";
				PRODUCT_NAME = Scintilla;
				SDKROOT = macosx10.7;
				WRAPPER_EXTENSION = framework;
			};
			name = Release;
		};
		1DEB91B208733DA50010E9CD /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
				GCC_C_LANGUAGE_STANDARD = c99;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				HEADER_SEARCH_PATHS = (
					../../include,
					../../src,
					../../lexlib,
				);
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = macosx10.7;
			};
			name = Debug;
		};
		1DEB91B308733DA50010E9CD /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
				GCC_C_LANGUAGE_STANDARD = c99;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				HEADER_SEARCH_PATHS = (
					../../include,
					../../src,
					../../lexlib,
				);
				SDKROOT = macosx10.7;
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Scintilla" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				1DEB91AE08733DA50010E9CD /* Debug */,
				1DEB91AF08733DA50010E9CD /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "ScintillaFramework" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				1DEB91B208733DA50010E9CD /* Debug */,
				1DEB91B308733DA50010E9CD /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
}

Added cocoa/ScintillaFramework/Scintilla_Prefix.pch.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
//
// Prefix header for all source files of the 'Scintilla' target in the 'Scintilla' project.
//

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
#endif

Added cocoa/ScintillaTest/AppController.h.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * AppController.h
 * SciTest
 *
 * Created by Mike Lischke on 01.04.09.
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <Cocoa/Cocoa.h>

#import "ScintillaView.h"
#import "InfoBar.h"

@interface AppController : NSObject {
  IBOutlet NSBox *mEditHost;
  ScintillaView* mEditor;
}

- (void) awakeFromNib;
- (void) setupEditor;
- (IBAction) searchText: (id) sender;

@end

Added cocoa/ScintillaTest/AppController.mm.











































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/**
 * AppController.m
 * ScintillaTest
 *
 * Created by Mike Lischke on 01.04.09.
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import "AppController.h"

const char major_keywords[] =
  "accessible add all alter analyze and as asc asensitive "
  "before between bigint binary blob both by "
  "call cascade case change char character check collate column condition connection constraint "
    "continue convert create cross current_date current_time current_timestamp current_user cursor "
  "database databases day_hour day_microsecond day_minute day_second dec decimal declare default "
    "delayed delete desc describe deterministic distinct distinctrow div double drop dual "
  "each else elseif enclosed escaped exists exit explain "
  "false fetch float float4 float8 for force foreign from fulltext "
  "goto grant group "
  "having high_priority hour_microsecond hour_minute hour_second "
  "if ignore in index infile inner inout insensitive insert int int1 int2 int3 int4 int8 integer "
    "interval into is iterate "
  "join "
  "key keys kill "
  "label leading leave left like limit linear lines load localtime localtimestamp lock long "
    "longblob longtext loop low_priority "
  "master_ssl_verify_server_cert match mediumblob mediumint mediumtext middleint minute_microsecond "
    "minute_second mod modifies "
  "natural not no_write_to_binlog null numeric "
  "on optimize option optionally or order out outer outfile "
  "precision primary procedure purge "
  "range read reads read_only read_write real references regexp release rename repeat replace "
    "require restrict return revoke right rlike "
  "schema schemas second_microsecond select sensitive separator set show smallint spatial specific "
    "sql sqlexception sqlstate sqlwarning sql_big_result sql_calc_found_rows sql_small_result ssl "
    "starting straight_join "
  "table terminated then tinyblob tinyint tinytext to trailing trigger true "
  "undo union unique unlock unsigned update upgrade usage use using utc_date utc_time utc_timestamp "
  "values varbinary varchar varcharacter varying "
  "when where while with write "
  "xor "
  "year_month "
  "zerofill";

const char procedure_keywords[] = // Not reserved words but intrinsic part of procedure definitions.
  "begin comment end";

const char client_keywords[] = // Definition of keywords only used by clients, not the server itself.
  "delimiter";

const char user_keywords[] = // Definition of own keywords, not used by MySQL.
  "edit";

//--------------------------------------------------------------------------------------------------

@implementation AppController

- (void) awakeFromNib
{
  // Manually set up the scintilla editor. Create an instance and dock it to our edit host.
  // Leave some free space around the new view to avoid overlapping with the box borders.
  NSRect newFrame = mEditHost.frame;
  newFrame.size.width -= 2 * newFrame.origin.x;
  newFrame.size.height -= 3 * newFrame.origin.y;
  
  mEditor = [[[ScintillaView alloc] initWithFrame: newFrame] autorelease];
  
  [mEditHost.contentView addSubview: mEditor];
  [mEditor setAutoresizesSubviews: YES];
  [mEditor setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
  
  // Let's load some text for the editor, as initial content.
  NSError* error = nil;
  
  NSString* path = [[NSBundle mainBundle] pathForResource: @"TestData" 
                                                   ofType: @"sql" inDirectory: nil];
  
  NSString* sql = [NSString stringWithContentsOfFile: path
                                            encoding: NSUTF8StringEncoding
                                               error: &error];
  if (error && [[error domain] isEqual: NSCocoaErrorDomain])
    NSLog(@"%@", error);
  
  [mEditor setString: sql];

  [self setupEditor];
}

//--------------------------------------------------------------------------------------------------

/**
 * Initialize scintilla editor (styles, colors, markers, folding etc.].
 */
- (void) setupEditor
{  
  // Lexer type is MySQL.
  [mEditor setGeneralProperty: SCI_SETLEXER parameter: SCLEX_MYSQL value: 0];
  // alternatively: [mEditor setEditorProperty: SCI_SETLEXERLANGUAGE parameter: nil value: (sptr_t) "mysql"];
  
  // Number of styles we use with this lexer.
  [mEditor setGeneralProperty: SCI_SETSTYLEBITS value: [mEditor getGeneralProperty: SCI_GETSTYLEBITSNEEDED]];
  
  // Keywords to highlight. Indices are:
  // 0 - Major keywords (reserved keywords)
  // 1 - Normal keywords (everything not reserved but integral part of the language)
  // 2 - Database objects
  // 3 - Function keywords
  // 4 - System variable keywords
  // 5 - Procedure keywords (keywords used in procedures like "begin" and "end")
  // 6..8 - User keywords 1..3
  [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 0 value: major_keywords];
  [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 5 value: procedure_keywords];
  [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 6 value: client_keywords];
  [mEditor setReferenceProperty: SCI_SETKEYWORDS parameter: 7 value: user_keywords];
  
  // Colors and styles for various syntactic elements. First the default style.
  [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Helvetica"];
  // [mEditor setStringProperty: SCI_STYLESETFONT parameter: STYLE_DEFAULT value: @"Monospac821 BT"]; // Very pleasing programmer's font.
  [mEditor setGeneralProperty: SCI_STYLESETSIZE parameter: STYLE_DEFAULT value: 14];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_DEFAULT value: [NSColor blackColor]];

  [mEditor setGeneralProperty: SCI_STYLECLEARALL parameter: 0 value: 0];	
  
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DEFAULT value: [NSColor blackColor]];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENT fromHTML: @"#097BF7"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_COMMENTLINE fromHTML: @"#097BF7"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#097BF7"];
  [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_HIDDENCOMMAND fromHTML: @"#F0F0F0"];
  
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_VARIABLE fromHTML: @"378EA5"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SYSTEMVARIABLE fromHTML: @"378EA5"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KNOWNSYSTEMVARIABLE fromHTML: @"#3A37A5"];
  
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_NUMBER fromHTML: @"#7F7F00"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_SQSTRING fromHTML: @"#FFAA3E"];
  
  // Note: if we were using ANSI quotes we would set the DQSTRING to the same color as the 
  //       the back tick string.
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DQSTRING fromHTML: @"#274A6D"];

  // Keyword highlighting.
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_MAJORKEYWORD fromHTML: @"#007F00"];
  [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_MAJORKEYWORD value: 1];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_KEYWORD fromHTML: @"#007F00"];
  [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_KEYWORD value: 1];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_PROCEDUREKEYWORD fromHTML: @"#56007F"];
  [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_MYSQL_PROCEDUREKEYWORD value: 1];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER1 fromHTML: @"#808080"];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_USER2 fromHTML: @"#808080"];
  [mEditor setColorProperty: SCI_STYLESETBACK parameter: SCE_MYSQL_USER2 fromHTML: @"#F0E0E0"];
  
  // The following 3 styles have no impact as we did not set a keyword list for any of them.
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_DATABASEOBJECT value: [NSColor redColor]];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_FUNCTION value: [NSColor redColor]];
  
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_IDENTIFIER value: [NSColor blackColor]];
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: SCE_MYSQL_QUOTEDIDENTIFIER fromHTML: @"#274A6D"];
  [mEditor setGeneralProperty: SCI_STYLESETBOLD parameter: SCE_SQL_OPERATOR value: 1];
  
  // Line number style.
  [mEditor setColorProperty: SCI_STYLESETFORE parameter: STYLE_LINENUMBER fromHTML: @"#F0F0F0"];
  [mEditor setColorProperty: SCI_STYLESETBACK parameter: STYLE_LINENUMBER fromHTML: @"#808080"];
  
  [mEditor setGeneralProperty: SCI_SETMARGINTYPEN parameter: 0 value: SC_MARGIN_NUMBER];
	[mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 0 value: 35];
  
  // Markers.
  [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 1 value: 16];
  
  // Some special lexer properties.
  [mEditor setLexerProperty: @"fold" value: @"1"];
  [mEditor setLexerProperty: @"fold.compact" value: @"0"];
  [mEditor setLexerProperty: @"fold.comment" value: @"1"];
  [mEditor setLexerProperty: @"fold.preprocessor" value: @"1"];
  
  // Folder setup.
  [mEditor setGeneralProperty: SCI_SETMARGINWIDTHN parameter: 2 value: 16];
  [mEditor setGeneralProperty: SCI_SETMARGINMASKN parameter: 2 value: SC_MASK_FOLDERS];
  [mEditor setGeneralProperty: SCI_SETMARGINSENSITIVEN parameter: 2 value: 1];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPEN value: SC_MARK_BOXMINUS];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDER value: SC_MARK_BOXPLUS];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERSUB value: SC_MARK_VLINE];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERTAIL value: SC_MARK_LCORNER];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEREND value: SC_MARK_BOXPLUSCONNECTED];
  [mEditor setGeneralProperty: SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDEROPENMID value: SC_MARK_BOXMINUSCONNECTED];
  [mEditor setGeneralProperty
   : SCI_MARKERDEFINE parameter: SC_MARKNUM_FOLDERMIDTAIL value: SC_MARK_TCORNER];
  for (int n= 25; n < 32; ++n) // Markers 25..31 are reserved for folding.
  {
    [mEditor setColorProperty: SCI_MARKERSETFORE parameter: n value: [NSColor whiteColor]];
    [mEditor setColorProperty: SCI_MARKERSETBACK parameter: n value: [NSColor blackColor]];
  }
  
  // Init markers & indicators for highlighting of syntax errors.
  [mEditor setColorProperty: SCI_INDICSETFORE parameter: 0 value: [NSColor redColor]];
  [mEditor setGeneralProperty: SCI_INDICSETUNDER parameter: 0 value: 1];
  [mEditor setGeneralProperty: SCI_INDICSETSTYLE parameter: 0 value: INDIC_SQUIGGLE];
  
  [mEditor setColorProperty: SCI_MARKERSETBACK parameter: 0 fromHTML: @"#B1151C"];
  
  [mEditor setColorProperty: SCI_SETSELBACK parameter: 1 value: [NSColor selectedTextBackgroundColor]];
  
  // Uncomment if you wanna see auto wrapping in action.
  //[mEditor setGeneralProperty: SCI_SETWRAPMODE parameter: SC_WRAP_WORD value: 0];
  
  InfoBar* infoBar = [[[InfoBar alloc] initWithFrame: NSMakeRect(0, 0, 400, 0)] autorelease];
  [infoBar setDisplay: IBShowAll];
  [mEditor setInfoBar: infoBar top: NO];
  [mEditor setStatusText: @"Operation complete"];
}

//--------------------------------------------------------------------------------------------------

/* XPM */
static const char * box_xpm[] = {
	"12 12 2 1",
	" 	c None",
	".	c #800000",
	"   .........",
	"  .   .   ..",
	" .   .   . .",
	".........  .",
	".   .   .  .",
	".   .   . ..",
	".   .   .. .",
	".........  .",
	".   .   .  .",
	".   .   . . ",
	".   .   ..  ",
	".........   "};


- (void) showAutocompletion
{
	const char *words = "Babylon-5?1 Battlestar-Galactica Millenium-Falcon?2 Moya?2 Serenity Voyager";
	[mEditor setGeneralProperty: SCI_AUTOCSETIGNORECASE parameter: 1 value:0];
	[mEditor setGeneralProperty: SCI_REGISTERIMAGE parameter: 1 value:(sptr_t)box_xpm];
	const int imSize = 12;
	[mEditor setGeneralProperty: SCI_RGBAIMAGESETWIDTH parameter: imSize value:0];
	[mEditor setGeneralProperty: SCI_RGBAIMAGESETHEIGHT parameter: imSize value:0];
	char image[imSize * imSize * 4];
	for (size_t y = 0; y < imSize; y++) {
		for (size_t x = 0; x < imSize; x++) {
			char *p = image + (y * imSize + x) * 4;
			p[0] = 0xFF;
			p[1] = 0xA0;
			p[2] = 0;
			p[3] = x * 23;
		}
	}
	[mEditor setGeneralProperty: SCI_REGISTERRGBAIMAGE parameter: 2 value:(sptr_t)image];
	[mEditor setGeneralProperty: SCI_AUTOCSHOW parameter: 0 value:(sptr_t)words];
}

- (IBAction) searchText: (id) sender
{
  NSSearchField* searchField = (NSSearchField*) sender;
  [mEditor findAndHighlightText: [searchField stringValue]
                      matchCase: NO
                      wholeWord: NO
                       scrollTo: YES
                           wrap: YES];

  long matchStart = [mEditor getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0];
  long matchEnd = [mEditor getGeneralProperty: SCI_GETSELECTIONEND parameter: 0];
  [mEditor setGeneralProperty: SCI_FINDINDICATORFLASH parameter: matchStart value:matchEnd];

  if ([[searchField stringValue] isEqualToString: @"XX"])
    [self showAutocompletion];
}

@end

//--------------------------------------------------------------------------------------------------

Added cocoa/ScintillaTest/English.lproj/InfoPlist.strings.





>
>
1
2
/* Localized versions of Info.plist keys */

Added cocoa/ScintillaTest/English.lproj/MainMenu.xib.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
	<data>
		<int key="IBDocument.SystemTarget">1050</int>
		<string key="IBDocument.SystemVersion">10D573</string>
		<string key="IBDocument.InterfaceBuilderVersion">762</string>
		<string key="IBDocument.AppKitVersion">1038.29</string>
		<string key="IBDocument.HIToolboxVersion">460.00</string>
		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
			<string key="NS.object.0">762</string>
		</object>
		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
			<bool key="EncodedWithXMLCoder">YES</bool>
			<integer value="372"/>
		</object>
		<object class="NSArray" key="IBDocument.PluginDependencies">
			<bool key="EncodedWithXMLCoder">YES</bool>
			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
		</object>
		<object class="NSMutableDictionary" key="IBDocument.Metadata">
			<bool key="EncodedWithXMLCoder">YES</bool>
			<object class="NSArray" key="dict.sortedKeys" id="0">
				<bool key="EncodedWithXMLCoder">YES</bool>
			</object>
			<object class="NSMutableArray" key="dict.values">
				<bool key="EncodedWithXMLCoder">YES</bool>
			</object>
		</object>
		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
			<bool key="EncodedWithXMLCoder">YES</bool>
			<object class="NSCustomObject" id="1021">
				<string key="NSClassName">NSApplication</string>
			</object>
			<object class="NSCustomObject" id="1014">
				<string key="NSClassName">FirstResponder</string>
			</object>
			<object class="NSCustomObject" id="1050">
				<string key="NSClassName">NSApplication</string>
			</object>
			<object class="NSMenu" id="649796088">
				<string key="NSTitle">AMainMenu</string>
				<object class="NSMutableArray" key="NSMenuItems">
					<bool key="EncodedWithXMLCoder">YES</bool>
					<object class="NSMenuItem" id="694149608">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">NewApplication</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<object class="NSCustomResource" key="NSOnImage" id="35465992">
							<string key="NSClassName">NSImage</string>
							<string key="NSResourceName">NSMenuCheckmark</string>
						</object>
						<object class="NSCustomResource" key="NSMixedImage" id="502551668">
							<string key="NSClassName">NSImage</string>
							<string key="NSResourceName">NSMenuMixedState</string>
						</object>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="110575045">
							<string key="NSTitle">NewApplication</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="238522557">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">About NewApplication</string>
									<string key="NSKeyEquiv"/>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="304266470">
									<reference key="NSMenu" ref="110575045"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="609285721">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Preferences…</string>
									<string key="NSKeyEquiv">,</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="481834944">
									<reference key="NSMenu" ref="110575045"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1046388886">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Services</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="752062318">
										<string key="NSTitle">Services</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
										</object>
										<string key="NSName">_NSServicesMenu</string>
									</object>
								</object>
								<object class="NSMenuItem" id="646227648">
									<reference key="NSMenu" ref="110575045"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="755159360">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Hide NewApplication</string>
									<string key="NSKeyEquiv">h</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="342932134">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Hide Others</string>
									<string key="NSKeyEquiv">h</string>
									<int key="NSKeyEquivModMask">1572864</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="908899353">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Show All</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1056857174">
									<reference key="NSMenu" ref="110575045"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="632727374">
									<reference key="NSMenu" ref="110575045"/>
									<string key="NSTitle">Quit NewApplication</string>
									<string key="NSKeyEquiv">q</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
							</object>
							<string key="NSName">_NSAppleMenu</string>
						</object>
					</object>
					<object class="NSMenuItem" id="379814623">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">File</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="720053764">
							<string key="NSTitle">File</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="705341025">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">New</string>
									<string key="NSKeyEquiv">n</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="722745758">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Open…</string>
									<string key="NSKeyEquiv">o</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1025936716">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Open Recent</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="1065607017">
										<string key="NSTitle">Open Recent</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="759406840">
												<reference key="NSMenu" ref="1065607017"/>
												<string key="NSTitle">Clear Menu</string>
												<string key="NSKeyEquiv"/>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
										<string key="NSName">_NSRecentDocumentsMenu</string>
									</object>
								</object>
								<object class="NSMenuItem" id="425164168">
									<reference key="NSMenu" ref="720053764"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="776162233">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Close</string>
									<string key="NSKeyEquiv">w</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1023925487">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Save</string>
									<string key="NSKeyEquiv">s</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="117038363">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Save As…</string>
									<string key="NSKeyEquiv">S</string>
									<int key="NSKeyEquivModMask">1179648</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="579971712">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Revert to Saved</string>
									<string key="NSKeyEquiv"/>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1010469920">
									<reference key="NSMenu" ref="720053764"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="294629803">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Page Setup...</string>
									<string key="NSKeyEquiv">P</string>
									<int key="NSKeyEquivModMask">1179648</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSToolTip"/>
								</object>
								<object class="NSMenuItem" id="49223823">
									<reference key="NSMenu" ref="720053764"/>
									<string key="NSTitle">Print…</string>
									<string key="NSKeyEquiv">p</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
							</object>
						</object>
					</object>
					<object class="NSMenuItem" id="952259628">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">Edit</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="789758025">
							<string key="NSTitle">Edit</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="1058277027">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Undo</string>
									<string key="NSKeyEquiv">z</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="790794224">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Redo</string>
									<string key="NSKeyEquiv">Z</string>
									<int key="NSKeyEquivModMask">1179648</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="1040322652">
									<reference key="NSMenu" ref="789758025"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="296257095">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Cut</string>
									<string key="NSKeyEquiv">x</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="860595796">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Copy</string>
									<string key="NSKeyEquiv">c</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="29853731">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Paste</string>
									<string key="NSKeyEquiv">v</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="437104165">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Delete</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="583158037">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Select All</string>
									<string key="NSKeyEquiv">a</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="212016141">
									<reference key="NSMenu" ref="789758025"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="892235320">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Find</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="963351320">
										<string key="NSTitle">Find</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="447796847">
												<reference key="NSMenu" ref="963351320"/>
												<string key="NSTitle">Find…</string>
												<string key="NSKeyEquiv">f</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">1</int>
											</object>
											<object class="NSMenuItem" id="326711663">
												<reference key="NSMenu" ref="963351320"/>
												<string key="NSTitle">Find Next</string>
												<string key="NSKeyEquiv">g</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">2</int>
											</object>
											<object class="NSMenuItem" id="270902937">
												<reference key="NSMenu" ref="963351320"/>
												<string key="NSTitle">Find Previous</string>
												<string key="NSKeyEquiv">G</string>
												<int key="NSKeyEquivModMask">1179648</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">3</int>
											</object>
											<object class="NSMenuItem" id="159080638">
												<reference key="NSMenu" ref="963351320"/>
												<string key="NSTitle">Use Selection for Find</string>
												<string key="NSKeyEquiv">e</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">7</int>
											</object>
											<object class="NSMenuItem" id="88285865">
												<reference key="NSMenu" ref="963351320"/>
												<string key="NSTitle">Jump to Selection</string>
												<string key="NSKeyEquiv">j</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
									</object>
								</object>
								<object class="NSMenuItem" id="972420730">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Spelling and Grammar</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="769623530">
										<string key="NSTitle">Spelling and Grammar</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="679648819">
												<reference key="NSMenu" ref="769623530"/>
												<string key="NSTitle">Show Spelling…</string>
												<string key="NSKeyEquiv">:</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="96193923">
												<reference key="NSMenu" ref="769623530"/>
												<string key="NSTitle">Check Spelling</string>
												<string key="NSKeyEquiv">;</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="948374510">
												<reference key="NSMenu" ref="769623530"/>
												<string key="NSTitle">Check Spelling While Typing</string>
												<string key="NSKeyEquiv"/>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="967646866">
												<reference key="NSMenu" ref="769623530"/>
												<string key="NSTitle">Check Grammar With Spelling</string>
												<string key="NSKeyEquiv"/>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
									</object>
								</object>
								<object class="NSMenuItem" id="507821607">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Substitutions</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="698887838">
										<string key="NSTitle">Substitutions</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="605118523">
												<reference key="NSMenu" ref="698887838"/>
												<string key="NSTitle">Smart Copy/Paste</string>
												<string key="NSKeyEquiv">f</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">1</int>
											</object>
											<object class="NSMenuItem" id="197661976">
												<reference key="NSMenu" ref="698887838"/>
												<string key="NSTitle">Smart Quotes</string>
												<string key="NSKeyEquiv">g</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">2</int>
											</object>
											<object class="NSMenuItem" id="708854459">
												<reference key="NSMenu" ref="698887838"/>
												<string key="NSTitle">Smart Links</string>
												<string key="NSKeyEquiv">G</string>
												<int key="NSKeyEquivModMask">1179648</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">3</int>
											</object>
										</object>
									</object>
								</object>
								<object class="NSMenuItem" id="676164635">
									<reference key="NSMenu" ref="789758025"/>
									<string key="NSTitle">Speech</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="785027613">
										<string key="NSTitle">Speech</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="731782645">
												<reference key="NSMenu" ref="785027613"/>
												<string key="NSTitle">Start Speaking</string>
												<string key="NSKeyEquiv"/>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="680220178">
												<reference key="NSMenu" ref="785027613"/>
												<string key="NSTitle">Stop Speaking</string>
												<string key="NSKeyEquiv"/>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
									</object>
								</object>
							</object>
						</object>
					</object>
					<object class="NSMenuItem" id="302598603">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">Format</string>
						<string key="NSKeyEquiv"/>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="941447902">
							<string key="NSTitle">Format</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="792887677">
									<reference key="NSMenu" ref="941447902"/>
									<string key="NSTitle">Font</string>
									<string key="NSKeyEquiv"/>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="786677654">
										<string key="NSTitle">Font</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="159677712">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Show Fonts</string>
												<string key="NSKeyEquiv">t</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="305399458">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Bold</string>
												<string key="NSKeyEquiv">b</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">2</int>
											</object>
											<object class="NSMenuItem" id="814362025">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Italic</string>
												<string key="NSKeyEquiv">i</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">1</int>
											</object>
											<object class="NSMenuItem" id="330926929">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Underline</string>
												<string key="NSKeyEquiv">u</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="533507878">
												<reference key="NSMenu" ref="786677654"/>
												<bool key="NSIsDisabled">YES</bool>
												<bool key="NSIsSeparator">YES</bool>
												<string key="NSTitle"/>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="158063935">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Bigger</string>
												<string key="NSKeyEquiv">+</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">3</int>
											</object>
											<object class="NSMenuItem" id="885547335">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Smaller</string>
												<string key="NSKeyEquiv">-</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<int key="NSTag">4</int>
											</object>
											<object class="NSMenuItem" id="901062459">
												<reference key="NSMenu" ref="786677654"/>
												<bool key="NSIsDisabled">YES</bool>
												<bool key="NSIsSeparator">YES</bool>
												<string key="NSTitle"/>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="767671776">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Kern</string>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<string key="NSAction">submenuAction:</string>
												<object class="NSMenu" key="NSSubmenu" id="175441468">
													<string key="NSTitle">Kern</string>
													<object class="NSMutableArray" key="NSMenuItems">
														<bool key="EncodedWithXMLCoder">YES</bool>
														<object class="NSMenuItem" id="252969304">
															<reference key="NSMenu" ref="175441468"/>
															<string key="NSTitle">Use Default</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="766922938">
															<reference key="NSMenu" ref="175441468"/>
															<string key="NSTitle">Use None</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="677519740">
															<reference key="NSMenu" ref="175441468"/>
															<string key="NSTitle">Tighten</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="238351151">
															<reference key="NSMenu" ref="175441468"/>
															<string key="NSTitle">Loosen</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
													</object>
												</object>
											</object>
											<object class="NSMenuItem" id="691570813">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Ligature</string>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<string key="NSAction">submenuAction:</string>
												<object class="NSMenu" key="NSSubmenu" id="1058217995">
													<string key="NSTitle">Ligature</string>
													<object class="NSMutableArray" key="NSMenuItems">
														<bool key="EncodedWithXMLCoder">YES</bool>
														<object class="NSMenuItem" id="706297211">
															<reference key="NSMenu" ref="1058217995"/>
															<string key="NSTitle">Use Default</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="568384683">
															<reference key="NSMenu" ref="1058217995"/>
															<string key="NSTitle">Use None</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="663508465">
															<reference key="NSMenu" ref="1058217995"/>
															<string key="NSTitle">Use All</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
													</object>
												</object>
											</object>
											<object class="NSMenuItem" id="769124883">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Baseline</string>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
												<string key="NSAction">submenuAction:</string>
												<object class="NSMenu" key="NSSubmenu" id="18263474">
													<string key="NSTitle">Baseline</string>
													<object class="NSMutableArray" key="NSMenuItems">
														<bool key="EncodedWithXMLCoder">YES</bool>
														<object class="NSMenuItem" id="257962622">
															<reference key="NSMenu" ref="18263474"/>
															<string key="NSTitle">Use Default</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="644725453">
															<reference key="NSMenu" ref="18263474"/>
															<string key="NSTitle">Superscript</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="1037576581">
															<reference key="NSMenu" ref="18263474"/>
															<string key="NSTitle">Subscript</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="941806246">
															<reference key="NSMenu" ref="18263474"/>
															<string key="NSTitle">Raise</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
														<object class="NSMenuItem" id="1045724900">
															<reference key="NSMenu" ref="18263474"/>
															<string key="NSTitle">Lower</string>
															<string key="NSKeyEquiv"/>
															<int key="NSMnemonicLoc">2147483647</int>
															<reference key="NSOnImage" ref="35465992"/>
															<reference key="NSMixedImage" ref="502551668"/>
														</object>
													</object>
												</object>
											</object>
											<object class="NSMenuItem" id="739652853">
												<reference key="NSMenu" ref="786677654"/>
												<bool key="NSIsDisabled">YES</bool>
												<bool key="NSIsSeparator">YES</bool>
												<string key="NSTitle"/>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="1012600125">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Show Colors</string>
												<string key="NSKeyEquiv">C</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="214559597">
												<reference key="NSMenu" ref="786677654"/>
												<bool key="NSIsDisabled">YES</bool>
												<bool key="NSIsSeparator">YES</bool>
												<string key="NSTitle"/>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="596732606">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Copy Style</string>
												<string key="NSKeyEquiv">c</string>
												<int key="NSKeyEquivModMask">1572864</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="393423671">
												<reference key="NSMenu" ref="786677654"/>
												<string key="NSTitle">Paste Style</string>
												<string key="NSKeyEquiv">v</string>
												<int key="NSKeyEquivModMask">1572864</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
										<string key="NSName">_NSFontMenu</string>
									</object>
								</object>
								<object class="NSMenuItem" id="15516124">
									<reference key="NSMenu" ref="941447902"/>
									<string key="NSTitle">Text</string>
									<string key="NSKeyEquiv"/>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
									<string key="NSAction">submenuAction:</string>
									<object class="NSMenu" key="NSSubmenu" id="23081656">
										<string key="NSTitle">Text</string>
										<object class="NSMutableArray" key="NSMenuItems">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSMenuItem" id="135107054">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Align Left</string>
												<string key="NSKeyEquiv">{</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="310547522">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Center</string>
												<string key="NSKeyEquiv">|</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="436088763">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Justify</string>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="498119243">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Align Right</string>
												<string key="NSKeyEquiv">}</string>
												<int key="NSKeyEquivModMask">1048576</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="607995063">
												<reference key="NSMenu" ref="23081656"/>
												<bool key="NSIsDisabled">YES</bool>
												<bool key="NSIsSeparator">YES</bool>
												<string key="NSTitle"/>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="420564933">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Show Ruler</string>
												<string key="NSKeyEquiv"/>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="479856769">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Copy Ruler</string>
												<string key="NSKeyEquiv">c</string>
												<int key="NSKeyEquivModMask">1310720</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
											<object class="NSMenuItem" id="333628178">
												<reference key="NSMenu" ref="23081656"/>
												<string key="NSTitle">Paste Ruler</string>
												<string key="NSKeyEquiv">v</string>
												<int key="NSKeyEquivModMask">1310720</int>
												<int key="NSMnemonicLoc">2147483647</int>
												<reference key="NSOnImage" ref="35465992"/>
												<reference key="NSMixedImage" ref="502551668"/>
											</object>
										</object>
									</object>
								</object>
							</object>
						</object>
					</object>
					<object class="NSMenuItem" id="586577488">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">View</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="466310130">
							<string key="NSTitle">View</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="102151532">
									<reference key="NSMenu" ref="466310130"/>
									<string key="NSTitle">Show Toolbar</string>
									<string key="NSKeyEquiv">t</string>
									<int key="NSKeyEquivModMask">1572864</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="237841660">
									<reference key="NSMenu" ref="466310130"/>
									<string key="NSTitle">Customize Toolbar…</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
							</object>
						</object>
					</object>
					<object class="NSMenuItem" id="713487014">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">Window</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="835318025">
							<string key="NSTitle">Window</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="1011231497">
									<reference key="NSMenu" ref="835318025"/>
									<string key="NSTitle">Minimize</string>
									<string key="NSKeyEquiv">m</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="575023229">
									<reference key="NSMenu" ref="835318025"/>
									<string key="NSTitle">Zoom</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="299356726">
									<reference key="NSMenu" ref="835318025"/>
									<bool key="NSIsDisabled">YES</bool>
									<bool key="NSIsSeparator">YES</bool>
									<string key="NSTitle"/>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
								<object class="NSMenuItem" id="625202149">
									<reference key="NSMenu" ref="835318025"/>
									<string key="NSTitle">Bring All to Front</string>
									<string key="NSKeyEquiv"/>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
							</object>
							<string key="NSName">_NSWindowsMenu</string>
						</object>
					</object>
					<object class="NSMenuItem" id="391199113">
						<reference key="NSMenu" ref="649796088"/>
						<string key="NSTitle">Help</string>
						<string key="NSKeyEquiv"/>
						<int key="NSKeyEquivModMask">1048576</int>
						<int key="NSMnemonicLoc">2147483647</int>
						<reference key="NSOnImage" ref="35465992"/>
						<reference key="NSMixedImage" ref="502551668"/>
						<string key="NSAction">submenuAction:</string>
						<object class="NSMenu" key="NSSubmenu" id="374024848">
							<string key="NSTitle">Help</string>
							<object class="NSMutableArray" key="NSMenuItems">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSMenuItem" id="238773614">
									<reference key="NSMenu" ref="374024848"/>
									<string key="NSTitle">NewApplication Help</string>
									<string key="NSKeyEquiv">?</string>
									<int key="NSKeyEquivModMask">1048576</int>
									<int key="NSMnemonicLoc">2147483647</int>
									<reference key="NSOnImage" ref="35465992"/>
									<reference key="NSMixedImage" ref="502551668"/>
								</object>
							</object>
						</object>
					</object>
				</object>
				<string key="NSName">_NSMainMenu</string>
			</object>
			<object class="NSWindowTemplate" id="972006081">
				<int key="NSWindowStyleMask">15</int>
				<int key="NSWindowBacking">2</int>
				<string key="NSWindowRect">{{335, 58}, {982, 692}}</string>
				<int key="NSWTFlags">1946157056</int>
				<string key="NSWindowTitle">Window</string>
				<string key="NSWindowClass">NSWindow</string>
				<nil key="NSViewClass"/>
				<string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
				<object class="NSView" key="NSWindowView" id="439893737">
					<reference key="NSNextResponder"/>
					<int key="NSvFlags">319</int>
					<object class="NSMutableArray" key="NSSubviews">
						<bool key="EncodedWithXMLCoder">YES</bool>
						<object class="NSBox" id="1016473779">
							<reference key="NSNextResponder" ref="439893737"/>
							<int key="NSvFlags">18</int>
							<object class="NSMutableArray" key="NSSubviews">
								<bool key="EncodedWithXMLCoder">YES</bool>
								<object class="NSView" id="33804839">
									<reference key="NSNextResponder" ref="1016473779"/>
									<int key="NSvFlags">256</int>
									<string key="NSFrame">{{1, 1}, {842, 590}}</string>
									<reference key="NSSuperview" ref="1016473779"/>
								</object>
							</object>
							<string key="NSFrame">{{17, 16}, {844, 606}}</string>
							<reference key="NSSuperview" ref="439893737"/>
							<string key="NSOffsets">{0, 0}</string>
							<object class="NSTextFieldCell" key="NSTitleCell">
								<int key="NSCellFlags">67239424</int>
								<int key="NSCellFlags2">0</int>
								<string key="NSContents">Scintilla Editor</string>
								<object class="NSFont" key="NSSupport">
									<string key="NSName">LucidaGrande</string>
									<double key="NSSize">11</double>
									<int key="NSfFlags">3100</int>
								</object>
								<object class="NSColor" key="NSBackgroundColor" id="561710607">
									<int key="NSColorSpace">6</int>
									<string key="NSCatalogName">System</string>
									<string key="NSColorName">textBackgroundColor</string>
									<object class="NSColor" key="NSColor">
										<int key="NSColorSpace">3</int>
										<bytes key="NSWhite">MQA</bytes>
									</object>
								</object>
								<object class="NSColor" key="NSTextColor">
									<int key="NSColorSpace">3</int>
									<bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
								</object>
							</object>
							<reference key="NSContentView" ref="33804839"/>
							<int key="NSBorderType">1</int>
							<int key="NSBoxType">0</int>
							<int key="NSTitlePosition">2</int>
							<bool key="NSTransparent">NO</bool>
						</object>
						<object class="NSButton" id="610247741">
							<reference key="NSNextResponder" ref="439893737"/>
							<int key="NSvFlags">289</int>
							<string key="NSFrame">{{872, 12}, {96, 32}}</string>
							<reference key="NSSuperview" ref="439893737"/>
							<bool key="NSEnabled">YES</bool>
							<object class="NSButtonCell" key="NSCell" id="1009897894">
								<int key="NSCellFlags">67239424</int>
								<int key="NSCellFlags2">134217728</int>
								<string key="NSContents">Quit</string>
								<object class="NSFont" key="NSSupport" id="887178038">
									<string key="NSName">LucidaGrande</string>
									<double key="NSSize">13</double>
									<int key="NSfFlags">1044</int>
								</object>
								<reference key="NSControlView" ref="610247741"/>
								<int key="NSButtonFlags">-2038284033</int>
								<int key="NSButtonFlags2">129</int>
								<string key="NSAlternateContents"/>
								<string key="NSKeyEquivalent"/>
								<int key="NSPeriodicDelay">200</int>
								<int key="NSPeriodicInterval">25</int>
							</object>
						</object>
						<object class="NSSearchField" id="552917647">
							<reference key="NSNextResponder" ref="439893737"/>
							<int key="NSvFlags">268</int>
							<string key="NSFrame">{{20, 630}, {287, 22}}</string>
							<reference key="NSSuperview" ref="439893737"/>
							<bool key="NSEnabled">YES</bool>
							<object class="NSSearchFieldCell" key="NSCell" id="515024530">
								<int key="NSCellFlags">343014976</int>
								<int key="NSCellFlags2">268436480</int>
								<string key="NSContents"/>
								<reference key="NSSupport" ref="887178038"/>
								<reference key="NSControlView" ref="552917647"/>
								<bool key="NSDrawsBackground">YES</bool>
								<int key="NSTextBezelStyle">1</int>
								<reference key="NSBackgroundColor" ref="561710607"/>
								<object class="NSColor" key="NSTextColor">
									<int key="NSColorSpace">6</int>
									<string key="NSCatalogName">System</string>
									<string key="NSColorName">controlTextColor</string>
									<object class="NSColor" key="NSColor">
										<int key="NSColorSpace">3</int>
										<bytes key="NSWhite">MAA</bytes>
									</object>
								</object>
								<object class="NSButtonCell" key="NSSearchButtonCell">
									<int key="NSCellFlags">130560</int>
									<int key="NSCellFlags2">0</int>
									<string key="NSContents">search</string>
									<reference key="NSControlView" ref="552917647"/>
									<string key="NSAction">_searchFieldSearch:</string>
									<reference key="NSTarget" ref="515024530"/>
									<int key="NSButtonFlags">138690815</int>
									<int key="NSButtonFlags2">0</int>
									<string key="NSKeyEquivalent"/>
									<int key="NSPeriodicDelay">400</int>
									<int key="NSPeriodicInterval">75</int>
								</object>
								<object class="NSButtonCell" key="NSCancelButtonCell">
									<int key="NSCellFlags">130560</int>
									<int key="NSCellFlags2">0</int>
									<string key="NSContents">clear</string>
									<object class="NSMutableArray" key="NSAccessibilityOverriddenAttributes">
										<bool key="EncodedWithXMLCoder">YES</bool>
										<object class="NSMutableDictionary">
											<bool key="EncodedWithXMLCoder">YES</bool>
											<object class="NSArray" key="dict.sortedKeys">
												<bool key="EncodedWithXMLCoder">YES</bool>
												<string>AXDescription</string>
												<string>NSAccessibilityEncodedAttributesValueType</string>
											</object>
											<object class="NSMutableArray" key="dict.values">
												<bool key="EncodedWithXMLCoder">YES</bool>
												<string>cancel</string>
												<integer value="1"/>
											</object>
										</object>
									</object>
									<reference key="NSControlView" ref="552917647"/>
									<string key="NSAction">_searchFieldCancel:</string>
									<reference key="NSTarget" ref="515024530"/>
									<int key="NSButtonFlags">138690815</int>
									<int key="NSButtonFlags2">0</int>
									<string key="NSKeyEquivalent"/>
									<int key="NSPeriodicDelay">400</int>
									<int key="NSPeriodicInterval">75</int>
								</object>
								<int key="NSMaximumRecents">255</int>
							</object>
						</object>
					</object>
					<string key="NSFrameSize">{982, 692}</string>
					<reference key="NSSuperview"/>
				</object>
				<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
				<string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
			</object>
			<object class="NSCustomObject" id="755631768">
				<string key="NSClassName">NSFontManager</string>
			</object>
			<object class="NSCustomObject" id="229445039">
				<string key="NSClassName">AppController</string>
			</object>
		</object>
		<object class="IBObjectContainer" key="IBDocument.Objects">
			<object class="NSMutableArray" key="connectionRecords">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">performMiniaturize:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1011231497"/>
					</object>
					<int key="connectionID">37</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">arrangeInFront:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="625202149"/>
					</object>
					<int key="connectionID">39</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">print:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="49223823"/>
					</object>
					<int key="connectionID">86</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">runPageLayout:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="294629803"/>
					</object>
					<int key="connectionID">87</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">clearRecentDocuments:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="759406840"/>
					</object>
					<int key="connectionID">127</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">orderFrontStandardAboutPanel:</string>
						<reference key="source" ref="1021"/>
						<reference key="destination" ref="238522557"/>
					</object>
					<int key="connectionID">142</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">performClose:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="776162233"/>
					</object>
					<int key="connectionID">193</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleContinuousSpellChecking:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="948374510"/>
					</object>
					<int key="connectionID">222</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">undo:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1058277027"/>
					</object>
					<int key="connectionID">223</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">copy:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="860595796"/>
					</object>
					<int key="connectionID">224</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">checkSpelling:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="96193923"/>
					</object>
					<int key="connectionID">225</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">paste:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="29853731"/>
					</object>
					<int key="connectionID">226</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">stopSpeaking:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="680220178"/>
					</object>
					<int key="connectionID">227</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">cut:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="296257095"/>
					</object>
					<int key="connectionID">228</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">showGuessPanel:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="679648819"/>
					</object>
					<int key="connectionID">230</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">redo:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="790794224"/>
					</object>
					<int key="connectionID">231</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">selectAll:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="583158037"/>
					</object>
					<int key="connectionID">232</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">startSpeaking:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="731782645"/>
					</object>
					<int key="connectionID">233</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">delete:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="437104165"/>
					</object>
					<int key="connectionID">235</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">performZoom:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="575023229"/>
					</object>
					<int key="connectionID">240</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">performFindPanelAction:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="447796847"/>
					</object>
					<int key="connectionID">241</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">centerSelectionInVisibleArea:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="88285865"/>
					</object>
					<int key="connectionID">245</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleGrammarChecking:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="967646866"/>
					</object>
					<int key="connectionID">347</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleSmartInsertDelete:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="605118523"/>
					</object>
					<int key="connectionID">355</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleAutomaticQuoteSubstitution:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="197661976"/>
					</object>
					<int key="connectionID">356</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleAutomaticLinkDetection:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="708854459"/>
					</object>
					<int key="connectionID">357</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">showHelp:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="238773614"/>
					</object>
					<int key="connectionID">360</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">saveDocument:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1023925487"/>
					</object>
					<int key="connectionID">362</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">saveDocumentAs:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="117038363"/>
					</object>
					<int key="connectionID">363</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">revertDocumentToSaved:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="579971712"/>
					</object>
					<int key="connectionID">364</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">runToolbarCustomizationPalette:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="237841660"/>
					</object>
					<int key="connectionID">365</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleToolbarShown:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="102151532"/>
					</object>
					<int key="connectionID">366</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">hide:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="755159360"/>
					</object>
					<int key="connectionID">367</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">hideOtherApplications:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="342932134"/>
					</object>
					<int key="connectionID">368</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">unhideAllApplications:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="908899353"/>
					</object>
					<int key="connectionID">370</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">newDocument:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="705341025"/>
					</object>
					<int key="connectionID">373</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">openDocument:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="722745758"/>
					</object>
					<int key="connectionID">374</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">addFontTrait:</string>
						<reference key="source" ref="755631768"/>
						<reference key="destination" ref="305399458"/>
					</object>
					<int key="connectionID">421</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">addFontTrait:</string>
						<reference key="source" ref="755631768"/>
						<reference key="destination" ref="814362025"/>
					</object>
					<int key="connectionID">422</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">modifyFont:</string>
						<reference key="source" ref="755631768"/>
						<reference key="destination" ref="885547335"/>
					</object>
					<int key="connectionID">423</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">orderFrontFontPanel:</string>
						<reference key="source" ref="755631768"/>
						<reference key="destination" ref="159677712"/>
					</object>
					<int key="connectionID">424</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">modifyFont:</string>
						<reference key="source" ref="755631768"/>
						<reference key="destination" ref="158063935"/>
					</object>
					<int key="connectionID">425</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">raiseBaseline:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="941806246"/>
					</object>
					<int key="connectionID">426</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">lowerBaseline:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1045724900"/>
					</object>
					<int key="connectionID">427</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">copyFont:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="596732606"/>
					</object>
					<int key="connectionID">428</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">subscript:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1037576581"/>
					</object>
					<int key="connectionID">429</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">superscript:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="644725453"/>
					</object>
					<int key="connectionID">430</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">tightenKerning:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="677519740"/>
					</object>
					<int key="connectionID">431</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">underline:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="330926929"/>
					</object>
					<int key="connectionID">432</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">orderFrontColorPanel:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="1012600125"/>
					</object>
					<int key="connectionID">433</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">useAllLigatures:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="663508465"/>
					</object>
					<int key="connectionID">434</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">loosenKerning:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="238351151"/>
					</object>
					<int key="connectionID">435</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">pasteFont:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="393423671"/>
					</object>
					<int key="connectionID">436</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">unscript:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="257962622"/>
					</object>
					<int key="connectionID">437</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">useStandardKerning:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="252969304"/>
					</object>
					<int key="connectionID">438</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">useStandardLigatures:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="706297211"/>
					</object>
					<int key="connectionID">439</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">turnOffLigatures:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="568384683"/>
					</object>
					<int key="connectionID">440</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">turnOffKerning:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="766922938"/>
					</object>
					<int key="connectionID">441</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">alignLeft:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="135107054"/>
					</object>
					<int key="connectionID">442</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">alignJustified:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="436088763"/>
					</object>
					<int key="connectionID">443</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">copyRuler:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="479856769"/>
					</object>
					<int key="connectionID">444</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">alignCenter:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="310547522"/>
					</object>
					<int key="connectionID">445</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">toggleRuler:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="420564933"/>
					</object>
					<int key="connectionID">446</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">alignRight:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="498119243"/>
					</object>
					<int key="connectionID">447</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">pasteRuler:</string>
						<reference key="source" ref="1014"/>
						<reference key="destination" ref="333628178"/>
					</object>
					<int key="connectionID">448</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">terminate:</string>
						<reference key="source" ref="1050"/>
						<reference key="destination" ref="632727374"/>
					</object>
					<int key="connectionID">449</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBOutletConnection" key="connection">
						<string key="label">mEditHost</string>
						<reference key="source" ref="229445039"/>
						<reference key="destination" ref="1016473779"/>
					</object>
					<int key="connectionID">454</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">terminate:</string>
						<reference key="source" ref="1050"/>
						<reference key="destination" ref="610247741"/>
					</object>
					<int key="connectionID">455</int>
				</object>
				<object class="IBConnectionRecord">
					<object class="IBActionConnection" key="connection">
						<string key="label">searchText:</string>
						<reference key="source" ref="229445039"/>
						<reference key="destination" ref="552917647"/>
					</object>
					<int key="connectionID">468</int>
				</object>
			</object>
			<object class="IBMutableOrderedSet" key="objectRecords">
				<object class="NSArray" key="orderedObjects">
					<bool key="EncodedWithXMLCoder">YES</bool>
					<object class="IBObjectRecord">
						<int key="objectID">0</int>
						<reference key="object" ref="0"/>
						<reference key="children" ref="1048"/>
						<nil key="parent"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">-2</int>
						<reference key="object" ref="1021"/>
						<reference key="parent" ref="0"/>
						<string key="objectName">File's Owner</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">-1</int>
						<reference key="object" ref="1014"/>
						<reference key="parent" ref="0"/>
						<string key="objectName">First Responder</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">-3</int>
						<reference key="object" ref="1050"/>
						<reference key="parent" ref="0"/>
						<string key="objectName">Application</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">29</int>
						<reference key="object" ref="649796088"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="713487014"/>
							<reference ref="694149608"/>
							<reference ref="391199113"/>
							<reference ref="952259628"/>
							<reference ref="379814623"/>
							<reference ref="586577488"/>
							<reference ref="302598603"/>
						</object>
						<reference key="parent" ref="0"/>
						<string key="objectName">MainMenu</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">19</int>
						<reference key="object" ref="713487014"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="835318025"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">56</int>
						<reference key="object" ref="694149608"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="110575045"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">103</int>
						<reference key="object" ref="391199113"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="374024848"/>
						</object>
						<reference key="parent" ref="649796088"/>
						<string key="objectName">1</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">217</int>
						<reference key="object" ref="952259628"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="789758025"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">83</int>
						<reference key="object" ref="379814623"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="720053764"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">81</int>
						<reference key="object" ref="720053764"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="1023925487"/>
							<reference ref="117038363"/>
							<reference ref="49223823"/>
							<reference ref="722745758"/>
							<reference ref="705341025"/>
							<reference ref="1025936716"/>
							<reference ref="294629803"/>
							<reference ref="776162233"/>
							<reference ref="425164168"/>
							<reference ref="579971712"/>
							<reference ref="1010469920"/>
						</object>
						<reference key="parent" ref="379814623"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">75</int>
						<reference key="object" ref="1023925487"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">3</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">80</int>
						<reference key="object" ref="117038363"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">8</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">78</int>
						<reference key="object" ref="49223823"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">6</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">72</int>
						<reference key="object" ref="722745758"/>
						<reference key="parent" ref="720053764"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">82</int>
						<reference key="object" ref="705341025"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">9</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">124</int>
						<reference key="object" ref="1025936716"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="1065607017"/>
						</object>
						<reference key="parent" ref="720053764"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">77</int>
						<reference key="object" ref="294629803"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">5</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">73</int>
						<reference key="object" ref="776162233"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">1</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">79</int>
						<reference key="object" ref="425164168"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">7</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">112</int>
						<reference key="object" ref="579971712"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">10</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">74</int>
						<reference key="object" ref="1010469920"/>
						<reference key="parent" ref="720053764"/>
						<string key="objectName">2</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">125</int>
						<reference key="object" ref="1065607017"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="759406840"/>
						</object>
						<reference key="parent" ref="1025936716"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">126</int>
						<reference key="object" ref="759406840"/>
						<reference key="parent" ref="1065607017"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">205</int>
						<reference key="object" ref="789758025"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="437104165"/>
							<reference ref="583158037"/>
							<reference ref="1058277027"/>
							<reference ref="212016141"/>
							<reference ref="296257095"/>
							<reference ref="29853731"/>
							<reference ref="860595796"/>
							<reference ref="1040322652"/>
							<reference ref="790794224"/>
							<reference ref="892235320"/>
							<reference ref="972420730"/>
							<reference ref="676164635"/>
							<reference ref="507821607"/>
						</object>
						<reference key="parent" ref="952259628"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">202</int>
						<reference key="object" ref="437104165"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">198</int>
						<reference key="object" ref="583158037"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">207</int>
						<reference key="object" ref="1058277027"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">214</int>
						<reference key="object" ref="212016141"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">199</int>
						<reference key="object" ref="296257095"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">203</int>
						<reference key="object" ref="29853731"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">197</int>
						<reference key="object" ref="860595796"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">206</int>
						<reference key="object" ref="1040322652"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">215</int>
						<reference key="object" ref="790794224"/>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">218</int>
						<reference key="object" ref="892235320"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="963351320"/>
						</object>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">216</int>
						<reference key="object" ref="972420730"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="769623530"/>
						</object>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">200</int>
						<reference key="object" ref="769623530"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="948374510"/>
							<reference ref="96193923"/>
							<reference ref="679648819"/>
							<reference ref="967646866"/>
						</object>
						<reference key="parent" ref="972420730"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">219</int>
						<reference key="object" ref="948374510"/>
						<reference key="parent" ref="769623530"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">201</int>
						<reference key="object" ref="96193923"/>
						<reference key="parent" ref="769623530"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">204</int>
						<reference key="object" ref="679648819"/>
						<reference key="parent" ref="769623530"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">220</int>
						<reference key="object" ref="963351320"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="270902937"/>
							<reference ref="88285865"/>
							<reference ref="159080638"/>
							<reference ref="326711663"/>
							<reference ref="447796847"/>
						</object>
						<reference key="parent" ref="892235320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">213</int>
						<reference key="object" ref="270902937"/>
						<reference key="parent" ref="963351320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">210</int>
						<reference key="object" ref="88285865"/>
						<reference key="parent" ref="963351320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">221</int>
						<reference key="object" ref="159080638"/>
						<reference key="parent" ref="963351320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">208</int>
						<reference key="object" ref="326711663"/>
						<reference key="parent" ref="963351320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">209</int>
						<reference key="object" ref="447796847"/>
						<reference key="parent" ref="963351320"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">106</int>
						<reference key="object" ref="374024848"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="238773614"/>
						</object>
						<reference key="parent" ref="391199113"/>
						<string key="objectName">2</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">111</int>
						<reference key="object" ref="238773614"/>
						<reference key="parent" ref="374024848"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">57</int>
						<reference key="object" ref="110575045"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="238522557"/>
							<reference ref="755159360"/>
							<reference ref="908899353"/>
							<reference ref="632727374"/>
							<reference ref="646227648"/>
							<reference ref="609285721"/>
							<reference ref="481834944"/>
							<reference ref="304266470"/>
							<reference ref="1046388886"/>
							<reference ref="1056857174"/>
							<reference ref="342932134"/>
						</object>
						<reference key="parent" ref="694149608"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">58</int>
						<reference key="object" ref="238522557"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">134</int>
						<reference key="object" ref="755159360"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">150</int>
						<reference key="object" ref="908899353"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">136</int>
						<reference key="object" ref="632727374"/>
						<reference key="parent" ref="110575045"/>
						<string key="objectName">1111</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">144</int>
						<reference key="object" ref="646227648"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">129</int>
						<reference key="object" ref="609285721"/>
						<reference key="parent" ref="110575045"/>
						<string key="objectName">121</string>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">143</int>
						<reference key="object" ref="481834944"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">236</int>
						<reference key="object" ref="304266470"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">131</int>
						<reference key="object" ref="1046388886"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="752062318"/>
						</object>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">149</int>
						<reference key="object" ref="1056857174"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">145</int>
						<reference key="object" ref="342932134"/>
						<reference key="parent" ref="110575045"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">130</int>
						<reference key="object" ref="752062318"/>
						<reference key="parent" ref="1046388886"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">24</int>
						<reference key="object" ref="835318025"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="299356726"/>
							<reference ref="625202149"/>
							<reference ref="575023229"/>
							<reference ref="1011231497"/>
						</object>
						<reference key="parent" ref="713487014"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">92</int>
						<reference key="object" ref="299356726"/>
						<reference key="parent" ref="835318025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">5</int>
						<reference key="object" ref="625202149"/>
						<reference key="parent" ref="835318025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">239</int>
						<reference key="object" ref="575023229"/>
						<reference key="parent" ref="835318025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">23</int>
						<reference key="object" ref="1011231497"/>
						<reference key="parent" ref="835318025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">295</int>
						<reference key="object" ref="586577488"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="466310130"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">296</int>
						<reference key="object" ref="466310130"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="102151532"/>
							<reference ref="237841660"/>
						</object>
						<reference key="parent" ref="586577488"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">297</int>
						<reference key="object" ref="102151532"/>
						<reference key="parent" ref="466310130"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">298</int>
						<reference key="object" ref="237841660"/>
						<reference key="parent" ref="466310130"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">211</int>
						<reference key="object" ref="676164635"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="785027613"/>
						</object>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">212</int>
						<reference key="object" ref="785027613"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="680220178"/>
							<reference ref="731782645"/>
						</object>
						<reference key="parent" ref="676164635"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">195</int>
						<reference key="object" ref="680220178"/>
						<reference key="parent" ref="785027613"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">196</int>
						<reference key="object" ref="731782645"/>
						<reference key="parent" ref="785027613"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">346</int>
						<reference key="object" ref="967646866"/>
						<reference key="parent" ref="769623530"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">348</int>
						<reference key="object" ref="507821607"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="698887838"/>
						</object>
						<reference key="parent" ref="789758025"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">349</int>
						<reference key="object" ref="698887838"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="605118523"/>
							<reference ref="197661976"/>
							<reference ref="708854459"/>
						</object>
						<reference key="parent" ref="507821607"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">350</int>
						<reference key="object" ref="605118523"/>
						<reference key="parent" ref="698887838"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">351</int>
						<reference key="object" ref="197661976"/>
						<reference key="parent" ref="698887838"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">354</int>
						<reference key="object" ref="708854459"/>
						<reference key="parent" ref="698887838"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">371</int>
						<reference key="object" ref="972006081"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="439893737"/>
						</object>
						<reference key="parent" ref="0"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">372</int>
						<reference key="object" ref="439893737"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="1016473779"/>
							<reference ref="610247741"/>
							<reference ref="552917647"/>
						</object>
						<reference key="parent" ref="972006081"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">375</int>
						<reference key="object" ref="302598603"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="941447902"/>
						</object>
						<reference key="parent" ref="649796088"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">376</int>
						<reference key="object" ref="941447902"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="792887677"/>
							<reference ref="15516124"/>
						</object>
						<reference key="parent" ref="302598603"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">377</int>
						<reference key="object" ref="792887677"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="786677654"/>
						</object>
						<reference key="parent" ref="941447902"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">378</int>
						<reference key="object" ref="15516124"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="23081656"/>
						</object>
						<reference key="parent" ref="941447902"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">379</int>
						<reference key="object" ref="23081656"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="135107054"/>
							<reference ref="310547522"/>
							<reference ref="436088763"/>
							<reference ref="498119243"/>
							<reference ref="607995063"/>
							<reference ref="420564933"/>
							<reference ref="479856769"/>
							<reference ref="333628178"/>
						</object>
						<reference key="parent" ref="15516124"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">380</int>
						<reference key="object" ref="135107054"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">381</int>
						<reference key="object" ref="310547522"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">382</int>
						<reference key="object" ref="436088763"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">383</int>
						<reference key="object" ref="498119243"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">384</int>
						<reference key="object" ref="607995063"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">385</int>
						<reference key="object" ref="420564933"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">386</int>
						<reference key="object" ref="479856769"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">387</int>
						<reference key="object" ref="333628178"/>
						<reference key="parent" ref="23081656"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">388</int>
						<reference key="object" ref="786677654"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="159677712"/>
							<reference ref="305399458"/>
							<reference ref="814362025"/>
							<reference ref="330926929"/>
							<reference ref="533507878"/>
							<reference ref="158063935"/>
							<reference ref="885547335"/>
							<reference ref="901062459"/>
							<reference ref="767671776"/>
							<reference ref="691570813"/>
							<reference ref="769124883"/>
							<reference ref="739652853"/>
							<reference ref="1012600125"/>
							<reference ref="214559597"/>
							<reference ref="596732606"/>
							<reference ref="393423671"/>
						</object>
						<reference key="parent" ref="792887677"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">389</int>
						<reference key="object" ref="159677712"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">390</int>
						<reference key="object" ref="305399458"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">391</int>
						<reference key="object" ref="814362025"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">392</int>
						<reference key="object" ref="330926929"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">393</int>
						<reference key="object" ref="533507878"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">394</int>
						<reference key="object" ref="158063935"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">395</int>
						<reference key="object" ref="885547335"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">396</int>
						<reference key="object" ref="901062459"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">397</int>
						<reference key="object" ref="767671776"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="175441468"/>
						</object>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">398</int>
						<reference key="object" ref="691570813"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="1058217995"/>
						</object>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">399</int>
						<reference key="object" ref="769124883"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="18263474"/>
						</object>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">400</int>
						<reference key="object" ref="739652853"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">401</int>
						<reference key="object" ref="1012600125"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">402</int>
						<reference key="object" ref="214559597"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">403</int>
						<reference key="object" ref="596732606"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">404</int>
						<reference key="object" ref="393423671"/>
						<reference key="parent" ref="786677654"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">405</int>
						<reference key="object" ref="18263474"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="257962622"/>
							<reference ref="644725453"/>
							<reference ref="1037576581"/>
							<reference ref="941806246"/>
							<reference ref="1045724900"/>
						</object>
						<reference key="parent" ref="769124883"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">406</int>
						<reference key="object" ref="257962622"/>
						<reference key="parent" ref="18263474"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">407</int>
						<reference key="object" ref="644725453"/>
						<reference key="parent" ref="18263474"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">408</int>
						<reference key="object" ref="1037576581"/>
						<reference key="parent" ref="18263474"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">409</int>
						<reference key="object" ref="941806246"/>
						<reference key="parent" ref="18263474"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">410</int>
						<reference key="object" ref="1045724900"/>
						<reference key="parent" ref="18263474"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">411</int>
						<reference key="object" ref="1058217995"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="706297211"/>
							<reference ref="568384683"/>
							<reference ref="663508465"/>
						</object>
						<reference key="parent" ref="691570813"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">412</int>
						<reference key="object" ref="706297211"/>
						<reference key="parent" ref="1058217995"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">413</int>
						<reference key="object" ref="568384683"/>
						<reference key="parent" ref="1058217995"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">414</int>
						<reference key="object" ref="663508465"/>
						<reference key="parent" ref="1058217995"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">415</int>
						<reference key="object" ref="175441468"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="252969304"/>
							<reference ref="766922938"/>
							<reference ref="677519740"/>
							<reference ref="238351151"/>
						</object>
						<reference key="parent" ref="767671776"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">416</int>
						<reference key="object" ref="252969304"/>
						<reference key="parent" ref="175441468"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">417</int>
						<reference key="object" ref="766922938"/>
						<reference key="parent" ref="175441468"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">418</int>
						<reference key="object" ref="677519740"/>
						<reference key="parent" ref="175441468"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">419</int>
						<reference key="object" ref="238351151"/>
						<reference key="parent" ref="175441468"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">420</int>
						<reference key="object" ref="755631768"/>
						<reference key="parent" ref="0"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">450</int>
						<reference key="object" ref="229445039"/>
						<reference key="parent" ref="0"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">451</int>
						<reference key="object" ref="1016473779"/>
						<reference key="parent" ref="439893737"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">452</int>
						<reference key="object" ref="610247741"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="1009897894"/>
						</object>
						<reference key="parent" ref="439893737"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">453</int>
						<reference key="object" ref="1009897894"/>
						<reference key="parent" ref="610247741"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">466</int>
						<reference key="object" ref="552917647"/>
						<object class="NSMutableArray" key="children">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<reference ref="515024530"/>
						</object>
						<reference key="parent" ref="439893737"/>
					</object>
					<object class="IBObjectRecord">
						<int key="objectID">467</int>
						<reference key="object" ref="515024530"/>
						<reference key="parent" ref="552917647"/>
					</object>
				</object>
			</object>
			<object class="NSMutableDictionary" key="flattenedProperties">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<object class="NSArray" key="dict.sortedKeys">
					<bool key="EncodedWithXMLCoder">YES</bool>
					<string>-3.IBPluginDependency</string>
					<string>103.IBPluginDependency</string>
					<string>103.ImportedFromIB2</string>
					<string>106.IBPluginDependency</string>
					<string>106.ImportedFromIB2</string>
					<string>106.editorWindowContentRectSynchronizationRect</string>
					<string>111.IBPluginDependency</string>
					<string>111.ImportedFromIB2</string>
					<string>112.IBPluginDependency</string>
					<string>112.ImportedFromIB2</string>
					<string>124.IBPluginDependency</string>
					<string>124.ImportedFromIB2</string>
					<string>125.IBPluginDependency</string>
					<string>125.ImportedFromIB2</string>
					<string>125.editorWindowContentRectSynchronizationRect</string>
					<string>126.IBPluginDependency</string>
					<string>126.ImportedFromIB2</string>
					<string>129.IBPluginDependency</string>
					<string>129.ImportedFromIB2</string>
					<string>130.IBPluginDependency</string>
					<string>130.ImportedFromIB2</string>
					<string>130.editorWindowContentRectSynchronizationRect</string>
					<string>131.IBPluginDependency</string>
					<string>131.ImportedFromIB2</string>
					<string>134.IBPluginDependency</string>
					<string>134.ImportedFromIB2</string>
					<string>136.IBPluginDependency</string>
					<string>136.ImportedFromIB2</string>
					<string>143.IBPluginDependency</string>
					<string>143.ImportedFromIB2</string>
					<string>144.IBPluginDependency</string>
					<string>144.ImportedFromIB2</string>
					<string>145.IBPluginDependency</string>
					<string>145.ImportedFromIB2</string>
					<string>149.IBPluginDependency</string>
					<string>149.ImportedFromIB2</string>
					<string>150.IBPluginDependency</string>
					<string>150.ImportedFromIB2</string>
					<string>19.IBPluginDependency</string>
					<string>19.ImportedFromIB2</string>
					<string>195.IBPluginDependency</string>
					<string>195.ImportedFromIB2</string>
					<string>196.IBPluginDependency</string>
					<string>196.ImportedFromIB2</string>
					<string>197.IBPluginDependency</string>
					<string>197.ImportedFromIB2</string>
					<string>198.IBPluginDependency</string>
					<string>198.ImportedFromIB2</string>
					<string>199.IBPluginDependency</string>
					<string>199.ImportedFromIB2</string>
					<string>200.IBPluginDependency</string>
					<string>200.ImportedFromIB2</string>
					<string>200.editorWindowContentRectSynchronizationRect</string>
					<string>201.IBPluginDependency</string>
					<string>201.ImportedFromIB2</string>
					<string>202.IBPluginDependency</string>
					<string>202.ImportedFromIB2</string>
					<string>203.IBPluginDependency</string>
					<string>203.ImportedFromIB2</string>
					<string>204.IBPluginDependency</string>
					<string>204.ImportedFromIB2</string>
					<string>205.IBPluginDependency</string>
					<string>205.ImportedFromIB2</string>
					<string>205.editorWindowContentRectSynchronizationRect</string>
					<string>206.IBPluginDependency</string>
					<string>206.ImportedFromIB2</string>
					<string>207.IBPluginDependency</string>
					<string>207.ImportedFromIB2</string>
					<string>208.IBPluginDependency</string>
					<string>208.ImportedFromIB2</string>
					<string>209.IBPluginDependency</string>
					<string>209.ImportedFromIB2</string>
					<string>210.IBPluginDependency</string>
					<string>210.ImportedFromIB2</string>
					<string>211.IBPluginDependency</string>
					<string>211.ImportedFromIB2</string>
					<string>212.IBPluginDependency</string>
					<string>212.ImportedFromIB2</string>
					<string>212.editorWindowContentRectSynchronizationRect</string>
					<string>213.IBPluginDependency</string>
					<string>213.ImportedFromIB2</string>
					<string>214.IBPluginDependency</string>
					<string>214.ImportedFromIB2</string>
					<string>215.IBPluginDependency</string>
					<string>215.ImportedFromIB2</string>
					<string>216.IBPluginDependency</string>
					<string>216.ImportedFromIB2</string>
					<string>217.IBPluginDependency</string>
					<string>217.ImportedFromIB2</string>
					<string>218.IBPluginDependency</string>
					<string>218.ImportedFromIB2</string>
					<string>219.IBPluginDependency</string>
					<string>219.ImportedFromIB2</string>
					<string>220.IBPluginDependency</string>
					<string>220.ImportedFromIB2</string>
					<string>220.editorWindowContentRectSynchronizationRect</string>
					<string>221.IBPluginDependency</string>
					<string>221.ImportedFromIB2</string>
					<string>23.IBPluginDependency</string>
					<string>23.ImportedFromIB2</string>
					<string>236.IBPluginDependency</string>
					<string>236.ImportedFromIB2</string>
					<string>239.IBPluginDependency</string>
					<string>239.ImportedFromIB2</string>
					<string>24.IBPluginDependency</string>
					<string>24.ImportedFromIB2</string>
					<string>24.editorWindowContentRectSynchronizationRect</string>
					<string>29.IBEditorWindowLastContentRect</string>
					<string>29.IBPluginDependency</string>
					<string>29.ImportedFromIB2</string>
					<string>29.WindowOrigin</string>
					<string>29.editorWindowContentRectSynchronizationRect</string>
					<string>295.IBPluginDependency</string>
					<string>296.IBPluginDependency</string>
					<string>296.editorWindowContentRectSynchronizationRect</string>
					<string>297.IBPluginDependency</string>
					<string>298.IBPluginDependency</string>
					<string>346.IBPluginDependency</string>
					<string>346.ImportedFromIB2</string>
					<string>348.IBPluginDependency</string>
					<string>348.ImportedFromIB2</string>
					<string>349.IBPluginDependency</string>
					<string>349.ImportedFromIB2</string>
					<string>349.editorWindowContentRectSynchronizationRect</string>
					<string>350.IBPluginDependency</string>
					<string>350.ImportedFromIB2</string>
					<string>351.IBPluginDependency</string>
					<string>351.ImportedFromIB2</string>
					<string>354.IBPluginDependency</string>
					<string>354.ImportedFromIB2</string>
					<string>371.IBEditorWindowLastContentRect</string>
					<string>371.IBPluginDependency</string>
					<string>371.IBWindowTemplateEditedContentRect</string>
					<string>371.NSWindowTemplate.visibleAtLaunch</string>
					<string>371.editorWindowContentRectSynchronizationRect</string>
					<string>371.windowTemplate.maxSize</string>
					<string>372.IBPluginDependency</string>
					<string>375.IBPluginDependency</string>
					<string>376.IBEditorWindowLastContentRect</string>
					<string>376.IBPluginDependency</string>
					<string>377.IBPluginDependency</string>
					<string>378.IBPluginDependency</string>
					<string>379.IBPluginDependency</string>
					<string>380.IBPluginDependency</string>
					<string>381.IBPluginDependency</string>
					<string>382.IBPluginDependency</string>
					<string>383.IBPluginDependency</string>
					<string>384.IBPluginDependency</string>
					<string>385.IBPluginDependency</string>
					<string>386.IBPluginDependency</string>
					<string>387.IBPluginDependency</string>
					<string>388.IBEditorWindowLastContentRect</string>
					<string>388.IBPluginDependency</string>
					<string>389.IBPluginDependency</string>
					<string>390.IBPluginDependency</string>
					<string>391.IBPluginDependency</string>
					<string>392.IBPluginDependency</string>
					<string>393.IBPluginDependency</string>
					<string>394.IBPluginDependency</string>
					<string>395.IBPluginDependency</string>
					<string>396.IBPluginDependency</string>
					<string>397.IBPluginDependency</string>
					<string>398.IBPluginDependency</string>
					<string>399.IBPluginDependency</string>
					<string>400.IBPluginDependency</string>
					<string>401.IBPluginDependency</string>
					<string>402.IBPluginDependency</string>
					<string>403.IBPluginDependency</string>
					<string>404.IBPluginDependency</string>
					<string>405.IBPluginDependency</string>
					<string>406.IBPluginDependency</string>
					<string>407.IBPluginDependency</string>
					<string>408.IBPluginDependency</string>
					<string>409.IBPluginDependency</string>
					<string>410.IBPluginDependency</string>
					<string>411.IBPluginDependency</string>
					<string>412.IBPluginDependency</string>
					<string>413.IBPluginDependency</string>
					<string>414.IBPluginDependency</string>
					<string>415.IBPluginDependency</string>
					<string>416.IBPluginDependency</string>
					<string>417.IBPluginDependency</string>
					<string>418.IBPluginDependency</string>
					<string>419.IBPluginDependency</string>
					<string>451.IBPluginDependency</string>
					<string>452.IBPluginDependency</string>
					<string>453.IBPluginDependency</string>
					<string>466.IBPluginDependency</string>
					<string>467.IBPluginDependency</string>
					<string>5.IBPluginDependency</string>
					<string>5.ImportedFromIB2</string>
					<string>56.IBPluginDependency</string>
					<string>56.ImportedFromIB2</string>
					<string>57.IBEditorWindowLastContentRect</string>
					<string>57.IBPluginDependency</string>
					<string>57.ImportedFromIB2</string>
					<string>57.editorWindowContentRectSynchronizationRect</string>
					<string>58.IBPluginDependency</string>
					<string>58.ImportedFromIB2</string>
					<string>72.IBPluginDependency</string>
					<string>72.ImportedFromIB2</string>
					<string>73.IBPluginDependency</string>
					<string>73.ImportedFromIB2</string>
					<string>74.IBPluginDependency</string>
					<string>74.ImportedFromIB2</string>
					<string>75.IBPluginDependency</string>
					<string>75.ImportedFromIB2</string>
					<string>77.IBPluginDependency</string>
					<string>77.ImportedFromIB2</string>
					<string>78.IBPluginDependency</string>
					<string>78.ImportedFromIB2</string>
					<string>79.IBPluginDependency</string>
					<string>79.ImportedFromIB2</string>
					<string>80.IBPluginDependency</string>
					<string>80.ImportedFromIB2</string>
					<string>81.IBPluginDependency</string>
					<string>81.ImportedFromIB2</string>
					<string>81.editorWindowContentRectSynchronizationRect</string>
					<string>82.IBPluginDependency</string>
					<string>82.ImportedFromIB2</string>
					<string>83.IBPluginDependency</string>
					<string>83.ImportedFromIB2</string>
					<string>92.IBPluginDependency</string>
					<string>92.ImportedFromIB2</string>
				</object>
				<object class="NSMutableArray" key="dict.values">
					<bool key="EncodedWithXMLCoder">YES</bool>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{596, 852}, {216, 23}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{522, 812}, {146, 23}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{436, 809}, {64, 6}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{608, 612}, {275, 83}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{187, 434}, {243, 243}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{608, 612}, {167, 43}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{608, 612}, {241, 103}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{525, 802}, {197, 73}}</string>
					<string>{{207, 285}, {478, 20}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{74, 862}</string>
					<string>{{6, 978}, {478, 20}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>{{475, 832}, {234, 43}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{608, 612}, {215, 63}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{274, 370}, {982, 692}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>{{274, 370}, {982, 692}}</string>
					<integer value="1"/>
					<string>{{33, 99}, {480, 360}}</string>
					<string>{3.40282e+38, 3.40282e+38}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>{{437, 242}, {86, 43}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>{{523, 2}, {178, 283}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{219, 102}, {245, 183}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{23, 794}, {245, 183}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>{{145, 474}, {199, 203}}</string>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
					<integer value="1"/>
				</object>
			</object>
			<object class="NSMutableDictionary" key="unlocalizedProperties">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<reference key="dict.sortedKeys" ref="0"/>
				<object class="NSMutableArray" key="dict.values">
					<bool key="EncodedWithXMLCoder">YES</bool>
				</object>
			</object>
			<nil key="activeLocalization"/>
			<object class="NSMutableDictionary" key="localizations">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<reference key="dict.sortedKeys" ref="0"/>
				<object class="NSMutableArray" key="dict.values">
					<bool key="EncodedWithXMLCoder">YES</bool>
				</object>
			</object>
			<nil key="sourceID"/>
			<int key="maxID">468</int>
		</object>
		<object class="IBClassDescriber" key="IBDocument.Classes">
			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<object class="IBPartialClassDescription">
					<string key="className">AppController</string>
					<string key="superclassName">NSObject</string>
					<object class="NSMutableDictionary" key="actions">
						<string key="NS.key.0">searchText:</string>
						<string key="NS.object.0">id</string>
					</object>
					<object class="NSMutableDictionary" key="outlets">
						<string key="NS.key.0">mEditHost</string>
						<string key="NS.object.0">NSBox</string>
					</object>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBProjectSource</string>
						<string key="minorKey">AppController.h</string>
					</object>
				</object>
			</object>
			<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<object class="IBPartialClassDescription">
					<string key="className">NSActionCell</string>
					<string key="superclassName">NSCell</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<string key="superclassName">NSResponder</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="905531705">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="854027565">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="562071960">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSApplication</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSBox</string>
					<string key="superclassName">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSBox.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSBrowser</string>
					<string key="superclassName">NSControl</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSButton</string>
					<string key="superclassName">NSControl</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSButton.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSButtonCell</string>
					<string key="superclassName">NSActionCell</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSButtonCell.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSCell</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSCell.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSControl</string>
					<string key="superclassName">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="10957210">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSDocument</string>
					<string key="superclassName">NSObject</string>
					<object class="NSMutableDictionary" key="actions">
						<bool key="EncodedWithXMLCoder">YES</bool>
						<object class="NSArray" key="dict.sortedKeys">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<string>printDocument:</string>
							<string>revertDocumentToSaved:</string>
							<string>runPageLayout:</string>
							<string>saveDocument:</string>
							<string>saveDocumentAs:</string>
							<string>saveDocumentTo:</string>
						</object>
						<object class="NSMutableArray" key="dict.values">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<string>id</string>
							<string>id</string>
							<string>id</string>
							<string>id</string>
							<string>id</string>
							<string>id</string>
						</object>
					</object>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDocument.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSDocument</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSDocumentController</string>
					<string key="superclassName">NSObject</string>
					<object class="NSMutableDictionary" key="actions">
						<bool key="EncodedWithXMLCoder">YES</bool>
						<object class="NSArray" key="dict.sortedKeys">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<string>clearRecentDocuments:</string>
							<string>newDocument:</string>
							<string>openDocument:</string>
							<string>saveAllDocuments:</string>
						</object>
						<object class="NSMutableArray" key="dict.values">
							<bool key="EncodedWithXMLCoder">YES</bool>
							<string>id</string>
							<string>id</string>
							<string>id</string>
							<string>id</string>
						</object>
					</object>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSFontManager</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="60454901">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSFormatter</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSMatrix</string>
					<string key="superclassName">NSControl</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSMenu</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="687201532">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSMenu.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSMenuItem</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="283337664">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSMovieView</string>
					<string key="superclassName">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="905531705"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="854027565"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="562071960"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="10957210"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDragging.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="60454901"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<reference key="sourceIdentifier" ref="687201532"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="1040540259">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSTableView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier" id="763667182">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSResponder</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSResponder</string>
					<string key="superclassName">NSObject</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSSearchField</string>
					<string key="superclassName">NSTextField</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSSearchField.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSSearchFieldCell</string>
					<string key="superclassName">NSTextFieldCell</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSSearchFieldCell.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSTableView</string>
					<string key="superclassName">NSControl</string>
					<reference key="sourceIdentifier" ref="1040540259"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSText</string>
					<string key="superclassName">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSText.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSTextField</string>
					<string key="superclassName">NSControl</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSTextField.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSTextFieldCell</string>
					<string key="superclassName">NSActionCell</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSTextView</string>
					<string key="superclassName">NSText</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSTextView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSClipView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSView</string>
					<reference key="sourceIdentifier" ref="283337664"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSView</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSView</string>
					<string key="superclassName">NSResponder</string>
					<reference key="sourceIdentifier" ref="763667182"/>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSWindow</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSWindow</string>
					<string key="superclassName">NSResponder</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
					</object>
				</object>
				<object class="IBPartialClassDescription">
					<string key="className">NSWindow</string>
					<object class="IBClassDescriptionSource" key="sourceIdentifier">
						<string key="majorKey">IBFrameworkSource</string>
						<string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string>
					</object>
				</object>
			</object>
		</object>
		<int key="IBDocument.localizationMode">0</int>
		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
			<integer value="1050" key="NS.object.0"/>
		</object>
		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
			<integer value="1050" key="NS.object.0"/>
		</object>
		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
			<integer value="3000" key="NS.object.0"/>
		</object>
		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
		<string key="IBDocument.LastKnownRelativeProjectPath">../ScintillaTest.xcodeproj</string>
		<int key="IBDocument.defaultPropertyAccessControl">3</int>
		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
			<bool key="EncodedWithXMLCoder">YES</bool>
			<object class="NSArray" key="dict.sortedKeys">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<string>NSMenuCheckmark</string>
				<string>NSMenuMixedState</string>
			</object>
			<object class="NSMutableArray" key="dict.values">
				<bool key="EncodedWithXMLCoder">YES</bool>
				<string>{9, 8}</string>
				<string>{7, 2}</string>
			</object>
		</object>
	</data>
</archive>

Added cocoa/ScintillaTest/Info.plist.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>com.sun.${PRODUCT_NAME:identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>

Added cocoa/ScintillaTest/Scintilla-Info.plist.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIdentifier</key>
	<string>com.sun.${PRODUCT_NAME:identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
</dict>
</plist>

Added cocoa/ScintillaTest/ScintillaTest.xcodeproj/project.pbxproj.









































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
		271FA52C0F850BE20033D021 /* AppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 271FA52B0F850BE20033D021 /* AppController.mm */; };
		2791F4490FC1A8E9009DBCF9 /* TestData.sql in Resources */ = {isa = PBXBuildFile; fileRef = 2791F4480FC1A8E9009DBCF9 /* TestData.sql */; };
		27AF7EC30FC2C351007160EF /* Scintilla.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */; };
		27AF7ECA0FC2C388007160EF /* Scintilla.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2744E5EA0FC16BE200E85C33 /* Scintilla.framework */; };
		8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
		8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
		8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		2744E5E90FC16BE200E85C33 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
			proxyType = 2;
			remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
			remoteInfo = Scintilla;
		};
		27AF7EC60FC2C36A007160EF /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
			proxyType = 1;
			remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
			remoteInfo = Scintilla;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		272133C20F973596006BE49A /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "";
			dstSubfolderSpec = 10;
			files = (
				27AF7ECA0FC2C388007160EF /* Scintilla.framework in CopyFiles */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
		13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
		1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = "<group>"; };
		271FA52A0F850BE20033D021 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
		271FA52B0F850BE20033D021 /* AppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppController.mm; sourceTree = "<group>"; wrapsLines = 0; };
		2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ScintillaFramework.xcodeproj; path = ../ScintillaFramework/ScintillaFramework.xcodeproj; sourceTree = SOURCE_ROOT; };
		2791F4480FC1A8E9009DBCF9 /* TestData.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestData.sql; sourceTree = "<group>"; };
		29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
		29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
		32CA4F630368D1EE00C91783 /* ScintillaTest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScintillaTest_Prefix.pch; sourceTree = "<group>"; };
		8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		8D1107320486CEB800E47090 /* ScintillaTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScintillaTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		8D11072E0486CEB800E47090 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				27AF7EC30FC2C351007160EF /* Scintilla.framework in Frameworks */,
				8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		080E96DDFE201D6D7F000001 /* Classes */ = {
			isa = PBXGroup;
			children = (
				271FA52A0F850BE20033D021 /* AppController.h */,
				271FA52B0F850BE20033D021 /* AppController.mm */,
			);
			name = Classes;
			sourceTree = "<group>";
		};
		1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
			isa = PBXGroup;
			children = (
				1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
			);
			name = "Linked Frameworks";
			sourceTree = "<group>";
		};
		1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
			isa = PBXGroup;
			children = (
				29B97324FDCFA39411CA2CEA /* AppKit.framework */,
				13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
				29B97325FDCFA39411CA2CEA /* Foundation.framework */,
			);
			name = "Other Frameworks";
			sourceTree = "<group>";
		};
		19C28FACFE9D520D11CA2CBB /* Products */ = {
			isa = PBXGroup;
			children = (
				8D1107320486CEB800E47090 /* ScintillaTest.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		2744E5E30FC16BE200E85C33 /* Products */ = {
			isa = PBXGroup;
			children = (
				2744E5EA0FC16BE200E85C33 /* Scintilla.framework */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		29B97314FDCFA39411CA2CEA /* ScintillaTest */ = {
			isa = PBXGroup;
			children = (
				2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */,
				080E96DDFE201D6D7F000001 /* Classes */,
				29B97315FDCFA39411CA2CEA /* Other Sources */,
				29B97317FDCFA39411CA2CEA /* Resources */,
				29B97323FDCFA39411CA2CEA /* Frameworks */,
				19C28FACFE9D520D11CA2CBB /* Products */,
			);
			name = ScintillaTest;
			sourceTree = "<group>";
		};
		29B97315FDCFA39411CA2CEA /* Other Sources */ = {
			isa = PBXGroup;
			children = (
				32CA4F630368D1EE00C91783 /* ScintillaTest_Prefix.pch */,
				29B97316FDCFA39411CA2CEA /* main.m */,
			);
			name = "Other Sources";
			sourceTree = "<group>";
		};
		29B97317FDCFA39411CA2CEA /* Resources */ = {
			isa = PBXGroup;
			children = (
				2791F4480FC1A8E9009DBCF9 /* TestData.sql */,
				8D1107310486CEB800E47090 /* Info.plist */,
				089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
				1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
			);
			name = Resources;
			sourceTree = "<group>";
		};
		29B97323FDCFA39411CA2CEA /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
				1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		8D1107260486CEB800E47090 /* ScintillaTest */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ScintillaTest" */;
			buildPhases = (
				8D1107290486CEB800E47090 /* Resources */,
				8D11072C0486CEB800E47090 /* Sources */,
				8D11072E0486CEB800E47090 /* Frameworks */,
				272133C20F973596006BE49A /* CopyFiles */,
			);
			buildRules = (
			);
			dependencies = (
				27AF7EC70FC2C36A007160EF /* PBXTargetDependency */,
			);
			name = ScintillaTest;
			productInstallPath = "$(HOME)/Applications";
			productName = ScintillaTest;
			productReference = 8D1107320486CEB800E47090 /* ScintillaTest.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		29B97313FDCFA39411CA2CEA /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0450;
			};
			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ScintillaTest" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 1;
			knownRegions = (
				English,
				Japanese,
				French,
				German,
			);
			mainGroup = 29B97314FDCFA39411CA2CEA /* ScintillaTest */;
			projectDirPath = "";
			projectReferences = (
				{
					ProductGroup = 2744E5E30FC16BE200E85C33 /* Products */;
					ProjectRef = 2744E5E20FC16BE200E85C33 /* ScintillaFramework.xcodeproj */;
				},
			);
			projectRoot = "";
			targets = (
				8D1107260486CEB800E47090 /* ScintillaTest */,
			);
		};
/* End PBXProject section */

/* Begin PBXReferenceProxy section */
		2744E5EA0FC16BE200E85C33 /* Scintilla.framework */ = {
			isa = PBXReferenceProxy;
			fileType = wrapper.framework;
			path = Scintilla.framework;
			remoteRef = 2744E5E90FC16BE200E85C33 /* PBXContainerItemProxy */;
			sourceTree = BUILT_PRODUCTS_DIR;
		};
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
		8D1107290486CEB800E47090 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
				1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
				2791F4490FC1A8E9009DBCF9 /* TestData.sql in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		8D11072C0486CEB800E47090 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				8D11072D0486CEB800E47090 /* main.m in Sources */,
				271FA52C0F850BE20033D021 /* AppController.mm in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		27AF7EC70FC2C36A007160EF /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			name = Scintilla;
			targetProxy = 27AF7EC60FC2C36A007160EF /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				089C165DFE840E0CC02AAC07 /* English */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
		1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {
			isa = PBXVariantGroup;
			children = (
				1DDD58150DA1D0A300B32029 /* English */,
			);
			name = MainMenu.xib;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		C01FCF4B08A954540054247B /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				COPY_PHASE_STRIP = NO;
				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_MODEL_TUNING = G5;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = ScintillaTest_Prefix.pch;
				GCC_PREPROCESSOR_DEFINITIONS = (
					SCI_LEXER,
					SCI_NAMESPACE,
				);
				HEADER_SEARCH_PATHS = "../..//**";
				INFOPLIST_FILE = Info.plist;
				INSTALL_PATH = "$(HOME)/Applications";
				LIBRARY_SEARCH_PATHS = "$(inherited)";
				OTHER_LDFLAGS = "";
				PRODUCT_NAME = ScintillaTest;
				SDKROOT = macosx10.7;
				USER_HEADER_SEARCH_PATHS = "";
			};
			name = Debug;
		};
		C01FCF4C08A954540054247B /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				FRAMEWORK_SEARCH_PATHS = "$(inherited)";
				GCC_MODEL_TUNING = G5;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = ScintillaTest_Prefix.pch;
				GCC_PREPROCESSOR_DEFINITIONS = (
					SCI_LEXER,
					SCI_NAMESPACE,
				);
				HEADER_SEARCH_PATHS = "../..//**";
				INFOPLIST_FILE = Info.plist;
				INSTALL_PATH = "$(HOME)/Applications";
				LIBRARY_SEARCH_PATHS = "$(inherited)";
				OTHER_LDFLAGS = "";
				PRODUCT_NAME = ScintillaTest;
				SDKROOT = macosx10.7;
				USER_HEADER_SEARCH_PATHS = "";
			};
			name = Release;
		};
		C01FCF4F08A954540054247B /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
				GCC_C_LANGUAGE_STANDARD = c99;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				ONLY_ACTIVE_ARCH = YES;
				OTHER_LDFLAGS = "";
				SDKROOT = macosx10.7;
			};
			name = Debug;
		};
		C01FCF5008A954540054247B /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
				GCC_C_LANGUAGE_STANDARD = c99;
				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
				GCC_WARN_ABOUT_RETURN_TYPE = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				OTHER_LDFLAGS = "";
				SDKROOT = macosx10.7;
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "ScintillaTest" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				C01FCF4B08A954540054247B /* Debug */,
				C01FCF4C08A954540054247B /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ScintillaTest" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				C01FCF4F08A954540054247B /* Debug */,
				C01FCF5008A954540054247B /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
}

Added cocoa/ScintillaTest/ScintillaTest_Prefix.pch.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
//
// Prefix header for all source files of the 'ScintillaTest' target in the 'ScintillaTest' project
//

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
#endif

Added cocoa/ScintillaTest/TestData.sql.















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
-- MySQL Administrator dump 1.4
--
-- ------------------------------------------------------
-- Server version	5.0.45


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI_QUOTES' */;

/**
 * Foldable multiline comment.
 */

-- {
-- Create schema sakila
-- }

CREATE DATABASE IF NOT EXISTS sakila;
USE sakila;
DROP TABLE IF EXISTS "sakila"."actor_info";
DROP VIEW IF EXISTS "sakila"."actor_info";
CREATE TABLE "sakila"."actor_info" (
  "actor_id" smallint(5) unsigned,
  "first_name" varchar(45),
  "last_name" varchar(45),
  "film_info" varchar(341)
);
DROP TABLE IF EXISTS "sakila"."actor";
CREATE TABLE  "sakila"."actor" (
  "actor_id" smallint(5) unsigned NOT NULL auto_increment,
  "first_name" varchar(45) NOT NULL,
  "last_name" varchar(45) NOT NULL,
  "last_update" timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  ("actor_id"),
  KEY "idx_actor_last_name" ("last_name")
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8;
INSERT INTO "sakila"."actor" VALUES  (1,'PENELOPE','GUINESS','2006-02-15 04:34:33'),
 (2,'NICK','WAHLBERG','2006-02-15 04:34:33'),
 (3,'ED','CHASE','2006-02-15 04:34:33'),
 (4,'JENNIFER','DAVIS','2006-02-15 04:34:33'),
 (149,'RUSSELL','TEMPLE','2006-02-15 04:34:33'),
 (150,'JAYNE','NOLTE','2006-02-15 04:34:33'),
 (151,'GEOFFREY','HESTON','2006-02-15 04:34:33'),
 (152,'BEN','HARRIS','2006-02-15 04:34:33'),
 (153,'MINNIE','KILMER','2006-02-15 04:34:33'),
 (154,'MERYL','GIBSON','2006-02-15 04:34:33'),
 (155,'IAN','TANDY','2006-02-15 04:34:33'),
 (156,'FAY','WOOD','2006-02-15 04:34:33'),
 (157,'GRETA','MALDEN','2006-02-15 04:34:33'),
 (158,'VIVIEN','BASINGER','2006-02-15 04:34:33'),
 (159,'LAURA','BRODY','2006-02-15 04:34:33'),
 (160,'CHRIS','DEPP','2006-02-15 04:34:33'),
 (161,'HARVEY','HOPE','2006-02-15 04:34:33'),
 (162,'OPRAH','KILMER','2006-02-15 04:34:33'),
 (163,'CHRISTOPHER','WEST','2006-02-15 04:34:33'),
 (164,'HUMPHREY','WILLIS','2006-02-15 04:34:33'),
 (165,'AL','GARLAND','2006-02-15 04:34:33'),
 (166,'NICK','DEGENERES','2006-02-15 04:34:33'),
 (167,'LAURENCE','BULLOCK','2006-02-15 04:34:33'),
 (168,'WILL','WILSON','2006-02-15 04:34:33'),
 (169,'KENNETH','HOFFMAN','2006-02-15 04:34:33'),
 (170,'MENA','HOPPER','2006-02-15 04:34:33'),
 (171,'OLYMPIA','PFEIFFER','2006-02-15 04:34:33'),
 (190,'AUDREY','BAILEY','2006-02-15 04:34:33'),
 (191,'GREGORY','GOODING','2006-02-15 04:34:33'),
 (192,'JOHN','SUVARI','2006-02-15 04:34:33'),
 (193,'BURT','TEMPLE','2006-02-15 04:34:33'),
 (194,'MERYL','ALLEN','2006-02-15 04:34:33'),
 (195,'JAYNE','SILVERSTONE','2006-02-15 04:34:33'),
 (196,'BELA','WALKEN','2006-02-15 04:34:33'),
 (197,'REESE','WEST','2006-02-15 04:34:33'),
 (198,'MARY','KEITEL','2006-02-15 04:34:33'),
 (199,'JULIA','FAWCETT','2006-02-15 04:34:33'),
 (200,'THORA','TEMPLE','2006-02-15 04:34:33');

DROP TRIGGER /*!50030 IF EXISTS */ "sakila"."payment_date";

DELIMITER $$

CREATE DEFINER = "root"@"localhost" TRIGGER  "sakila"."payment_date" BEFORE INSERT ON "payment" FOR EACH ROW SET NEW.payment_date = NOW() $$

DELIMITER ;


DROP TABLE IF EXISTS "sakila"."sales_by_store";
DROP VIEW IF EXISTS "sakila"."sales_by_store";
CREATE ALGORITHM=UNDEFINED DEFINER="root"@"localhost" SQL SECURITY DEFINER VIEW "sakila"."sales_by_store" AS select concat("c"."city",_utf8',',"cy"."country") AS "store",concat("m"."first_name",_utf8' ',"m"."last_name") AS "manager",sum("p"."amount") AS "total_sales" from ((((((("sakila"."payment" "p" join "sakila"."rental" "r" on(("p"."rental_id" = "r"."rental_id"))) join "sakila"."inventory" "i" on(("r"."inventory_id" = "i"."inventory_id"))) join "sakila"."store" "s" on(("i"."store_id" = "s"."store_id"))) join "sakila"."address" "a" on(("s"."address_id" = "a"."address_id"))) join "sakila"."city" "c" on(("a"."city_id" = "c"."city_id"))) join "sakila"."country" "cy" on(("c"."country_id" = "cy"."country_id"))) join "sakila"."staff" "m" on(("s"."manager_staff_id" = "m"."staff_id"))) group by "s"."store_id" order by "cy"."country","c"."city";

--
-- View structure for view `staff_list`
--

CREATE VIEW staff_list 
AS 
SELECT s.staff_id AS ID, CONCAT(s.first_name, _utf8' ', s.last_name) AS name, a.address AS address, a.postal_code AS `zip code`, a.phone AS phone,
	city.city AS city, country.country AS country, s.store_id AS SID 
FROM staff AS s JOIN address AS a ON s.address_id = a.address_id JOIN city ON a.city_id = city.city_id 
	JOIN country ON city.country_id = country.country_id;

--
-- View structure for view `actor_info`
--

CREATE DEFINER=CURRENT_USER SQL SECURITY INVOKER VIEW actor_info 
AS
SELECT      
a.actor_id,
a.first_name,
a.last_name,
GROUP_CONCAT(DISTINCT CONCAT(c.name, ': ',
		(SELECT GROUP_CONCAT(f.title ORDER BY f.title SEPARATOR ', ')
                    FROM sakila.film f
                    INNER JOIN sakila.film_category fc
                      ON f.film_id = fc.film_id
                    INNER JOIN sakila.film_actor fa
                      ON f.film_id = fa.film_id
                    WHERE fc.category_id = c.category_id
                    AND fa.actor_id = a.actor_id
                 )
             )
             ORDER BY c.name SEPARATOR '; ')
AS film_info
FROM sakila.actor a
LEFT JOIN sakila.film_actor fa
  ON a.actor_id = fa.actor_id
LEFT JOIN sakila.film_category fc
  ON fa.film_id = fc.film_id
LEFT JOIN sakila.category c
  ON fc.category_id = c.category_id
GROUP BY a.actor_id, a.first_name, a.last_name;

DELIMITER $$

CREATE FUNCTION get_customer_balance(p_customer_id INT, p_effective_date DATETIME) RETURNS DECIMAL(5,2)
    DETERMINISTIC
    READS SQL DATA
BEGIN

       #OK, WE NEED TO CALCULATE THE CURRENT BALANCE GIVEN A CUSTOMER_ID AND A DATE
       #THAT WE WANT THE BALANCE TO BE EFFECTIVE FOR. THE BALANCE IS:
       #   1) RENTAL FEES FOR ALL PREVIOUS RENTALS
       #   2) ONE DOLLAR FOR EVERY DAY THE PREVIOUS RENTALS ARE OVERDUE
       #   3) IF A FILM IS MORE THAN RENTAL_DURATION * 2 OVERDUE, CHARGE THE REPLACEMENT_COST
       #   4) SUBTRACT ALL PAYMENTS MADE BEFORE THE DATE SPECIFIED

  DECLARE v_rentfees DECIMAL(5,2); #FEES PAID TO RENT THE VIDEOS INITIALLY
  DECLARE v_overfees INTEGER;      #LATE FEES FOR PRIOR RENTALS
  DECLARE v_payments DECIMAL(5,2); #SUM OF PAYMENTS MADE PREVIOUSLY

  SELECT IFNULL(SUM(film.rental_rate),0) INTO v_rentfees
    FROM film, inventory, rental
    WHERE film.film_id = inventory.film_id
      AND inventory.inventory_id = rental.inventory_id
      AND rental.rental_date <= p_effective_date
      AND rental.customer_id = p_customer_id;

  SELECT IFNULL(SUM(IF((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) > film.rental_duration,
        ((TO_DAYS(rental.return_date) - TO_DAYS(rental.rental_date)) - film.rental_duration),0)),0) INTO v_overfees
    FROM rental, inventory, film
    WHERE film.film_id = inventory.film_id
      AND inventory.inventory_id = rental.inventory_id
      AND rental.rental_date <= p_effective_date
      AND rental.customer_id = p_customer_id;


  SELECT IFNULL(SUM(payment.amount),0) INTO v_payments
    FROM payment

    WHERE payment.payment_date <= p_effective_date
    AND payment.customer_id = p_customer_id;

  RETURN v_rentfees + v_overfees - v_payments;
END $$

DELIMITER ;

DELIMITER $$

CREATE FUNCTION inventory_in_stock(p_inventory_id INT) RETURNS BOOLEAN
READS SQL DATA
BEGIN
    DECLARE v_rentals INT;
    DECLARE v_out     INT;

    #AN ITEM IS IN-STOCK IF THERE ARE EITHER NO ROWS IN THE rental TABLE
    #FOR THE ITEM OR ALL ROWS HAVE return_date POPULATED

    SELECT COUNT(*) INTO v_rentals
    FROM rental
    WHERE inventory_id = p_inventory_id;

    IF v_rentals = 0 THEN
      RETURN TRUE;
    END IF;

    SELECT COUNT(rental_id) INTO v_out
    FROM inventory LEFT JOIN rental USING(inventory_id)
    WHERE inventory.inventory_id = p_inventory_id
    AND rental.return_date IS NULL;

    IF v_out > 0 THEN
      RETURN FALSE;
    ELSE
      RETURN TRUE;
    END IF;
END $$

DELIMITER ;

Added cocoa/ScintillaTest/main.m.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * main.m
 * ScintillaTest
 *
 * Created by Mike Lischke on 02.04.09.
 * Copyright Sun Microsystems, Inc 2009. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <Cocoa/Cocoa.h>

int main(int argc, char *argv[])
{
    return NSApplicationMain(argc,  (const char **) argv);
}

Added cocoa/ScintillaView.h.



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

/**
 * Declaration of the native Cocoa View that serves as container for the scintilla parts.
 *
 * Created by Mike Lischke.
 *
 * Copyright 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2009, 2011 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import <Cocoa/Cocoa.h>

#import "Platform.h"
#import "Scintilla.h"
#import "SciLexer.h"

#import "InfoBarCommunicator.h"
#import "ScintillaCocoa.h"

@class ScintillaView;

extern NSString *SCIUpdateUINotification;

@protocol ScintillaNotificationProtocol
- (void)notification: (Scintilla::SCNotification*)notification;
@end

/**
 * MarginView draws line numbers and other margins next to the text view.
 */
@interface MarginView : NSRulerView
{
@private
  int marginWidth;
  ScintillaView *owner;
  NSMutableArray *currentCursors;
}

@property (assign) int marginWidth;
@property (assign) ScintillaView *owner;

- (id)initWithScrollView:(NSScrollView *)aScrollView;

@end

/**
 * InnerView is the Cocoa interface to the Scintilla backend. It handles text input and
 * provides a canvas for painting the output.
 */
@interface InnerView : NSView <NSTextInput>
{
@private
  ScintillaView* mOwner;
  NSCursor* mCurrentCursor;
  NSTrackingRectTag mCurrentTrackingRect;

  // Set when we are in composition mode and partial input is displayed.
  NSRange mMarkedTextRange;
  BOOL undoCollectionWasActive;
}

@property (nonatomic, assign) ScintillaView* owner;

- (void) dealloc;
- (void) removeMarkedText;
- (void) setCursor: (Scintilla::Window::Cursor) cursor;

- (BOOL) canUndo;
- (BOOL) canRedo;

@end

@interface ScintillaView : NSView <InfoBarCommunicator>
{
@private
  // The back end is kind of a controller and model in one.
  // It uses the content view for display.
  Scintilla::ScintillaCocoa* mBackend;
  
  // This is the actual content to which the backend renders itself.
  InnerView* mContent;
  
  NSScrollView *scrollView;
  MarginView *marginView;
  
  CGFloat zoomDelta;
  
  // Area to display additional controls (e.g. zoom info, caret position, status info).
  NSView <InfoBarCommunicator>* mInfoBar;
  BOOL mInfoBarAtTop;
  int mInitialInfoBarWidth;

  id<ScintillaNotificationProtocol> mDelegate;
}

@property (nonatomic, readonly) Scintilla::ScintillaCocoa* backend;
@property (nonatomic, assign) id<ScintillaNotificationProtocol> delegate;
@property (nonatomic, readonly) NSScrollView *scrollView;

- (void) dealloc;
- (void) positionSubViews;

- (void) sendNotification: (NSString*) notificationName;
- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
          value: (float) value;
- (void) setCallback: (id <InfoBarCommunicator>) callback;

- (void) suspendDrawing: (BOOL) suspend;

// Scroller handling
- (void) setMarginWidth: (int) width;
- (void) scrollerAction: (id) sender;
- (InnerView*) content;

// NSTextView compatibility layer.
- (NSString*) string;
- (void) setString: (NSString*) aString;
- (void) insertText: (NSString*) aString;
- (void) setEditable: (BOOL) editable;
- (BOOL) isEditable;
- (NSRange) selectedRange;

- (NSString*) selectedString;

- (void)setFontName: (NSString*) font
               size: (int) size
               bold: (BOOL) bold
             italic: (BOOL) italic;

// Native call through to the backend.
+ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam
               lParam: (sptr_t) lParam;

// Back end properties getters and setters.
- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value;
- (void) setGeneralProperty: (int) property value: (long) value;

- (long) getGeneralProperty: (int) property;
- (long) getGeneralProperty: (int) property parameter: (long) parameter;
- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra;
- (long) getGeneralProperty: (int) property ref: (const void*) ref;
- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value;
- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML;
- (NSColor*) getColorProperty: (int) property parameter: (long) parameter;
- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value;
- (const void*) getReferenceProperty: (int) property parameter: (long) parameter;
- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value;
- (NSString*) getStringProperty: (int) property parameter: (long) parameter;
- (void) setLexerProperty: (NSString*) name value: (NSString*) value;
- (NSString*) getLexerProperty: (NSString*) name;

- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback;

- (void) setInfoBar: (NSView <InfoBarCommunicator>*) aView top: (BOOL) top;
- (void) setStatusText: (NSString*) text;

- (BOOL) findAndHighlightText: (NSString*) searchText
                    matchCase: (BOOL) matchCase
                    wholeWord: (BOOL) wholeWord
                     scrollTo: (BOOL) scrollTo
                         wrap: (BOOL) wrap;

- (BOOL) findAndHighlightText: (NSString*) searchText
                    matchCase: (BOOL) matchCase
                    wholeWord: (BOOL) wholeWord
                     scrollTo: (BOOL) scrollTo
                         wrap: (BOOL) wrap
                    backwards: (BOOL) backwards;

- (int) findAndReplaceText: (NSString*) searchText
                    byText: (NSString*) newText
                 matchCase: (BOOL) matchCase
                 wholeWord: (BOOL) wholeWord
                     doAll: (BOOL) doAll;

@end

Added cocoa/ScintillaView.mm.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761

/**
 * Implementation of the native Cocoa View that serves as container for the scintilla parts.
 *
 * Created by Mike Lischke.
 *
 * Copyright 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2009, 2011 Sun Microsystems, Inc. All rights reserved.
 * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt).
 */

#import "ScintillaView.h"

using namespace Scintilla;

// Two additional cursors we need, which aren't provided by Cocoa.
static NSCursor* reverseArrowCursor;
static NSCursor* waitCursor;

// The scintilla indicator used for keyboard input.
#define INPUT_INDICATOR INDIC_MAX - 1

NSString *SCIUpdateUINotification = @"SCIUpdateUI";

/**
 * Provide an NSCursor object that matches the Window::Cursor enumeration.
 */
static NSCursor *cursorFromEnum(Window::Cursor cursor)
{
  switch (cursor)
  {
    case Window::cursorText:
      return [NSCursor IBeamCursor];
    case Window::cursorArrow:
      return [NSCursor arrowCursor];
    case Window::cursorWait:
      return waitCursor;
    case Window::cursorHoriz:
      return [NSCursor resizeLeftRightCursor];
    case Window::cursorVert:
      return [NSCursor resizeUpDownCursor];
    case Window::cursorReverseArrow:
      return reverseArrowCursor;
    case Window::cursorUp:
    default:
      return [NSCursor arrowCursor];
  }
}


@implementation MarginView

@synthesize marginWidth, owner;

- (id)initWithScrollView:(NSScrollView *)aScrollView
{
  self = [super initWithScrollView:aScrollView orientation:NSVerticalRuler];
  if (self != nil)
  {
    owner = nil;
    marginWidth = 20;
    currentCursors = [[NSMutableArray arrayWithCapacity:0] retain];
    for (size_t i=0; i<5; i++)
    {
      [currentCursors addObject: [reverseArrowCursor retain]];
    }
    [self setClientView:[aScrollView documentView]];
  }
  return self;
}

- (void) dealloc
{
  [currentCursors release];
  [super dealloc];
}

- (void) setFrame: (NSRect) frame
{
  [super setFrame: frame];
  
  [[self window] invalidateCursorRectsForView: self];
}

- (CGFloat)requiredThickness
{
  return marginWidth;
}

- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect
{
  if (owner) {
    NSRect contentRect = [[[self scrollView] contentView] bounds];
    NSRect marginRect = [self bounds];
    // Ensure paint to bottom of view to avoid glitches
    if (marginRect.size.height > contentRect.size.height) {
      // Legacy scroll bar mode leaves a poorly painted corner
      aRect = marginRect;
    }
    owner.backend->PaintMargin(aRect);
  }
}

- (void) mouseDown: (NSEvent *) theEvent
{
  owner.backend->MouseDown(theEvent);
}

- (void) mouseDragged: (NSEvent *) theEvent
{
  owner.backend->MouseMove(theEvent);
}

- (void) mouseMoved: (NSEvent *) theEvent
{
  owner.backend->MouseMove(theEvent);
}

- (void) mouseUp: (NSEvent *) theEvent
{
  owner.backend->MouseUp(theEvent);
}

/**
 * This method is called to give us the opportunity to define our mouse sensitive rectangle.
 */
- (void) resetCursorRects
{
  [super resetCursorRects];
  
  int x = 0;
  NSRect marginRect = [self bounds];
  size_t co = [currentCursors count];
  for (size_t i=0; i<co; i++)
  {
    int cursType = owner.backend->WndProc(SCI_GETMARGINCURSORN, i, 0);
    int width =owner.backend->WndProc(SCI_GETMARGINWIDTHN, i, 0);
    NSCursor *cc = cursorFromEnum(static_cast<Window::Cursor>(cursType));
    [currentCursors replaceObjectAtIndex:i withObject: cc];
    marginRect.origin.x = x;
    marginRect.size.width = width;
    [self addCursorRect: marginRect cursor: cc];
    [cc setOnMouseEntered: YES];
    x += width;
  }
}

@end

@implementation InnerView

@synthesize owner = mOwner;

//--------------------------------------------------------------------------------------------------

- (NSView*) initWithFrame: (NSRect) frame
{
  self = [super initWithFrame: frame];
  
  if (self != nil)
  {
    // Some initialization for our view.
    mCurrentCursor = [[NSCursor arrowCursor] retain];
    mCurrentTrackingRect = 0;
    mMarkedTextRange = NSMakeRange(NSNotFound, 0);
    
    [self registerForDraggedTypes: [NSArray arrayWithObjects:
                                   NSStringPboardType, ScintillaRecPboardType, NSFilenamesPboardType, nil]];
  }
  
  return self;
}

//--------------------------------------------------------------------------------------------------

/**
 * When the view is resized we need to update our tracking rectangle and let the backend know.
 */
- (void) setFrame: (NSRect) frame
{
  [super setFrame: frame];

  // Make the content also a tracking rectangle for mouse events.
  if (mCurrentTrackingRect != 0)
    [self removeTrackingRect: mCurrentTrackingRect];
	mCurrentTrackingRect = [self addTrackingRect: [self bounds]
                                         owner: self
                                      userData: nil
                                  assumeInside: YES];
  mOwner.backend->Resize();
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by the backend if a new cursor must be set for the view.
 */
- (void) setCursor: (Window::Cursor) cursor
{
  [mCurrentCursor autorelease];
  mCurrentCursor = cursorFromEnum(cursor);
  [mCurrentCursor retain];
  
  // Trigger recreation of the cursor rectangle(s).
  [[self window] invalidateCursorRectsForView: self];
}

//--------------------------------------------------------------------------------------------------

/**
 * This method is called to give us the opportunity to define our mouse sensitive rectangle.
 */
- (void) resetCursorRects
{
  [super resetCursorRects];
  
  // We only have one cursor rect: our bounds.
  [self addCursorRect: [self bounds] cursor: mCurrentCursor];
  [mCurrentCursor setOnMouseEntered: YES];
}

//--------------------------------------------------------------------------------------------------

/**
 * Gets called by the runtime when the view needs repainting.
 */
- (void) drawRect: (NSRect) rect
{
  CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
  
  if (!mOwner.backend->Draw(rect, context)) {
    dispatch_async(dispatch_get_main_queue(), ^{
      [self setNeedsDisplay:YES];
    });
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Windows uses a client coordinate system where the upper left corner is the origin in a window
 * (and so does Scintilla). We have to adjust for that. However by returning YES here, we are 
 * already done with that.
 * Note that because of returning YES here most coordinates we use now (e.g. for painting,
 * invalidating rectangles etc.) are given with +Y pointing down!
 */
- (BOOL) isFlipped
{
  return YES;
}

//--------------------------------------------------------------------------------------------------

- (BOOL) isOpaque
{
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * Implement the "click through" behavior by telling the caller we accept the first mouse event too.
 */
- (BOOL) acceptsFirstMouse: (NSEvent *) theEvent
{
#pragma unused(theEvent)
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * Make this view accepting events as first responder.
 */
- (BOOL) acceptsFirstResponder
{
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by the framework if it wants to show a context menu for the editor.
 */
- (NSMenu*) menuForEvent: (NSEvent*) theEvent
{
  if (![mOwner respondsToSelector: @selector(menuForEvent:)])
    return mOwner.backend->CreateContextMenu(theEvent);
  else
    return [mOwner menuForEvent: theEvent];
}

//--------------------------------------------------------------------------------------------------

// Adoption of NSTextInput protocol.

- (NSAttributedString*) attributedSubstringFromRange: (NSRange) range
{
  return nil;
}

//--------------------------------------------------------------------------------------------------

- (NSUInteger) characterIndexForPoint: (NSPoint) point
{
  return NSNotFound;
}

//--------------------------------------------------------------------------------------------------

- (NSInteger) conversationIdentifier
{
  return (NSInteger) self;

}

//--------------------------------------------------------------------------------------------------

- (void) doCommandBySelector: (SEL) selector
{
  if ([self respondsToSelector: @selector(selector)])
    [self performSelector: selector withObject: nil];
}

//--------------------------------------------------------------------------------------------------

- (NSRect) firstRectForCharacterRange: (NSRange) range
{
  return NSZeroRect;
}

//--------------------------------------------------------------------------------------------------

- (BOOL) hasMarkedText
{
  return mMarkedTextRange.length > 0;
}

//--------------------------------------------------------------------------------------------------

/**
 * General text input. Used to insert new text at the current input position, replacing the current
 * selection if there is any.
 */
- (void) insertText: (id) aString
{
	// Remove any previously marked text first.
	[self removeMarkedText];
	NSString* newText = @"";
	if ([aString isKindOfClass:[NSString class]])
		newText = (NSString*) aString;
	else if ([aString isKindOfClass:[NSAttributedString class]])
		newText = (NSString*) [aString string];
	
	mOwner.backend->InsertText(newText);
}

//--------------------------------------------------------------------------------------------------

- (NSRange) markedRange
{
  return mMarkedTextRange;
}

//--------------------------------------------------------------------------------------------------

- (NSRange) selectedRange
{
  long begin = [mOwner getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0];
  long end = [mOwner getGeneralProperty: SCI_GETSELECTIONEND parameter: 0];
  return NSMakeRange(begin, end - begin);
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by the input manager to set text which might be combined with further input to form
 * the final text (e.g. composition of ^ and a to â).
 *
 * @param aString The text to insert, either what has been marked already or what is selected already
 *                or simply added at the current insertion point. Depending on what is available.
 * @param range The range of the new text to select (given relative to the insertion point of the new text).
 */
- (void) setMarkedText: (id) aString selectedRange: (NSRange) range
{
  NSString* newText = @"";
  if ([aString isKindOfClass:[NSString class]])
    newText = (NSString*) aString;
  else
    if ([aString isKindOfClass:[NSAttributedString class]])
      newText = (NSString*) [aString string];
  
  long currentPosition = [mOwner getGeneralProperty: SCI_GETCURRENTPOS parameter: 0];

  // Replace marked text if there is one.
  if (mMarkedTextRange.length > 0)
  {
    [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
                         value: mMarkedTextRange.location];
    [mOwner setGeneralProperty: SCI_SETSELECTIONEND 
                         value: mMarkedTextRange.location + mMarkedTextRange.length];
    currentPosition = mMarkedTextRange.location;
  }

  // Keep Scintilla from collecting undo actions for the composition task.
  undoCollectionWasActive = [mOwner getGeneralProperty: SCI_GETUNDOCOLLECTION] != 0;
  [mOwner setGeneralProperty: SCI_SETUNDOCOLLECTION value: 0];
  
  // Note: Scintilla internally works almost always with bytes instead chars, so we need to take
  //       this into account when determining selection ranges and such.
  std::string raw_text = [newText UTF8String];
  int lengthInserted = mOwner.backend->InsertText(newText);

  mMarkedTextRange.location = currentPosition;
  mMarkedTextRange.length = lengthInserted;
    
  if (lengthInserted > 0)
  {
    // Mark the just inserted text. Keep the marked range for later reset.
    [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR];
    [mOwner setGeneralProperty: SCI_INDICATORFILLRANGE
                     parameter: mMarkedTextRange.location
                         value: mMarkedTextRange.length];
  }
  else
  {
    // Re-enable undo action collection if composition ended (indicated by an empty mark string).
    if (undoCollectionWasActive)
      [mOwner setGeneralProperty: SCI_SETUNDOCOLLECTION value: range.length == 0];
  }

  // Select the part which is indicated in the given range. It does not scroll the caret into view.
  if (range.length > 0)
  {
    [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
                     value: currentPosition + range.location];
    [mOwner setGeneralProperty: SCI_SETSELECTIONEND 
                     value: currentPosition + range.location + range.length];
  }
}

//--------------------------------------------------------------------------------------------------

- (void) unmarkText
{
  if (mMarkedTextRange.length > 0)
  {
    [mOwner setGeneralProperty: SCI_SETINDICATORCURRENT value: INPUT_INDICATOR];
    [mOwner setGeneralProperty: SCI_INDICATORCLEARRANGE
                     parameter: mMarkedTextRange.location
                         value: mMarkedTextRange.length];
    mMarkedTextRange = NSMakeRange(NSNotFound, 0);

    // Reenable undo action collection, after we are done with text composition.    
    if (undoCollectionWasActive)
      [mOwner setGeneralProperty: SCI_SETUNDOCOLLECTION value: 1];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Removes any currently marked text.
 */
- (void) removeMarkedText
{
  if (mMarkedTextRange.length > 0)
  {
    // We have already marked text. Replace that.
    [mOwner setGeneralProperty: SCI_SETSELECTIONSTART
                     value: mMarkedTextRange.location];
    [mOwner setGeneralProperty: SCI_SETSELECTIONEND 
                     value: mMarkedTextRange.location + mMarkedTextRange.length];
    mOwner.backend->InsertText(@"");
    mMarkedTextRange = NSMakeRange(NSNotFound, 0);

    // Reenable undo action collection, after we are done with text composition.    
    if (undoCollectionWasActive)
      [mOwner setGeneralProperty: SCI_SETUNDOCOLLECTION value: 1];
  }
}

//--------------------------------------------------------------------------------------------------

- (NSArray*) validAttributesForMarkedText
{
  return nil;
}

// End of the NSTextInput protocol adoption.

//--------------------------------------------------------------------------------------------------

/**
 * Generic input method. It is used to pass on keyboard input to Scintilla. The control itself only
 * handles shortcuts. The input is then forwarded to the Cocoa text input system, which in turn does
 * its own input handling (character composition via NSTextInput protocol):
 */
- (void) keyDown: (NSEvent *) theEvent
{
  if (mMarkedTextRange.length == 0)
	mOwner.backend->KeyboardInput(theEvent);
  NSArray* events = [NSArray arrayWithObject: theEvent];
  [self interpretKeyEvents: events];
}

//--------------------------------------------------------------------------------------------------

- (void) mouseDown: (NSEvent *) theEvent  
{
  mOwner.backend->MouseDown(theEvent);
}

//--------------------------------------------------------------------------------------------------

- (void) mouseDragged: (NSEvent *) theEvent
{
  mOwner.backend->MouseMove(theEvent);
}

//--------------------------------------------------------------------------------------------------

- (void) mouseUp: (NSEvent *) theEvent
{
  mOwner.backend->MouseUp(theEvent);
}

//--------------------------------------------------------------------------------------------------

- (void) mouseMoved: (NSEvent *) theEvent
{
  mOwner.backend->MouseMove(theEvent);
}

//--------------------------------------------------------------------------------------------------

- (void) mouseEntered: (NSEvent *) theEvent
{
  mOwner.backend->MouseEntered(theEvent);
}

//--------------------------------------------------------------------------------------------------

- (void) mouseExited: (NSEvent *) theEvent
{
  mOwner.backend->MouseExited(theEvent);
}

//--------------------------------------------------------------------------------------------------

/**
 * Mouse wheel with command key magnifies text.
 */
- (void) scrollWheel: (NSEvent *) theEvent
{
  if (([theEvent modifierFlags] & NSCommandKeyMask) != 0) {
    mOwner.backend->MouseWheel(theEvent);
  } else {
    [super scrollWheel:theEvent];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Ensure scrolling is aligned to whole lines instead of starting part-way through a line
 */
- (NSRect)adjustScroll:(NSRect)proposedVisibleRect
{
  NSRect rc = proposedVisibleRect;
  // Snap to lines
  NSRect contentRect = [self bounds];
  if ((rc.origin.y > 0) && (NSMaxY(rc) < contentRect.size.height)) {
    // Only snap for positions inside the document - allow outside
    // for overshoot.
    int lineHeight = mOwner.backend->WndProc(SCI_TEXTHEIGHT, 0, 0);
    rc.origin.y = roundf(rc.origin.y / lineHeight) * lineHeight;
  }
  return rc;
}

//--------------------------------------------------------------------------------------------------

/**
 * The editor is getting the foreground control (the one getting the input focus).
 */
- (BOOL) becomeFirstResponder
{
  mOwner.backend->WndProc(SCI_SETFOCUS, 1, 0);
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * The editor is losing the input focus.
 */
- (BOOL) resignFirstResponder
{
  mOwner.backend->WndProc(SCI_SETFOCUS, 0, 0);
  return YES;
}

//--------------------------------------------------------------------------------------------------

/**
 * Called when an external drag operation enters the view. 
 */
- (NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
{
  return mOwner.backend->DraggingEntered(sender);
}

//--------------------------------------------------------------------------------------------------

/**
 * Called frequently during an external drag operation if we are the target.
 */
- (NSDragOperation) draggingUpdated: (id <NSDraggingInfo>) sender
{
  return mOwner.backend->DraggingUpdated(sender);
}

//--------------------------------------------------------------------------------------------------

/**
 * Drag image left the view. Clean up if necessary.
 */
- (void) draggingExited: (id <NSDraggingInfo>) sender
{
  mOwner.backend->DraggingExited(sender);
}

//--------------------------------------------------------------------------------------------------

- (BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
{
#pragma unused(sender)
  return YES;
}

//--------------------------------------------------------------------------------------------------

- (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
{
  return mOwner.backend->PerformDragOperation(sender);  
}

//--------------------------------------------------------------------------------------------------

/**
 * Returns operations we allow as drag source.
 */
- (NSDragOperation) draggingSourceOperationMaskForLocal: (BOOL) flag
{
  return NSDragOperationCopy | NSDragOperationMove | NSDragOperationDelete;
}

//--------------------------------------------------------------------------------------------------

/**
 * Finished a drag: may need to delete selection.
 */

- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation {
    if (operation == NSDragOperationDelete) {
        mOwner.backend->WndProc(SCI_CLEAR, 0, 0);
    }
}

//--------------------------------------------------------------------------------------------------

/**
 * Drag operation is done. Notify editor.
 */
- (void) concludeDragOperation: (id <NSDraggingInfo>) sender
{
  // Clean up is the same as if we are no longer the drag target.
  mOwner.backend->DraggingExited(sender);
}

//--------------------------------------------------------------------------------------------------

// NSResponder actions.

- (void) selectAll: (id) sender
{
#pragma unused(sender)
  mOwner.backend->SelectAll();
}

- (void) deleteBackward: (id) sender
{
#pragma unused(sender)
  mOwner.backend->DeleteBackward();
}

- (void) cut: (id) sender
{
#pragma unused(sender)
  mOwner.backend->Cut();
}

- (void) copy: (id) sender
{
#pragma unused(sender)
  mOwner.backend->Copy();
}

- (void) paste: (id) sender
{
#pragma unused(sender)
  mOwner.backend->Paste();
}

- (void) undo: (id) sender
{
#pragma unused(sender)
  mOwner.backend->Undo();
}

- (void) redo: (id) sender
{
#pragma unused(sender)
  mOwner.backend->Redo();
}

- (BOOL) canUndo
{
  return mOwner.backend->CanUndo();
}

- (BOOL) canRedo
{
  return mOwner.backend->CanRedo();
}


- (BOOL) isEditable
{
  return mOwner.backend->WndProc(SCI_GETREADONLY, 0, 0) == 0;
}

//--------------------------------------------------------------------------------------------------

- (void) dealloc
{
  [mCurrentCursor release];
  [super dealloc];
}

@end

//--------------------------------------------------------------------------------------------------

@implementation ScintillaView

@synthesize backend = mBackend;
@synthesize delegate = mDelegate;
@synthesize scrollView;

/**
 * ScintillaView is a composite control made from an NSView and an embedded NSView that is
 * used as canvas for the output (by the backend, using its CGContext), plus other elements
 * (scrollers, info bar).
 */

//--------------------------------------------------------------------------------------------------

/**
 * Initialize custom cursor.
 */
+ (void) initialize
{
  if (self == [ScintillaView class])
  {
    NSBundle* bundle = [NSBundle bundleForClass: [ScintillaView class]];
    
    NSString* path = [bundle pathForResource: @"mac_cursor_busy" ofType: @"png" inDirectory: nil];
    NSImage* image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease];
    waitCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(2, 2)];
    
    path = [bundle pathForResource: @"mac_cursor_flipped" ofType: @"png" inDirectory: nil];
    image = [[[NSImage alloc] initWithContentsOfFile: path] autorelease];
    reverseArrowCursor = [[NSCursor alloc] initWithImage: image hotSpot: NSMakePoint(12, 2)];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Receives zoom messages, for example when a "pinch zoom" is performed on the trackpad.
 */
- (void) magnifyWithEvent: (NSEvent *) event
{
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
  zoomDelta += event.magnification * 10.0;

  if (fabsf(zoomDelta)>=1.0) {
    long zoomFactor = [self getGeneralProperty: SCI_GETZOOM] + zoomDelta;
    [self setGeneralProperty: SCI_SETZOOM parameter: zoomFactor value:0];
    zoomDelta = 0.0;
  }     
#endif
}

- (void) beginGestureWithEvent: (NSEvent *) event
{
  zoomDelta = 0.0;
}

//--------------------------------------------------------------------------------------------------

/**
 * Sends a new notification of the given type to the default notification center.
 */
- (void) sendNotification: (NSString*) notificationName
{
  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
  [center postNotificationName: notificationName object: self];
}

//--------------------------------------------------------------------------------------------------

/**
 * Called by a connected component (usually the info bar) if something changed there.
 *
 * @param type The type of the notification.
 * @param message Carries the new status message if the type is a status message change.
 * @param location Carries the new location (e.g. caret) if the type is a caret change or similar type.
 * @param location Carries the new zoom value if the type is a zoom change.
 */
- (void) notify: (NotificationType) type message: (NSString*) message location: (NSPoint) location
          value: (float) value
{
  switch (type)
  {
    case IBNZoomChanged:
    {
      // Compute point increase/decrease based on default font size.
      long fontSize = [self getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
      int zoom = (int) (fontSize * (value - 1));
      [self setGeneralProperty: SCI_SETZOOM value: zoom];
      break;
    }
    default:
      break;
  };
}

//--------------------------------------------------------------------------------------------------

- (void) setCallback: (id <InfoBarCommunicator>) callback
{
  // Not used. Only here to satisfy protocol.
}

//--------------------------------------------------------------------------------------------------

/**
 * Prevents drawing of the inner view to avoid flickering when doing many visual updates
 * (like clearing all marks and setting new ones etc.).
 */
- (void) suspendDrawing: (BOOL) suspend
{
  if (suspend)
    [[self window] disableFlushWindow];
  else
    [[self window] enableFlushWindow];
}

//--------------------------------------------------------------------------------------------------

/**
 * Notification function used by Scintilla to call us back (e.g. for handling clicks on the 
 * folder margin or changes in the editor).
 * A delegate can be set to receive all notifications. If set no handling takes place here, except
 * for action pertaining to internal stuff (like the info bar).
 */
static void notification(intptr_t windowid, unsigned int iMessage, uintptr_t wParam, uintptr_t lParam)
{
  // WM_NOTIFY means we got a parent notification with a special notification structure.
  // Here we don't really differentiate between parent and own notifications and handle both.
  ScintillaView* editor;
  switch (iMessage)
  {
    case WM_NOTIFY:
    {
      // Parent notification. Details are passed as SCNotification structure.
      SCNotification* scn = reinterpret_cast<SCNotification*>(lParam);
      ScintillaCocoa *psc = reinterpret_cast<ScintillaCocoa*>(scn->nmhdr.hwndFrom);
      editor = reinterpret_cast<InnerView*>(psc->ContentView()).owner;

      if (editor.delegate != nil)
      {
        [editor.delegate notification: scn];
        if (scn->nmhdr.code != SCN_ZOOM && scn->nmhdr.code != SCN_UPDATEUI)
          return;
      }
      
      switch (scn->nmhdr.code)
      {
        case SCN_MARGINCLICK:
        {
          if (scn->margin == 2)
          {
            // Click on the folder margin. Toggle the current line if possible.
            long line = [editor getGeneralProperty: SCI_LINEFROMPOSITION parameter: scn->position];
            [editor setGeneralProperty: SCI_TOGGLEFOLD value: line];
          }
          break;
          };
        case SCN_MODIFIED:
        {
          // Decide depending on the modification type what to do.
          // There can be more than one modification carried by one notification.
          if (scn->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT))
            [editor sendNotification: NSTextDidChangeNotification];
          break;
        }
        case SCN_ZOOM:
        {
          // A zoom change happend. Notify info bar if there is one.
          float zoom = [editor getGeneralProperty: SCI_GETZOOM parameter: 0];
          long fontSize = [editor getGeneralProperty: SCI_STYLEGETSIZE parameter: STYLE_DEFAULT];
          float factor = (zoom / fontSize) + 1;
          [editor->mInfoBar notify: IBNZoomChanged message: nil location: NSZeroPoint value: factor];
          break;
        }
        case SCN_UPDATEUI:
        {
          // Triggered whenever changes in the UI state need to be reflected.
          // These can be: caret changes, selection changes etc.
          NSPoint caretPosition = editor->mBackend->GetCaretPosition();
          [editor->mInfoBar notify: IBNCaretChanged message: nil location: caretPosition value: 0];
          [editor sendNotification: SCIUpdateUINotification];
          [editor sendNotification: NSTextViewDidChangeSelectionNotification];
          break;
      }
      }
      break;
    }
    case WM_COMMAND:
    {
      // Notifications for the editor itself.
      ScintillaCocoa* backend = reinterpret_cast<ScintillaCocoa*>(lParam);
      editor = backend->TopContainer();
      switch (wParam >> 16)
      {
        case SCEN_KILLFOCUS:
          [editor sendNotification: NSTextDidEndEditingNotification];
          break;
        case SCEN_SETFOCUS: // Nothing to do for now.
          break;
      }
      break;
    }
  };
}

//--------------------------------------------------------------------------------------------------

/**
 * Initialization of the view. Used to setup a few other things we need.
 */
- (id) initWithFrame: (NSRect) frame
{
  self = [super initWithFrame:frame];
  if (self)
  {
    mContent = [[[InnerView alloc] init] autorelease];
    mContent.owner = self;

    // Initialize the scrollers but don't show them yet.
    // Pick an arbitrary size, just to make NSScroller selecting the proper scroller direction
    // (horizontal or vertical).
    NSRect scrollerRect = NSMakeRect(0, 0, 100, 10);
    scrollView = [[[NSScrollView alloc] initWithFrame: scrollerRect] autorelease];
    [scrollView setDocumentView: mContent];
    [scrollView setHasVerticalScroller:YES];
    [scrollView setHasHorizontalScroller:YES];
    [scrollView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
    //[scrollView setScrollerStyle:NSScrollerStyleLegacy];
    //[scrollView setScrollerKnobStyle:NSScrollerKnobStyleDark];
    //[scrollView setHorizontalScrollElasticity:NSScrollElasticityNone];
    [self addSubview: scrollView];

    marginView = [[MarginView alloc] initWithScrollView:scrollView];
    marginView.owner = self;
    [marginView setRuleThickness:[marginView requiredThickness]];
    [scrollView setVerticalRulerView:marginView];
    [scrollView setHasHorizontalRuler:NO];
    [scrollView setHasVerticalRuler:YES];
    [scrollView setRulersVisible:YES];
    
    mBackend = new ScintillaCocoa(mContent, marginView);

    // Establish a connection from the back end to this container so we can handle situations
    // which require our attention.
    mBackend->RegisterNotifyCallback(nil, notification);
    
    // Setup a special indicator used in the editor to provide visual feedback for 
    // input composition, depending on language, keyboard etc.
    [self setColorProperty: SCI_INDICSETFORE parameter: INPUT_INDICATOR fromHTML: @"#FF0000"];
    [self setGeneralProperty: SCI_INDICSETUNDER parameter: INPUT_INDICATOR value: 1];
    [self setGeneralProperty: SCI_INDICSETSTYLE parameter: INPUT_INDICATOR value: INDIC_PLAIN];
    [self setGeneralProperty: SCI_INDICSETALPHA parameter: INPUT_INDICATOR value: 100];
      
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center addObserver:self
               selector:@selector(applicationDidResignActive:)
                   name:NSApplicationDidResignActiveNotification
                 object:nil];
      
    [center addObserver:self
               selector:@selector(applicationDidBecomeActive:)
                   name:NSApplicationDidBecomeActiveNotification
                 object:nil];

    [[scrollView contentView] setPostsBoundsChangedNotifications:YES];
    [center addObserver:self
	       selector:@selector(scrollerAction:)
		   name:NSViewBoundsDidChangeNotification
		 object:[scrollView contentView]];
  }
  return self;
}

//--------------------------------------------------------------------------------------------------

- (void) dealloc
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  delete mBackend;
  [super dealloc];
}

//--------------------------------------------------------------------------------------------------

- (void) applicationDidResignActive: (NSNotification *)note {
#pragma unused(note)
    mBackend->ActiveStateChanged(false);
}

//--------------------------------------------------------------------------------------------------

- (void) applicationDidBecomeActive: (NSNotification *)note {
#pragma unused(note)
    mBackend->ActiveStateChanged(true);
}

//--------------------------------------------------------------------------------------------------

- (void) viewDidMoveToWindow
{
  [super viewDidMoveToWindow];
  
  [self positionSubViews];
  
  // Enable also mouse move events for our window (and so this view).
  [[self window] setAcceptsMouseMovedEvents: YES];
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to position and size the parts of the editor (content, scrollers, info bar).
 */
- (void) positionSubViews
{
  int scrollerWidth = [NSScroller scrollerWidth];

  NSSize size = [self frame].size;
  NSRect barFrame = {0, size.height - scrollerWidth, size.width, static_cast<CGFloat>(scrollerWidth)};
  BOOL infoBarVisible = mInfoBar != nil && ![mInfoBar isHidden];

  // Horizontal offset of the content. Almost always 0 unless the vertical scroller
  // is on the left side.
  int contentX = 0;
  NSRect scrollRect = {contentX, 0, size.width, size.height};

  // Info bar frame.
  if (infoBarVisible)
  {
    scrollRect.size.height -= scrollerWidth;
    // Initial value already is as if the bar is at top.
    if (!mInfoBarAtTop)
    {
      scrollRect.origin.y += scrollerWidth;
      barFrame.origin.y = 0;
    }
  }

  if (!NSEqualRects([scrollView frame], scrollRect)) {
    [scrollView setFrame: scrollRect];
  }

  if (infoBarVisible)
    [mInfoBar setFrame: barFrame];
}

//--------------------------------------------------------------------------------------------------

/**
 * Set the width of the margin.
 */
- (void) setMarginWidth: (int) width
{
  if (marginView.ruleThickness != width)
  {
    marginView.marginWidth = width;
    [marginView setRuleThickness:[marginView requiredThickness]];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Triggered by one of the scrollers when it gets manipulated by the user. Notify the backend
 * about the change.
 */
- (void) scrollerAction: (id) sender
{
  mBackend->UpdateForScroll();
}

//--------------------------------------------------------------------------------------------------

/**
 * Used to reposition our content depending on the size of the view.
 */
- (void) setFrame: (NSRect) newFrame
{
  NSRect previousFrame = [self frame];
  [super setFrame: newFrame];
  [self positionSubViews];
  if (!NSEqualRects(previousFrame, newFrame)) {
    mBackend->Resize();
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Getter for the currently selected text in raw form (no formatting information included).
 * If there is no text available an empty string is returned.
 */
- (NSString*) selectedString
{
  NSString *result = @"";
  
  char *buffer(0);
  const long length = mBackend->WndProc(SCI_GETSELTEXT, 0, 0);
  if (length > 0)
  {
    buffer = new char[length + 1];
    try
    {
      mBackend->WndProc(SCI_GETSELTEXT, length + 1, (sptr_t) buffer);
      
      result = [NSString stringWithUTF8String: buffer];
      delete[] buffer;
    }
    catch (...)
    {
      delete[] buffer;
      buffer = 0;
    }
  }
  
  return result;
}

//--------------------------------------------------------------------------------------------------

/**
 * Getter for the current text in raw form (no formatting information included).
 * If there is no text available an empty string is returned.
 */
- (NSString*) string
{
  NSString *result = @"";
  
  char *buffer(0);
  const long length = mBackend->WndProc(SCI_GETLENGTH, 0, 0);
  if (length > 0)
  {
    buffer = new char[length + 1];
    try
    {
      mBackend->WndProc(SCI_GETTEXT, length + 1, (sptr_t) buffer);
      
      result = [NSString stringWithUTF8String: buffer];
      delete[] buffer;
    }
    catch (...)
    {
      delete[] buffer;
      buffer = 0;
    }
  }
  
  return result;
}

//--------------------------------------------------------------------------------------------------

/**
 * Setter for the current text (no formatting included).
 */
- (void) setString: (NSString*) aString
{
  const char* text = [aString UTF8String];
  mBackend->WndProc(SCI_SETTEXT, 0, (long) text);
}

//--------------------------------------------------------------------------------------------------

- (void) insertString: (NSString*) aString atOffset: (int)offset
{
  const char* text = [aString UTF8String];
  mBackend->WndProc(SCI_ADDTEXT, offset, (long) text);
}

//--------------------------------------------------------------------------------------------------

- (void) setEditable: (BOOL) editable
{
  mBackend->WndProc(SCI_SETREADONLY, editable ? 0 : 1, 0);
}

//--------------------------------------------------------------------------------------------------

- (BOOL) isEditable
{
  return mBackend->WndProc(SCI_GETREADONLY, 0, 0) == 0;
}

//--------------------------------------------------------------------------------------------------

- (InnerView*) content
{
  return mContent;
}

//--------------------------------------------------------------------------------------------------

/**
 * Direct call into the backend to allow uninterpreted access to it. The values to be passed in and
 * the result heavily depend on the message that is used for the call. Refer to the Scintilla
 * documentation to learn what can be used here.
 */
+ (sptr_t) directCall: (ScintillaView*) sender message: (unsigned int) message wParam: (uptr_t) wParam
               lParam: (sptr_t) lParam
{
  return ScintillaCocoa::DirectFunction(sender->mBackend, message, wParam, lParam);
}

//--------------------------------------------------------------------------------------------------

/**
 * This is a helper method to set properties in the backend, with native parameters.
 *
 * @param property Main property like SCI_STYLESETFORE for which a value is to be set.
 * @param parameter Additional info for this property like a parameter or index.
 * @param value The actual value. It depends on the property what this parameter means.
 */
- (void) setGeneralProperty: (int) property parameter: (long) parameter value: (long) value
{
  mBackend->WndProc(property, parameter, value);
}

//--------------------------------------------------------------------------------------------------

/**
 * A simplified version for setting properties which only require one parameter.
 *
 * @param property Main property like SCI_STYLESETFORE for which a value is to be set.
 * @param value The actual value. It depends on the property what this parameter means.
 */
- (void) setGeneralProperty: (int) property value: (long) value
{
  mBackend->WndProc(property, value, 0);
}

//--------------------------------------------------------------------------------------------------

/**
 * This is a helper method to get a property in the backend, with native parameters.
 *
 * @param property Main property like SCI_STYLESETFORE for which a value is to get.
 * @param parameter Additional info for this property like a parameter or index.
 * @param extra Yet another parameter if needed.
 * @result A generic value which must be interpreted depending on the property queried.
 */
- (long) getGeneralProperty: (int) property parameter: (long) parameter extra: (long) extra
{
  return mBackend->WndProc(property, parameter, extra);
}

//--------------------------------------------------------------------------------------------------

/**
 * Convenience function to avoid unneeded extra parameter.
 */
- (long) getGeneralProperty: (int) property parameter: (long) parameter
{
  return mBackend->WndProc(property, parameter, 0);
}

//--------------------------------------------------------------------------------------------------

/**
 * Convenience function to avoid unneeded parameters.
 */
- (long) getGeneralProperty: (int) property
{
  return mBackend->WndProc(property, 0, 0);
}

//--------------------------------------------------------------------------------------------------

/**
 * Use this variant if you have to pass in a reference to something (e.g. a text range).
 */
- (long) getGeneralProperty: (int) property ref: (const void*) ref
{
  return mBackend->WndProc(property, 0, (sptr_t) ref);  
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property setter for colors.
 */
- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor*) value
{
  if ([value colorSpaceName] != NSDeviceRGBColorSpace)
    value = [value colorUsingColorSpaceName: NSDeviceRGBColorSpace];
  long red = [value redComponent] * 255;
  long green = [value greenComponent] * 255;
  long blue = [value blueComponent] * 255;
  
  long color = (blue << 16) + (green << 8) + red;
  mBackend->WndProc(property, parameter, color);
}

//--------------------------------------------------------------------------------------------------

/**
 * Another color property setting, which allows to specify the color as string like in HTML
 * documents (i.e. with leading # and either 3 hex digits or 6).
 */
- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString*) fromHTML
{
  if ([fromHTML length] > 3 && [fromHTML characterAtIndex: 0] == '#')
  {
    bool longVersion = [fromHTML length] > 6;
    int index = 1;
    
    char value[3] = {0, 0, 0};
    value[0] = [fromHTML characterAtIndex: index++];
    if (longVersion)
      value[1] = [fromHTML characterAtIndex: index++];
    else
      value[1] = value[0];

    unsigned rawRed;
    [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawRed];

    value[0] = [fromHTML characterAtIndex: index++];
    if (longVersion)
      value[1] = [fromHTML characterAtIndex: index++];
    else
      value[1] = value[0];
    
    unsigned rawGreen;
    [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawGreen];

    value[0] = [fromHTML characterAtIndex: index++];
    if (longVersion)
      value[1] = [fromHTML characterAtIndex: index++];
    else
      value[1] = value[0];
    
    unsigned rawBlue;
    [[NSScanner scannerWithString: [NSString stringWithUTF8String: value]] scanHexInt: &rawBlue];

    long color = (rawBlue << 16) + (rawGreen << 8) + rawRed;
    mBackend->WndProc(property, parameter, color);
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property getter for colors.
 */
- (NSColor*) getColorProperty: (int) property parameter: (long) parameter
{
  long color = mBackend->WndProc(property, parameter, 0);
  float red = (color & 0xFF) / 255.0;
  float green = ((color >> 8) & 0xFF) / 255.0;
  float blue = ((color >> 16) & 0xFF) / 255.0;
  NSColor* result = [NSColor colorWithDeviceRed: red green: green blue: blue alpha: 1];
  return result;
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property setter for references (pointers, addresses).
 */
- (void) setReferenceProperty: (int) property parameter: (long) parameter value: (const void*) value
{
  mBackend->WndProc(property, parameter, (sptr_t) value);
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property getter for references (pointers, addresses).
 */
- (const void*) getReferenceProperty: (int) property parameter: (long) parameter
{
  return (const void*) mBackend->WndProc(property, parameter, 0);
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property setter for string values.
 */
- (void) setStringProperty: (int) property parameter: (long) parameter value: (NSString*) value
{
  const char* rawValue = [value UTF8String];
  mBackend->WndProc(property, parameter, (sptr_t) rawValue);
}


//--------------------------------------------------------------------------------------------------

/**
 * Specialized property getter for string values.
 */
- (NSString*) getStringProperty: (int) property parameter: (long) parameter
{
  const char* rawValue = (const char*) mBackend->WndProc(property, parameter, 0);
  return [NSString stringWithUTF8String: rawValue];
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property setter for lexer properties, which are commonly passed as strings.
 */
- (void) setLexerProperty: (NSString*) name value: (NSString*) value
{
  const char* rawName = [name UTF8String];
  const char* rawValue = [value UTF8String];
  mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, (sptr_t) rawValue);
}

//--------------------------------------------------------------------------------------------------

/**
 * Specialized property getter for references (pointers, addresses).
 */
- (NSString*) getLexerProperty: (NSString*) name
{
  const char* rawName = [name UTF8String];
  const char* result = (const char*) mBackend->WndProc(SCI_SETPROPERTY, (sptr_t) rawName, 0);
  return [NSString stringWithUTF8String: result];
}

//--------------------------------------------------------------------------------------------------

/**
 * Sets the notification callback
 */
- (void) registerNotifyCallback: (intptr_t) windowid value: (Scintilla::SciNotifyFunc) callback
{
	mBackend->RegisterNotifyCallback(windowid, callback);
}


//--------------------------------------------------------------------------------------------------

/**
 * Sets the new control which is displayed as info bar at the top or bottom of the editor.
 * Set newBar to nil if you want to hide the bar again.
 * When aligned to bottom position then the info bar and the horizontal scroller share the available
 * space. The info bar will then only get the width it is currently set to less a minimal amount
 * reserved for the scroller. At the top position it gets the full width of the control.
 * The info bar's height is set to the height of the scrollbar.
 */
- (void) setInfoBar: (NSView <InfoBarCommunicator>*) newBar top: (BOOL) top
{
  if (mInfoBar != newBar)
  {
    [mInfoBar removeFromSuperview];
    
    mInfoBar = newBar;
    mInfoBarAtTop = top;
    if (mInfoBar != nil)
    {
      [self addSubview: mInfoBar];
      [mInfoBar setCallback: self];
      
      // Keep the initial width as reference for layout changes.
      mInitialInfoBarWidth = [mInfoBar frame].size.width;
    }
    
    [self positionSubViews];
  }
}

//--------------------------------------------------------------------------------------------------

/**
 * Sets the edit's info bar status message. This call only has an effect if there is an info bar.
 */
- (void) setStatusText: (NSString*) text
{
  if (mInfoBar != nil)
    [mInfoBar notify: IBNStatusChanged message: text location: NSZeroPoint value: 0];
}

//--------------------------------------------------------------------------------------------------

- (NSRange) selectedRange
{
  return [mContent selectedRange];
}

//--------------------------------------------------------------------------------------------------

- (void)insertText: (NSString*)text
{
  [mContent insertText: text];
}

//--------------------------------------------------------------------------------------------------

/**
 * For backwards compatibility.
 */
- (BOOL) findAndHighlightText: (NSString*) searchText
                    matchCase: (BOOL) matchCase
                    wholeWord: (BOOL) wholeWord
                     scrollTo: (BOOL) scrollTo
                         wrap: (BOOL) wrap
{
  return [self findAndHighlightText: searchText
                          matchCase: matchCase
                          wholeWord: wholeWord
                           scrollTo: scrollTo
                               wrap: wrap
                          backwards: NO];
}

//--------------------------------------------------------------------------------------------------

/**
 * Searches and marks the first occurance of the given text and optionally scrolls it into view.
 *
 * @result YES if something was found, NO otherwise.
 */
- (BOOL) findAndHighlightText: (NSString*) searchText
                    matchCase: (BOOL) matchCase
                    wholeWord: (BOOL) wholeWord
                     scrollTo: (BOOL) scrollTo
                         wrap: (BOOL) wrap
                    backwards: (BOOL) backwards
{
  int searchFlags= 0;
  if (matchCase)
    searchFlags |= SCFIND_MATCHCASE;
  if (wholeWord)
    searchFlags |= SCFIND_WHOLEWORD;

  int selectionStart = [self getGeneralProperty: SCI_GETSELECTIONSTART parameter: 0];
  int selectionEnd = [self getGeneralProperty: SCI_GETSELECTIONEND parameter: 0];
  
  // Sets the start point for the comming search to the begin of the current selection.
  // For forward searches we have therefore to set the selection start to the current selection end
  // for proper incremental search. This does not harm as we either get a new selection if something
  // is found or the previous selection is restored.
  if (!backwards)
    [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: selectionEnd];
  [self setGeneralProperty: SCI_SEARCHANCHOR value: 0];
  sptr_t result;
  const char* textToSearch = [searchText UTF8String];

  // The following call will also set the selection if something was found.
  if (backwards)
  {
    result = [ScintillaView directCall: self
                               message: SCI_SEARCHPREV
                                wParam: searchFlags
                                lParam: (sptr_t) textToSearch];
    if (result < 0 && wrap)
    {
      // Try again from the end of the document if nothing could be found so far and
      // wrapped search is set.
      [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: [self getGeneralProperty: SCI_GETTEXTLENGTH parameter: 0]];
      [self setGeneralProperty: SCI_SEARCHANCHOR value: 0];
      result = [ScintillaView directCall: self
                                 message: SCI_SEARCHNEXT
                                  wParam: searchFlags
                                  lParam: (sptr_t) textToSearch];
    }
  }
  else
  {
    result = [ScintillaView directCall: self
                               message: SCI_SEARCHNEXT
                                wParam: searchFlags
                                lParam: (sptr_t) textToSearch];
    if (result < 0 && wrap)
    {
      // Try again from the start of the document if nothing could be found so far and
      // wrapped search is set.
      [self getGeneralProperty: SCI_SETSELECTIONSTART parameter: 0];
      [self setGeneralProperty: SCI_SEARCHANCHOR value: 0];
      result = [ScintillaView directCall: self
                                 message: SCI_SEARCHNEXT
                                  wParam: searchFlags
                                  lParam: (sptr_t) textToSearch];
    }
  }

  if (result >= 0)
  {
    if (scrollTo)
      [self setGeneralProperty: SCI_SCROLLCARET value: 0];
  }
  else
  {
    // Restore the former selection if we did not find anything.
    [self setGeneralProperty: SCI_SETSELECTIONSTART value: selectionStart];
    [self setGeneralProperty: SCI_SETSELECTIONEND value: selectionEnd];
  }
  return (result >= 0) ? YES : NO;
}

//--------------------------------------------------------------------------------------------------

/**
 * Searches the given text and replaces
 *
 * @result Number of entries replaced, 0 if none.
 */
- (int) findAndReplaceText: (NSString*) searchText
                    byText: (NSString*) newText
                 matchCase: (BOOL) matchCase
                 wholeWord: (BOOL) wholeWord
                     doAll: (BOOL) doAll
{
  // The current position is where we start searching for single occurences. Otherwise we start at
  // the beginning of the document.
  int startPosition;
  if (doAll)
    startPosition = 0; // Start at the beginning of the text if we replace all occurrences.
  else
    // For a signle replacement we start at the current caret position.
    startPosition = [self getGeneralProperty: SCI_GETCURRENTPOS];
  int endPosition = [self getGeneralProperty: SCI_GETTEXTLENGTH];

  int searchFlags= 0;
  if (matchCase)
    searchFlags |= SCFIND_MATCHCASE;
  if (wholeWord)
    searchFlags |= SCFIND_WHOLEWORD;
  [self setGeneralProperty: SCI_SETSEARCHFLAGS value: searchFlags];
  [self setGeneralProperty: SCI_SETTARGETSTART value: startPosition];
  [self setGeneralProperty: SCI_SETTARGETEND value: endPosition];

  const char* textToSearch = [searchText UTF8String];
  int sourceLength = strlen(textToSearch); // Length in bytes.
  const char* replacement = [newText UTF8String];
  int targetLength = strlen(replacement);  // Length in bytes.
  sptr_t result;
  
  int replaceCount = 0;
  if (doAll)
  {
    while (true)
    {
      result = [ScintillaView directCall: self
                                 message: SCI_SEARCHINTARGET
                                  wParam: sourceLength
                                  lParam: (sptr_t) textToSearch];
      if (result < 0)
        break;

      replaceCount++;
      [ScintillaView directCall: self
                                 message: SCI_REPLACETARGET
                                  wParam: targetLength
                                  lParam: (sptr_t) replacement];

      // The replacement changes the target range to the replaced text. Continue after that til the end.
      // The text length might be changed by the replacement so make sure the target end is the actual
      // text end.
      [self setGeneralProperty: SCI_SETTARGETSTART value: [self getGeneralProperty: SCI_GETTARGETEND]];
      [self setGeneralProperty: SCI_SETTARGETEND value: [self getGeneralProperty: SCI_GETTEXTLENGTH]];
    }
  }
  else
  {
    result = [ScintillaView directCall: self
                               message: SCI_SEARCHINTARGET
                                wParam: sourceLength
                                lParam: (sptr_t) textToSearch];
    replaceCount = (result < 0) ? 0 : 1;

    if (replaceCount > 0)
    {
      [ScintillaView directCall: self
                                 message: SCI_REPLACETARGET
                                  wParam: targetLength
                                  lParam: (sptr_t) replacement];

    // For a single replace we set the new selection to the replaced text.
    [self setGeneralProperty: SCI_SETSELECTIONSTART value: [self getGeneralProperty: SCI_GETTARGETSTART]];
    [self setGeneralProperty: SCI_SETSELECTIONEND value: [self getGeneralProperty: SCI_GETTARGETEND]];
    }
  }
  
  return replaceCount;
}

//--------------------------------------------------------------------------------------------------

- (void) setFontName: (NSString*) font
                size: (int) size
                bold: (BOOL) bold
                italic: (BOOL) italic
{
  for (int i = 0; i < 128; i++)
  {
    [self setGeneralProperty: SCI_STYLESETFONT
                   parameter: i
                       value: (sptr_t)[font UTF8String]];
    [self setGeneralProperty: SCI_STYLESETSIZE
                   parameter: i
                       value: size];
    [self setGeneralProperty: SCI_STYLESETBOLD
                   parameter: i
                       value: bold];
    [self setGeneralProperty: SCI_STYLESETITALIC
                   parameter: i
                       value: italic];
  }
}

//--------------------------------------------------------------------------------------------------

@end

Added cocoa/checkbuildosx.sh.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Script to build Scintilla for OS X with most supported build files.
# Current directory should be scintilla/cocoa before running.

cd ../..

# ************************************************************
# Target 1: build framework and test app with Xcode targetting OS X 10.7
# Clean both then build both -- if perform clean in ScintillaTest, also cleans ScintillaFramework
# which can cause double build
cd scintilla/cocoa/ScintillaFramework
xcodebuild clean
cd ../ScintillaTest
xcodebuild clean
cd ../ScintillaFramework
xcodebuild -sdk macosx10.7
cd ../ScintillaTest
xcodebuild -sdk macosx10.7
cd ../../..

# ************************************************************
# Target 2: build framework and test app with Xcode targetting OS X 10.6
cd scintilla/cocoa/ScintillaFramework
xcodebuild clean
cd ../ScintillaTest
xcodebuild clean
cd ../ScintillaFramework
xcodebuild -sdk macosx10.6
cd ../ScintillaTest
xcodebuild -sdk macosx10.6
cd ../../..

# ************************************************************
# Target 3: build framework and test app with Xcode targetting OS X 10.5
cd scintilla/cocoa/ScintillaFramework
xcodebuild clean
cd ../ScintillaTest
xcodebuild clean
cd ../ScintillaFramework
xcodebuild -sdk macosx10.5
cd ../ScintillaTest
xcodebuild -sdk macosx10.5
cd ../../..

# ************************************************************
# Target 4: Qt builds
# Requires Qt development libraries and qmake to be installed
cd scintilla/qt
cd ScintillaEditBase
qmake
xcodebuild clean
xcodebuild
cd ..

cd ScintillaEdit
python WidgetGen.py
qmake
xcodebuild clean
xcodebuild
cd ..

cd ScintillaEditPy
python sepbuild.py
cd ..
cd ../..

# ************************************************************
# Target 5: build framework and test app with make
cd scintilla/cocoa

make -f Framework.mk clean
make -f Framework.mk all

make -f SciTest.mk all

cd ../..

Added cocoa/common.mk.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
### shared variables and targets between Framework.mk and SciTest.mk ###

# build directories
BLD=build
APP_BLD=$(BLD)/Application
FRM_BLD=$(BLD)/Framework

ifdef DBG
CFLAGS=-g -O0
else
CFLAGS=-Os
endif

# compiler and compiler options
ARCH=-arch i386 $(CFLAGS)
CC=gcc -x c++ $(ARCH)
CO=gcc -x objective-c++ $(ARCH)
CCX=$(CC) $(gDEFs) $(INCS)
CCO=$(CO) $(gDEFs) $(INCS)

# include directories and global #define
gDEFs=-DSCI_NAMESPACE -DSCI_LEXER

# source directories
SRC_DIRS=../src ./ScintillaFramework ./ScintillaTest ./ \
	../lexers ../lexlib

INC_DIRS=$(SRC_DIRS) ../include

INCS=$(addprefix -I,$(INC_DIRS))

vpath %.m $(SRC_DIRS)
vpath %.mm $(SRC_DIRS)
vpath %.cpp $(SRC_DIRS)
vpath %.cxx $(SRC_DIRS)
vpath %.c $(SRC_DIRS)
vpath %.h $(INC_DIRS)

# clean everything
clean:
	-rm -rf $(BLD)

# build application objective-c++ files
$(APP_BLD)/%.o : %.mm
	$(CCO) -c $< -o $@

# build application objective-c files
$(APP_BLD)/%.o : %.m
	$(CCO) -c $< -o $@

# build framework c++ files
$(FRM_BLD)/%.o : %.cxx
	$(CCX) -c $< -o $@

# build framework objective-c++ files
$(FRM_BLD)/%.o : %.mm
	$(CCO) -c $< -o $@

Added cocoa/res/info_bar_bg.png.

cannot compute difference between binary files

Added cocoa/res/mac_cursor_busy.png.

cannot compute difference between binary files

Added cocoa/res/mac_cursor_flipped.png.

cannot compute difference between binary files

Added delbin.bat.



>
1
del /S /Q *.a *.aps *.bsc *.dll *.dsw *.exe *.idb *.ilc *.ild *.ilf *.ilk *.ils *.lib *.map *.ncb *.obj *.o *.opt *.pdb *.plg *.res *.sbr *.tds *.exp *.tlog >NUL:

Added delcvs.bat.



>
1
del /S /Q .cvsignore

Added doc/CommandValues.html.

















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!--Generated by scite/scripts/commandsdoc.py -->
<style type="text/css">
    table { border: 1px solid #1F1F1F; border-collapse: collapse; }
    td { border: 1px solid; border-color: #E0E0E0 #000000; padding: 1px 5px 1px 5px; }
    th { border: 1px solid #1F1F1F; padding: 1px 5px 1px 5px; }
    thead { background-color: #000000; color: #FFFFFF; }
</style>
<body>
<h2>SciTE menu commands</h2>
<table>
<thead><td>Command</td><td>Menu text</td></thead>
<tr><td>IDM_NEW</td><td>New</td></tr>
<tr><td>IDM_OPEN</td><td>Open</td></tr>
<tr><td>IDM_OPENSELECTED</td><td>Open Selected Filename</td></tr>
<tr><td>IDM_REVERT</td><td>Revert</td></tr>
<tr><td>IDM_CLOSE</td><td>Close</td></tr>
<tr><td>IDM_SAVE</td><td>Save</td></tr>
<tr><td>IDM_SAVEAS</td><td>Save As</td></tr>
<tr><td>IDM_SAVEACOPY</td><td>Save a Copy</td></tr>
<tr><td>IDM_COPYPATH</td><td>Copy Path</td></tr>
<tr><td>IDM_ENCODING_DEFAULT</td><td>Code Page Property</td></tr>
<tr><td>IDM_ENCODING_UCS2BE</td><td>UTF-16 Big Endian</td></tr>
<tr><td>IDM_ENCODING_UCS2LE</td><td>UTF-16 Little Endian</td></tr>
<tr><td>IDM_ENCODING_UTF8</td><td>UTF-8 with BOM</td></tr>
<tr><td>IDM_ENCODING_UCOOKIE</td><td>UTF-8</td></tr>
<tr><td>IDM_SAVEASHTML</td><td>As HTML</td></tr>
<tr><td>IDM_SAVEASRTF</td><td>As RTF</td></tr>
<tr><td>IDM_SAVEASPDF</td><td>As PDF</td></tr>
<tr><td>IDM_SAVEASTEX</td><td>As LaTeX</td></tr>
<tr><td>IDM_SAVEASXML</td><td>As XML</td></tr>
<tr><td>IDM_PRINTSETUP</td><td>Page Setup</td></tr>
<tr><td>IDM_PRINT</td><td>Print</td></tr>
<tr><td>IDM_LOADSESSION</td><td>Load Session</td></tr>
<tr><td>IDM_SAVESESSION</td><td>Save Session</td></tr>
<tr><td>IDM_QUIT</td><td>Exit</td></tr>
<tr><td>IDM_UNDO</td><td>Undo</td></tr>
<tr><td>IDM_REDO</td><td>Redo</td></tr>
<tr><td>IDM_CUT</td><td>Cut</td></tr>
<tr><td>IDM_COPY</td><td>Copy</td></tr>
<tr><td>IDM_PASTE</td><td>Paste</td></tr>
<tr><td>IDM_DUPLICATE</td><td>Duplicate</td></tr>
<tr><td>IDM_CLEAR</td><td>Delete</td></tr>
<tr><td>IDM_SELECTALL</td><td>Select All</td></tr>
<tr><td>IDM_COPYASRTF</td><td>Copy as RTF</td></tr>
<tr><td>IDM_MATCHBRACE</td><td>Match Brace</td></tr>
<tr><td>IDM_SELECTTOBRACE</td><td>Select to Brace</td></tr>
<tr><td>IDM_SHOWCALLTIP</td><td>Show Calltip</td></tr>
<tr><td>IDM_COMPLETE</td><td>Complete Symbol</td></tr>
<tr><td>IDM_COMPLETEWORD</td><td>Complete Word</td></tr>
<tr><td>IDM_ABBREV</td><td>Expand Abbreviation</td></tr>
<tr><td>IDM_INS_ABBREV</td><td>Insert Abbreviation</td></tr>
<tr><td>IDM_BLOCK_COMMENT</td><td>Block Comment or Uncomment</td></tr>
<tr><td>IDM_BOX_COMMENT</td><td>Box Comment</td></tr>
<tr><td>IDM_STREAM_COMMENT</td><td>Stream Comment</td></tr>
<tr><td>IDM_UPRCASE</td><td>Make Selection Uppercase</td></tr>
<tr><td>IDM_LWRCASE</td><td>Make Selection Lowercase</td></tr>
<tr><td>IDM_JOIN</td><td>Join</td></tr>
<tr><td>IDM_SPLIT</td><td>Split</td></tr>
<tr><td>IDM_FIND</td><td>Find</td></tr>
<tr><td>IDM_FINDNEXT</td><td>Find Next</td></tr>
<tr><td>IDM_FINDNEXTBACK</td><td>Find Previous</td></tr>
<tr><td>IDM_FINDINFILES</td><td>Find in Files</td></tr>
<tr><td>IDM_REPLACE</td><td>Replace</td></tr>
<tr><td>IDM_INCSEARCH</td><td>Incremental Search</td></tr>
<tr><td>IDM_GOTO</td><td>Go to</td></tr>
<tr><td>IDM_BOOKMARK_NEXT</td><td>Next Bookmark</td></tr>
<tr><td>IDM_BOOKMARK_PREV</td><td>Previous Bookmark</td></tr>
<tr><td>IDM_BOOKMARK_TOGGLE</td><td>Toggle Bookmark</td></tr>
<tr><td>IDM_BOOKMARK_CLEARALL</td><td>Clear All Bookmarks</td></tr>
<tr><td>IDM_EXPAND</td><td>Toggle current fold</td></tr>
<tr><td>IDM_TOGGLE_FOLDALL</td><td>Toggle all folds</td></tr>
<tr><td>IDM_FULLSCREEN</td><td>Full Screen</td></tr>
<tr><td>IDM_VIEWTOOLBAR</td><td>Tool Bar</td></tr>
<tr><td>IDM_VIEWTABBAR</td><td>Tab Bar</td></tr>
<tr><td>IDM_VIEWSTATUSBAR</td><td>Status Bar</td></tr>
<tr><td>IDM_VIEWSPACE</td><td>Whitespace</td></tr>
<tr><td>IDM_VIEWEOL</td><td>End of Line</td></tr>
<tr><td>IDM_VIEWGUIDES</td><td>Indentation Guides</td></tr>
<tr><td>IDM_LINENUMBERMARGIN</td><td>Line Numbers</td></tr>
<tr><td>IDM_SELMARGIN</td><td>Margin</td></tr>
<tr><td>IDM_FOLDMARGIN</td><td>Fold Margin</td></tr>
<tr><td>IDM_TOGGLEOUTPUT</td><td>Output</td></tr>
<tr><td>IDM_TOGGLEPARAMETERS</td><td>Parameters</td></tr>
<tr><td>IDM_COMPILE</td><td>Compile</td></tr>
<tr><td>IDM_BUILD</td><td>Build</td></tr>
<tr><td>IDM_GO</td><td>Go</td></tr>
<tr><td>IDM_STOPEXECUTE</td><td>Stop Executing</td></tr>
<tr><td>IDM_NEXTMSG</td><td>Next Message</td></tr>
<tr><td>IDM_PREVMSG</td><td>Previous Message</td></tr>
<tr><td>IDM_CLEAROUTPUT</td><td>Clear Output</td></tr>
<tr><td>IDM_SWITCHPANE</td><td>Switch Pane</td></tr>
<tr><td>IDM_ONTOP</td><td>Always On Top</td></tr>
<tr><td>IDM_OPENFILESHERE</td><td>Open Files Here</td></tr>
<tr><td>IDM_SPLITVERTICAL</td><td>Vertical Split</td></tr>
<tr><td>IDM_WRAP</td><td>Wrap</td></tr>
<tr><td>IDM_WRAPOUTPUT</td><td>Wrap Output</td></tr>
<tr><td>IDM_READONLY</td><td>Read-Only</td></tr>
<tr><td>IDM_EOL_CRLF</td><td>CR + LF</td></tr>
<tr><td>IDM_EOL_CR</td><td>CR</td></tr>
<tr><td>IDM_EOL_LF</td><td>LF</td></tr>
<tr><td>IDM_EOL_CONVERT</td><td>Convert Line End Characters</td></tr>
<tr><td>IDM_TABSIZE</td><td>Change Indentation Settings</td></tr>
<tr><td>IDM_MONOFONT</td><td>Use Monospaced Font</td></tr>
<tr><td>IDM_OPENLOCALPROPERTIES</td><td>Open Local Options File</td></tr>
<tr><td>IDM_OPENDIRECTORYPROPERTIES</td><td>Open Directory Options File</td></tr>
<tr><td>IDM_OPENUSERPROPERTIES</td><td>Open User Options File</td></tr>
<tr><td>IDM_OPENGLOBALPROPERTIES</td><td>Open Global Options File</td></tr>
<tr><td>IDM_OPENABBREVPROPERTIES</td><td>Open Abbreviations File</td></tr>
<tr><td>IDM_OPENLUAEXTERNALFILE</td><td>Open Lua Startup Script</td></tr>
<tr><td>IDM_PREVFILE</td><td>Previous</td></tr>
<tr><td>IDM_NEXTFILE</td><td>Next</td></tr>
<tr><td>IDM_CLOSEALL</td><td>Close All</td></tr>
<tr><td>IDM_SAVEALL</td><td>Save All</td></tr>
<tr><td>IDM_HELP</td><td>Help</td></tr>
<tr><td>IDM_HELP_SCITE</td><td>Sc1 Help</td></tr>
<tr><td>IDM_ABOUT</td><td>About Sc1</td></tr>
<tr><td>IDM_HELP_SCITE</td><td>SciTE Help</td></tr>
<tr><td>IDM_ABOUT</td><td>About SciTE</td></tr>
</table>
<h2>Scintilla key commands</h2>
<table>
<thead><td>Command</td><td>Name</td><td>Explanation</td></thead>
<tr><td>2547</td><td>AnnotationClearAll</td><td>Clear the annotations from all lines</td></tr>
<tr><td>2101</td><td>AutoCCancel</td><td>Remove the auto-completion list from the screen.</td></tr>
<tr><td>2104</td><td>AutoCComplete</td><td>User has selected an item so remove the list and insert the selection.</td></tr>
<tr><td>2328</td><td>BackTab</td><td>Dedent the selected lines.</td></tr>
<tr><td>2078</td><td>BeginUndoAction</td><td>Start a sequence of actions that is undone and redone as a unit. May be nested.</td></tr>
<tr><td>2201</td><td>CallTipCancel</td><td>Remove the call tip from the screen.</td></tr>
<tr><td>2325</td><td>Cancel</td><td>Cancel any modes such as call tip or auto-completion list display.</td></tr>
<tr><td>2304</td><td>CharLeft</td><td>Move caret left one character.</td></tr>
<tr><td>2305</td><td>CharLeftExtend</td><td>Move caret left one character extending selection to new caret position.</td></tr>
<tr><td>2428</td><td>CharLeftRectExtend</td><td>Move caret left one character, extending rectangular selection to new caret position.</td></tr>
<tr><td>2306</td><td>CharRight</td><td>Move caret right one character.</td></tr>
<tr><td>2307</td><td>CharRightExtend</td><td>Move caret right one character extending selection to new caret position.</td></tr>
<tr><td>2429</td><td>CharRightRectExtend</td><td>Move caret right one character, extending rectangular selection to new caret position.</td></tr>
<tr><td>2399</td><td>ChooseCaretX</td><td>Set the last x chosen value to be the caret x position.</td></tr>
<tr><td>2180</td><td>Clear</td><td>Clear the selection.</td></tr>
<tr><td>2004</td><td>ClearAll</td><td>Delete all text in the document.</td></tr>
<tr><td>2072</td><td>ClearAllCmdKeys</td><td>Drop all key mappings.</td></tr>
<tr><td>2005</td><td>ClearDocumentStyle</td><td>Set all style bytes to 0, remove all folding information.</td></tr>
<tr><td>2408</td><td>ClearRegisteredImages</td><td>Clear all the registered XPM images.</td></tr>
<tr><td>2571</td><td>ClearSelections</td><td>Clear selections to a single empty stream selection</td></tr>
<tr><td>2178</td><td>Copy</td><td>Copy the selection to the clipboard.</td></tr>
<tr><td>2519</td><td>CopyAllowLine</td><td>Copy the selection, if selection empty copy the line with the caret</td></tr>
<tr><td>2177</td><td>Cut</td><td>Cut the selection to the clipboard.</td></tr>
<tr><td>2395</td><td>DelLineLeft</td><td>Delete back from the current position to the start of the line.</td></tr>
<tr><td>2396</td><td>DelLineRight</td><td>Delete forwards from the current position to the end of the line.</td></tr>
<tr><td>2335</td><td>DelWordLeft</td><td>Delete the word to the left of the caret.</td></tr>
<tr><td>2336</td><td>DelWordRight</td><td>Delete the word to the right of the caret.</td></tr>
<tr><td>2518</td><td>DelWordRightEnd</td><td>Delete the word to the right of the caret, but not the trailing non-word characters.</td></tr>
<tr><td>2326</td><td>DeleteBack</td><td>Delete the selection or if no selection, the character before the caret.</td></tr>
<tr><td>2344</td><td>DeleteBackNotLine</td><td>Delete the selection or if no selection, the character before the caret. Will not delete the character before at the start of a line.</td></tr>
<tr><td>2318</td><td>DocumentEnd</td><td>Move caret to last position in document.</td></tr>
<tr><td>2319</td><td>DocumentEndExtend</td><td>Move caret to last position in document extending selection to new caret position.</td></tr>
<tr><td>2316</td><td>DocumentStart</td><td>Move caret to first position in document.</td></tr>
<tr><td>2317</td><td>DocumentStartExtend</td><td>Move caret to first position in document extending selection to new caret position.</td></tr>
<tr><td>2324</td><td>EditToggleOvertype</td><td>Switch from insert to overtype mode or the reverse.</td></tr>
<tr><td>2175</td><td>EmptyUndoBuffer</td><td>Delete the undo history.</td></tr>
<tr><td>2079</td><td>EndUndoAction</td><td>End a sequence of actions that is undone and redone as a unit.</td></tr>
<tr><td>2642</td><td>FindIndicatorHide</td><td>On OS X, hide the find indicator.</td></tr>
<tr><td>2330</td><td>FormFeed</td><td>Insert a Form Feed character.</td></tr>
<tr><td>4023</td><td>FreeSubStyles</td><td>Free allocated sub styles</td></tr>
<tr><td>2400</td><td>GrabFocus</td><td>Set the focus to this Scintilla widget.</td></tr>
<tr><td>2312</td><td>Home</td><td>Move caret to first position on line.</td></tr>
<tr><td>2345</td><td>HomeDisplay</td><td>Move caret to first position on display line.</td></tr>
<tr><td>2346</td><td>HomeDisplayExtend</td><td>Move caret to first position on display line extending selection to new caret position.</td></tr>
<tr><td>2313</td><td>HomeExtend</td><td>Move caret to first position on line extending selection to new caret position.</td></tr>
<tr><td>2430</td><td>HomeRectExtend</td><td>Move caret to first position on line, extending rectangular selection to new caret position.</td></tr>
<tr><td>2349</td><td>HomeWrap</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2450</td><td>HomeWrapExtend</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2455</td><td>LineCopy</td><td>Copy the line containing the caret.</td></tr>
<tr><td>2337</td><td>LineCut</td><td>Cut the line containing the caret.</td></tr>
<tr><td>2338</td><td>LineDelete</td><td>Delete the line containing the caret.</td></tr>
<tr><td>2300</td><td>LineDown</td><td>Move caret down one line.</td></tr>
<tr><td>2301</td><td>LineDownExtend</td><td>Move caret down one line extending selection to new caret position.</td></tr>
<tr><td>2426</td><td>LineDownRectExtend</td><td>Move caret down one line, extending rectangular selection to new caret position.</td></tr>
<tr><td>2404</td><td>LineDuplicate</td><td>Duplicate the current line.</td></tr>
<tr><td>2314</td><td>LineEnd</td><td>Move caret to last position on line.</td></tr>
<tr><td>2347</td><td>LineEndDisplay</td><td>Move caret to last position on display line.</td></tr>
<tr><td>2348</td><td>LineEndDisplayExtend</td><td>Move caret to last position on display line extending selection to new caret position.</td></tr>
<tr><td>2315</td><td>LineEndExtend</td><td>Move caret to last position on line extending selection to new caret position.</td></tr>
<tr><td>2432</td><td>LineEndRectExtend</td><td>Move caret to last position on line, extending rectangular selection to new caret position.</td></tr>
<tr><td>2451</td><td>LineEndWrap</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2452</td><td>LineEndWrapExtend</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2342</td><td>LineScrollDown</td><td>Scroll the document down, keeping the caret visible.</td></tr>
<tr><td>2343</td><td>LineScrollUp</td><td>Scroll the document up, keeping the caret visible.</td></tr>
<tr><td>2339</td><td>LineTranspose</td><td>Switch the current line with the previous.</td></tr>
<tr><td>2302</td><td>LineUp</td><td>Move caret up one line.</td></tr>
<tr><td>2303</td><td>LineUpExtend</td><td>Move caret up one line extending selection to new caret position.</td></tr>
<tr><td>2427</td><td>LineUpRectExtend</td><td>Move caret up one line, extending rectangular selection to new caret position.</td></tr>
<tr><td>2288</td><td>LinesJoin</td><td>Join the lines in the target.</td></tr>
<tr><td>2340</td><td>LowerCase</td><td>Transform the selection to lower case.</td></tr>
<tr><td>2536</td><td>MarginTextClearAll</td><td>Clear the margin text on all lines</td></tr>
<tr><td>2401</td><td>MoveCaretInsideView</td><td>Move the caret inside current view if it's not there already.</td></tr>
<tr><td>2621</td><td>MoveSelectedLinesDown</td><td>Move the selected lines down one line, shifting the line below before the selection</td></tr>
<tr><td>2620</td><td>MoveSelectedLinesUp</td><td>Move the selected lines up one line, shifting the line above after the selection</td></tr>
<tr><td>2329</td><td>NewLine</td><td>Insert a new line, may use a CRLF, CR or LF depending on EOL mode.</td></tr>
<tr><td>2172</td><td>Null</td><td>Null operation.</td></tr>
<tr><td>2322</td><td>PageDown</td><td>Move caret one page down.</td></tr>
<tr><td>2323</td><td>PageDownExtend</td><td>Move caret one page down extending selection to new caret position.</td></tr>
<tr><td>2434</td><td>PageDownRectExtend</td><td>Move caret one page down, extending rectangular selection to new caret position.</td></tr>
<tr><td>2320</td><td>PageUp</td><td>Move caret one page up.</td></tr>
<tr><td>2321</td><td>PageUpExtend</td><td>Move caret one page up extending selection to new caret position.</td></tr>
<tr><td>2433</td><td>PageUpRectExtend</td><td>Move caret one page up, extending rectangular selection to new caret position.</td></tr>
<tr><td>2413</td><td>ParaDown</td><td>Move caret between paragraphs (delimited by empty lines).</td></tr>
<tr><td>2414</td><td>ParaDownExtend</td><td>Move caret between paragraphs (delimited by empty lines).</td></tr>
<tr><td>2415</td><td>ParaUp</td><td>Move caret between paragraphs (delimited by empty lines).</td></tr>
<tr><td>2416</td><td>ParaUpExtend</td><td>Move caret between paragraphs (delimited by empty lines).</td></tr>
<tr><td>2179</td><td>Paste</td><td>Paste the contents of the clipboard into the document replacing the selection.</td></tr>
<tr><td>2011</td><td>Redo</td><td>Redoes the next action on the undo history.</td></tr>
<tr><td>2552</td><td>ReleaseAllExtendedStyles</td><td>Release all extended (>255) style numbers</td></tr>
<tr><td>2606</td><td>RotateSelection</td><td>Set the main selection to the next selection.</td></tr>
<tr><td>2169</td><td>ScrollCaret</td><td>Ensure the caret is visible.</td></tr>
<tr><td>2629</td><td>ScrollToEnd</td><td>Scroll to end of document.</td></tr>
<tr><td>2628</td><td>ScrollToStart</td><td>Scroll to start of document.</td></tr>
<tr><td>2366</td><td>SearchAnchor</td><td>Sets the current caret position to be the search anchor.</td></tr>
<tr><td>2013</td><td>SelectAll</td><td>Select all the text in the document.</td></tr>
<tr><td>2469</td><td>SelectionDuplicate</td><td>Duplicate the selection. If selection empty duplicate the line containing the caret.</td></tr>
<tr><td>2444</td><td>SetCharsDefault</td><td>Reset the set of characters for whitespace and word characters to the defaults.</td></tr>
<tr><td>2014</td><td>SetSavePoint</td><td>Remember the current position in the undo history as the position at which the document was saved.</td></tr>
<tr><td>3001</td><td>StartRecord</td><td>Start notifying the container of all key presses and commands.</td></tr>
<tr><td>3002</td><td>StopRecord</td><td>Stop notifying the container of all key presses and commands.</td></tr>
<tr><td>2437</td><td>StutteredPageDown</td><td>Move caret to bottom of page, or one page down if already at bottom of page.</td></tr>
<tr><td>2438</td><td>StutteredPageDownExtend</td><td>Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position.</td></tr>
<tr><td>2435</td><td>StutteredPageUp</td><td>Move caret to top of page, or one page up if already at top of page.</td></tr>
<tr><td>2436</td><td>StutteredPageUpExtend</td><td>Move caret to top of page, or one page up if already at top of page, extending selection to new caret position.</td></tr>
<tr><td>2050</td><td>StyleClearAll</td><td>Clear all the styles and make equivalent to the global default style.</td></tr>
<tr><td>2058</td><td>StyleResetDefault</td><td>Reset the default style to its state at startup</td></tr>
<tr><td>2607</td><td>SwapMainAnchorCaret</td><td>Swap that caret and anchor of the main selection.</td></tr>
<tr><td>2327</td><td>Tab</td><td>If selection is empty or all on one line replace the selection with a tab character. If more than one line selected, indent the lines.</td></tr>
<tr><td>2287</td><td>TargetFromSelection</td><td>Make the target range start and end be the same as the selection range start and end.</td></tr>
<tr><td>2459</td><td>ToggleCaretSticky</td><td>Switch between sticky and non-sticky: meant to be bound to a key.</td></tr>
<tr><td>2176</td><td>Undo</td><td>Undo one action in the undo history.</td></tr>
<tr><td>2341</td><td>UpperCase</td><td>Transform the selection to upper case.</td></tr>
<tr><td>2331</td><td>VCHome</td><td>Move caret to before first visible character on line. If already there move to first character on line.</td></tr>
<tr><td>2652</td><td>VCHomeDisplay</td><td>Move caret to before first visible character on display line. If already there move to first character on display line.</td></tr>
<tr><td>2653</td><td>VCHomeDisplayExtend</td><td>Like VCHomeDisplay but extending selection to new caret position.</td></tr>
<tr><td>2332</td><td>VCHomeExtend</td><td>Like VCHome but extending selection to new caret position.</td></tr>
<tr><td>2431</td><td>VCHomeRectExtend</td><td>Move caret to before first visible character on line. If already there move to first character on line. In either case, extend rectangular selection to new caret position.</td></tr>
<tr><td>2453</td><td>VCHomeWrap</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2454</td><td>VCHomeWrapExtend</td><td>These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)? except they behave differently when word-wrap is enabled: They go first to the start / end of the display line, like (Home|LineEnd)Display The difference is that, the cursor is already at the point, it goes on to the start or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.</td></tr>
<tr><td>2619</td><td>VerticalCentreCaret</td><td>Centre current line in window.</td></tr>
<tr><td>2308</td><td>WordLeft</td><td>Move caret left one word.</td></tr>
<tr><td>2439</td><td>WordLeftEnd</td><td>Move caret left one word, position cursor at end of word.</td></tr>
<tr><td>2440</td><td>WordLeftEndExtend</td><td>Move caret left one word, position cursor at end of word, extending selection to new caret position.</td></tr>
<tr><td>2309</td><td>WordLeftExtend</td><td>Move caret left one word extending selection to new caret position.</td></tr>
<tr><td>2390</td><td>WordPartLeft</td><td>Move to the previous change in capitalisation.</td></tr>
<tr><td>2391</td><td>WordPartLeftExtend</td><td>Move to the previous change in capitalisation extending selection to new caret position.</td></tr>
<tr><td>2392</td><td>WordPartRight</td><td>Move to the change next in capitalisation.</td></tr>
<tr><td>2393</td><td>WordPartRightExtend</td><td>Move to the next change in capitalisation extending selection to new caret position.</td></tr>
<tr><td>2310</td><td>WordRight</td><td>Move caret right one word.</td></tr>
<tr><td>2441</td><td>WordRightEnd</td><td>Move caret right one word, position cursor at end of word.</td></tr>
<tr><td>2442</td><td>WordRightEndExtend</td><td>Move caret right one word, position cursor at end of word, extending selection to new caret position.</td></tr>
<tr><td>2311</td><td>WordRightExtend</td><td>Move caret right one word extending selection to new caret position.</td></tr>
<tr><td>2333</td><td>ZoomIn</td><td>Magnify the displayed text by increasing the sizes by 1 point.</td></tr>
<tr><td>2334</td><td>ZoomOut</td><td>Make the displayed text smaller by decreasing the sizes by 1 point.</td></tr>
</table>
</body>
</html>

Added doc/Design.html.



















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla and SciTE
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          Component Design</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Top level structure
    </h2>
    <p>
       Scintilla consists of three major layers of C++ code
    </p>
    <ul>
      <li>
        Portability Library
      </li>
      <li>
        Core Code
      </li>
      <li>
        Platform Events and API
      </li>
    </ul>
    <p>
       The primary purpose of this structure is to separate the platform dependent code from the
      platform independent core code. This makes it easier to port Scintilla to a new platform and
      ensures that most readers of the code do not have to deal with platform details. To minimise
      portability problems and avoid code bloat, a conservative subset of C++ is used in Scintilla
      with no exception handling, run time type information or use of the standard C++
      library and with limited use of templates.
    </p>
    <p>
       The currently supported platforms, Windows, GTK+/Linux and wxWindows are fairly similar in 
      many ways.
      Each has windows, menus and bitmaps. These features generally work in similar ways so each
      has a way to move a window or draw a red line. Sometimes one platform requires a sequence of
      calls rather than a single call. At other times, the differences are more profound. Reading
      the Windows clipboard occurs synchronously but reading the GTK+ clipboard requires a request
      call that will be asynchronously answered with a message containing the clipboard data.
      The wxWindows platform is available from the <a href="http://wxwindows.org/">wxWindows site</a>
    </p>
    <br />
    <h3>
       Portability Library
    </h3>
    <p>
       This is a fairly small and thin layer over the platform's native capabilities.
    </p>
    <p>
       The portability library is defined in Platform.h and is implemented once for each platform.
      PlatWin.cxx defines the Windows variants of the methods and PlatGTK.cxx the GTK+ variants.
    </p>
    <p>
       Several of the classes here hold platform specific object identifiers and act as proxies to
      these platform objects. Most client code can thus manipulate the platform objects without
      caring which is the current platform. Sometimes client code needs access to the underlying
      object identifiers and this is provided by the GetID method. The underlying types of the
      platform specific identifiers are typedefed to common names to allow them to be transferred
      around in client code where needed.
    </p>
    <h4>
       Point, PRectangle
    </h4>
    <p>
       These are simple classes provided to hold the commonly used geometric primitives. A
      PRectangle follows the Mac / Windows convention of not including its bottom and right sides
      instead of including all its sides as is normal in GTK+. It is not called Rectangle as this may be
      the name of a macro on Windows.
    </p>
    <h4>
       Colour, ColourPair, Palette
    </h4>
    <p>
       Colour holds a platform specific colour identifier - COLORREF for Windows and GdkColor for
      GTK+. The red, green and blue components that make up the colour are limited to the 8 bits of
      precision available on Windows. ColourPairs are used because not all possible colours are
      always available. Using an 8 bit colour mode, which is a common setting for both Windows and
      GTK+, only 256 colours are possible on the display. Thus when an application asks for a dull
      red, say #400000, it may only be allocated an already available colour such as #800000 or
      #330000. With 16 or 2 colour modes even less choice is available and the application will
      have to use the limited set of already available colours.
    </p>
    A Palette object holds a set of colour pairs and can make the appropriate calls to ask to
    allocate these colours and to see what the platform has decided will be allowed. 
    <h4>
       Font
    </h4>
    <p>
       Font holds a platform specific font identifier - HFONT for Windows, GdkFont* for GTK+. It
      does not own the identifier and so will not delete the platform font object in its
      destructor. Client code should call Destroy at appropriate times.
    </p>
    <h4>
       Surface
    </h4>
    <p>
       Surface is an abstraction over each platform's concept of somewhere that graphical drawing
      operations can be done. It may wrap an already created drawing place such as a window or be
      used to create a bitmap that can be drawn into and later copied onto another surface. On
      Windows it wraps a HDC and possibly a HBITMAP. On GTK+ it wraps a GdkDrawable* and possibly a
      GdkPixmap*. Other platform specific objects are created (and correctly destroyed) whenever
      required to perform drawing actions.
    </p>
    <p>
       Drawing operations provided include drawing filled and unfilled polygons, lines, rectangles,
      ellipses and text. The height and width of text as well as other details can be measured.
      Operations can be clipped to a rectangle. Most of the calls are stateless with all parameters
      being passed at each call. The exception to this is line drawing which is performed by
      calling MoveTo and then LineTo.
    </p>
    <h4>
       Window
    </h4>
    <p>
       Window acts as a proxy to a platform window allowing operations such as showing, moving,
      redrawing, and destroying to be performed. It contains a platform specific window identifier
      - HWND for Windows, GtkWidget* for GTK+.
    </p>
    <h4>
       ListBox
    </h4>
    <p>
       ListBox is a subclass of Window and acts as a proxy to a platform listbox adding methods for
      operations such as adding, retrieving, and selecting items.
    </p>
    <h4>
       Menu
    </h4>
    <p>
       Menu is a small helper class for constructing popup menus. It contains the platform specific
      menu identifier - HMENU for Windows, GtkItemFactory* for GTK+. Most of the work in
      constructing menus requires access to platform events and so is done in the Platform Events
      and API layer.
    </p>
    <h4>
       Platform
    </h4>
    <p>
       The Platform class is used to access the facilities of the platform. System wide parameters
      such as double click speed and chrome colour are available from Platform. Utility functions
      such as DebugPrintf are also available from Platform.
    </p>
    <h3>
       Core Code
    </h3>
    <p>
       The bulk of Scintilla's code is platform independent. This is made up of the CellBuffer,
      ContractionState, Document, Editor, Indicator, LineMarker, Style, ViewStyle, KeyMap, 
      ScintillaBase, CallTip,
      and AutoComplete primary classes.
    </p>
    <h4>
       CellBuffer
    </h4>
    <p>
       A CellBuffer holds text and styling information, the undo stack, the assignment of line
      markers to lines, and the fold structure.
    </p>
    <p>
       A cell contains a character byte and its associated style byte. The current state of the
      cell buffer is the sequence of cells that make up the text and a sequence of line information
      containing the starting position of each line and any markers assigned to each line.
    </p>
    <p>
       The undo stack holds a sequence of actions on the cell buffer. Each action is one of a text
      insertion, a text deletion or an undo start action. The start actions are used to group
      sequences of text insertions and deletions together so they can be undone together. To
      perform an undo operation, each insertion or deletion is undone in reverse sequence.
      Similarly, redo reapplies each action to the buffer in sequence. Whenever a character is
      inserted in the buffer either directly through a call such as InsertString or through undo or
      redo, its styling byte is initially set to zero. Client code is responsible for styling each
      character whenever convenient. Styling information is not stored in undo actions.
    </p>
    <h4>
       Document
    </h4>
    <p>
       A document contains a CellBuffer and deals with some higher level abstractions such as
      words, DBCS character sequences and line end character sequences. It is responsible for
      managing the styling process and for notifying other objects when changes occur to the
      document.
    </p>
    <h4>
       Editor
    </h4>
    <p>
       The Editor object is central to Scintilla. It is responsible for displaying a document and
      responding to user actions and requests from the container. It uses ContractionState, Indicator, 
      LineMarker, Style, and ViewStyle objects to display the document and a KeyMap class to 
      map key presses to functions. 
      The visibility of each line is kept in the ContractionState which is also responsible for mapping 
      from display lines to documents lines and vice versa.
    </p>
    <p>
       There may be multiple Editor objects attached to one Document object. Changes to a 
       document are broadcast to the editors through the DocWatcher mechanism.
    </p>
    <h4>
       ScintillaBase
    </h4>
    <p>
       ScintillaBase is a subclass of Editor and adds extra windowing features including display of
      calltips, autocompletion lists and context menus. These features use CallTip and AutoComplete
      objects. This class is optional so a lightweight implementation of Scintilla may bypass it if
      the added functionality is not required.
    </p>
    <h3>
       Platform Events and API
    </h3>
    <p>
       Each platform uses different mechanisms for receiving events. On Windows, events are
      received through messages and COM. On GTK+, callback functions are used.
    </p>
    <p>
       For each platform, a class is derived from ScintillaBase (and thus from Editor). This is
      ScintillaWin on Windows and ScintillaGTK on GTK+. These classes are responsible for
      connecting to the platforms event mechanism and also to implement some virtual methods in
      Editor and ScintillaBase which are different on the platforms. For example, this layer has to
      support this difference between the synchronous Windows clipboard and the asynchronous GTK+
      clipboard.
    </p>
    <p>
       The external API is defined in this layer as each platform has different preferred styles of
      API - messages on Windows and function calls on GTK+. This also allows multiple APIs to be
      defined on a platform. The currently available API on GTK+ is similar to the Windows API and
      does not follow platform conventions well. A second API could be implemented here that did
      follow platform conventions.
    </p>
  </body>
</html>

Added doc/Icons.html.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla icons
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Icons
    </h2>
    <p>
       These images may be used under the same license as Scintilla. 
    </p>
    <p>
       Drawn by Iago Rubio, Philippe Lhoste, and Neil Hodgson. 
    </p>
    <p>
       <a href="http://prdownloads.sourceforge.net/scintilla/icons1.zip?download">zip format</a> (70K)
    </p>
    <table>
    <tr>
    <td>For autocompletion lists</td>
    <td colspan="3">For margin markers</td>
    </tr>
    <tr>
    <td>12x12</td>
    <td>16x16</td>
    <td>24x24</td>
    <td>32x32</td>
    </tr>
    <tr>
    <td valign="top"><img src="12.png" /></td>
    <td valign="top"><img src="16.png" /></td>
    <td valign="top"><img src="24.png" /></td>
    <td valign="top"><img src="32.png" /></td>
    </tr>
    </table>
  </body>
</html>

Added doc/Lexer.txt.





































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
How to write a scintilla lexer

A lexer for a particular language determines how a specified range of
text shall be colored.  Writing a lexer is relatively straightforward
because the lexer need only color given text.  The harder job of
determining how much text actually needs to be colored is handled by
Scintilla itself, that is, the lexer's caller.


Parameters

The lexer for language LLL has the following prototype:

    static void ColouriseLLLDoc (
        unsigned int startPos, int length,
        int initStyle,
        WordList *keywordlists[],
        Accessor &styler);

The styler parameter is an Accessor object.  The lexer must use this
object to access the text to be colored.  The lexer gets the character
at position i using styler.SafeGetCharAt(i);

The startPos and length parameters indicate the range of text to be
recolored; the lexer must determine the proper color for all characters
in positions startPos through startPos+length.

The initStyle parameter indicates the initial state, that is, the state
at the character before startPos. States also indicate the coloring to
be used for a particular range of text.

Note:  the character at StartPos is assumed to start a line, so if a
newline terminates the initStyle state the lexer should enter its
default state (or whatever state should follow initStyle).

The keywordlists parameter specifies the keywords that the lexer must
recognize.  A WordList class object contains methods that make simplify
the recognition of keywords.  Present lexers use a helper function
called classifyWordLLL to recognize keywords.  These functions show how
to use the keywordlists parameter to recognize keywords.  This
documentation will not discuss keywords further.


The lexer code

The task of a lexer can be summarized briefly: for each range r of
characters that are to be colored the same, the lexer should call

    styler.ColourTo(i, state)
        
where i is the position of the last character of the range r.  The lexer
should set the state variable to the coloring state of the character at
position i and continue until the entire text has been colored.

Note 1:  the styler (Accessor) object remembers the i parameter in the
previous calls to styler.ColourTo, so the single i parameter suffices to
indicate a range of characters.

Note 2: As a side effect of calling styler.ColourTo(i,state), the
coloring states of all characters in the range are remembered so that
Scintilla may set the initStyle parameter correctly on future calls to
the
lexer.


Lexer organization

There are at least two ways to organize the code of each lexer.  Present
lexers use what might be called a "character-based" approach: the outer
loop iterates over characters, like this:

  lengthDoc = startPos + length ;
  for (unsigned int i = startPos; i < lengthDoc; i++) {
    chNext = styler.SafeGetCharAt(i + 1);
    << handle special cases >>
    switch(state) {
      // Handlers examine only ch and chNext.
      // Handlers call styler.ColorTo(i,state) if the state changes.
      case state_1: << handle ch in state 1 >>
      case state_2: << handle ch in state 2 >>
      ...
      case state_n: << handle ch in state n >>
    }
    chPrev = ch;
  }
  styler.ColourTo(lengthDoc - 1, state);


An alternative would be to use a "state-based" approach.  The outer loop
would iterate over states, like this:

  lengthDoc = startPos+lenth ;
  for ( unsigned int i = startPos ;; ) {
    char ch = styler.SafeGetCharAt(i);
    int new_state = 0 ;
    switch ( state ) {
      // scanners set new_state if they set the next state.
      case state_1: << scan to the end of state 1 >> break ;
      case state_2: << scan to the end of state 2 >> break ;
      case default_state:
        << scan to the next non-default state and set new_state >>
    }
    styler.ColourTo(i, state);
    if ( i >= lengthDoc ) break ;
    if ( ! new_state ) {
      ch = styler.SafeGetCharAt(i);
      << set state based on ch in the default state >>
    }
  }
  styler.ColourTo(lengthDoc - 1, state);

This approach might seem to be more natural.  State scanners are simpler
than character scanners because less needs to be done.  For example,
there is no need to test for the start of a C string inside the scanner
for a C comment.  Also this way makes it natural to define routines that
could be used by more than one scanner; for example, a scanToEndOfLine
routine.

However, the special cases handled in the main loop in the
character-based approach would have to be handled by each state scanner,
so both approaches have advantages.  These special cases are discussed
below.

Special case: Lead characters

Lead bytes are part of DBCS processing for languages such as Japanese
using an encoding such as Shift-JIS. In these encodings, extended
(16-bit) characters are encoded as a lead byte followed by a trail byte.

Lead bytes are rarely of any lexical significance, normally only being
allowed within strings and comments. In such contexts, lexers should
ignore ch if styler.IsLeadByte(ch) returns TRUE.

Note: UTF-8 is simpler than Shift-JIS, so no special handling is
applied for it. All UTF-8 extended characters are >= 128 and none are
lexically significant in programming languages which, so far, use only
characters in ASCII for operators, comment markers, etc.


Special case: Folding

Folding may be performed in the lexer function. It is better to use a 
separate folder function as that avoids some troublesome interaction 
between styling and folding. The folder function will be run after the
lexer function if folding is enabled. The rest of this section explains
how to perform folding within the lexer function.

During initialization, lexers that support folding set

    bool fold = styler.GetPropertyInt("fold");
        
If folding is enabled in the editor, fold will be TRUE and the lexer
should call:

    styler.SetLevel(line, level);
        
at the end of each line and just before exiting.

The line parameter is simply the count of the number of newlines seen. 
It's initial value is styler.GetLine(startPos) and it is incremented
(after calling styler.SetLevel) whenever a newline is seen.

The level parameter is the desired indentation level in the low 12 bits,
along with flag bits in the upper four bits. The indentation level
depends on the language.  For C++, it is incremented when the lexer sees
a '{' and decremented when the lexer sees a '}' (outside of strings and
comments, of course).

The following flag bits, defined in Scintilla.h, may be set or cleared
in the flags parameter. The SC_FOLDLEVELWHITEFLAG flag is set if the
lexer considers that the line contains nothing but whitespace.  The
SC_FOLDLEVELHEADERFLAG flag indicates that the line is a fold point. 
This normally means that the next line has a greater level than present
line.  However, the lexer may have some other basis for determining a
fold point.  For example, a lexer might create a header line for the
first line of a function definition rather than the last.

The SC_FOLDLEVELNUMBERMASK mask denotes the level number in the low 12
bits of the level param. This mask may be used to isolate either flags
or level numbers.

For example, the C++ lexer contains the following code when a newline is
seen:

  if (fold) {
    int lev = levelPrev;

    // Set the "all whitespace" bit if the line is blank.
    if (visChars == 0)
      lev |= SC_FOLDLEVELWHITEFLAG;

    // Set the "header" bit if needed.
    if ((levelCurrent > levelPrev) && (visChars > 0))
      lev |= SC_FOLDLEVELHEADERFLAG;
      styler.SetLevel(lineCurrent, lev);
        
    // reinitialize the folding vars describing the present line.
    lineCurrent++;
    visChars = 0;  // Number of non-whitespace characters on the line.
    levelPrev = levelCurrent;
  }

The following code appears in the C++ lexer just before exit:

  // Fill in the real level of the next line, keeping the current flags
  // as they will be filled in later.
  if (fold) {
    // Mask off the level number, leaving only the previous flags.
    int flagsNext = styler.LevelAt(lineCurrent);
    flagsNext &= ~SC_FOLDLEVELNUMBERMASK;
    styler.SetLevel(lineCurrent, levelPrev | flagsNext);
  }
        

Don't worry about performance

The writer of a lexer may safely ignore performance considerations: the
cost of redrawing the screen is several orders of magnitude greater than
the cost of function calls, etc.  Moreover, Scintilla performs all the
important optimizations; Scintilla ensures that a lexer will be called
only to recolor text that actually needs to be recolored.  Finally, it
is not necessary to avoid extra calls to styler.ColourTo: the sytler
object buffers calls to ColourTo to avoid multiple updates of the
screen.

Page contributed by Edward K. Ream

Added doc/PaneAPI.html.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
<?xml version="1.0" encoding='utf-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html" />
    <title>
      SciTE Pane API
    </title>
<style type="text/css">
        table {
            border: 1px solid #1F1F1F;
            border-collapse: collapse;
	    font-family: Verdana, Arial, Helvetica
        }
        p {
	    font-family: Verdana, Arial, Helvetica
        }
        td {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        th {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        .windowsonly {
            background: #EBF3FF;
        }
        .gtkonly {
            background: #FFFFE7;
        }
        .osxonly {
            background: #FFE7E7;
        }
        .example {
            color: #008000;
            font-weight: bold;
        }
        .comment {
	     font-style:italic;
            font-size: 80%;
        }
        DIV.example {
            background: #F7FCF7;
            border: 1px solid #C0D7C0;
            margin: 0.3em 3em;
            padding: 0.3em 0.6em;
            font-size: 80%;
        }
        h2 {
            border: 2px solid #FFCC00;
            background-color: #FFF7EE;
            padding: 2px 5px;
	     font-family: Verdana, Arial, Helvetica
            font-size: 180%;
        }
        h3 {
            border: 2px solid #FFCC00;
            background-color: #FFF7EE;
            padding: 2px 5px;
        }
        .header{
            border: 1px solid #CCCCCC;
        }
        .headerlinks {
            padding: 7px;
            background-color: #CCCCCC;
            border: 0px solid #FF0000;
            font-size: 120%;
        }
 </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" style="border:0px solid #FF0000" border="0"  summary="banner">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
          SciTE Lua scripting of edit and output panes using Scintilla API</font></a>
        </td>
      </tr>
    </table>
	<h1>Scintilla API calls</h1>
	<p>Both the edit and output panes are Scintilla controls and can be scripted using Scintilla's API.</p>
	<p>The API is presented here as it is called from Lua for the edit pane. All of the same features
	are available for the output pane by substituting 'output' for 'editor'.</p>
	<p>In Lua methods are called with the ':' operator and properties accessed with the '.' operator.
	Properties are both readable and writeable by default and are otherwise marked "read-only" or "write-only".</p>
    
<!-- <Autogenerated> -->
	<h2>Text retrieval and modification</h2>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETTEXT'>GetText</a>()<span class="comment"> -- Retrieve all the text in the document. Returns number of characters retrieved.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTEXT'>SetText</a>(string text)<span class="comment"> -- Replace the contents of the document with the argument text.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSAVEPOINT'>SetSavePoint</a>()<span class="comment"> -- Remember the current position in the undo history as the position at which the document was saved.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINE'>GetLine</a>(int line)<span class="comment"> -- Retrieve the contents of a line. Returns the length of the line.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REPLACESEL'>ReplaceSel</a>(string text)<span class="comment"> -- Replace the selected text with the argument text.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETREADONLY'>ReadOnly</a><span class="comment"> -- Set to read only or read write.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ALLOCATE'>Allocate</a>(int bytes)<span class="comment"> -- Enlarge the document to a particular size of text bytes.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ADDTEXT'>AddText</a>(string text)<span class="comment"> -- Add text to the document at current position.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_APPENDTEXT'>AppendText</a>(string text)<span class="comment"> -- Append a string to the end of the document without changing the selection.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INSERTTEXT'>InsertText</a>(position pos, string text)<span class="comment"> -- Insert string at a position.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARALL'>ClearAll</a>()<span class="comment"> -- Delete all text in the document.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_DELETERANGE'>DeleteRange</a>(position pos, int deleteLength)<span class="comment"> -- Delete a range of text in the document.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARDOCUMENTSTYLE'>ClearDocumentStyle</a>()<span class="comment"> -- Set all style bytes to 0, remove all folding information.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETCHARAT'>CharAt</a>[position pos] read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSTYLEAT'>StyleAt</a>[position pos] read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSTYLEBITS'>StyleBits</a><span class="comment"> -- Divide each styling byte into lexical class bits (default: 5) and indicator bits (default: 3). If a lexer requires more than 32 lexical states, then this is used to expand the possible states.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_RELEASEALLEXTENDEDSTYLES'>ReleaseAllExtendedStyles</a>()<span class="comment"> -- Release all extended (>255) style numbers</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ALLOCATEEXTENDEDSTYLES'>AllocateExtendedStyles</a>(int numberStyles)<span class="comment"> -- Allocate some extended (>255) style numbers and return the start of the range</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TARGETASUTF8'>TargetAsUTF8</a>()<span class="comment"> -- Returns the target converted to UTF8. Return the length in bytes.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ENCODEDFROMUTF8'>EncodedFromUTF8</a>(string utf8)<span class="comment"> -- Translates a UTF8 string into the document encoding. Return the length of the result in bytes. On error return 0.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLENGTHFORENCODE'>SetLengthForEncode</a>(int bytes)<span class="comment"> -- Set the length of the utf8 argument for calling EncodedFromUTF8. Set to -1 and the string will be measured to the first nul.</span></p>
	<h2>Searching</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SEARCHANCHOR'>SearchAnchor</a>()<span class="comment"> -- Sets the current caret position to be the search anchor.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SEARCHNEXT'>SearchNext</a>(int flags, string text)<span class="comment"> -- Find some text starting at the search anchor. Does not ensure the selection is visible.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SEARCHPREV'>SearchPrev</a>(int flags, string text)<span class="comment"> -- Find some text starting at the search anchor and moving backwards. Does not ensure the selection is visible.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTARGETSTART'>TargetStart</a><span class="comment"> -- Sets the position that starts the target which is used for updating the document without affecting the scroll position.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTARGETEND'>TargetEnd</a><span class="comment"> -- Sets the position that ends the target which is used for updating the document without affecting the scroll position.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TARGETFROMSELECTION'>TargetFromSelection</a>()<span class="comment"> -- Make the target range start and end be the same as the selection range start and end.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSEARCHFLAGS'>SearchFlags</a><span class="comment"> -- Set the search flags used by SearchInTarget.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SEARCHINTARGET'>SearchInTarget</a>(string text)<span class="comment"> -- Search for a counted string in the target and set the target to the found range. Text is counted so it can contain NULs. Returns length of range or -1 for failure in which case target is not moved.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REPLACETARGET'>ReplaceTarget</a>(string text)<span class="comment"> -- Replace the target text with the argument text. Text is counted so it can contain NULs. Returns the length of the replacement text.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REPLACETARGETRE'>ReplaceTargetRE</a>(string text)<span class="comment"> -- Replace the target text with the argument text after \d processing. Text is counted so it can contain NULs. Looks for \d where d is between 1 and 9 and replaces these with the strings matched in the last search operation which were surrounded by \( and \). Returns the length of the replacement text including any change caused by processing the \d patterns.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETTAG'>Tag</a>[int tagNumber] read-only</p>
	<h2>Overtype</h2>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETOVERTYPE'>Overtype</a><span class="comment"> -- Set to overtype (true) or insert mode.</span></p>
	<h2>Cut, copy and paste</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CUT'>Cut</a>()<span class="comment"> -- Cut the selection to the clipboard.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COPY'>Copy</a>()<span class="comment"> -- Copy the selection to the clipboard.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_PASTE'>Paste</a>()<span class="comment"> -- Paste the contents of the clipboard into the document replacing the selection.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEAR'>Clear</a>()<span class="comment"> -- Clear the selection.</span></p>
	<p>bool editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CANPASTE'>CanPaste</a>()<span class="comment"> -- Will a paste succeed?</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COPYALLOWLINE'>CopyAllowLine</a>()<span class="comment"> -- Copy the selection, if selection empty copy the line with the caret</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COPYRANGE'>CopyRange</a>(position start, position end)<span class="comment"> -- Copy a range of text to the clipboard. Positions are clipped into the document.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COPYTEXT'>CopyText</a>(string text)<span class="comment"> -- Copy argument text to the clipboard.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPASTECONVERTENDINGS'>PasteConvertEndings</a><span class="comment"> -- Enable/Disable convert-on-paste for line endings</span></p>
	<h2>Error handling</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSTATUS'>Status</a><span class="comment"> -- Change error status - 0 = OK.</span></p>
	<h2>Undo and Redo</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_UNDO'>Undo</a>()<span class="comment"> -- Undo one action in the undo history.</span></p>
	<p>bool editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CANUNDO'>CanUndo</a>()<span class="comment"> -- Are there any undoable actions in the undo history?</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REDO'>Redo</a>()<span class="comment"> -- Redoes the next action on the undo history.</span></p>
	<p>bool editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CANREDO'>CanRedo</a>()<span class="comment"> -- Are there any redoable actions in the undo history?</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_EMPTYUNDOBUFFER'>EmptyUndoBuffer</a>()<span class="comment"> -- Delete the undo history.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETUNDOCOLLECTION'>UndoCollection</a><span class="comment"> -- Choose between collecting actions into the undo history and discarding them.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_BEGINUNDOACTION'>BeginUndoAction</a>()<span class="comment"> -- Start a sequence of actions that is undone and redone as a unit. May be nested.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ENDUNDOACTION'>EndUndoAction</a>()<span class="comment"> -- End a sequence of actions that is undone and redone as a unit.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ADDUNDOACTION'>AddUndoAction</a>(int token, int flags)<span class="comment"> -- Add a container action to the undo stack</span></p>
	<h2>Selection and information</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETTEXTLENGTH'>TextLength</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLENGTH'>Length</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINECOUNT'>LineCount</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFIRSTVISIBLELINE'>FirstVisibleLine</a><span class="comment"> -- Scroll so that a display line is at the top of the display.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINESONSCREEN'>LinesOnScreen</a> read-only</p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETMODIFY'>Modify</a> read-only</p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSEL'>SetSel</a>(position start, position end)<span class="comment"> -- Select a range of text.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GOTOPOS'>GotoPos</a>(position pos)<span class="comment"> -- Set caret to a position and ensure it is visible.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GOTOLINE'>GotoLine</a>(int line)<span class="comment"> -- Set caret to start of a line and ensure it is visible.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCURRENTPOS'>CurrentPos</a><span class="comment"> -- Sets the position of the caret.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETANCHOR'>Anchor</a><span class="comment"> -- Set the selection anchor to a position. The anchor is the opposite end of the selection from the caret.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONSTART'>SelectionStart</a><span class="comment"> -- Sets the position that starts the selection - this becomes the anchor.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONEND'>SelectionEnd</a><span class="comment"> -- Sets the position that ends the selection - this becomes the currentPosition.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEMPTYSELECTION'>SetEmptySelection</a>(position pos)<span class="comment"> -- Set caret to a position, while removing any existing selection.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SELECTALL'>SelectAll</a>()<span class="comment"> -- Select all the text in the document.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINEFROMPOSITION'>LineFromPosition</a>(position pos)<span class="comment"> -- Retrieve the line containing a position.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POSITIONFROMLINE'>PositionFromLine</a>(int line)<span class="comment"> -- Retrieve the position at the start of a line.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINEENDPOSITION'>LineEndPosition</a>[int line] read-only</p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINELENGTH'>LineLength</a>(int line)<span class="comment"> -- How many characters are on a line, including end of line characters?</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSELTEXT'>GetSelText</a>()<span class="comment"> -- Retrieve the selected text. Return the length of the text.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETCURLINE'>GetCurLine</a>()<span class="comment"> -- Retrieve the text of the line containing the caret. Returns the index of the caret on the line.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SELECTIONISRECTANGLE'>SelectionIsRectangle</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONMODE'>SelectionMode</a><span class="comment"> -- Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or by lines (SC_SEL_LINES).</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINESELSTARTPOSITION'>GetLineSelStartPosition</a>(int line)<span class="comment"> -- Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line).</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINESELENDPOSITION'>GetLineSelEndPosition</a>(int line)<span class="comment"> -- Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line).</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MOVECARETINSIDEVIEW'>MoveCaretInsideView</a>()<span class="comment"> -- Move the caret inside current view if it's not there already.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_WORDENDPOSITION'>WordEndPosition</a>(position pos, bool onlyWordCharacters)<span class="comment"> -- Get position of end of word.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_WORDSTARTPOSITION'>WordStartPosition</a>(position pos, bool onlyWordCharacters)<span class="comment"> -- Get position of start of word.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POSITIONBEFORE'>PositionBefore</a>(position pos)<span class="comment"> -- Given a valid document position, return the previous position taking code page into account. Returns 0 if passed 0.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POSITIONAFTER'>PositionAfter</a>(position pos)<span class="comment"> -- Given a valid document position, return the next position taking code page into account. Maximum value returned is the last position in the document.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COUNTCHARACTERS'>CountCharacters</a>(int startPos, int endPos)<span class="comment"> -- Count characters between two positions.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TEXTWIDTH'>TextWidth</a>(int style, string text)<span class="comment"> -- Measure the pixel width of some text in a particular style. NUL terminated text argument. Does not handle tab or control characters.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TEXTHEIGHT'>TextHeight</a>(int line)<span class="comment"> -- Retrieve the height of a particular line of text in pixels.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETCOLUMN'>Column</a>[position pos] read-only</p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_FINDCOLUMN'>FindColumn</a>(int line, int column)<span class="comment"> -- Find the position of a column on a line taking into account tabs and multi-byte characters. If beyond end of line, return line end position.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POSITIONFROMPOINT'>PositionFromPoint</a>(int x, int y)<span class="comment"> -- Find the position from a point within the window.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POSITIONFROMPOINTCLOSE'>PositionFromPointClose</a>(int x, int y)<span class="comment"> -- Find the position from a point within the window but return INVALID_POSITION if not close to text.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CHARPOSITIONFROMPOINT'>CharPositionFromPoint</a>(int x, int y)<span class="comment"> -- Find the position of a character from a point within the window.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CHARPOSITIONFROMPOINTCLOSE'>CharPositionFromPointClose</a>(int x, int y)<span class="comment"> -- Find the position of a character from a point within the window. Return INVALID_POSITION if not close to text.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POINTXFROMPOSITION'>PointXFromPosition</a>(position pos)<span class="comment"> -- Retrieve the x value of the point in the window where a position is displayed.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_POINTYFROMPOSITION'>PointYFromPosition</a>(position pos)<span class="comment"> -- Retrieve the y value of the point in the window where a position is displayed.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_HIDESELECTION'>HideSelection</a>(bool normal)<span class="comment"> -- Draw the selection in normal style or with selection highlighted.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CHOOSECARETX'>ChooseCaretX</a>()<span class="comment"> -- Set the last x chosen value to be the caret x position.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MOVESELECTEDLINESUP'>MoveSelectedLinesUp</a>()<span class="comment"> -- Move the selected lines up one line, shifting the line above after the selection</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MOVESELECTEDLINESDOWN'>MoveSelectedLinesDown</a>()<span class="comment"> -- Move the selected lines down one line, shifting the line below before the selection</span></p>
	<h2>Multiple Selection and Virtual Space</h2>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMULTIPLESELECTION'>MultipleSelection</a><span class="comment"> -- Set whether multiple selections can be made</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALSELECTIONTYPING'>AdditionalSelectionTyping</a><span class="comment"> -- Set whether typing can be performed into multiple selections</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMULTIPASTE'>MultiPaste</a><span class="comment"> -- Change the effect of pasting when there are multiple selections.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETVIRTUALSPACEOPTIONS'>VirtualSpaceOptions</a><span class="comment"> -- Returns the position at the end of the selection.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETRECTANGULARSELECTIONMODIFIER'>RectangularSelectionModifier</a><span class="comment"> -- On GTK+, allow selecting the modifier key to use for mouse-based rectangular selection. Often the window manager requires Alt+Mouse Drag for moving windows. Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSELECTIONS'>Selections</a> read-only</p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSELECTIONEMPTY'>SelectionEmpty</a> read-only</p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARSELECTIONS'>ClearSelections</a>()<span class="comment"> -- Clear selections to a single empty stream selection</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTION'>SetSelection</a>(int caret, int anchor)<span class="comment"> -- Set a simple selection</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ADDSELECTION'>AddSelection</a>(int caret, int anchor)<span class="comment"> -- Add a selection</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMAINSELECTION'>MainSelection</a><span class="comment"> -- Set the main selection</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNCARET'>SelectionNCaret</a>[int selection]<span class="comment"> -- Which selection is the main selection</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNCARETVIRTUALSPACE'>SelectionNCaretVirtualSpace</a>[int selection]<span class="comment"> -- Which selection is the main selection</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNANCHOR'>SelectionNAnchor</a>[int selection]<span class="comment"> -- Which selection is the main selection</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNANCHORVIRTUALSPACE'>SelectionNAnchorVirtualSpace</a>[int selection]<span class="comment"> -- Which selection is the main selection</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNSTART'>SelectionNStart</a>[int selection]<span class="comment"> -- Sets the position that starts the selection - this becomes the anchor.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELECTIONNEND'>SelectionNEnd</a>[int selection]<span class="comment"> -- Sets the position that ends the selection - this becomes the currentPosition.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETRECTANGULARSELECTIONCARET'>RectangularSelectionCaret</a><span class="comment"> -- Returns the position at the end of the selection.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE'>RectangularSelectionCaretVirtualSpace</a><span class="comment"> -- Returns the position at the end of the selection.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETRECTANGULARSELECTIONANCHOR'>RectangularSelectionAnchor</a><span class="comment"> -- Returns the position at the end of the selection.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE'>RectangularSelectionAnchorVirtualSpace</a><span class="comment"> -- Returns the position at the end of the selection.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALSELALPHA'>AdditionalSelAlpha</a><span class="comment"> -- Set the alpha of the selection.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALSELFORE'>AdditionalSelFore</a> write-only<span class="comment"> -- Set the foreground colour of additional selections. Must have previously called SetSelFore with non-zero first argument for this to have an effect.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALSELBACK'>AdditionalSelBack</a> write-only<span class="comment"> -- Set the background colour of additional selections. Must have previously called SetSelBack with non-zero first argument for this to have an effect.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALCARETFORE'>AdditionalCaretFore</a><span class="comment"> -- Set the foreground colour of additional carets.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALCARETSBLINK'>AdditionalCaretsBlink</a><span class="comment"> -- Set whether additional carets will blink</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETADDITIONALCARETSVISIBLE'>AdditionalCaretsVisible</a><span class="comment"> -- Set whether additional carets are visible</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SWAPMAINANCHORCARET'>SwapMainAnchorCaret</a>()<span class="comment"> -- Swap that caret and anchor of the main selection.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ROTATESELECTION'>RotateSelection</a>()<span class="comment"> -- Set the main selection to the next selection.</span></p>
	<h2>Scrolling and automatic scrolling</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINESCROLL'>LineScroll</a>(int columns, int lines)<span class="comment"> -- Scroll horizontally and vertically.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SCROLLCARET'>ScrollCaret</a>()<span class="comment"> -- Ensure the caret is visible.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETXCARETPOLICY'>SetXCaretPolicy</a>(int caretPolicy, int caretSlop)<span class="comment"> -- Set the way the caret is kept visible when going sideways. The exclusion zone is given in pixels.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETYCARETPOLICY'>SetYCaretPolicy</a>(int caretPolicy, int caretSlop)<span class="comment"> -- Set the way the line the caret is on is kept visible. The exclusion zone is given in lines.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETVISIBLEPOLICY'>SetVisiblePolicy</a>(int visiblePolicy, int visibleSlop)<span class="comment"> -- Set the way the display area is determined when a particular line is to be moved to by Find, FindNext, GotoLine, etc.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHSCROLLBAR'>HScrollBar</a><span class="comment"> -- Show or hide the horizontal scroll bar.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETVSCROLLBAR'>VScrollBar</a><span class="comment"> -- Show or hide the vertical scroll bar.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETXOFFSET'>XOffset</a><span class="comment"> -- Get and Set the xOffset (ie, horizontal scroll position).</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSCROLLWIDTH'>ScrollWidth</a><span class="comment"> -- Sets the document width assumed for scrolling.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSCROLLWIDTHTRACKING'>ScrollWidthTracking</a><span class="comment"> -- Sets whether the maximum width line displayed is used to set scroll width.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETENDATLASTLINE'>EndAtLastLine</a><span class="comment"> -- Sets the scroll range so that maximum scroll position has the last line at the bottom of the view (default). Setting this to false allows scrolling one page below the last line.</span></p>
	<h2>White space</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETVIEWWS'>ViewWS</a><span class="comment"> -- Make white space characters invisible, always visible or visible outside indentation.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWHITESPACEFORE'>SetWhitespaceFore</a>(bool useSetting, colour fore)<span class="comment"> -- Set the foreground colour of all whitespace and whether to use this setting.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWHITESPACEBACK'>SetWhitespaceBack</a>(bool useSetting, colour back)<span class="comment"> -- Set the background colour of all whitespace and whether to use this setting.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWHITESPACESIZE'>WhitespaceSize</a><span class="comment"> -- Set the size of the dots used to mark space characters.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEXTRAASCENT'>ExtraAscent</a><span class="comment"> -- Set extra ascent for each line</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEXTRADESCENT'>ExtraDescent</a><span class="comment"> -- Set extra descent for each line</span></p>
	<h2>Cursor</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCURSOR'>Cursor</a><span class="comment"> -- Sets the cursor to one of the SC_CURSOR* values.</span></p>
	<h2>Mouse capture</h2>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMOUSEDOWNCAPTURES'>MouseDownCaptures</a><span class="comment"> -- Set whether the mouse is captured when its button is pressed.</span></p>
	<h2>Line endings</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEOLMODE'>EOLMode</a><span class="comment"> -- Set the current end of line mode.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CONVERTEOLS'>ConvertEOLs</a>(int eolMode)<span class="comment"> -- Convert all line endings in the document to one mode.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETVIEWEOL'>ViewEOL</a><span class="comment"> -- Make the end of line characters visible or invisible.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINEENDTYPESSUPPORTED'>LineEndTypesSupported</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLINEENDTYPESALLOWED'>LineEndTypesAllowed</a><span class="comment"> -- Set the line end types that the application wants to use. May not be used if incompatible with lexer or encoding.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINEENDTYPESACTIVE'>LineEndTypesActive</a> read-only</p>
	<h2>Styling</h2>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETENDSTYLED'>EndStyled</a> read-only</p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STARTSTYLING'>StartStyling</a>(position pos, int mask)<span class="comment"> -- Set the current styling position to pos and the styling mask to mask. The styling mask can be used to protect some bits in each styling byte from modification.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSTYLING'>SetStyling</a>(int length, int style)<span class="comment"> -- Change style from current styling position for length characters to a style and move the current styling position to after this newly styled segment.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSTYLINGEX'>SetStylingEx</a>(string styles)<span class="comment"> -- Set the styles for a segment of the document.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLINESTATE'>LineState</a>[int line]<span class="comment"> -- Used to hold extra styling information for each line.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETMAXLINESTATE'>MaxLineState</a> read-only</p>
	<h2>Style definition</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLERESETDEFAULT'>StyleResetDefault</a>()<span class="comment"> -- Reset the default style to its state at startup</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLECLEARALL'>StyleClearAll</a>()<span class="comment"> -- Clear all the styles and make equivalent to the global default style.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETFONT'>StyleFont</a>[int style]<span class="comment"> -- Set the font of a style.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETSIZE'>StyleSize</a>[int style]<span class="comment"> -- Set the size of characters of a style.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETSIZEFRACTIONAL'>StyleSizeFractional</a>[int style]<span class="comment"> -- Set the size of characters of a style. Size is in points multiplied by 100.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETBOLD'>StyleBold</a>[int style]<span class="comment"> -- Set a style to be bold or not.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETWEIGHT'>StyleWeight</a>[int style]<span class="comment"> -- Set the weight of characters of a style.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETITALIC'>StyleItalic</a>[int style]<span class="comment"> -- Set a style to be italic or not.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETUNDERLINE'>StyleUnderline</a>[int style]<span class="comment"> -- Set a style to be underlined or not.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETFORE'>StyleFore</a>[int style]<span class="comment"> -- Set the foreground colour of a style.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETBACK'>StyleBack</a>[int style]<span class="comment"> -- Set the background colour of a style.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETEOLFILLED'>StyleEOLFilled</a>[int style]<span class="comment"> -- Set a style to have its end of line filled or not.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETCHARACTERSET'>StyleCharacterSet</a>[int style]<span class="comment"> -- Set the character set of the font in a style.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETCASE'>StyleCase</a>[int style]<span class="comment"> -- Set a style to be mixed case, or to force upper or lower case.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETVISIBLE'>StyleVisible</a>[int style]<span class="comment"> -- Set a style to be visible or not.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETCHANGEABLE'>StyleChangeable</a>[int style]<span class="comment"> -- Set a style to be changeable or not (read only). Experimental feature, currently buggy.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STYLESETHOTSPOT'>StyleHotSpot</a>[int style]<span class="comment"> -- Set a style to be a hotspot or not.</span></p>
	<h2>Caret, selection, and hotspot styles</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELFORE'>SetSelFore</a>(bool useSetting, colour fore)<span class="comment"> -- Set the foreground colour of the main and additional selections and whether to use this setting.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELBACK'>SetSelBack</a>(bool useSetting, colour back)<span class="comment"> -- Set the background colour of the main and additional selections and whether to use this setting.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELALPHA'>SelAlpha</a><span class="comment"> -- Set the alpha of the selection.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETSELEOLFILLED'>SelEOLFilled</a><span class="comment"> -- Set the selection to have its end of line filled or not.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETFORE'>CaretFore</a><span class="comment"> -- Set the foreground colour of the caret.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETLINEVISIBLE'>CaretLineVisible</a><span class="comment"> -- Display the background of the line containing the caret in a different colour.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETLINEBACK'>CaretLineBack</a><span class="comment"> -- Set the colour of the background of the line containing the caret.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETLINEBACKALPHA'>CaretLineBackAlpha</a><span class="comment"> -- Set background alpha of the caret line.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETLINEVISIBLEALWAYS'>CaretLineVisibleAlways</a><span class="comment"> -- Sets the caret line to always visible.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETPERIOD'>CaretPeriod</a><span class="comment"> -- Get the time in milliseconds that the caret is on and off. 0 = steady on.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETSTYLE'>CaretStyle</a><span class="comment"> -- Set the style of the caret to be drawn.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETWIDTH'>CaretWidth</a><span class="comment"> -- Set the width of the insert mode caret.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHOTSPOTACTIVEFORE'>SetHotspotActiveFore</a>(bool useSetting, colour fore)<span class="comment"> -- Set a fore colour for active hotspots.</span></p>
	<p>colour editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETHOTSPOTACTIVEFORE'>GetHotspotActiveFore</a>()<span class="comment"> -- Get the fore colour for active hotspots.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHOTSPOTACTIVEBACK'>SetHotspotActiveBack</a>(bool useSetting, colour back)<span class="comment"> -- Set a back colour for active hotspots.</span></p>
	<p>colour editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETHOTSPOTACTIVEBACK'>GetHotspotActiveBack</a>()<span class="comment"> -- Get the back colour for active hotspots.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHOTSPOTACTIVEUNDERLINE'>HotspotActiveUnderline</a><span class="comment"> -- Enable / Disable underlining active hotspots.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHOTSPOTSINGLELINE'>HotspotSingleLine</a><span class="comment"> -- Limit hotspots to single line so hotspots on two lines don't merge.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCONTROLCHARSYMBOL'>ControlCharSymbol</a><span class="comment"> -- Change the way control characters are displayed: If symbol is < 32, keep the drawn way, else, use the given character.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCARETSTICKY'>CaretSticky</a><span class="comment"> -- Stop the caret preferred x position changing when the user types.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TOGGLECARETSTICKY'>ToggleCaretSticky</a>()<span class="comment"> -- Switch between sticky and non-sticky: meant to be bound to a key.</span></p>
	<h2>Margins</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINTYPEN'>MarginTypeN</a>[int margin]<span class="comment"> -- Set a margin to be either numeric or symbolic.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINWIDTHN'>MarginWidthN</a>[int margin]<span class="comment"> -- Set the width of a margin to a width expressed in pixels.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINMASKN'>MarginMaskN</a>[int margin]<span class="comment"> -- Set a mask that determines which markers are displayed in a margin.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINSENSITIVEN'>MarginSensitiveN</a>[int margin]<span class="comment"> -- Make a margin sensitive or insensitive to mouse clicks.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINCURSORN'>MarginCursorN</a>[int margin]<span class="comment"> -- Set the cursor shown when the mouse is inside a margin.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINLEFT'>MarginLeft</a><span class="comment"> -- Sets the size in pixels of the left margin.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINRIGHT'>MarginRight</a><span class="comment"> -- Sets the size in pixels of the right margin.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOLDMARGINCOLOUR'>SetFoldMarginColour</a>(bool useSetting, colour back)<span class="comment"> -- Set the colours used as a chequerboard pattern in the fold margin</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOLDMARGINHICOLOUR'>SetFoldMarginHiColour</a>(bool useSetting, colour fore)<span class="comment"> -- Set the colours used as a chequerboard pattern in the fold margin</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARGINSETTEXT'>MarginText</a>[int line]<span class="comment"> -- Set the text in the text margin for a line</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARGINSETSTYLE'>MarginStyle</a>[int line]<span class="comment"> -- Set the style number for the text margin for a line</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARGINSETSTYLES'>MarginStyles</a>[int line]<span class="comment"> -- Set the style in the text margin for a line</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARGINTEXTCLEARALL'>MarginTextClearAll</a>()<span class="comment"> -- Clear the margin text on all lines</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARGINSETSTYLEOFFSET'>MarginStyleOffset</a><span class="comment"> -- Get the start of the range of style numbers used for margin text</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMARGINOPTIONS'>MarginOptions</a><span class="comment"> -- Set the margin options.</span></p>
	<h2>Annotations</h2>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONSETTEXT'>AnnotationText</a>[int line]<span class="comment"> -- Set the annotation text for a line</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONSETSTYLE'>AnnotationStyle</a>[int line]<span class="comment"> -- Set the style number for the annotations for a line</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONSETSTYLES'>AnnotationStyles</a>[int line]<span class="comment"> -- Set the annotation styles for a line</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONGETLINES'>AnnotationLines</a>[int line] read-only</p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONCLEARALL'>AnnotationClearAll</a>()<span class="comment"> -- Clear the annotations from all lines</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONSETVISIBLE'>AnnotationVisible</a><span class="comment"> -- Set the visibility for the annotations for a view</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ANNOTATIONSETSTYLEOFFSET'>AnnotationStyleOffset</a><span class="comment"> -- Get the start of the range of style numbers used for annotations</span></p>
	<h2>Other settings</h2>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETBUFFEREDDRAW'>BufferedDraw</a><span class="comment"> -- If drawing is buffered then each line of text is drawn into a bitmap buffer before drawing it to the screen to avoid flicker.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTWOPHASEDRAW'>TwoPhaseDraw</a><span class="comment"> -- In twoPhaseDraw mode, drawing is performed in two phases, first the background and then the foreground. This avoids chopping off characters that overlap the next run.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY'>Technology</a><span class="comment"> -- Set the technology used.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFONTQUALITY'>FontQuality</a><span class="comment"> -- Choose the quality level for text from the FontQuality enumeration.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCODEPAGE'>CodePage</a><span class="comment"> -- Set the code page used to interpret the bytes of the document as characters. The SC_CP_UTF8 value can be used to enter Unicode mode.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETKEYSUNICODE'>KeysUnicode</a><span class="comment"> -- Always interpret keyboard input as Unicode</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWORDCHARS'>WordChars</a><span class="comment"> -- Set the set of characters making up words for when moving or selecting by word. First sets defaults like SetCharsDefault.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWHITESPACECHARS'>WhitespaceChars</a><span class="comment"> -- Set the set of characters making up whitespace for when moving or selecting by word. Should be called after SetWordChars.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPUNCTUATIONCHARS'>PunctuationChars</a><span class="comment"> -- Set the set of characters making up punctuation characters Should be called after SetWordChars.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETCHARSDEFAULT'>SetCharsDefault</a>()<span class="comment"> -- Reset the set of characters for whitespace and word characters to the defaults.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GRABFOCUS'>GrabFocus</a>()<span class="comment"> -- Set the focus to this Scintilla widget.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOCUS'>Focus</a><span class="comment"> -- Change internal focus flag.</span></p>
	<h2>Brace highlighting</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_BRACEHIGHLIGHT'>BraceHighlight</a>(position pos1, position pos2)<span class="comment"> -- Highlight the characters at two positions.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_BRACEBADLIGHT'>BraceBadLight</a>(position pos)<span class="comment"> -- Highlight the character at a position indicating there is no matching brace.</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_BRACEMATCH'>BraceMatch</a>(position pos)<span class="comment"> -- Find the position of a matching brace or INVALID_POSITION if no match.</span></p>
	<h2>Tabs and Indentation Guides</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTABWIDTH'>TabWidth</a><span class="comment"> -- Change the visible size of a tab to be a multiple of the width of a space character.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETUSETABS'>UseTabs</a><span class="comment"> -- Indentation will only use space characters if useTabs is false, otherwise it will use a combination of tabs and spaces.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETINDENT'>Indent</a><span class="comment"> -- Set the number of spaces used for one level of indentation.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETTABINDENTS'>TabIndents</a><span class="comment"> -- Sets whether a tab pressed when caret is within indentation indents.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETBACKSPACEUNINDENTS'>BackSpaceUnIndents</a><span class="comment"> -- Sets whether a backspace pressed when caret is within indentation unindents.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLINEINDENTATION'>LineIndentation</a>[int line]<span class="comment"> -- Change the indentation of a line to a number of columns.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINEINDENTPOSITION'>LineIndentPosition</a>[int line] read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETINDENTATIONGUIDES'>IndentationGuides</a><span class="comment"> -- Show or hide indentation guides.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETHIGHLIGHTGUIDE'>HighlightGuide</a><span class="comment"> -- Set the highlighted indentation guide column. 0 = no highlighted guide.</span></p>
	<h2>Markers</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDEFINE'>MarkerDefine</a>(int markerNumber, int markerSymbol)<span class="comment"> -- Set the symbol used for a particular marker number.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDEFINEPIXMAP'>MarkerDefinePixmap</a>(int markerNumber, string pixmap)<span class="comment"> -- Define a marker from a pixmap.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_RGBAIMAGESETWIDTH'>RGBAImageWidth</a> write-only<span class="comment"> -- Set the width for future RGBA image data.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_RGBAIMAGESETHEIGHT'>RGBAImageHeight</a> write-only<span class="comment"> -- Set the height for future RGBA image data.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_RGBAIMAGESETSCALE'>RGBAImageScale</a> write-only<span class="comment"> -- Set the scale factor in percent for future RGBA image data.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDEFINERGBAIMAGE'>MarkerDefineRGBAImage</a>(int markerNumber, string pixels)<span class="comment"> -- Define a marker from RGBA data. It has the width and height from RGBAImageSetWidth/Height</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERSYMBOLDEFINED'>MarkerSymbolDefined</a>(int markerNumber)<span class="comment"> -- Which symbol was defined for markerNumber with MarkerDefine</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERSETFORE'>MarkerFore</a>[int markerNumber] write-only<span class="comment"> -- Set the foreground colour used for a particular marker number.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERSETBACK'>MarkerBack</a>[int markerNumber] write-only<span class="comment"> -- Set the background colour used for a particular marker number.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERSETBACKSELECTED'>MarkerBackSelected</a>[int markerNumber] write-only<span class="comment"> -- Set the background colour used for a particular marker number when its folding block is selected.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERENABLEHIGHLIGHT'>MarkerEnableHighlight</a>(bool enabled)<span class="comment"> -- Enable/disable highlight for current folding bloc (smallest one that contains the caret)</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERSETALPHA'>MarkerAlpha</a>[int markerNumber] write-only<span class="comment"> -- Set the alpha used for a marker that is drawn in the text area, not the margin.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERADD'>MarkerAdd</a>(int line, int markerNumber)<span class="comment"> -- Add a marker to a line, returning an ID which can be used to find or delete the marker.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERADDSET'>MarkerAddSet</a>(int line, int set)<span class="comment"> -- Add a set of markers to a line.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDELETE'>MarkerDelete</a>(int line, int markerNumber)<span class="comment"> -- Delete a marker from a line.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDELETEALL'>MarkerDeleteAll</a>(int markerNumber)<span class="comment"> -- Delete all markers with a particular number from all lines.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERGET'>MarkerGet</a>(int line)<span class="comment"> -- Get a bit mask of all the markers set on a line.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERNEXT'>MarkerNext</a>(int lineStart, int markerMask)<span class="comment"> -- Find the next line at or after lineStart that includes a marker in mask. Return -1 when no more lines.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERPREVIOUS'>MarkerPrevious</a>(int lineStart, int markerMask)<span class="comment"> -- Find the previous line before lineStart that includes a marker in mask.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERLINEFROMHANDLE'>MarkerLineFromHandle</a>(int handle)<span class="comment"> -- Retrieve the line number at which a particular marker is located.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_MARKERDELETEHANDLE'>MarkerDeleteHandle</a>(int handle)<span class="comment"> -- Delete a marker.</span></p>
	<h2>Indicators</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICSETSTYLE'>IndicStyle</a>[int indic]<span class="comment"> -- Set an indicator to plain, squiggle or TT.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICSETFORE'>IndicFore</a>[int indic]<span class="comment"> -- Set the foreground colour of an indicator.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICSETALPHA'>IndicAlpha</a>[int indicator]<span class="comment"> -- Set the alpha fill colour of the given indicator.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICSETOUTLINEALPHA'>IndicOutlineAlpha</a>[int indicator]<span class="comment"> -- Set the alpha outline colour of the given indicator.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICSETUNDER'>IndicUnder</a>[int indic]<span class="comment"> -- Set an indicator to draw under text or over(default).</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETINDICATORCURRENT'>IndicatorCurrent</a><span class="comment"> -- Set the indicator used for IndicatorFillRange and IndicatorClearRange</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETINDICATORVALUE'>IndicatorValue</a><span class="comment"> -- Set the value used for IndicatorFillRange</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATORFILLRANGE'>IndicatorFillRange</a>(int position, int fillLength)<span class="comment"> -- Turn a indicator on over a range.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATORCLEARRANGE'>IndicatorClearRange</a>(int position, int clearLength)<span class="comment"> -- Turn a indicator off over a range.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATORALLONFOR'>IndicatorAllOnFor</a>(int position)<span class="comment"> -- Are any indicators present at position?</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATORVALUEAT'>IndicatorValueAt</a>(int indicator, int position)<span class="comment"> -- What value does a particular indicator have at at a position?</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATORSTART'>IndicatorStart</a>(int indicator, int position)<span class="comment"> -- Where does a particular indicator start?</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_INDICATOREND'>IndicatorEnd</a>(int indicator, int position)<span class="comment"> -- Where does a particular indicator end?</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_FINDINDICATORSHOW'>FindIndicatorShow</a>(position start, position end)<span class="comment"> -- On OS X, show a find indicator.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_FINDINDICATORFLASH'>FindIndicatorFlash</a>(position start, position end)<span class="comment"> -- On OS X, flash a find indicator, then fade out.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_FINDINDICATORHIDE'>FindIndicatorHide</a>()<span class="comment"> -- On OS X, hide the find indicator.</span></p>
	<h2>Autocompletion</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSHOW'>AutoCShow</a>(int lenEntered, string itemList)<span class="comment"> -- Display a auto-completion list. The lenEntered parameter indicates how many characters before the caret should be used to provide context.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCCANCEL'>AutoCCancel</a>()<span class="comment"> -- Remove the auto-completion list from the screen.</span></p>
	<p>bool editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCACTIVE'>AutoCActive</a>()<span class="comment"> -- Is there an auto-completion list visible?</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCPOSSTART'>AutoCPosStart</a>()<span class="comment"> -- Retrieve the position of the caret when the auto-completion list was displayed.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCCOMPLETE'>AutoCComplete</a>()<span class="comment"> -- User has selected an item so remove the list and insert the selection.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSTOPS'>AutoCStops</a>(string characterSet)<span class="comment"> -- Define a set of character that when typed cancel the auto-completion list.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETSEPARATOR'>AutoCSeparator</a><span class="comment"> -- Change the separator character in the string setting up an auto-completion list. Default is space but can be changed if items contain space.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSELECT'>AutoCSelect</a>(string text)<span class="comment"> -- Select the item in the auto-completion list that starts with a string.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCGETCURRENT'>AutoCCurrent</a> read-only</p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCGETCURRENTTEXT'>AutoCCurrentText</a> read-only</p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETCANCELATSTART'>AutoCCancelAtStart</a><span class="comment"> -- Should the auto-completion list be cancelled if the user backspaces to a position before where the box was created.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETFILLUPS'>AutoCFillUps</a> write-only<span class="comment"> -- Define a set of characters that when typed will cause the autocompletion to choose the selected item.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETCHOOSESINGLE'>AutoCChooseSingle</a><span class="comment"> -- Should a single item auto-completion list automatically choose the item.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETIGNORECASE'>AutoCIgnoreCase</a><span class="comment"> -- Set whether case is significant when performing auto-completion searches.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR'>AutoCCaseInsensitiveBehaviour</a><span class="comment"> -- Set auto-completion case insensitive behaviour to either prefer case-sensitive matches or have no preference.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETAUTOHIDE'>AutoCAutoHide</a><span class="comment"> -- Set whether or not autocompletion is hidden automatically when nothing matches.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETDROPRESTOFWORD'>AutoCDropRestOfWord</a><span class="comment"> -- Set whether or not autocompletion deletes any word characters after the inserted text upon completion.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REGISTERIMAGE'>RegisterImage</a>(int type, string xpmData)<span class="comment"> -- Register an XPM image for use in autocompletion lists.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_REGISTERRGBAIMAGE'>RegisterRGBAImage</a>(int type, string pixels)<span class="comment"> -- Register an RGBA image for use in autocompletion lists. It has the width and height from RGBAImageSetWidth/Height</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARREGISTEREDIMAGES'>ClearRegisteredImages</a>()<span class="comment"> -- Clear all the registered XPM images.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETTYPESEPARATOR'>AutoCTypeSeparator</a><span class="comment"> -- Change the type-separator character in the string setting up an auto-completion list. Default is '?' but can be changed if items contain '?'.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETMAXHEIGHT'>AutoCMaxHeight</a><span class="comment"> -- Set the maximum height, in rows, of auto-completion and user lists. The default is 5 rows.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_AUTOCSETMAXWIDTH'>AutoCMaxWidth</a><span class="comment"> -- Set the maximum width, in characters, of auto-completion and user lists. Set to 0 to autosize to fit longest item, which is the default.</span></p>
	<h2>User lists</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_USERLISTSHOW'>UserListShow</a>(int listType, string itemList)<span class="comment"> -- Display a list of strings and send notification when user chooses one.</span></p>
	<h2>Call tips</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSHOW'>CallTipShow</a>(position pos, string definition)<span class="comment"> -- Show a call tip containing a definition near position pos.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPCANCEL'>CallTipCancel</a>()<span class="comment"> -- Remove the call tip from the screen.</span></p>
	<p>bool editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPACTIVE'>CallTipActive</a>()<span class="comment"> -- Is there an active call tip?</span></p>
	<p>position editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPPOSSTART'>CallTipPosStart</a>()<span class="comment"> -- Retrieve the position where the caret was before displaying the call tip.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSETHLT'>CallTipSetHlt</a>(int start, int end)<span class="comment"> -- Highlight a segment of the definition.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSETBACK'>CallTipBack</a> write-only<span class="comment"> -- Set the background colour for the call tip.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSETFORE'>CallTipFore</a> write-only<span class="comment"> -- Set the foreground colour for the call tip.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSETFOREHLT'>CallTipForeHlt</a> write-only<span class="comment"> -- Set the foreground colour for the highlighted part of the call tip.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPUSESTYLE'>CallTipUseStyle</a> write-only<span class="comment"> -- Enable use of STYLE_CALLTIP and set call tip tab size in pixels.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CALLTIPSETPOSITION'>CallTipPosition</a> write-only<span class="comment"> -- Set position of calltip, above or below text.</span></p>
	<h2>Key bindings</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ASSIGNCMDKEY'>AssignCmdKey</a>(keymod km, int msg)<span class="comment"> -- When key+modifier combination km is pressed perform msg.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARCMDKEY'>ClearCmdKey</a>(keymod km)<span class="comment"> -- When key+modifier combination km is pressed do nothing.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CLEARALLCMDKEYS'>ClearAllCmdKeys</a>()<span class="comment"> -- Drop all key mappings.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_NULL'>Null</a>()<span class="comment"> -- Null operation.</span></p>
	<h2>Popup edit menu</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_USEPOPUP'>UsePopUp</a>(bool allowPopUp)<span class="comment"> -- Set whether a pop up menu is displayed automatically when the user presses the wrong mouse button.</span></p>
	<h2>Macro recording</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STARTRECORD'>StartRecord</a>()<span class="comment"> -- Start notifying the container of all key presses and commands.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_STOPRECORD'>StopRecord</a>()<span class="comment"> -- Stop notifying the container of all key presses and commands.</span></p>
	<h2>Printing</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPRINTMAGNIFICATION'>PrintMagnification</a><span class="comment"> -- Sets the print magnification added to the point size of each style for printing.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPRINTCOLOURMODE'>PrintColourMode</a><span class="comment"> -- Modify colours when printing for clearer printed text.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPRINTWRAPMODE'>PrintWrapMode</a><span class="comment"> -- Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE).</span></p>
	<h2>Direct access</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETDIRECTFUNCTION'>DirectFunction</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETDIRECTPOINTER'>DirectPointer</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETCHARACTERPOINTER'>CharacterPointer</a> read-only</p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETRANGEPOINTER'>GetRangePointer</a>(int position, int rangeLength)<span class="comment"> -- Return a read-only pointer to a range of characters in the document. May move the gap so that the range is contiguous, but will only move up to rangeLength bytes.</span></p>
	<p>position editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETGAPPOSITION'>GapPosition</a> read-only</p>
	<h2>Multiple views</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETDOCPOINTER'>DocPointer</a><span class="comment"> -- Change the document object used.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CREATEDOCUMENT'>CreateDocument</a>()<span class="comment"> -- Create a new document object. Starts with reference count of 1 and not selected into editor.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ADDREFDOCUMENT'>AddRefDocument</a>(int doc)<span class="comment"> -- Extend life of document.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_RELEASEDOCUMENT'>ReleaseDocument</a>(int doc)<span class="comment"> -- Release a reference to the document, deleting document if it fades to black.</span></p>
	<h2>Background loading and saving</h2>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CREATELOADER'>CreateLoader</a>(int bytes)<span class="comment"> -- Create an ILoader*.</span></p>
	<h2>Folding</h2>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_VISIBLEFROMDOCLINE'>VisibleFromDocLine</a>(int line)<span class="comment"> -- Find the display line of a document line taking hidden lines into account.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_DOCLINEFROMVISIBLE'>DocLineFromVisible</a>(int lineDisplay)<span class="comment"> -- Find the document line of a display line taking hidden lines into account.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SHOWLINES'>ShowLines</a>(int lineStart, int lineEnd)<span class="comment"> -- Make a range of lines visible.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_HIDELINES'>HideLines</a>(int lineStart, int lineEnd)<span class="comment"> -- Make a range of lines invisible.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLINEVISIBLE'>LineVisible</a>[int line] read-only</p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETALLLINESVISIBLE'>AllLinesVisible</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOLDLEVEL'>FoldLevel</a>[int line]<span class="comment"> -- Set the fold level of a line. This encodes an integer level along with flags indicating whether the line is a header and whether it is effectively white space.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOLDFLAGS'>FoldFlags</a> write-only<span class="comment"> -- Set some style options for folding.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETLASTCHILD'>GetLastChild</a>(int line, int level)<span class="comment"> -- Find the last child line of a header line.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETFOLDPARENT'>FoldParent</a>[int line] read-only</p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_TOGGLEFOLD'>ToggleFold</a>(int line)<span class="comment"> -- Switch a header line between expanded and contracted.</span></p>
	<p>bool editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETFOLDEXPANDED'>FoldExpanded</a>[int line]<span class="comment"> -- Show the children of a header line.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CONTRACTEDFOLDNEXT'>ContractedFoldNext</a>(int lineStart)<span class="comment"> -- Find the next line at or after lineStart that is a contracted fold header line. Return -1 when no more lines.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ENSUREVISIBLE'>EnsureVisible</a>(int line)<span class="comment"> -- Ensure a particular line is visible by expanding any header line hiding it.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ENSUREVISIBLEENFORCEPOLICY'>EnsureVisibleEnforcePolicy</a>(int line)<span class="comment"> -- Ensure a particular line is visible by expanding any header line hiding it. Use the currently set visibility policy to determine which range to display.</span></p>
	<h2>Line wrapping</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWRAPMODE'>WrapMode</a><span class="comment"> -- Sets whether text is word wrapped.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWRAPVISUALFLAGS'>WrapVisualFlags</a><span class="comment"> -- Set the display mode of visual flags for wrapped lines.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWRAPVISUALFLAGSLOCATION'>WrapVisualFlagsLocation</a><span class="comment"> -- Set the location of visual flags for wrapped lines.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWRAPINDENTMODE'>WrapIndentMode</a><span class="comment"> -- Sets how wrapped sublines are placed. Default is fixed.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETWRAPSTARTINDENT'>WrapStartIndent</a><span class="comment"> -- Set the start indent for wrapped lines.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLAYOUTCACHE'>LayoutCache</a><span class="comment"> -- Sets the degree of caching of layout information.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPOSITIONCACHE'>PositionCache</a><span class="comment"> -- Set number of entries in position cache</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINESSPLIT'>LinesSplit</a>(int pixelWidth)<span class="comment"> -- Split the lines in the target into lines that are less wide than pixelWidth where possible.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LINESJOIN'>LinesJoin</a>()<span class="comment"> -- Join the lines in the target.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_WRAPCOUNT'>WrapCount</a>(int line)<span class="comment"> -- The number of display lines needed to wrap a document line</span></p>
	<h2>Zooming</h2>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ZOOMIN'>ZoomIn</a>()<span class="comment"> -- Magnify the displayed text by increasing the sizes by 1 point.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ZOOMOUT'>ZoomOut</a>()<span class="comment"> -- Make the displayed text smaller by decreasing the sizes by 1 point.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETZOOM'>Zoom</a><span class="comment"> -- Set the zoom level. This number of points is added to the size of all fonts. It may be positive to magnify or negative to reduce.</span></p>
	<h2>Long lines</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEDGEMODE'>EdgeMode</a><span class="comment"> -- The edge may be displayed by a line (EDGE_LINE) or by highlighting text that goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE).</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEDGECOLUMN'>EdgeColumn</a><span class="comment"> -- Set the column number of the edge. If text goes past the edge then it is highlighted.</span></p>
	<p>colour editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETEDGECOLOUR'>EdgeColour</a><span class="comment"> -- Change the colour used in edge indication.</span></p>
	<h2>Lexer</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLEXER'>Lexer</a><span class="comment"> -- Set the lexing language of the document.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETLEXERLANGUAGE'>LexerLanguage</a><span class="comment"> -- Set the lexing language of the document based on string name.</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_LOADLEXERLIBRARY'>LoadLexerLibrary</a>(string path)<span class="comment"> -- Load a lexer library (dll / so).</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_COLOURISE'>Colourise</a>(position start, position end)<span class="comment"> -- Colourise a segment of the document using the current lexing language.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_CHANGELEXERSTATE'>ChangeLexerState</a>(position start, position end)<span class="comment"> -- Indicate that the internal state of a lexer has changed over a range and therefore there may be a need to redraw.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_PROPERTYNAMES'>PropertyNames</a>()<span class="comment"> -- Retrieve a '\n' separated list of properties understood by the current lexer.</span></p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_PROPERTYTYPE'>PropertyType</a>(string name)<span class="comment"> -- Retrieve the type of a property.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_DESCRIBEPROPERTY'>DescribeProperty</a>(string name)<span class="comment"> -- Describe a property.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETPROPERTY'>Property</a>[string key]<span class="comment"> -- Set up a value that may be used by a lexer for some optional feature.</span></p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETPROPERTYEXPANDED'>PropertyExpanded</a>[string key] read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETPROPERTYINT'>PropertyInt</a>[string key] read-only</p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETKEYWORDS'>KeyWords</a>[int keywordSet] write-only<span class="comment"> -- Set up the key words used by the lexer.</span></p>
	<p>string editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_DESCRIBEKEYWORDSETS'>DescribeKeyWordSets</a>()<span class="comment"> -- Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSTYLEBITSNEEDED'>StyleBitsNeeded</a> read-only</p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSUBSTYLEBASES'>SubStyleBases</a> read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_DISTANCETOSECONDARYSTYLES'>DistanceToSecondaryStyles</a> read-only</p>
	<p>int editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_ALLOCATESUBSTYLES'>AllocateSubStyles</a>(int styleBase, int numberStyles)<span class="comment"> -- Allocate a set of sub styles for a particular base style, returning start of range</span></p>
	<p>editor:<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_FREESUBSTYLES'>FreeSubStyles</a>()<span class="comment"> -- Free allocated sub styles</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSUBSTYLESSTART'>SubStylesStart</a>[int styleBase] read-only</p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_GETSUBSTYLESLENGTH'>SubStylesLength</a>[int styleBase] read-only</p>
	<p>string editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETIDENTIFIERS'>Identifiers</a>[int style] write-only<span class="comment"> -- Set the identifiers that are shown in a particular style</span></p>
	<h2>Notifications</h2>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETIDENTIFIER'>Identifier</a><span class="comment"> -- Set the identifier reported as idFrom in notification messages.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMODEVENTMASK'>ModEventMask</a><span class="comment"> -- Set which document modification events are sent to the container.</span></p>
	<p>int editor.<a href='http://www.scintilla.org/ScintillaDoc.html#SCI_SETMOUSEDWELLTIME'>MouseDwellTime</a><span class="comment"> -- Sets the time the mouse must sit still to generate a mouse dwell event.</span></p>

<!-- </Autogenerated> -->
  </body>
</html>

Added doc/PrintHi.png.

cannot compute difference between binary files

Added doc/SciBreak.jpg.

cannot compute difference between binary files

Added doc/SciBreak2.jpg.

cannot compute difference between binary files

Added doc/SciCoding.html.







































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla and SciTE Code Style Preferences
    </title>
	<style>
	.S0 {
		color: #808080;
	}
	.S1 {
		font-family: Comic Sans MS;
		color: #007F00;
		font-size: 9pt;
	}
	.S2 {
		font-family: Comic Sans MS;
		color: #007F00;
		font-size: 9pt;
	}
	.S3 {
		font-family: Comic Sans MS;
		color: #3F703F;
		font-size: 9pt;
	}
	.S4 {
		color: #007F7F;
	}
	.S5 {
		font-weight: bold;
		color: #00007F;
	}
	.S6 {
		color: #7F007F;
	}
	.S7 {
		color: #7F007F;
	}
	.S8 {
		color: #804080;
	}
	.S9 {
		color: #7F7F00;
	}
	.S10 {
		font-weight: bold;
		color: #000000;
	}
	.S12 {
		font-family: Courier New;
		color: #000000;
		background: #E0C0E0;
		font-size: 10pt;
	}
	.S13 {
		font-family: Courier New;
		color: #007F00;
		background: #E0FFE0;
		font-size: 10pt;
	}
	.S14 {
		font-family: Courier New;
		color: #3F7F3F;
		background: #E0F0FF;
		font-size: 10pt;
	}
	.S15 {
		font-family: Comic Sans MS;
		color: #3F703F;
		font-size: 9pt;
	}
	SPAN {
		font-family: Verdana;
		font-size: 10pt;
	}
	</style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Code Style
    </h2>
    <h3>
       Introduction
    </h3>
	<p>
	The source code of Scintilla and SciTE follow my preferences.
	Some of these decisions are arbitrary and based on my sense of aesthetics
	but its good to have all the code look the same even if its not exactly how
	everyone would prefer.
	</p>
	<p>
	Code that does not follow these conventions will be accepted, but will be modified
	as time goes by to fit the conventions. Scintilla code follows the conventions more
	closely than SciTE except for lexers which are relatively independent modules.
	Lexers that are maintained by others are left as they are submitted except that
	warnings will be fixed so the whole project can compile cleanly.
	</p>
	<p>
	The <a href="http://astyle.sourceforge.net/">AStyle</a> formatting
	program with '-taOHUKk3 -M8' arguments formats code in much the right way although
	there are a few bugs in AStyle.
	</p>
    <h3>
       Language features
    </h3>
	<p>
	Design goals for Scintilla and SciTE include portability to currently available C++
	compilers on diverse platforms with high performance and low resource usage.
	Scintilla has stricter portability requirements to SciTE as it may be ported to
	low capability platforms.
	</p>
	<p>
	To achieve portability, only a subset of C++ features are used.
	Exceptions and templates may be used but, since Scintilla can be used from C as well as
	C++, exceptions may not be thrown out of Scintilla and all exceptions should be caught
	before returning from Scintilla.
	Run-time type information adds to memory use so is turned off.
	A 'Scintilla' name spaces is optionally used based on the SCI_NAMESPACE
	definition. This helps with name clashes on OS X.
	</p>
	<p>
	The goto statement is not used because of bad memories from my first job
	maintaining FORTRAN programs. The union feature is not used as it can lead to
	non-type-safe value access.
	</p>
    <h3>
       Casting
    </h3>
	<p>
	Do not use old C style casts like (char *)s. Instead use the most strict form of C++
	cast possible like const_cast&lt;char *&gt;(s). Use static_cast and const_cast
	where possible rather than reinterpret_cast. Because the code is compiled with
	run-time type information turned off, dynamic_cast will not work.
	</p>
	<p>
	The benefit to using the new style casts is that they explicitly detail what evil is
	occurring and act as signals that something potentially unsafe is being done.
	</p>
	<p>
	Code that treats const seriously is easier to reason about both for humans
	and compilers, so use const parameters and avoid const_cast.
	</p>
    <h3>
       Warnings
    </h3>
	<p>
	To help ensure code is well written and portable, it is compiled with almost all
	warnings turned on. This sometimes results in warnings about code that is
	completely good (false positives) but changing the code to avoid the warnings
	is generally fast and has little impact on readability.
	</p>
	<p>
	Initialise all variables and minimise the scope of variables. If a variable is defined
	just before its use then it can't be misused by code before that point.
	Use loop declarations that are compatible with both the C++ standard and currently
	available compilers.
	</p>
    <h3>
       Allocation
    </h3>
	<p>
	Memory exhaustion can occur in many Scintilla methods.
	This should be checked for and handled but once it has happened, it is very difficult to do
	anything as Scintilla's data structures may be in an inconsistent state.
	Fixed length buffers are often used as these are simple and avoid the need to
	worry about memory exhaustion but then require that buffer lengths are
	respected.
	</p>
	<p>
	The C++ new and delete operators are preferred over C's malloc and free
	as new and delete are type safe.
	</p>
    <h3>
       Bracketing
    </h3>
	<p>
	Start brackets, '{', should be located on the line of the control structure they
	start and end brackets, '}', should be at the indented start of a line. When there is
	an else clause, this occurs on the same line as the '}'.
	This format uses less lines than alternatives, allowing more code to be seen on screen.
	Fully bracketed control
	structures are preferred because this makes it more likely that modifications will
	be correct and it allows Scintilla's folder to work. No braces on returned
	expressions as return is a keyword, not a function call.
	</p>
<SPAN class=S0></SPAN><SPAN class=S5>bool</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>fn</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>t</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>else</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>u</SPAN><SPAN class=S10>();</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>return</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>!</SPAN><SPAN class=S11>a</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
</SPAN>    <h3>
       Spacing
    </h3>
	<p>
	Spaces on both sides of '=' and comparison operators and no attempt to line up '='.
	No space before or after '(', when used in calls, but a space after every ','.
	No spaces between tokens in short expressions but may be present in
	longer expressions. Space before '{'. No space before ';'.
	No space after '*' when used to mean pointer and no space after '[' or ']'.
	One space between keywords and '('.
	</p>
<SPAN class=S0></SPAN><SPAN class=S5>void</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>StoreConditionally</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>c</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>const</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>char</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>c</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>&amp;&amp;</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>==</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>trustSegment</SPAN><SPAN class=S10>[</SPAN><SPAN class=S6>"html"</SPAN><SPAN class=S10>]))</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>+</SPAN><SPAN class=S4>1</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>Store</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>baseSegment</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S6>"html"</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S10>}</SPAN>
    <h3>
       Names
    </h3>
	<p>
	Identifiers use mixed case and no underscores.
	Class, function and method names start with an uppercase letter and use
	further upper case letters to distinguish words. Variables start with a lower
	case letter and use upper case letters to distinguish words.
	Loop counters and similar variables can have simple names like 'i'.
	Function calls should be differentiated from method calls with an initial '::'
	global scope modifier.
	</p>
<SPAN class=S0></SPAN><SPAN class=S5>class</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>StorageZone</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S5>public</SPAN><SPAN class=S10>:</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>void</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>Store</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>const</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>char</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>Media</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>*</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>GetBaseMedia</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>zoneDefault</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>for</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>=</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>-&gt;</SPAN><SPAN class=S11>cursor</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>[</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>],</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>++)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>mediaStore</SPAN><SPAN class=S10>-&gt;</SPAN><SPAN class=S11>Persist</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>s</SPAN><SPAN class=S10>[</SPAN><SPAN class=S11>i</SPAN><SPAN class=S10>]);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S10>};</SPAN>
    <h3>
       Submitting a lexer
    </h3>

	<p>Add a public feature request to the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=352439">Feature Request Tracker</a>.</p>
	<p>Send all the modified and new files as full text (not patches) in an archive (.zip or .tgz).</p>
	<p>Define all of the lexical states in a modified Scintilla.iface.</p>
	<p>Ensure there are no warnings under the compiler you use. Warnings from other compilers
	will be noted on the feature request.</p>
	<p>sc.ch is an int: do not pass this around as a char.</p>
  </body>
</html>

Added doc/SciRest.jpg.

cannot compute difference between binary files

Added doc/SciTE.html.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
    <meta name="Description"
    content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
    <meta name="Date.Modified" content="20130226" />
    <script type="text/javascript">
   	function IsRemote() {
		var loc = '' + window.location;
		return loc.indexOf('http:') != -1;
   	}
   </script>
    <style type="text/css">
        #versionlist {
            margin: 0;
            padding: .5em;
            list-style-type: none;
            color: #FFCC99;
            background: #000000;
        }
        #versionlist li {
            margin-bottom: .5em;
        }
        #menu {
            margin: 0;
            padding: .5em 0;
            list-style-type: none;
            font-size: larger;
            background: #CCCCCC;
        }
        #menu li {
            margin: 0;
            padding: 0 .5em;
            display: inline;
        }
    </style>
    <title>
      Scintilla and SciTE
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td width="256">
          <img src="http://www.scintilla.org/SciTEWord.jpg" height="85" width="200" alt="Scintilla" />
        </td>
        <td width="40%" align="left">
          <font color="#FFCC99" size="4"> A free source code editor for Win32 and
          X</font>
        </td>
        <td width="40%" align="right">
          <font color="#FFCC99" size="3"> Release version 3.2.5<br />
           Site last modified February 26 2013</font>
        </td>
        <td width="20%">
          &nbsp;
        </td>
      </tr>
    </table>
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td width="100%" style="background: url(http://www.scintilla.org/SciBreak2.jpg) no-repeat;height:150px;">
          &nbsp;
        </td>
      </tr>
    </table>
    <ul id="versionlist">
      <li>Version 3.2.5 caret x positions are remembered when switching documents.</li>
      <li>Version 3.2.4 does not truncate copies to clipboard at NULs.</li>
      <li>Version 3.2.3 defines PLAT_UNIX for all Unix variants and fixes minor problems.</li>
      <li>Version 3.2.2 remains responsive by limiting highlight.current.word to 0.25 seconds.</li>
      <li>Version 3.2.1 retrieves string properties from the Scintilla API using property notation in Lua scripts.</li>
      <li>Version 3.2.0 allows Ctrl to be used with mouse double and triple clicks to add words and lines to the selection.</li>
    </ul>
    <ul id="menu">
      <li><a href="http://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
      <li id="remote1"><a href="http://www.scintilla.org/SciTEDownload.html">Download</a></li>
      <li><a href="http://www.scintilla.org/SciTEDoc.html">Documentation</a></li>
      <li id="remote2"><a href="http://www.scintilla.org/index.html">Scintilla</a></li>
      <li><a href="http://code.google.com/p/scite-files/wiki/Customization">Extras</a></li>
      <li><a href="http://code.google.com/p/scite-files/wiki/Translations">Translations</a></li>
      <li><a href="http://www.scintilla.org/SciTEFAQ.html">Frequently Asked Questions</a></li>
    </ul>
<script type="text/javascript" language="JavaScript"><!--
if (!IsRemote()) { //if NOT remote...
    document.getElementById('remote1').style.display='none';
    document.getElementById('remote2').style.display='none';
}
//--></script>
    <p>
       <a href="http://www.scintilla.org/SciTEDoc.html">SciTE</a> is a SCIntilla based Text Editor. Originally built to
      demonstrate <a href="http://www.scintilla.org">Scintilla</a>, it has grown to be a generally useful editor with facilities for
      building and running programs. It is best used for jobs with simple configurations - I use it
      for building test and demonstration programs as well as SciTE and Scintilla, themselves.
    </p>
    <p>
       SciTE is currently available for Intel Windows (XP or later) and Linux compatible operating
      systems with GTK+. It has been run on Windows 7 and on Fedora 12 and Ubuntu 10.10
      with GTK+ 2.20. <a href="http://www.scintilla.org/SciTEImage.html">Here is a screenshot of
      SciTE.</a><br />
    </p>
<script type="text/javascript" language="JavaScript"><!--
if (IsRemote()) {
    document.write('<p>You can <a href="http://www.scintilla.org/SciTEDownload.html">download Scintilla and SciTE.</a></p>');
}
//--></script>
<noscript>
<p>You can <a href="http://www.scintilla.org/SciTEDownload.html">download Scintilla and SciTE.</a></p>
</noscript>
    <p>
       For OS X, there is a commercial version of SciTE available from the <a href="http://www.scintilla.org/SciTE-OSX.html">Mac App Store</a>.
    </p>
    <p>
       There are some <a href="http://code.google.com/p/scite-files/wiki/Customization">extra configuration files</a> that can
       enhance SciTE for various languages and APIs.
    </p>
    <p>
      Questions and comments about SciTE should be directed to the
      <a href="http://groups.google.com/group/scite-interest">scite-interest</a>
      mailing list,
      which is for discussion of SciTE and related projects, their bugs and future features.
      This is a low traffic list, averaging less than 50 messages per week.
      To avoid spam, only list members can write to the list.
      New versions of SciTE are announced on scite-interest and may also be received by SourceForge
      members by clicking on the Monitor column icon for "scite" on
      <a href="https://sourceforge.net/project/showfiles.php?group_id=2439">the downloads page</a>.
      Messages sent to my personal email address that could have been sent to the list
      may receive no response.
      <br />
    </p>
There is a <a href="https://sourceforge.net/project/?group_id=2439">Scintilla project page</a> hosted on
<script type="text/javascript" language="JavaScript">
<!--
if (IsRemote()) {
    document.write('<a href="http://sourceforge.net/projects/scintilla">');
    document.write('<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a> ');
} else {
    document.write('<a href="http://sourceforge.net/projects/scintilla">SourceForge<\/a>');
}
//-->
</script>
<noscript>
<a href="http://sourceforge.net/projects/scintilla">
<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</noscript>
  </body>
</html>

Added doc/SciTEDirector.html.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      SciTE Director Interface
    </title>
    <style type="text/css">
	table {
		border: 1px solid black;
		border-collapse: collapse;
	}
	td {
		border: 1px solid black;
		padding: 1px 5px 1px 5px;
	}
	.S0 {
		color: #808080;
	}
	.S1 {
		font-family: Comic Sans MS;
		color: #007F00;
		font-size: 9pt;
	}
	.S2 {
		font-family: Comic Sans MS;
		color: #007F00;
		font-size: 9pt;
	}
	.S3 {
		font-family: Comic Sans MS;
		color: #3F703F;
		font-size: 9pt;
	}
	.S4 {
		color: #007F7F;
	}
	.S5 {
		font-weight: bold;
		color: #00007F;
	}
	.S6 {
		color: #7F007F;
	}
	.S7 {
		color: #7F007F;
	}
	.S8 {
		color: #804080;
	}
	.S9 {
		color: #7F7F00;
	}
	.S10 {
		font-weight: bold;
		color: #000000;
	}
	.S12 {
		font-family: Courier New;
		color: #000000;
		background: #E0C0E0;
		font-size: 10pt;
	}
	.S13 {
		font-family: Courier New;
		color: #007F00;
		background: #E0FFE0;
		font-size: 10pt;
	}
	.S14 {
		font-family: Courier New;
		color: #3F7F3F;
		background: #E0F0FF;
		font-size: 10pt;
	}
	.S15 {
		font-family: Comic Sans MS;
		color: #3F703F;
		font-size: 9pt;
	}
	SPAN {
		font-family: Verdana;
		font-size: 10pt;
	}
	.example {
		color: #00A000;
		font-weight: bold;
	}
	DIV.example {
		background: #F7FCF7;
		border: 1px solid #C0D7C0;
		margin: 0.3em 3em;
		padding: 0.3em 0.6em;
		font-size: 80%;
	}
	DIV.highlighted {
		background: #F7FCF7;
		border: 1px solid #C0D7C0;
		margin: 0.3em 3em;
		padding: 0.3em 0.6em;
		font-size: 80%;
	}
    </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  SciTE Director Interface</font></a>
        </td>
      </tr>
    </table>
    <h3>
       Purpose.
    </h3>
	<p>Software development does not occur only at the single file level handled by SciTE.
	A developer will generally work on a group of related files together in the context of one
	project. Project manager functionality could be added to SciTE as it has to other editors
	but this would impose a particular view of how projects are to be managed including the
	format of project files. Instead, SciTE has an interface that can be used by project
	managers or similar applications to control SciTE. Any application that controls SciTE is
	referred to as a "Director".</p>
	<p>The current Director interface only works on Windows. In the future, it should be
	possible to replace the low level interface and so make this interface available on other
	platforms.</p>
	<p>There is currently one director application,
	<a href="http://llt.chez.tiscali.fr/">Filerx</a>, available.</p>
	<p>This interface is implemented on top of the
	<a href="SciTEExtension.html">SciTE Extension Interface</a>, in the
	file scite\win32\DirectorExtension.cxx.</p>
    <h3>
       Direct connection, broadcasting and explicit return addresses.
    </h3>
	<p>One application at a time is <i>the director</i> of SciTE,
	controlling SciTE as it wishes. To support other communications techniques
	applications may broadcast to all active director interfaces. When doing so,
	each message should contain an explicit return address where replies to the
	broadcast message will be sent.
	</p>
    <h3>
       Low level interface on Windows.
    </h3>
	<p>The Windows WM_COPYDATA message is used to transfer data between
	SciTE and a Director. The messages are sent between windows created by the two
	applications. SciTE uses a window that has no other purpose than to receive these
	messages.
	The lpData and cbData fields of the COPYDATASTRUCT
	are used to transfer a string between the two processes, with cbData holding the length
	of the string pointed to by lpData. The string does not have to be terminated with '\0'.
	The dwData should be 0.</p>
	<p>Before messages can be sent from one application to the other, the window handle
	of the window to receive the message must be found. This is normally transferred when
	starting the other application as a command line parameter. Either application may
	start the other. SciTE makes its window handle available in the WindowID
	property and accepts a director.hwnd property as the window handle to which it
	sends data.</p>
	<p>As an example of communicating the window handle, to install Filerx in the Tools
	menu of SciTE these properties could be used:</p>
	<div class="example">
	command.name.0.*=Project Editor<br/>
	command.0.*="C:\os\scite\bin\filerx.exe" "$(FileDir)" "$(WindowID)"<br/>
	command.subsystem.0.*=2
	</div>
	<p>In the opposite direction, Filerx can start up SciTE with a command line that
	specifies its window handle as well as the file it wants edited:</p>
	<div class="example">
	SciTE -director.hwnd=937846 c:\os\scite\src\SciTEBase.cxx
	</div>
	<p>Once one application has the window handle of the other application, it should send
	its window handle to the other application using an identity message as described later.
	Then both sides are able to send messages.</p>
	<p>To broadcast a message on Windows, the set of active director
	interfaces can be found by broadcasting the "SciTEDirectorInterface"
	message and seeing which windows reply with the same value as that message.
	Example broadcast code:</p>
	<div class="highlighted">
<SPAN class=S0></SPAN><SPAN class=S5>unsigned</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>RegisterWindowMessage</SPAN><SPAN class=S10>(</SPAN><SPAN class=S0></SPAN><SPAN class=S6>"SciTEDirectorInterface"</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S11>HWND</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>w</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>GetWindow</SPAN><SPAN class=S10>(::</SPAN><SPAN class=S11>GetDesktopWindow</SPAN><SPAN class=S10>(),</SPAN><SPAN class=S0></SPAN><SPAN class=S11>GW_CHILD</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S5>while</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>w</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>DWORD</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>res</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S4>0</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S2>//&nbsp;Need&nbsp;time&nbsp;out&nbsp;to&nbsp;avoid&nbsp;hung&nbsp;applications</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>SendMessageTimeout</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>w</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S4>0</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S4>0</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>SMTO_NORMAL</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S4>1000</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>&amp;</SPAN><SPAN class=S11>res</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>res</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>==</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>static_cast</SPAN><SPAN class=S10>&lt;</SPAN><SPAN class=S11>DWORD</SPAN><SPAN class=S10>&gt;(</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S10>))</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S2>//&nbsp;Replied&nbsp;with&nbsp;same&nbsp;SDI&nbsp;code&nbsp;so&nbsp;should</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S2>//&nbsp;understand&nbsp;SDI's&nbsp;version&nbsp;of&nbsp;WM_COPYDATA</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>SendMessage</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>w</SPAN><SPAN class=S10>,</SPAN><SPAN class=S11>WM_COPYDATA</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>UINT</SPAN><SPAN class=S10>)</SPAN><SPAN class=S11>m_hWnd</SPAN><SPAN class=S10>,(</SPAN><SPAN class=S5>long</SPAN><SPAN class=S10>)&amp;</SPAN><SPAN class=S11>cds</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>w</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>GetWindow</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>w</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>GW_HWNDNEXT</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
</SPAN>
</div>
<p>To advertise that a top level window supports the Director interface:</p>
	<div class="highlighted">
<SPAN class=S0></SPAN><SPAN class=S11>LRESULT</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>PASCAL</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>DirectorExtension_WndProc</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>HWND</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>hWnd</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S11>UINT</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>iMessage</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>WPARAM</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>wParam</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>LPARAM</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>lParam</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>unsigned</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S5>int</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>=</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>RegisterWindowMessage</SPAN><SPAN class=S10>(</SPAN><SPAN class=S6>"SciTEDirectorInterface"</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>if</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>iMessage</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>==</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S10>)</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>{</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>return</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>SDI</SPAN><SPAN class=S10>;</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S10>}</SPAN><SPAN class=S0><BR>
&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN class=S5>return</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S10>::</SPAN><SPAN class=S11>DefWindowProc</SPAN><SPAN class=S10>(</SPAN><SPAN class=S11>hWnd</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>iMessage</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0>&nbsp;</SPAN><SPAN class=S11>wParam</SPAN><SPAN class=S10>,</SPAN><SPAN class=S0></SPAN><SPAN class=S11>lParam</SPAN><SPAN class=S10>);</SPAN><SPAN class=S0><BR>
</SPAN><SPAN class=S10>}</SPAN><BR>
</div>
    <h3>
       Low level interface on GTK+.
    </h3>
	<p>This is not yet implemented.
	The proposed design uses an input fifo for each application supporting the director
	interface located in /tmp with a name using a pattern such as
	"/tmp/SciTE&lt;PID&gt;.director".
	This allows enumerating all active director interfaces and also opening
	a specific interface when the fifo name has been communicated through some
	other means such as a command line argument or an identity: command.</p>
    <h3>
       High level interface.
    </h3>
	<p>Messages use C style escapes to represent control characters and
	ensure that only visible characters are transmitted apart from the use
	of '\n' to separate messages.</p>
	<p>The string transmitted by the low level interface contains an optional
	return address surrounded by ':' characters, an action, a ':' character and
	an optional argument. The argument is often a file path. The ':' must be present even if there
	is no argument. For example, SciTE understands the message</p>
	<div class="example">
	open:c:\\os\\scintilla\\include\\Scintilla.iface
	</div>
	<p>as a command to open the file "c:\os\scintilla\include\Scintilla.iface" just as if the user
	had performed this operation.</p>
	<p>If the first character of the message is a ':' then up to the next ':' is a return
	address, so SciTE will reply to the message</p>
	<div class="example">
	:73658:askfilename:
	</div>
	<p>by sending the filename being edited to the return address 73658
	rather than to its director.</p>
	<h4>The actions understood by SciTE are:</h4>
	<table border="1">
		<tr>
			<td>askfilename:</td>
			<td>Return the name of the file being edited.</td>
		</tr>
		<tr>
			<td>askproperty:&lt;key&gt;</td>
			<td>Return the value of a property.</td>
		</tr>
		<tr>
			<td>close:</td>
			<td>Close the current file.</td>
		</tr>
		<tr>
			<td>closing:</td>
			<td>Director is closing - SciTE closes if it was started by the director.</td>
		</tr>
		<tr>
			<td>currentmacro:&lt;string&gt;</td>
			<td>Set the current macro to name.</td>
		</tr>
		<tr>
			<td>cwd:</td>
			<td>Change the working directory.</td>
		</tr>
		<tr>
			<td>enumproperties:dyn|local|user|base|embed</td>
			<td>Enumerate all the properties in the argument set.</td>
		</tr>
		<tr>
			<td>exportashtml:&lt;path&gt;</td>
			<td>Save the document in HTML format as the indicated file.</td>
		</tr>
		<tr>
			<td>exportasrtf:&lt;path&gt;</td>
			<td>Save the document in RTF format as the indicated file.</td>
		</tr>
		<tr>
			<td>exportaspdf:&lt;path&gt;</td>
			<td>Save the document in PDF format as the indicated file.</td>
		</tr>
		<tr>
			<td>exportaslatex:&lt;path&gt;</td>
			<td>Save the document in LaTeX format as the indicated file.</td>
		</tr>
		<tr>
			<td>exportasxml:&lt;path&gt;</td>
			<td>Save the document in XML format as the indicated file.</td>
		</tr>
		<tr>
			<td>extender:&lt;command&gt;</td>
			<td>Call the extension interface with the given command.</td>
		</tr>
		<tr>
			<td>find:&lt;string&gt;</td>
			<td>Search for a string, select and show it.</td>
		</tr>
		<tr>
			<td>focus:&lt;timeStamp&gt;</td>
			<td>On GTK+ bring this SciTE window to the front.
			The timeStamp is from the window manager and ensures that windows are only
			activated because of a user command.
			Has no effect on Windows as applications on Windows can only donate focus, not take focus.</td>
		</tr>
		<tr>
			<td>goto:&lt;lineNumber&gt;[,&lt;columnNumber&gt;]</td>
			<td>Move caret to a particular line and make it visible.<br>
			If there is a column number then select the word at that column number
			or move the caret there if no word is present.</td>
		</tr>
		<tr>
			<td>identity:&lt;hwndDirector&gt;</td>
			<td>Sets the director window handle to which SciTE sends messages.
			The argument is in decimal.</td>
		</tr>
		<tr>
			<td>insert:&lt;value&gt;</td>
			<td>Display the value in the editor pane replacing the selection.</td>
		</tr>
		<tr>
			<td>loadsession:&lt;path&gt;</td>
			<td>Load a session as given by the indicated file.</td>
		</tr>
		<tr>
			<td>macrocommand:&lt;command&gt;</td>
			<td>Execute a macro command.
			See the SciTE source code for the syntax of the
			command argument.</td>
		</tr>
		<tr>
			<td>macroenable:&lt;enable&gt;</td>
			<td>If enable, display menu commands in SciTE for recording
			and playing macros.</td>
		</tr>
		<tr>
			<td>macrolist:&lt;list&gt;</td>
			<td>Display a list for the user to choose from.</td>
		</tr>
		<tr>
			<td>menucommand:&lt;cmd&gt;</td>
			<td>Execute a menu command based on numeric ID.</td>
		</tr>
		<tr>
			<td>open:&lt;path&gt;</td>
			<td>Open the indicated file.</td>
		</tr>
		<tr>
			<td>output:&lt;value&gt;</td>
			<td>Display the value in the output pane replacing the selection.</td>
		</tr>
		<tr>
			<td>property:&lt;key&gt;=&lt;value&gt;</td>
			<td>Set a property to a value.</td>
		</tr>
		<tr>
			<td>quit:</td>
			<td>Shut down SciTE.</td>
		</tr>
		<tr>
			<td>reloadproperties:</td>
			<td>Reload properties from files.</td>
		</tr>
		<tr>
			<td>replaceall:&lt;search&gt;\000&lt;replace&gt;</td>
			<td>Replace all instances of he search string in the
			document with the replace string.</td>
		</tr>
		<tr>
			<td>saveas:&lt;path&gt;</td>
			<td>Save the document as the indicated file.</td>
		</tr>
		<tr>
			<td>savesession:&lt;path&gt;</td>
			<td>Save a session as given by the indicated file.</td>
		</tr>
	</table>
	<h4>The actions sent by SciTE are:</h4>
	<table border="1">
		<tr>
			<td>closed:&lt;path&gt;</td>
			<td>SciTE has closed the indicated file.</td>
		</tr>
		<tr>
			<td>closing:</td>
			<td>SciTE is closing.</td>
		</tr>
		<tr>
			<td>dyn|local|user|base|embed:&lt;key&gt;=&lt;value&gt;</td>
			<td>Set a property in a set to a value.</td>
		</tr>
		<tr>
			<td>filename:&lt;path&gt;</td>
			<td>The file being edited is path.
			This is the reply to the askfilename: command.</td>
		</tr>
		<tr>
			<td>identity:&lt;hwndSciTEReceiving&gt;</td>
			<td>SciTE indicates to the director the window handle to which it should send
			messages. The argument is in decimal.</td>
		</tr>
		<tr>
			<td>macro:getlist</td>
			<td>Retrieve the list of available macros which will be
			returned by the macrolist command.</td>
		</tr>
		<tr>
			<td>macro:record:&lt;details&gt;</td>
			<td>Start recording a macro.
			See the SciTE source code for the syntax of the
			details argument.</td>
		</tr>
		<tr>
			<td>macro:run:&lt;macroName&gt;</td>
			<td>Run the named macro.</td>
		</tr>
		<tr>
			<td>macro:stoprecord</td>
			<td>Stop recording a macro.</td>
		</tr>
		<tr>
			<td>opened:&lt;path&gt;</td>
			<td>SciTE has opened the indicated file.</td>
		</tr>
		<tr>
			<td>switched:&lt;path&gt;</td>
			<td>SciTE has switched buffers to the indicated file.</td>
		</tr>
		<tr>
			<td>saved:&lt;path&gt;</td>
			<td>SciTE has saved the indicated file.</td>
		</tr>
	</table>
  <p>In the future, more actions will be defined. Applications should ignore any
  actions that they do not understand.</p>
  </body>
</html>

Added doc/SciTEDoc.html.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
<?xml version="1.0" encoding='utf-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html" />
    <title>
      SciTE
    </title>
<style type="text/css">
        table {
            border: 1px solid #1F1F1F;
            border-collapse: collapse;
        }
        td {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        th {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        .windowsonly {
            background: #EBF3FF;
        }
        .gtkonly {
            background: #FFFFE7;
        }
        .osxonly {
            background: #FFE7E7;
        }
        .example {
            color: #008000;
            font-weight: bold;
        }
        DIV.example {
            background: #F7FCF7;
            border: 1px solid #C0D7C0;
            margin: 0.3em 3em;
            padding: 0.3em 0.6em;
            font-size: 80%;
        }
        h3 {
            border: 2px solid #FFCC00;
            background-color: #FFF7EE;
            padding: 2px 5px;
        }
        .header{
            border: 1px solid #CCCCCC;
        }
        .headerlinks {
            padding: 7px;
            background-color: #CCCCCC;
            border: 0px solid #FF0000;
            font-size: 120%;
        }
 </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" style="border:0px solid #FF0000" border="0"  summary="banner">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
          SciTE Documentation</font></a>
        </td>
      </tr>
    </table>
    <table class="header" width="100%" summary="header">
      <tr>
        <td class="headerlinks">
	  <a href="SciTEFAQ.html">
          Frequently Asked Questions</a>&nbsp;&nbsp;
	  <a href="SciTELua.html">
          Scripting</a>&nbsp;&nbsp;
	  <a href="SciTERegEx.html">Regular Expressions</a>&nbsp;&nbsp;
        </td>
      </tr>
    </table>
    <h3 id="StandardEditing">
       Standard Editing
    </h3>
    <p>
        Text editing in SciTE works similarly to most Macintosh or Windows editors with the added
        feature of automatic syntax styling. SciTE can hold multiple files in memory at one time but
        only one file will be visible. Rectangular
        blocks of text can be selected in SciTE by holding down the Alt key on Windows or the Ctrl
        key on GTK+ while dragging the mouse over the text. The modifier key used on GTK+
        can be changed with the rectangular.selection.modifier property.
    </p>
    <p>
       There are two panes in SciTE, the editing pane and the output pane. The output pane is
      located either to the right of the editing pane or below it. Initially it is of zero size, but
      it can be made larger by dragging the divider between it and the editing pane. The Options |
      Vertical Split command can be used to move the output pane beneath the editing pane.
    </p>
    <p>
       SciTE can perform commands to compile or run source files with the output from these
      commands directed into the output pane.
    </p>
    <p>
       For example, if <a href="http://www.python.org">Python</a> is installed on the machine, open
      a new document, type:
    </p>
    <blockquote>
<kbd>
print "Hi"
</kbd>
    </blockquote>
    <p>
       as that document's text.
    </p>
    Save the document as printhi.py. <br />
     The document should now appear coloured as SciTE is using the file's extension to decide upon
    the syntax styling to use:
    <blockquote>
        <code>
                <b><font color="#000080">print </font></b>
                <i><font color="#800080">"hi"</font></i>
        </code>
    </blockquote>
    Perform the Tools | Go command.<br />
     The output window will be made visible if it is not already visible and will show:<br />
    <blockquote>
        <code>
                <font color="#0000FF">&gt;python -u printhi.py</font><br />
                hi<br />
                <font color="#0000FF">&gt;Exit code: 0</font>
        </code>
    </blockquote>
    The first blue line is from SciTE showing the command it will use to run the program. The black
    line is the output from running the Python program. The last blue line is from SciTE showing
    that the program has finished and displaying its exit code. An exit code of zero indicates a
    successful run. <br />

    <p>
       SciTE partially understands the error messages produced by Python, GCC, Visual C++, Borland
      C++, PHP and other tools which use the same format as one of these. To see this, add a mistake to
      the Python file by adding a second line to make the file:
    </p>
    <blockquote>
        <code>
        <span style="color:#000080;font-weight:bold;">print </span>
        <span style="color:#800080;font-style:italic;">"hi"</span><br />
        mistake
        </code>
    </blockquote>
    <p>
       Perform the Tools | Go command. The results should look like:
    </p>
    <blockquote>
<pre>
<span style="color:#0000FF">&gt;python -u printhi.py</span>
hi
Traceback (innermost last):
  <span style="color:#FF0000">File "printhi.py", line 2, in ?</span>
    mistake
NameError: mistake
<span style="color:#0000FF">&gt;Exit code: 1</span>
</pre>
    </blockquote>
    <p>
       While it is easy to see where the problem is in this simple case, when a file is larger the
      Tools | Next Message command can be used to view each of the reported errors. Upon performing
      Tools | Next Message, the first error message in the output pane is highlighted with a yellow
      background, and an error indicator is displayed for the appropriate line in the editing pane.
      The caret is moved to this line and the pane is scrolled if needed to show the line. SciTE
      now looks like this:
    </p>
    <img src="PrintHi.png" alt="SciTE after running Python interpreter" />
    <p>
       SciTE understands both the file name and line number parts of error messages in most cases
      so can open another file (such as a header file) if errors were caused by that file. This
      feature may not work where the file name is complicated by containing spaces or ".."
    </p>
    <p>
       If command execution has failed and is taking too long to complete then the Tools | Stop
      Executing command can be used.
    </p>
    <h3 id="CommandSubsystem">
       Command subsystem
    </h3>
    <p>
    Tools can be executed in various modes by SciTE which are called "subsystems". Different
    subsystems are supported on Windows and GTK+. The default subsystem is 0.
    </p>
    <table class="windowsonly" cellpadding="0" cellspacing="0" border="1" summary="Command line commands">
    <thead><tr><td colspan="3">Windows</td></tr></thead>
    <tr><td>0</td><td>console</td><td>Command line programs<br/>Do not use for GUI programs as their windows will not be visible.</td></tr>
    <tr><td>1</td><td>windows</td><td>Programs that create their own windows</td></tr>
    <tr><td>2</td><td>shellexec</td><td>Run using ShellExecute<br />
    A good way to open HTML files and
      similar as it handles this similarly to a user opening the file from the shell.</td></tr>
    <tr><td>3</td><td>lua<br />director</td><td>Internal extension or director extension</td></tr>
    <tr><td>4</td><td>htmlhelp</td><td>Open in HtmlHelp program<br />
	Two part command separated by ! with the first
	part being the topic to search for and the second the name of the help file
    </td></tr>
    <tr><td>5</td><td>winhelp</td><td>Open with WinHelp function<br />
    Two part command similar to subsystem 4</td></tr>
    </table>
    <br />
    <table class="gtkonly" cellpadding="0" cellspacing="0" border="1" summary="Command line commands">
    <thead><tr><td colspan="3">GTK+</td></tr></thead>
    <tr><td>0</td><td>console</td><td>Execute tool and wait for it to finish</td></tr>
    <tr><td>2</td><td>shellexec</td><td>Execute in background</td></tr>
    </table>
    <h3 id="CommandLineArguments">
       Command line arguments
    </h3>
    <p>
       Command line arguments to SciTE include file names, commands and properties.
       Commands and properties are preceded by "-" and are differentiated by the use in
       commands of ':' as the first character that is not '.' or alphabetic.
       Properties use the syntax used in property set files and override any
       properties set in property files. If there is no value given for a property, it is set to 1.
       Double quotes may be placed around arguments that contain spaces but they must be
       placed around the whole argument, not just around a file name, so "-open:x y.txt" works but
       -open:"x y.txt" doesn't.
       On Linux, the standard shell quoting is available.
       The "-p" argument causes SciTE to print the file and then exit.
    </p>
    <p>
	For <span class="windowsonly">Windows</span>:<br />
	The command line arguments "-" and "--" (without the quotes) are special in that they read the
	stdin stream into the last buffer ("-"), or the output pane ("--"))<br />
	The command line argument "-@" (without the quotes) is special in that file names are read from stdin
	and opened.<br />
	<b>Note:</b> when reading stdin into the output pane, when the property split.vertical is 0, the
	output pane is increased to its maximum height.  When the property split.vertical is 1, the output pane is
	increased to approximately half of the screen width.<br />
	<b>Note:</b> If stdin is not redirected, these arguments are effectively ignored.
    </p>
    <div>
       For example,</div>
       <div class="example">
       SciTE "-font.base=font:MS Gothic,size:11" -save.recent ScintillaGTK.cxx
       </div>
       <div>starts SciTE, opens ScintillaGTK.cxx, loads the recent file list, and uses
       11 point MS Gothic as the base font.<br />
       A group of properties can be saved as a property set file (with the extension
       ".properties") and the import command used on the command line:</div>
       <div class="example">
       SciTE "-import c:\os\web_work" SciTEDoc.html
       </div>
       <p>
       A few commands are currently available although this will expand in the future.
       These commands are available:</p>
       <table cellpadding="0" cellspacing="0" border="1" summary="Command line commands">
        <thead>
        <tr><th>Command</th><th>Argument</th></tr>
        </thead>
        <tr><td>close:</td><td></td></tr>
        <tr><td>cwd:</td><td>change working directory</td></tr>
        <tr><td>find:</td><td>search text</td></tr>
        <tr><td>goto:</td><td>line number[,column number]</td></tr>
        <tr><td>open:</td><td>file name</td></tr>
        <tr><td>loadsession:</td><td>file name</td></tr>
        <tr><td>quit:</td><td></td></tr>
        <tr><td>replaceall:</td><td>search text\000replacement text</td></tr>
        <tr><td>saveas:</td><td>file name</td></tr>
       </table>
       <br />
       Commands use C style escape sequences which include:
       <table cellpadding="0" cellspacing="0" border="1"  summary="Command line escape sequences">
        <thead>
        <tr><th>Escape Sequence</th><th>Meaning</th></tr>
        </thead>
        <tr><td>\\</td><td>backslash</td></tr>
        <tr><td>\a</td><td>bell</td></tr>
        <tr><td>\b</td><td>backspace</td></tr>
        <tr><td>\f</td><td>form feed</td></tr>
        <tr><td>\n</td><td>new line</td></tr>
        <tr><td>\r</td><td>carriage return</td></tr>
        <tr><td>\t</td><td>tab</td></tr>
        <tr><td>\v</td><td>vertical tab</td></tr>
        <tr><td>\&lt;ooo&gt;</td><td>octal number specified by 1, 2, or 3 digits</td></tr>
        <tr><td>\x&lt;hh&gt;</td><td>hexadecimal number specified by 2 digits</td></tr>
       </table>
       The following opens /big/icon.txt:<br />
       <div class="example">
       SciTE -open:/big/icon.txt
       </div>
       On Windows, the following opens C:\Program Files\SciTE\SciTEDoc.html
       and goes to the 123rd line:<br />
       <div class="example">
       SciTE "-open:C:\\Program Files\\SciTE\\SciTEDoc.html" -goto:123
       </div>
    <p>
        Command line arguments are evaluated left to right in two phases because
        opening files requires the user interface to be available and there is also a need
        to set some user interface properties before the user interface is displayed.
        The first phase process arguments until just before the first file name would be opened.
        The second phase processes the remaining arguments.
    </p>
    <p>
        So, if you need to perform e.g. a find: or a goto: command on a file, you must put
        the command after the filename, to allow SciTE to open the file before performing the command.
    </p>
	<p>
	For <span class="windowsonly">Windows</span>:<br />
	If any simple file name on the command line matches a directory name, the file open dialog appears - this is dependant upon the property
	"open.dialog.in.file.directory"<br /><br />
	If the property "buffers" is greater than one and the file name matches either a existing file or by means of a wildcard search, one or more files, the
	matching files are loaded up to the property "buffers" count.  Directories are not considered a match in this case<br /><br />
	If the file name is an extension, optionally preceded by a path, and no such simple file name exists, the file open dialog appears, with the given extension as
	the filter.<br /><br />
	If the file name contains no extension, the property "source.default.extensions" is used to provide default extensions to attempt to match the file name to an
	existing file.
	</p>
    <h3 id="Buffers">
       Buffers
    </h3>
    <p>
       SciTE may be configured to use between 1 and 100 buffers each containing a
       file. The default is 1 and this effectively turns off buffers. With more than one buffer,
       the Buffers menu can be used to switch between buffers, either by selecting the
       file name or using the Previous (F6) and Next (Shift+F6) commands.
       A tab is displayed for each buffer in the tab bar although this can be turned off with the
       View | Tab Bar command.
       A tab may be closed by clicking on it with the middle mouse button.
       Setting large numbers of buffers may cause problems as some menus are fixed in length
       and thus files beyond that length may not be accessible.
     </p>
     <p>
       When all the buffers contain files, then opening a new file causes a buffer to be reused
       which may require a file to be saved. In this case an alert is displayed to ensure the user
       wants the file saved.
    </p>
    <h3 id="Sessions">
        Sessions
    </h3>
     <p>
        A session is a list of file names. You can save a complete set of your
        currently opened buffers as a session for fast batch-loading in the
        future.
        Sessions are stored as properties files with the extension ".session".
     </p>
     <p>
        Use File | Load Session and File | Save Session to load/save sessions.
        You can turn on/off "last session autoloading" using SciTE properties
        variable "save.session".
     </p>
     <p>
        If "buffers" variable is set to "0" session management is turned off.
     </p>
     <p>
        Loading previously saved session will close your currently opened
        buffers. However you will not lose your edits, because you will be
        asked to save unsaved buffers first.
     </p>
     <p>
        Opening a specific file from command line overrides "save.session"
        variable state. When you start SciTE loading a specific file from
        command line last session will not restore even if "save.session"
        variable is set to "1". This makes "save.session" safe to use - you
        will never open a couple of files when you are trying to open just
        one, specific file.
     </p>
     <p>
        By setting "session.bookmarks" and "session.folds" variables bookmarks
        and folding states of the currently opened buffers are saved in session
        files and restored when sessions are loaded.
     </p>
    <h3 id="Languages">
       Languages understood by SciTE
    </h3>
    <p>
       SciTE currently is able to syntax style these languages (* denotes
       support for folding):
    </p>
    <ul>
        <li>Abaqus*</li>
        <li>Ada</li>
        <li>ANS.1 MIB definition files*</li>
        <li>APDL</li>
        <li>Assembler (NASM, MASM)</li>
        <li>Asymptote*</li>
        <li>AutoIt*</li>
        <li>Avenue*</li>
        <li>Batch files (MS-DOS)</li>
        <li>Baan*</li>
        <li>Bash*</li>
        <li>BlitzBasic*</li>
        <li>Bullant*</li>
        <li>C/C++/C#*</li>
        <li>Clarion*</li>
        <li>cmake*</li>
        <li>conf (Apache)*</li>
        <li>CSound*</li>
        <li>CSS*</li>
        <li>D</li>
        <li>diff files*</li>
        <li>E-Script*</li>
        <li>Eiffel*</li>
        <li>Erlang*</li>
        <li>Flagship (Clipper / XBase)*</li>
        <li>Flash (ActionScript)*</li>
        <li>Fortran*</li>
        <li>Forth*</li>
        <li>GAP*</li>
        <li>Gettext</li>
        <li>Haskell</li>
        <li>HTML*</li>
        <li>HTML with embedded JavaScript, VBScript, PHP and ASP*</li>
        <li>Gui4Cli*</li>
        <li>IDL - both MSIDL and XPIDL*</li>
        <li>INI, properties* and similar</li>
        <li>InnoSetup*</li>
        <li>Java*</li>
        <li>JavaScript*</li>
        <li>LISP*</li>
        <li>LOT*</li>
        <li>Lout*</li>
        <li>Lua*</li>
        <li>Make</li>
        <li>Matlab*</li>
        <li>Metapost*</li>
        <li>MMIXAL</li>
        <li>MSSQL</li>
        <li>nnCron</li>
        <li>NSIS*</li>
        <li>Objective Caml*</li>
        <li>Opal</li>
        <li>Octave*</li>
        <li>Pascal/Delphi*</li>
        <li>Perl, most of it except for some ambiguous cases*</li>
        <li>PL/M*</li>
        <li>Progress*</li>
        <li>PostScript*</li>
        <li>POV-Ray*</li>
        <li>PowerBasic*</li>
        <li>PowerShell*</li>
        <li>PureBasic*</li>
        <li>Python*</li>
        <li>R*</li>
        <li>Rebol*</li>
        <li>Ruby*</li>
        <li>Scheme*</li>
        <li>scriptol*</li>
        <li>Specman E*</li>
        <li>Spice</li>
        <li>Smalltalk</li>
        <li>SQL and PLSQL</li>
        <li>TADS3*</li>
        <li>TeX and LaTeX</li>
        <li>Tcl/Tk*</li>
        <li>VB and VBScript*</li>
        <li>Verilog*</li>
        <li>VHDL*</li>
        <li>XML*</li>
        <li>YAML*</li>
    </ul>
    <p>
       Running and building commands for some of these languages have been set up but should be
      checked as they will have to be modified to work for many people.
    </p>
    <p>
      To keep menus to a reasonable length some languages are included but have been commented
      out in global options. These should be enabled by removing the comment character '#'.
    </p>
    <p>
      Language settings are determined from the file extension but this can be changed
      by selecting another language from the Language menu. The language menu can be
      changed with the menu.language property.
    </p>
    <h3 id="FindReplace">
       Find and Replace
    </h3>
    <p>
       Either dialogs or strips may be used for find and replace, with dialogs being the default.
       Strips are similar to find in web browsers, appearing at the bottom of the
       window and are smaller and less distracting than dialogs.
       They are specified with the find.use.strip and replace.use.strip properties.
    </p>
    <p>
       SciTE has options to allow searching for words, regular expressions,
       matching case, in the reverse direction, wrapping around the end of the
       document.
       C style backslash escapes which are listed in the command line
       arguments section, may be used to search and replace control
       characters.
       Replacements can be made individually, over the current selection or
       over the whole file. When regular expressions are used tagged
       subexpressions can be used in the replacement text.
       Regular expressions will not match across a line end.
    </p>
    <p>
       SciTE supports
       <a href="SciTERegEx.html">basic regular expressions</a>
       with tagging.
    </p>
    <p>
       On Windows, pressing Shift+Enter when the focus is in a text entry field will search
       in the opposite of the current direction, so will normally search backwards.
    </p>
    <h3 id="Keyboard">
       Keyboard commands
    </h3>
    <p>
       Keyboard commands in SciTE mostly follow common Windows and GTK+ conventions.
       All movement keys (arrows, page up/down, home and end)
       allow to extend or reduce a stream selection when holding the Shift key,
       and a rectangular selection when holding the Shift and Alt keys.
       Some keys may not be available with some national keyboards or because
       they are taken by the system such as by a window manager on GTK+.
       The user.shortcuts setting may be used to assign a key to a function.
       Note that Home key behaviour is changed by the vc.home.key option.
       Keyboard equivalents of menu commands are listed in the menus.
       Some less common commands with no menu equivalent are:
    </p>
<table cellpadding="0" cellspacing="0" border="1" summary="Keyboard commands">
      <tr>
        <td>Magnify text size.</td><td>Ctrl+Keypad+</td>
      </tr>
      <tr>
        <td>Reduce text size.</td><td>Ctrl+Keypad-</td>
      </tr>
      <tr>
        <td>Restore text size to normal.</td><td>Ctrl+Keypad/</td>
      </tr>
      <tr>
        <td>Cycle through recent files.</td><td>Ctrl+Tab</td>
      </tr>
      <tr>
        <td>Indent block.</td><td>Tab</td>
      </tr>
      <tr>
        <td>Dedent block.</td><td>Shift+Tab</td>
      </tr>
      <tr>
        <td>Delete to start of word.</td><td>Ctrl+BackSpace</td>
      </tr>
      <tr>
        <td>Delete to end of word.</td><td>Ctrl+Delete</td>
      </tr>
      <tr>
        <td>Delete to start of line.</td><td>Ctrl+Shift+BackSpace</td>
      </tr>
      <tr>
        <td>Delete to end of line.</td><td>Ctrl+Shift+Delete</td>
      </tr>
      <tr>
        <td>Go to start of document.</td><td>Ctrl+Home</td>
      </tr>
      <tr>
        <td>Extend selection to start of document.</td><td>Ctrl+Shift+Home</td>
      </tr>
      <tr>
        <td>Go to start of display line.</td><td>Alt+Home</td>
      </tr>
      <tr>
        <td>Go to end of document.</td><td>Ctrl+End</td>
      </tr>
      <tr>
        <td>Extend selection to end of document.</td><td>Ctrl+Shift+End</td>
      </tr>
      <tr>
        <td>Go to end of display line.</td><td>Alt+End</td>
      </tr>
      <tr>
        <td>Expand or contract a fold point.</td><td>Ctrl+Keypad*</td>
      </tr>
      <tr>
        <td>Select to next bookmark.</td><td>Alt+F2</td>
      </tr>
      <tr>
        <td>Select to previous bookmark.</td><td>Alt+Shift+F2</td>
      </tr>
      <tr>
        <td>Find selection.</td><td>Ctrl+F3</td>
      </tr>
      <tr>
        <td>Find selection backwards.</td><td>Ctrl+Shift+F3</td>
      </tr>
      <tr>
        <td>Scroll up.</td><td>Ctrl+Up</td>
      </tr>
      <tr>
        <td>Scroll down.</td><td>Ctrl+Down</td>
      </tr>
      <tr>
        <td>Line cut.</td><td>Ctrl+L</td>
      </tr>
      <tr>
        <td>Line copy.</td><td>Ctrl+Shift+T</td>
      </tr>
      <tr>
        <td>Line delete.</td><td>Ctrl+Shift+L</td>
      </tr>
      <tr>
        <td>Line transpose with previous.</td><td>Ctrl+T</td>
      </tr>
      <tr>
        <td>Selection duplicate.</td><td>Ctrl+D</td>
      </tr>
      <tr>
        <td>Find matching preprocessor conditional, skipping nested ones.</td><td>Ctrl+K</td>
      </tr>
      <tr>
        <td>Select to matching preprocessor conditional.</td><td>Ctrl+Shift+K</td>
      </tr>
      <tr>
        <td>Find matching preprocessor conditional backwards, skipping nested ones.</td><td>Ctrl+J</td>
      </tr>
      <tr>
        <td>Select to matching preprocessor conditional backwards.</td><td>Ctrl+Shift+J</td>
      </tr>
      <tr>
        <td>Previous paragraph. Shift extends selection.</td><td>Ctrl+[</td>
      </tr>
      <tr>
        <td>Next paragraph. Shift extends selection.</td><td>Ctrl+]</td>
      </tr>
      <tr>
        <td>Previous word. Shift extends selection.</td><td>Ctrl+Left</td>
      </tr>
      <tr>
        <td>Next word. Shift extends selection.</td><td>Ctrl+Right</td>
      </tr>
      <tr>
        <td>Previous word part. Shift extends selection</td><td>Ctrl+/</td>
      </tr>
      <tr>
        <td>Next word part. Shift extends selection.</td><td>Ctrl+\</td>
      </tr>
      <tr>
        <td>Rectangular block selection.</td><td>Alt+Shift+Movement</td>
      </tr>
      <tr>
        <td>Extend rectangular selection to start of line.</td><td>Alt+Shift+Home</td>
      </tr>
      <tr>
        <td>Extend rectangular selection to end of line.</td><td>Alt+Shift+End</td>
      </tr>
    </table>
    <p class="windowsonly">
       On Windows, a search can be performed in the opposite direction by
       using Shift+Enter in the Find or Replace strips or dialogs.
    </p>
    <h3 id="Abbreviations">
       Abbreviations
    </h3>
    <p>
       To use an abbreviation, type it and use the Expand Abbreviation
       command or the Ctrl+B key. The abbreviation is replaced by an
       expansion defined in the Abbreviations file. You can open the
       Abbreviations file with a command in the Options menu and
       add abbreviations. There is a default abbreviations file but a different
	    abbreviations file can be set for particular file extensions.
    </p>
    <p>
       Each line in the files looks like "abbreviation=expansion".<br />
       The abbreviations names can have any character (except perhaps control chars,
       surely for CR and LF), including high Ascii chars (accented chars).<br />
       Names have properties files limits: they cannot start with sharp (#) or space or tab
       (but can have spaces inside); and they cannot have '=' character inside.<br />
       Abbreviations names are limited to 32 characters. It is probably enough for
       <em>abbreviations</em>...<br />
    </p>
    <p>
       An expansion may contain new line characters indicated by '\n' and
       a caret position indicated by the '|' character. To include a literal '|'
       character, use '||'.<br />
       Some simple examples are included in the distributed Abbreviations file.<br />
       When expanding, the names don't need to be separated from the previous text.
       Ie. if you define 'é' as '&amp;eacute;', you can expand it inside a word.<br />
       When multiple abbreviation names match, the longest matching name will be expanded.
    </p>
    <h3 id="Folding">
       Folding
    </h3>
    <p>
       SciTE supports folding for many languages (see the list of languages
       understood by SciTE for more information.) Fold points are based upon
       indentation for Python and on counting braces for the other languages.
    </p>

    <p>
       The fold point markers (in the fold margin) can be clicked to expand and
       contract folds. Normal clicking does not alter the fold state of child fold
       points; naturally the children are hidden when the parent fold is
       contracted, but when the parent is expanded again, each child is still
       folded or not, as before.
    </p>

    <p>
       Ctrl+Click on a fold point toggles it and performs the same operation on
       all children.
    </p>

    <p>
       Shift+Click on a fold point does not toggle that fold, it expands all the
       child folds.
    </p>

    <p>
       Ctrl+Shift+Click in the fold margin expands or contracts all the top level
       folds.
       "Toggle all folds" in the View menu does the same; it toggles only
       top-level folds.
    </p>

    <p>
       Tip:
       To open a large code block with all its children folded, fold it with
       Ctrl+Click, then open it with a normal click. Then on opening a child fold,
       you will see that the grandchild folds are still closed; if you want those
       'grandchild' folds open, Shift+Click the child fold.
    </p>
    <h3 id="PropertiesFile">
       Properties file
    </h3>
    <p>
       Much of SciTE's behaviour can be changed by editing the properties files.
    </p>
    <p>
       There are four properties files used:</p>
       <ul>
       <li>Local properties file called "SciTE.properties" which may be
       present in the same directory as the file being edited.</li>
       <li>Directory properties file called "SciTEDirectory.properties" which may be
       present in the same or in a parent directory as the file being edited.</li>
       <li>User properties file called "SciTEUser.properties" on Windows
       and ".SciTEUser.properties" on GTK+</li>
       <li>Global properties file called "SciTEGlobal.properties"</li>
       </ul>
    <p>
      Settings in the local properties file override those in the directory properties file
	   which overrides those in the user properties file which override those
      in the global properties files. Environment variables are also available as properties and these
      are overridden by an explicit setting in one of the properties files.
    </p>
	<p>
      The directory properties file can be used as project options file where user commands and
      compile, build commands should work in the same manner in subdirectories of a project. The
      benefit is that local properties files in subdirectories can be replaced by one properties file
      which is located at the root of the project.
      The evalution of the directory properties file is disabled by default and must be enabled by
      setting the variable properties.directory.enable to 1 in the user or global properties file.
    </p>
    <p>
      The user properties file is intended for customisation by the user,
      leaving the global properties file to contain the default options distributed with SciTE.
      The main use of the local properties files is to change the effects of the
      Compile, Build and Go commands for the files in a directory. For example, I use the javac
      compiler from the Java Development Kit for most work, so SciTEGlobal.properties sets the
      command for compiling .java files to "javac". If I want to use the jvc compiler for the files
      in one directory, then the SciTE.properties file in that directory contains an entry setting
      the command to "jvc".
    </p>
    <p>
     On Windows, the global properties file is located in the directory of the executable.
      The user properties file is looked for in the user profile directory as set in the
      USERPROFILE environment variable, or in the directory of the executable if
      USERPROFILE is not set.
      For GTK+ the user properties file is found in the user's home directory and the global
      properties in a directory set at build time - normally /usr/share/scite.
      If the "SciTE_HOME" environment variable is set on either Windows or GTK+ then it is where
      both the global and user properties files are found.
    </p>
    <p>
       There are commands in the Options menu for opening each of the properties files.
    </p>
    <p>
       The files are in approximately the same format as Java properties files which have a simple
      text format. Lines that start with '#' or that are completely blank are comments. Other lines
      are of the form
    </p>
    <p>
       variable=value
    </p>
    <p>
       For long values, a '\' character at the end of the line continues that value on the next
      line. Space characters are significant so <span class="example">x&nbsp;=1</span> defines a variable called
      "x&nbsp;".
      Values may include the values of other variables by using $(variablename). There are
      some variables set by the environment to access the name of the current file as well:
    </p>
       <table cellpadding="0" cellspacing="0" border="1" summary="Variables set by the environment for use in property files">
        <thead>
        <tr><th>Name</th><th>Meaning</th></tr>
        </thead>
               <tr id='property-FilePath'><td>FilePath</td><td>full path of the current file</td></tr>
               <tr id='property-FileDir'><td>FileDir</td><td>directory of the current file without a trailing slash</td></tr>
               <tr id='property-FileName'><td>FileName</td><td>base name of the current file</td></tr>
               <tr id='property-FileExt'><td>FileExt</td><td>extension of the current file</td></tr>
               <tr id='property-FileNameExt'><td>FileNameExt</td><td>$(FileName).$(FileExt)</td></tr>
               <tr id='property-Language'><td>Language</td><td>name of the lexer used for the current file</td></tr>
               <tr id='property-SessionPath'><td>SessionPath</td><td>full path of the current session</td></tr>
               <tr id='property-CurrentSelection'><td>CurrentSelection</td><td>value of the currently selected text</td></tr>
               <tr id='property-CurrentWord'><td>CurrentWord</td><td>value of word which the caret is within or near</td></tr>
               <tr id='property-Replacements'><td>Replacements</td><td>number of replacements made by last Replace command</td></tr>
               <tr id='property-SelectionStartColumn'><td>SelectionStartColumn</td><td>column where selection starts</td></tr>
               <tr id='property-SelectionStartLine'><td>SelectionStartLine</td><td>line where selection starts</td></tr>
               <tr id='property-SelectionEndColumn'><td>SelectionEndColumn</td><td>column where selection ends</td></tr>
               <tr id='property-SelectionEndLine'><td>SelectionEndLine</td><td>line where selection ends</td></tr>
               <tr id='property-CurrentMessage'><td>CurrentMessage</td><td>most recently selected output pane message</td></tr>
               <tr id='property-SciteDefaultHome'><td>SciteDefaultHome</td><td>directory in which the Global Options file is found</td></tr>
               <tr id='property-SciteUserHome'><td>SciteUserHome</td><td>directory in which the User Options file is found</td></tr>
               <tr id='property-SciteDirectoryHome'><td>SciteDirectoryHome</td><td>directory in which the Directory Options file is found</td></tr>
               <tr id='property-APIPath'><td>APIPath</td><td>list of full paths of API files from api.<i>filepattern</i></td></tr>
               <tr id='property-AbbrevPath'><td>AbbrevPath</td><td>full path of abbreviations file</td></tr>
        </table>
    <p>
       Some features use file name patterns to see which variable to use. For example, the lexer
      variable can be specialised for a particular file, or a group of files based upon wildcard
      matching so:<br />
       <b>lexer.makefile=makefile</b> indicates that the lexer called "makefile" should be used on
      files called "makefile".<br />
       <b>lexer.*.cxx=cpp</b> indicates that the lexer called "cpp" should be used on files with a
      "cxx" extension.<br />
       Variable substitution is available on the left hand side of file pattern assignments and
      look like this:<br />
       <b>file.patterns.html=*.html;*.htm;*.asp;*.shtml</b><br />
       <b>command.go.$(file.patterns.html)=file://$(FilePath)</b>
    </p>
    <p>
    Wildcard matching only works where the wildcard is at the start of a file specification, so "*.mak" will match "proj.mak" but
    "Makefile*" will not match "Makefile.in".
    </p>
    <p>
    Properties files are not treated as having a particular encoding, however individual property values
    may be treated as having an encoding. For file names, commands, and user interface text, this is
    UTF-8 so it may be easier to edit properties files as UTF-8 by inserting a coding cookie as explained later.
    Other properties may be treated as byte sequences (like word.characters.<i>filepattern</i>) or in an implicit
    encoding (such as keywords.<i>filepattern</i> matching the document encoding) so that it may be better to
    edit these settings using a non-UTF-8 encoding. Where both UTF-8 and non-UTF-8 values are wanted,
    two files can be used with different encodings and an import statement to include one in the other.
    </p>
    <h3 id="ImportAndConditional">
       Importing properties files and conditional logic
    </h3>
    <p>
      <a name="property-import"></a>
       The 'import' statement includes a properties file as if the text were
       inline at that point. The imported properties file
       must be in the same directory as the current file and a properties
       extension is assumed. Therefore a "import Lua" statement in
       c:\os\scite\bin\SciTEGlobal.properties will import
       c:\os\scite\bin\Lua.properties.
    </p>
    <p>
       All of the properties files in a directory can be imported with "import *".
       This does not import generic properties files like user properties or abbreviations.
       The set of files that are imported can be controlled with the imports.include and imports.exclude
       properties.
    </p>
    <p>
      <a name="property-if"></a>
      The 'if' statement takes one argument which is a
      symbol that may be defined earlier in this property set file or in a base
      property set. If the symbol evaluates to '0' then the test fails. An empty
      string or not present symbol evaluates to 0. Into the very top property set
      is inserted one of 'PLAT_GTK' with value '1',
      'PLAT_WIN' with value '1', or 'PLAT_MAC' with value '1'.
      For both PLAT_GTK and PLAT_MAC, 'PLAT_UNIX' is inserted with value '1'.
      If the test succeeds then following indented statements are executed. When a
      non-indented statement is found the if clause is finished. Only simple set
      statements are allowed in if clauses. The evaluation of if statements occurs
      at read time, not at evaluation time.
    </p>
    <h3 id="Parameters">
       Command parameters and prompting
    </h3>
    <p>
      SciTE has 4 properties $(1) .. $(4) which can be used to run commands with
      changeable parameters. To set the parameter values, use the View | Parameters
      command to view the modeless Parameters dialog which shows the current values
      of these parameters and allows setting new values. The accelerator keys for the main
      window remain active while this dialog is displayed, so it can be used to rapidly run
      a command several times with different parameters. Alternatively, a command can be
      made to display the modal Parameters dialog when executed by starting the
      command with a '*' which is otherwise ignored. If the modeless Parameters dialog is
      already visible, then the '*' is ignored.
    </p>
    <h3 id="Encodings">
       Encodings
    </h3>
    <p>
      SciTE will automatically detect the encoding scheme used for Unicode files that
      start with a Byte Order Mark (BOM).
      The UTF-8 and UTF-16 encodings are recognised including both Little Endian and
      Big Endian variants of UTF-16.
    </p>
    <p>
      UTF-8 files will also be recognised when they contain a coding cookie on one of the
      first two lines. A coding cookie looks similar to "coding: utf-8" ("coding" followed by ':'
      or '=', optional whitespace, optional quote, "utf-8") and is normally contained in
      a comment:</p>
      <div class="example"># -*- coding: utf-8 -*-</div>
      For XML there is a declaration:<br />
      <div class="example">&lt;?xml version='1.0' encoding='utf-8'?&gt;</div>
    <p>
      For other encodings set the code.page and character.set properties.
    </p>
    <h3 id="DefinedVariables">
      <a name="property-"></a>
       Defined variables in properties files
    </h3>
    <p>
      Some properties are only available on
      <span class="windowsonly">Windows</span>,
      <span class="gtkonly">GTK+</span>, or.
      <span class="osxonly">OS X</span>.
    </p>
    <table cellpadding="1" cellspacing="0" border="1" summary="Defined variables in property files">
      <tr id='property-position.left'>
        <td>
          <a name='property-position.top'></a><a name='property-position.width'></a><a name='property-position.height'></a><a name='property-position.maximize'></a>
          position.left<br />
           position.top<br />
           position.width<br />
           position.height<br />
           position.maximize
        </td>
        <td>
          Set the initial window size and position. If these are omitted then the
          environment's defaults are used. If the width or height are -1 or the
          position.maximize property is set then the window is maximised.
        </td>
      </tr>
      <tr class="windowsonly" id='property-position.tile'>
        <td>
          position.tile
        </td>
        <td>
          If there is another copy of SciTE open, set the initial window position to be
          with the left side at position.left + position.width so that most of the time
          you can see both copies at once without overlap.
          Works nicely if position.left set to 0 and position.width set to half of the
          screen width.
        </td>
      </tr>
      <tr id='property-buffers'>
        <td>
          buffers
        </td>
        <td>
          Set to a number between 1 and 100 to configure that many buffers.
        Values outside this range are clamped to be within the range.
        The default is 1 which turns off UI features concerned with buffers.<br />
        This value is read only once, early in the startup process and only from the
        global properties files. So after changing it, restart SciTE to see the effect.
        </td>
      </tr>
      <tr id='property-buffers.zorder.switching'>
        <td>
        buffers.zorder.switching
        </td>
        <td>
          This setting chooses the ordering of buffer switching when Ctrl+Tab pressed.
        Set to 1, the buffers are selected in the order of their previous selection otherwise
        they are chosen based on the buffer number.
        </td>
      </tr>
      <tr id='property-are.you.sure'>
        <td>
          <a name='property-are.you.sure.for.build'></a>
          are.you.sure<br />
           are.you.sure.for.build
        </td>
        <td>
          The classic GUI question. Normally, when SciTE is about to close a file which has unsaved
          edits it asks this annoying question. To turn off the question, set are.you.sure to 0 and
          files will be automatically saved without bothering the user. To abandon edits to a file
          use the New command. New always asks "Are you sure?" giving an opportunity to not save
          the file.<br />
           When running or building a file, its most likely that you want the file to be saved
          first. To enable a confirmation dialog for performing Compile, Build or Go commands, set
          are.you.sure.for.build=1.
        </td>
      </tr>
      <tr id='property-save.all.for.build'>
        <td>
           save.all.for.build
        </td>
        <td>
          SciTE normally saves the current buffer when performing a Compile, Build, or Go
	  command. To save all buffers set save.all.for.build=1
        </td>
      </tr>
      <tr id='property-view.whitespace'>
        <td>
          <a name='property-view.indentation.whitespace'></a>
          view.whitespace<br />
        view.indentation.whitespace
        </td>
        <td>
          Setting view.whitespace to 1 makes SciTE start up with whitespace visible.<br />
          Setting view.indentation.whitespace to 0 hides visible whitespace inside indentation.
        </td>
      </tr>
      <tr id='property-whitespace.fore'>
        <td>
          <a name='property-whitespace.back'></a>
          whitespace.fore<br />
        whitespace.back
        </td>
        <td>
        Sets the colours used for displaying all visible whitespace, overriding any styling
        applied by the lexer.
        </td>
      </tr>
      <tr id='property-view.indentation.guides'>
        <td>
          <a name='property-view.indentation.examine'></a><a name='property-highlight.indentation.guides'></a>
          view.indentation.guides<br />
          view.indentation.examine<br />
          view.indentation.examine.<i>filepattern</i><br />
          highlight.indentation.guides
        </td>
        <td>
          Setting view.indentation.guides to 1 displays dotted vertical lines within indentation white
          space every indent.size columns.<br />
          Setting view.indentation.examine to 1 to display guides within real indentation whitespace only,
	  2 according to the next non-empty line (good for Python) or 3 according to both the next and
	  previous non-empty lines (good for most languages).<br />
          Setting highlight.indentation.guides to 1 highlights the indentation guide associated with a
          brace when that brace is highlighted.
        </td>
      </tr>
       <tr id='property-view.eol'>
        <td>
          view.eol
        </td>
        <td>
          Setting this to 1 makes SciTE display the characters that make up line ends. This looks
          similar to (CR), (LF), or (CR)(LF). This is useful when using files created on another
          operating system with software that is picky about line ends.
        </td>
      </tr>
      <tr id='property-eol.mode'>
        <td>
          eol.mode
        </td>
        <td>
          The default EOL mode (characters that make up line ends)
          depends on your platform.
          You can overwrite this behaviour by setting the property to
          <div class="example">
  LF   for UNIX and OS X format<br />
  CR   for Macintosh format prior to OS X<br />
  CRLF for DOS/Windows format</div>
        </td>
      </tr>
      <tr id='property-eol.auto'>
        <td>
          eol.auto
        </td>
        <td>
          This setting overrides the eol.mode value and chooses the end of
          line character sequence based on the current contents of the file
          when it is opened. The line ending used the most in the file is chosen.
        </td>
      </tr>
      <tr id='property-blank.margin.left'>
        <td>
          <a name='property-blank.margin.right'></a>
          blank.margin.left<br />
           blank.margin.right
        </td>
        <td>
          There is a blank margin on both sides of the text. It is drawn in the background colour
          of default text. This defaults to one pixel for both left and right sides but may be
          altered with these settings.
        </td>
      </tr>
      <tr id='property-margin.width'>
        <td>
          margin.width
        </td>
        <td>
          Setting this to a number makes SciTE display a selection margin to the left of the text.
          The value is the number of pixels wide the selection margin should be. Line markers are
          displayed in the selection margin area.
        </td>
      </tr>
      <tr class="windowsonly" id='property-full.screen.hides.menu'>
        <td>
          full.screen.hides.menu
        </td>
        <td>
        Setting this to 1 hides the menu bar when the Full Screen command is used on
        Windows.
        On GTK+ the menu is always visible.
        </td>
      </tr>
      <tr class="windowsonly" id='property-minimize.to.tray'>
        <td>
          minimize.to.tray
        </td>
        <td>
        Setting this to 1 minimizes SciTE to the system tray rather than to the task bar.
        </td>
      </tr>
      <tr id='property-line.margin.visible'>
        <td>
          <a name='property-line.margin.width'></a>
          line.margin.visible<br />
          line.margin.width
        </td>
        <td>
          SciTE is able to display a column of line numbers to the left of the selection
          margin.  Setting line.margin.visible to 1 makes this column visible at startup.
          The line.margin.width property controls how much space is reserved for the line
          numbers, in terms of the number of digits that can be displayed.  To specify that
          the margin should expand if needed to accomodate larger line numbers, add a '+'
          after the number of digits, e.g. <span class="example">line.margin.width=3+</span>.
        </td>
      </tr>
      <tr id='property-tabbar.visible'>
        <td>
          tabbar.visible
        </td>
        <td>
          Setting tabbar.visible to 1 makes the tab bar visible at start up.
          The buffers property must be set to a value greater than 1 for this option to work.
        </td>
      </tr>
      <tr id='property-tabbar.hide.one'>
        <td>
          tabbar.hide.one
        </td>
        <td>
          Setting tabbar.hide.one to 1 hides the tab bar until there is more than one tab.
        </td>
      </tr>
      <tr class="windowsonly" id='property-tabbar.multiline'>
        <td>
        tabbar.multiline
        </td>
        <td>
          Setting tabbar.multiline uses multiple lines for the tab bar
        </td>
      </tr>
      <tr id='property-toolbar.visible'>
        <td>
          toolbar.visible
        </td>
        <td>
          Setting this to 1 makes the tool bar visible at start up.
        </td>
      </tr>
      <tr class="gtkonly" id='property-toolbar.usestockicons'>
        <td>
          toolbar.usestockicons
        </td>
        <td>
          SciTE has a built-in icon set for the toolbar, setting this to 1 makes
	SciTE more integrated in the GNOME desktop by using the icons
	provided by the current theme used in GNOME.
        </td>
      </tr>
      <tr class="gtkonly" id='property-pathbar.visible'>
        <td>
          pathbar.visible
        </td>
        <td>
          The path bar is a line of text under the tab bar showing the full path of the currently selected tab.
	Setting pathbar.visible to 1 makes the path bar visible on GTK+.
        </td>
      </tr>
      <tr id='property-undo.redo.lazy'>
        <td>
          undo.redo.lazy
        </td>
        <td>
          Setting this to 1 changes the technique used to determine when to enable or disable
          tool bar buttons to be less accurate. This may improve performance on slow machines.
        </td>
      </tr>
      <tr id='property-statusbar.visible'>
        <td>
          statusbar.visible
        </td>
        <td>
          Setting this to 1 makes the status bar visible at start up.
        </td>
      </tr>
      <tr id='property-statusbar.number'>
        <td>
          <a name='property-statusbar.text'></a>
          statusbar.number<br />
          statusbar.text.<i>number</i>
        </td>
        <td>
        The statusbar.text.1 option defines the information displayed in the status bar
        by default on all platforms.
        Property values may be used in this text using the $() syntax.
          Commonly used properties are: ReadOnly, EOLMode, BufferLength,
          NbOfLines (in buffer), SelLength (chars), SelHeight (lines).
          Extra properties defined for the status bar are LineNumber, ColumnNumber, and
          OverType which is either "OVR" or "INS" depending on the overtype status.
          You can also use file properties, which, unlike those above, are not updated
          on each keystroke: FileName or FileNameExt, FileDate and FileTime and
          FileAttr. Plus CurrentDate and CurrentTime.<br />
          On Windows only, further texts may be set as statusbar.text.2 .. and these may be
          cycled between by clicking the status bar.<br />
          The statusbar.number option defines how many texts are to be cycled through.
        </td>
      </tr>
      <tr id='property-buffered.draw'>
        <td>
          buffered.draw
        </td>
        <td>
          Setting this to 0 rather than the default 1 makes SciTE draw output directly to the
          screen rather than into a buffer bitmap first and then to the screen. Buffered drawing
          flickers less but is slower.
        </td>
      </tr>
      <tr id='property-two.phase.draw'>
        <td>
          two.phase.draw
        </td>
        <td>
        Two phase drawing is a better but slower way of drawing text.
        In single phase drawing each run of characters in one style is drawn along with
        its background.
        If a character overhangs the end of a run, such as in "<i>V</i>_" where the
        "<i>V</i>" is in a different style from the "_", then this can cause the right hand
        side of the "<i>V</i>" to be overdrawn by the background of the "_" which
        cuts it off. Two phase drawing
        fixes this by drawing all the backgrounds first and then drawing the text in
        transparent mode. Two phase drawing may flicker more than single phase
        unless buffered drawing is on. The default is for drawing to be two phase.
        </td>
      </tr>
      <tr class="windowsonly" id='property-technology'>
        <td>
          technology
        </td>
        <td>
        On Windows Vista or newer, this can be set to 1 to use the Direct2D and DirectWrite APIs
        for higher quality antialiased drawing. The default is 0.
        </td>
      </tr>
      <tr id='property-load.on.activate'>
        <td>
          <a name='property-save.on.deactivate'></a>
          load.on.activate<br />
           save.on.deactivate
        </td>
        <td>
          The load.on.activate property causes SciTE to check whether the current file has been
          updated by another process whenever it is activated. This is useful when another editor
          such as a WYSIWYG HTML editor, is being used in conjunction with SciTE.<br />
           The save.on.deactivate property causes SciTE to save the file whenever the SciTE
          application loses focus. This is useful when developing web pages and you want to often
          check the appearance of the page in a browser.
        </td>
      </tr>
       <tr id='property-are.you.sure.on.reload'>
         <td>
          are.you.sure.on.reload
        </td>
        <td>
          When both this and load.on.activate are set to 1, SciTE will ask if you really want to
          reload the modified file, giving you the chance to keep the file as it is. By default this
          property is disabled, causing SciTE to reload the file without bothering you.
        </td>
      </tr>
      <tr id='property-save.on.timer'>
        <td>
           save.on.timer
        </td>
        <td>
          The save.on.timer property causes SciTE to save modified files whenever there have been no
	  modifications for the number of seconds specified by the property.
	  When set to 0, the default, this feature is disabled and files are not automatically saved.
        </td>
      </tr>
      <tr id='property-reload.preserves.undo'>
        <td>
          reload.preserves.undo
        </td>
        <td>
          When set to 1, reloading a file does not delete all the undo history. This is useful
          when load.on.activate is used in conjunction with filter commands.
        </td>
      </tr>
      <tr id='property-check.if.already.open'>
        <td>
           check.if.already.open
        </td>
        <td>
	This option allows opening files in an existing instance of SciTE rather than
	always opening a new instance.
	When this option is set and SciTE is started, it checks to see if
	there are any other instances of SciTE open. If there is, another
	instance is asked to open the file and become active and the new
	instance exits.
	On Windows, the instance with the Options | Open Files Here
	menu item checked opens the file.
	On GTK+, an arbitrary instance opens the file.
        </td>
      </tr>
      <tr id='property-read.only'>
        <td>
           read.only
        </td>
        <td>
        When this option is set then opened documents are initially read only.
        New files are not affected by this setting.
        </td>
      </tr>
      <tr id='property-background.open.size'>
        <td>
          <a name='property-background.save.size'></a>
	background.open.size<br />
	background.save.size
        </td>
        <td>
          This setting controls whether files are opened and saved without blocking the user interface
	while they are being read or written.
	Files larger than the given size in bytes will be read or written in the background while
	smaller files will be read or written directly and SciTE will not respond until the file access is completed.
	The default value is -1 allows background processing for all files.
	For saving, the size used is the in-memory size in bytes which will differ from the on-disk size
	when the UTF-16 encoding is used.
        </td>
      </tr>
      <tr class="windowsonly" id='property-temp.files.sync.load'>
        <td>
          temp.files.sync.load
        </td>
        <td>
          Files dropped on SciTE on Windows are normally opened asynchronously
	as there may be a long list. However, files dragged from some applications
	such as 7-Zip may only exist for a moment in the temporary directory and
	be deleted once the drop has occurred.<br />
	Setting this to 1 makes SciTE open dropped files in the temporary directory
	immediately.
        </td>
      </tr>
      <tr id='property-quit.on.close.last'>
        <td>
           quit.on.close.last
        </td>
        <td>
        If this option is set, SciTE will close when its last buffer has been
        closed, e.g. with File/Close.  (By default, if this option is not set,
        SciTE will remain open and will create a new blank document when its
        last buffer is closed.)
        </td>
      </tr>
      <tr id='property-highlight.current.word'>
        <td>
           highlight.current.word
        </td>
        <td>
	When set to 1, all occurrences of the selected word are highlighted with the
	colour defined by highlight.current.word.colour. By default, this option is disabled. (See indicators.alpha and indicators.under)
        </td>
      </tr>
      <tr id='property-highlight.current.word.colour'>
        <td>
          <a name='property-highlight.current.word.by.style'></a>
	   highlight.current.word.colour<br />
	   highlight.current.word.by.style
        </td>
        <td>
	The option highlight.current.word.colour defines the colour of highlight.
	The default value is #A0A000.<br />
	If the option highlight.current.word.by.style is set, then only words with the same style
        are highlighted (e.g. if you select this word in a comment, then only occurrences of words in
	comments are selected).
        </td>
      </tr>
      <tr class="gtkonly" id='property-rectangular.selection.modifier'>
        <td>
           rectangular.selection.modifier
        </td>
        <td>
        On GTK+, the modifier key used to make rectangular selections can be set with this
        property. Valid options are 2 (Ctrl), 4 (Alt) or 8 (Super). Super is often assigned to the
        Windows/Start key on Windows keyboards or the Command key on Mac keyboards.
        <br />
        Since the Alt key is often used by window managers to move windows, this will need to
        be configured off to use the combination in SciTE. This can be done for Metacity using
        gconf-editor to modify the /apps/metacity/general/mouse_button_modifier. A valid value here
        is &lt;Super&gt;.
        </td>
      </tr>
      <tr id='property-selection.fore'>
        <td>
          <a name='property-selection.back'></a><a name='property-selection.alpha'></a>
          selection.fore<br />
           selection.back<br />
           selection.alpha
        </td>
        <td>
          Sets the colours used for displaying selected text. If one of these is not set then that
          attribute is not changed for the selection. The default is to show the selection by
          changing the background to light grey and leaving the foreground the same as when it was
          not selected. The translucency of the selection is set with selection.alpha with an alpha
	of 256 turning translucency off.
        </td>
      </tr>
      <tr id='property-caret.fore'>
        <td>
          caret.fore
        </td>
        <td>
          Sets the colour used for the caret.
        </td>
      </tr>
      <tr id='property-selection.additional.fore'>
        <td>
          <a name='property-selection.additional.back'></a><a name='property-selection.additional.alpha'></a>
          selection.additional.fore<br />
           selection.additional.back<br />
           selection.additional.alpha
        </td>
        <td>
          Similar to selection.fore, selection.back, selection.alpha.
        Sets the colours used for displaying additional selections when multiple selections are
        enabled or a rectangular selection is made.
        </td>
      </tr>
      <tr id='property-caret.additional.blinks'>
        <td>
          caret.additional.blinks
        </td>
        <td>
          Set whether all carets blink. 0 means only the main caret blinks. Default is 1.
        </td>
      </tr>
      <tr id='property-caret.line.back'>
        <td>
          <a name='property-caret.line.back.alpha'></a>
          caret.line.back<br />
          caret.line.back.alpha
        </td>
        <td>
          Sets the background colour and translucency used for line containing the caret.
		    Translucency ranges from 0 for completely transparent to 255 for opaque with
			 256 being opaque and not using translucent drawing code which may be slower.
        </td>
      </tr>
      <tr id='property-caret.period'>
        <td>
          caret.period
        </td>
        <td>
          Sets the rate at which the caret blinks. The value is the time in milliseconds that the
          caret is visible before it is switched to invisible. It then stays invisible for the same
          period before appearing again. A value of 0 stops the caret from blinking.
        </td>
      </tr>
      <tr id='property-caret.width'>
        <td>
          caret.width
        </td>
        <td>
          Sets the width of the caret in pixels. Only values of 1, 2, or 3 work.
        </td>
      </tr>
      <tr id='property-selection.multiple'>
        <td>
          <a name='property-selection.additional.typing'></a>
          selection.multiple<br />
          selection.additional.typing
        </td>
        <td>
	Set selection.multiple to make multiple selections with the mouse by holding down the Ctrl key.<br />
	Set selection.additional.typing to 1. to allow typing, backspace and delete to affect all selections including each line
	of rectangular selections. When set to 0, typing only affectes the main selection.
        </td>
      </tr>
      <tr id='property-virtual.space'>
        <td>
          virtual.space
        </td>
        <td>
          Determines whether the caret can be moved into virtual space, that is, beyond the last character on a line.
	Set to 1 to allow virtual space when making a rectangular selection, 2 to allow the arrow keys or a mouse
	click to  move the caret into virtual space, and 3 to allow both.
        </td>
      </tr>
      <tr id='property-caret.policy.xslop'>
        <td>
          <a name='property-caret.policy.width'></a><a name='property-caret.policy.xstrict'></a><a name='property-caret.policy.xeven'></a><a name='property-caret.policy.xjumps'></a><a name='property-caret.policy.yslop'></a><a name='property-caret.policy.lines'></a><a name='property-caret.policy.ystrict'></a><a name='property-caret.policy.yeven'></a><a name='property-caret.policy.yjumps'></a>
          caret.policy.xslop<br />
          caret.policy.width<br />
          caret.policy.xstrict<br />
          caret.policy.xeven<br />
          caret.policy.xjumps<br /><br />
          caret.policy.yslop<br />
          caret.policy.lines<br />
          caret.policy.ystrict<br />
          caret.policy.yeven<br />
          caret.policy.yjumps<br />
        </td>
        <td>
          <p>If slop is set, we can define a slop value: width for xslop, lines for yslop.<br />
          This value defines an unwanted zone (UZ) where the caret is... unwanted.<br />
          This zone is defined as a number of pixels near the vertical margins,
          and as a number of lines near the horizontal margins.<br />
          By keeping the caret away from the edges, it is seen within its context,
          so it is likely that the identifier that the caret is on can be completely seen,
          and that the current line is seen with some of the lines following it which are
          often dependent on that line.</p>

          <p>If strict is set, the policy is enforced... strictly.<br />
          The caret is centred on the display if slop is not set,
          and cannot go in the UZ if slop is set.</p>

          <p>If jumps is set, the display is moved more energetically
          so the caret can move in the same direction longer before the policy is applied again.<br />
          '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.</p>

          <p>If even is not set, instead of having symmetrical UZs,
          the left and bottom UZs are extended up to right and top UZs respectively.<br />
          This way, we favour the displaying of useful information: the begining of lines,
          where most code reside, and the lines after the caret, eg. the body of a function.</p>
          <p>See the table below to see how these settings interact.<br />
          Default: xslop, yslop, xeven, yeven=1, width=50, all others = 0.</p>
        </td>
      </tr>
      <tr id='property-visible.policy.strict'>
        <td>
          <a name='property-visible.policy.slop'></a><a name='property-visible.policy.lines'></a>
          visible.policy.strict<br />
          visible.policy.slop<br />
        visible.policy.lines
        </td>
        <td>
          Determines how the display area is determined after a Go to command or
        equivalent such as a Find or Next Message. Options are similar to caret.policy.*.
        </td>
      </tr>
      <tr id='property-edge.mode'>
        <td>
          <a name='property-edge.column'></a><a name='property-edge.colour'></a>
          edge.mode<br />
           edge.column<br />
           edge.colour<br />
        </td>
        <td>
          Indicates long lines. The default edge.mode, 0, does not indicate long lines. An
          edge.mode of 1 uses a vertical line to indicate the specified column and an edge.mode of
          2 changes the background colour of characters beyond that column. For proportional fonts,
          an edge.mode of 2 is more useful than 1.
        </td>
      </tr>
      <tr id='property-control.char.symbol'>
        <td>
          control.char.symbol
        </td>
        <td>
          Sets the character to use to indicate control characters. If
          not set, control characters are shown as mnemonics.
        </td>
      </tr>
      <tr id='property-error.marker.fore'>
        <td>
          <a name='property-error.marker.back'></a>
          error.marker.fore<br />
          error.marker.back
        </td>
        <td>
          The colours used to indicate error and warning lines in both the edit and output panes
          are set with these two values.
          If there is a margin on a pane then a symbol is displayed in the margin to indicate
          the error message for the output pane or the line causing the error message for the edit pane.
          The error.marker.back is used as the fill colour of the symbol and the error.marker.fore
          as the outline colour. If there is no margin then the background to the line is set to the
          error.marker.back colour.
        </td>
       </tr>
      <tr id='property-error.inline'>
        <td>
          <a name='property-style.error.0'></a><a name='property-style.error.1'></a><a name='property-style.error.2'></a><a name='property-style.error.3'></a>
          error.inline<br />
          style.error.0<br />
          style.error.1<br />
          style.error.2<br />
          style.error.3
        </td>
        <td>
          To see error messages interspersed with the source code, set error.inline=1.<br />
          Different visual styles are used for different severities: style.error.0 is the default;
          style.error.1 for warnings; style.error.2 for errors; and style.error.3 for fatal errors.
          The severity of a message is inferred from finding the text "warning", "error", or "fatal" in the message.
        </td>
       </tr>
      <tr id='property-bookmark.fore'>
        <td>
          <a name='property-bookmark.back'></a><a name='property-bookmark.alpha'></a>
          bookmark.fore<br />
          bookmark.back<br />
          bookmark.alpha
        </td>
        <td>
          The colours used to display bookmarks in the margin. If bookmark.fore is not set then
          a blue sphere is used. When the margin is turned off, bookmarks are shown by a
          change in the background colour of the line with the translucency set with bookmark.alpha.
        </td>
       </tr>
      <tr id='property-find.mark'>
        <td>
          find.mark
        </td>
        <td>
          If set, then the Mark All command in the Find dialog will draw translucent boxes over
		    each string found. (See indicators.alpha and indicators.under)
        </td>
       </tr>
       <tr id='property-indicators.alpha'>
        <td>
          indicators.alpha
        </td>
        <td>
           This property defines the alpha level for indicators (default value is 30).
	   The alpha value can range from 0 (completely transparent) to 255 (no transparency).
	   A value out of this range is ignored and the default one is used.
        </td>
       </tr>
       <tr id='property-indicators.under'>
        <td>
          indicators.under
        </td>
        <td>
          If set, the indicators are drawn under text or over (by default, it is over).
        </td>
       </tr>
       <tr id='property-error.select.line'>
        <td>
          error.select.line
        </td>
        <td>
          When a command execution produces error messages, and you step with F4 key through
          the matching source lines, this option selects the line where the error occurs.
          Most useful if the error message contains the column of error too as the selection will
          start at the column of the error. The error message must contain the column and must be
          understood by SciTE (currently only supported for HTML Tidy). The tab size assumed by
          the external tool must match the tab size of your source file for correct column reporting.
        </td>
       </tr>
       <tr id='property-openpath'>
        <td>openpath.<i>filepattern</i></td>
        <td>Defines a path for the Open Selected Filename command in the File
        menu. The path is searched if the selected filename doesn't contain an
        absolute path or the file is not found in the document directory. The
        directories in openpath are separated by ';' on Windows and ':' on OS X and GTK+.<br />
        An openpath setting may look like:
        <div class="example">
        openpath.*.txt=c:\dos\;f:\;<br />
        openpath.$(file.patterns.cpp)=$(cpp_includes)</div>
        </td>
       </tr>
       <tr id='property-open.suffix'>
        <td>open.suffix.<i>filepattern</i></td>
        <td>Defines a suffix to add to the selected file name for the
        Open Selected Filename command in the File menu.
	This is used in languages where the suffix is not given when accessing a file.
	An example is python where "import xlib" will most often mean to import from
	a file called "xlib.py".<br />
        An open.suffix setting may look like:<br />
        <div class="example">open.suffix.*.py=.py</div>
        </td>
       </tr>
       <tr id='property-strip.trailing.spaces'>
        <td>
          strip.trailing.spaces<br />
          strip.trailing.spaces.<i>filepattern</i>
        </td>
        <td>
          Strips trailing white spaces from the file while saving.<br />
          The global strip.trailing.spaces property can be overridden for
          files that match a pattern by using the file pattern forms: <br />
          <div class="example">
          strip.trailing.spaces.*.yaml=0<br />
          or <br />
          strip.trailing.spaces.$(file.patterns.yaml)=0<br />
          </div>
        </td>
      </tr>
       <tr id='property-ensure.final.line.end'>
        <td>
          ensure.final.line.end
        </td>
        <td>
          Ensures file ends with a line end when saved.
        </td>
      </tr>
       <tr id='property-ensure.consistent.line.ends'>
        <td>
          ensure.consistent.line.ends
        </td>
        <td>
          Ensures all lines end with the current Line End Characters setting when saved.
        </td>
      </tr>
      <tr id='property-abbreviations'>
        <td>
          abbreviations.<i>filepattern</i>
        </td>
        <td>
          Loads an abbreviations file for a particular language overriding the default abbreviations file.
          For example,
         <div class="example">
                abbreviations.*.c=$(SciteUserHome)/c_abbrev.properties<br />
         </div>
        </td>
      </tr>
      <tr id='property-api'>
        <td>
          api.<i>filepattern</i>
        </td>
        <td>
          Loads a set of API files for a particular language.
          If there is more than one API file then the file names are separated by ';'.
          API files contain a sorted list of
          identifiers and function prototypes, one per line. If there are multiple files then each file should
	end with a line end or the next file's first line will merge with the previous file's last line.
	The "Complete Symbol" command
          looks at the characters before the caret and displayed the subset of the API file
          starting with that string. When an opening brace is typed, the file is searched for the
          text preceding the caret and if a function prototype is found then it is displayed as a
          calltip.
          For example, the setting
         <div class="example">
                api.*.c=w.api<br />
         </div>
                  could be used with a w.api file containing
         <div class="example">
                fclose(FILE* fileClose)<br />
                FILE<br />
                fopen(const char* szFileName, const char* szMode)<br />
                fpos_t<br />
                fread(void* buf, size_t size, size_t count, FILE* file)<br />
                fseek(FILE* file, long lnOffset, int nOrigin)<br />
         </div>
          to provide autocompletion and calltips for some of the C file functions. It is best to
          use the full path to the API file as otherwise the current directory is used.
        See the Creating API files section for ways to create API files.
        </td>
      </tr>
      <tr id='property-autocomplete.choose.single'>
        <td>
          autocomplete.choose.single
        </td>
        <td>
          When set to 1 and an autocompletion list is invoked and there is only one element
        in that list then that element is automatically chosen. This means that the matched
        element is inserted and the list is not displayed.
        </td>
      </tr>
      <tr id='property-autocomplete.*.ignorecase'>
        <td>
          autocomplete.<i>lexer</i>.ignorecase<br />
          autocomplete.*.ignorecase
        </td>
        <td>
          When set to 1 the API file is searched in a case insensitive way to find elements
        for autocompletion lists. Otherwise matches only occur if case also matches.
        The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-autocomplete.*.start.characters'>
        <td>
          autocomplete.<i>lexer</i>.start.characters<br />
          autocomplete.*.start.characters
        </td>
        <td>
        If this setting is not empty, typing any of the characters will cause
        autocompletion to start. For example, if
        autocomplete.python.start.characters=. and the API file for Python
        contains "string.rjust" and "string.replace" then typing "string." will
        cause the autocompletion to display both identifiers.
        The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-autocomplete.*.fillups'>
        <td>
          autocomplete.<i>lexer</i>.fillups<br />
          autocomplete.*.fillups
        </td>
        <td>
        If this setting is not empty, typing any of the characters will cause
        autocompletion to complete.
        For example, if
        autocomplete.python.fillups=( and the API file for Python
        contains "string.replace" then typing "string.r(" will
        cause "string.replace(" to be inserted.
        The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-autocompleteword.automatic'>
        <td>
          autocompleteword.automatic
        </td>
        <td>
        If this setting is 1 then when typing a word, if only one word in the document
        starts with that string then an autocompletion list is displayed with that word so it
        can be chosen by pressing Tab.
        </td>
      </tr>
      <tr id='property-calltip.*.ignorecase'>
        <td>
          calltip.<i>lexer</i>.ignorecase<br />
          calltip.*.ignorecase
        </td>
        <td>
          When set to 1 the API file is searched in a case insensitive way to find the function
        which will have its signature displayed as a calltip. The * form is used if there
        is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-calltip.*.use.escapes'>
        <td>
          calltip.<i>lexer</i>.use.escapes<br />
          calltip.*.use.escapes
        </td>
        <td>
          When set to 1 the API file may contain C style backslash escapes which are listed in
        the command line arguments section. The * form is used if there is no lexer specific
        setting.
        </td>
      </tr>
      <tr id='property-calltip.*.word.characters'>
        <td>
          calltip.<i>lexer</i>.word.characters<br />
          calltip.*.word.characters
        </td>
        <td>
        To determine the identifier to look up for calltips, a search is performed
        allowing the characters in this set to be included in the identifier.
        While the same setting can be used as for word.characters, sometimes
        additional characters may be allowed.
        For example, in Python, '.' is not normally considered part of a word
        when selecting text, but it is good to allow "string.replace" to show a
        calltip so calltip.python.word.characters=._$(chars.alpha) would be a
        reasonable setting.
        The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-calltip.*.parameters.start'>
        <td>
          <a name='property-calltip.*.parameters.end'></a><a name='property-calltip.*.parameters.separators'></a>
          calltip.<i>lexer</i>.parameters.start<br />
          calltip.<i>lexer</i>.parameters.end<br />
          calltip.<i>lexer</i>.parameters.separators<br />
          calltip.*.parameters.start<br />
          calltip.*.parameters.end<br />
          calltip.*.parameters.separators
        </td>
        <td>
          Allows you to specify characters which start, end and separate
          parameters. For most common languages, it's usually left brace for
          start, right brace for end and comma or semicolon for separator.
          E.g. CSS has colon for start, space for separator and nothing for
          end. You can specify more characters for each property.
          The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-calltip.*.end.definition'>
        <td>
          calltip.<i>lexer</i>.end.definition<br />
          calltip.*.end.definition
        </td>
        <td>
        API files may contain explanatory text after each function definition.
        To display the explanation on a second line, set this property to the character used at the
        end of the definition part. For most languages, this is ')'.
        The * form is used if there is no lexer specific setting.
        </td>
      </tr>
      <tr id='property-xml.auto.close.tags'>
        <td>
          xml.auto.close.tags
        </td>
        <td>
          For XML and HTML, setting this property to 1 will automatically insert the
        corresponding end tag when '&gt;' is typed to end a start tag.
        Type "&lt;td&gt;" and the result will be "&lt;td&gt;&lt;/td&gt;" with the caret
        placed between the tags.
        </td>
      </tr>
<!--++Autogenerated - run ../../scintilla/src/LexGen.py to regenerate -->
<!--**\(\*\n\) -->
	<tr id='property-asp.default.language'>
	<td>asp.default.language</td>
	<td>Script in ASP code is initially assumed to be in JavaScript. To change this to VBScript set asp.default.language to 2. Python is 3.</td>
	</tr>
	<tr id='property-fold.asm.comment.explicit'>
	<td>fold.asm.comment.explicit</td>
	<td>This option enables folding explicit fold points when using the Asm lexer. Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} at the end of a section that should fold.</td>
	</tr>
	<tr id='property-fold.asm.comment.multiline'>
	<td>fold.asm.comment.multiline</td>
	<td>Set this property to 1 to enable folding multi-line comments.</td>
	</tr>
	<tr id='property-fold.asm.explicit.anywhere'>
	<td>fold.asm.explicit.anywhere</td>
	<td>Set this property to 1 to enable explicit fold points anywhere, not just in line comments.</td>
	</tr>
	<tr id='property-fold.asm.explicit.end'>
	<td>fold.asm.explicit.end</td>
	<td>The string to use for explicit fold end points, replacing the standard ;}.</td>
	</tr>
	<tr id='property-fold.asm.explicit.start'>
	<td>fold.asm.explicit.start</td>
	<td>The string to use for explicit fold start points, replacing the standard ;{.</td>
	</tr>
	<tr id='property-fold.asm.syntax.based'>
	<td>fold.asm.syntax.based</td>
	<td>Set this property to 0 to disable syntax based folding.</td>
	</tr>
	<tr id='property-fold.at.else'>
	<td>fold.at.else</td>
	<td>This option enables C++ folding on a "} else {" line of an if statement.</td>
	</tr>
	<tr id='property-fold.basic.comment.explicit'>
	<td>fold.basic.comment.explicit</td>
	<td>This option enables folding explicit fold points when using the Basic lexer. Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded.</td>
	</tr>
	<tr id='property-fold.basic.explicit.anywhere'>
	<td>fold.basic.explicit.anywhere</td>
	<td>Set this property to 1 to enable explicit fold points anywhere, not just in line comments.</td>
	</tr>
	<tr id='property-fold.basic.explicit.end'>
	<td>fold.basic.explicit.end</td>
	<td>The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB).</td>
	</tr>
	<tr id='property-fold.basic.explicit.start'>
	<td>fold.basic.explicit.start</td>
	<td>The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB).</td>
	</tr>
	<tr id='property-fold.basic.syntax.based'>
	<td>fold.basic.syntax.based</td>
	<td>Set this property to 0 to disable syntax based folding.</td>
	</tr>
	<tr id='property-fold.comment'>
	<td>fold.comment</td>
	<td>This option enables folding multi-line comments and explicit fold points when using the C++ lexer. Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} at the end of a section that should fold.</td>
	</tr>
	<tr id='property-fold.cpp.comment.explicit'>
	<td>fold.cpp.comment.explicit</td>
	<td>Set this property to 0 to disable folding explicit fold points when fold.comment=1.</td>
	</tr>
	<tr id='property-fold.cpp.comment.multiline'>
	<td>fold.cpp.comment.multiline</td>
	<td>Set this property to 0 to disable folding multi-line comments when fold.comment=1.</td>
	</tr>
	<tr id='property-fold.cpp.explicit.anywhere'>
	<td>fold.cpp.explicit.anywhere</td>
	<td>Set this property to 1 to enable explicit fold points anywhere, not just in line comments.</td>
	</tr>
	<tr id='property-fold.cpp.explicit.end'>
	<td>fold.cpp.explicit.end</td>
	<td>The string to use for explicit fold end points, replacing the standard //}.</td>
	</tr>
	<tr id='property-fold.cpp.explicit.start'>
	<td>fold.cpp.explicit.start</td>
	<td>The string to use for explicit fold start points, replacing the standard //{.</td>
	</tr>
	<tr id='property-fold.cpp.syntax.based'>
	<td>fold.cpp.syntax.based</td>
	<td>Set this property to 0 to disable syntax based folding.</td>
	</tr>
	<tr id='property-fold.d.comment.explicit'>
	<td>fold.d.comment.explicit</td>
	<td>Set this property to 0 to disable folding explicit fold points when fold.comment=1.</td>
	</tr>
	<tr id='property-fold.d.comment.multiline'>
	<td>fold.d.comment.multiline</td>
	<td>Set this property to 0 to disable folding multi-line comments when fold.comment=1.</td>
	</tr>
	<tr id='property-fold.d.explicit.anywhere'>
	<td>fold.d.explicit.anywhere</td>
	<td>Set this property to 1 to enable explicit fold points anywhere, not just in line comments.</td>
	</tr>
	<tr id='property-fold.d.explicit.end'>
	<td>fold.d.explicit.end</td>
	<td>The string to use for explicit fold end points, replacing the standard //}.</td>
	</tr>
	<tr id='property-fold.d.explicit.start'>
	<td>fold.d.explicit.start</td>
	<td>The string to use for explicit fold start points, replacing the standard //{.</td>
	</tr>
	<tr id='property-fold.d.syntax.based'>
	<td>fold.d.syntax.based</td>
	<td>Set this property to 0 to disable syntax based folding.</td>
	</tr>
	<tr id='property-fold.html'>
	<td>fold.html</td>
	<td>Folding is turned on or off for HTML and XML files with this option. The fold option must also be on for folding to occur.</td>
	</tr>
	<tr id='property-fold.html.preprocessor'>
	<td>fold.html.preprocessor</td>
	<td>Folding is turned on or off for scripts embedded in HTML files with this option. The default is on.</td>
	</tr>
	<tr id='property-fold.hypertext.comment'>
	<td>fold.hypertext.comment</td>
	<td>Allow folding for comments in scripts embedded in HTML. The default is off.</td>
	</tr>
	<tr id='property-fold.hypertext.heredoc'>
	<td>fold.hypertext.heredoc</td>
	<td>Allow folding for heredocs in scripts embedded in HTML. The default is off.</td>
	</tr>
	<tr id='property-fold.perl.at.else'>
	<td>fold.perl.at.else</td>
	<td>This option enables Perl folding on a "} else {" line of an if statement.</td>
	</tr>
	<tr id='property-fold.perl.comment.explicit'>
	<td>fold.perl.comment.explicit</td>
	<td>Set to 0 to disable explicit folding.</td>
	</tr>
	<tr id='property-fold.perl.package'>
	<td>fold.perl.package</td>
	<td>Set to 0 to disable folding packages when using the Perl lexer.</td>
	</tr>
	<tr id='property-fold.perl.pod'>
	<td>fold.perl.pod</td>
	<td>Set to 0 to disable folding Pod blocks when using the Perl lexer.</td>
	</tr>
	<tr id='property-fold.preprocessor'>
	<td>fold.preprocessor</td>
	<td>This option enables folding preprocessor directives when using the C++ lexer. Includes C#'s explicit #region and #endregion folding directives.</td>
	</tr>
	<tr id='property-fold.quotes.python'>
	<td>fold.quotes.python</td>
	<td>This option enables folding multi-line quoted strings when using the Python lexer.</td>
	</tr>
	<tr id='property-fold.sql.at.else'>
	<td>fold.sql.at.else</td>
	<td>This option enables SQL folding on a "ELSE" and "ELSIF" line of an IF statement.</td>
	</tr>
	<tr id='property-html.tags.case.sensitive'>
	<td>html.tags.case.sensitive</td>
	<td>For XML and HTML, setting this property to 1 will make tags match in a case sensitive way which is the expected behaviour for XML and XHTML.</td>
	</tr>
	<tr id='property-lexer.asm.comment.delimiter'>
	<td>lexer.asm.comment.delimiter</td>
	<td>Character used for COMMENT directive's delimiter, replacing the standard "~".</td>
	</tr>
	<tr id='property-lexer.cpp.allow.dollars'>
	<td>lexer.cpp.allow.dollars</td>
	<td>Set to 0 to disallow the '$' character in identifiers with the cpp lexer.</td>
	</tr>
	<tr id='property-lexer.cpp.hashquoted.strings'>
	<td>lexer.cpp.hashquoted.strings</td>
	<td>Set to 1 to enable highlighting of hash-quoted strings.</td>
	</tr>
	<tr id='property-lexer.cpp.track.preprocessor'>
	<td>lexer.cpp.track.preprocessor</td>
	<td>Set to 1 to interpret #if/#else/#endif to grey out code that is not active.</td>
	</tr>
	<tr id='property-lexer.cpp.triplequoted.strings'>
	<td>lexer.cpp.triplequoted.strings</td>
	<td>Set to 1 to enable highlighting of triple-quoted strings.</td>
	</tr>
	<tr id='property-lexer.cpp.update.preprocessor'>
	<td>lexer.cpp.update.preprocessor</td>
	<td>Set to 1 to update preprocessor definitions when #define found.</td>
	</tr>
	<tr id='property-lexer.css.hss.language'>
	<td>lexer.css.hss.language</td>
	<td>Set to 1 for HSS (.hss)</td>
	</tr>
	<tr id='property-lexer.css.less.language'>
	<td>lexer.css.less.language</td>
	<td>Set to 1 for Less CSS (.less)</td>
	</tr>
	<tr id='property-lexer.css.scss.language'>
	<td>lexer.css.scss.language</td>
	<td>Set to 1 for Sassy CSS (.scss)</td>
	</tr>
	<tr id='property-lexer.d.fold.at.else'>
	<td>lexer.d.fold.at.else</td>
	<td>This option enables D folding on a "} else {" line of an if statement.</td>
	</tr>
	<tr id='property-lexer.errorlist.value.separate'>
	<td>lexer.errorlist.value.separate</td>
	<td>For lines in the output pane that are matches from Find in Files or GCC-style diagnostics, style the path and line number separately from the rest of the line with style 21 used for the rest of the line. This allows matched text to be more easily distinguished from its location.</td>
	</tr>
	<tr id='property-lexer.flagship.styling.within.preprocessor'>
	<td>lexer.flagship.styling.within.preprocessor</td>
	<td>For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code.</td>
	</tr>
	<tr id='property-lexer.html.django'>
	<td>lexer.html.django</td>
	<td>Set to 1 to enable the django template language.</td>
	</tr>
	<tr id='property-lexer.html.mako'>
	<td>lexer.html.mako</td>
	<td>Set to 1 to enable the mako template language.</td>
	</tr>
	<tr id='property-lexer.props.allow.initial.spaces'>
	<td>lexer.props.allow.initial.spaces</td>
	<td>For properties files, set to 0 to style all lines that start with whitespace in the default style. This is not suitable for SciTE .properties files which use indentation for flow control but can be used for RFC2822 text where indentation is used for continuation lines.</td>
	</tr>
	<tr id='property-lexer.python.keywords2.no.sub.identifiers'>
	<td>lexer.python.keywords2.no.sub.identifiers</td>
	<td>When enabled, it will not style keywords2 items that are used as a sub-identifier. Example: when set, will not highlight "foo.open" when "open" is a keywords2 item.</td>
	</tr>
	<tr id='property-lexer.python.literals.binary'>
	<td>lexer.python.literals.binary</td>
	<td>Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712.</td>
	</tr>
	<tr id='property-lexer.python.strings.b'>
	<td>lexer.python.strings.b</td>
	<td>Set to 0 to not recognise Python 3 bytes literals b"x".</td>
	</tr>
	<tr id='property-lexer.python.strings.over.newline'>
	<td>lexer.python.strings.over.newline</td>
	<td>Set to 1 to allow strings to span newline characters.</td>
	</tr>
	<tr id='property-lexer.python.strings.u'>
	<td>lexer.python.strings.u</td>
	<td>Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3.</td>
	</tr>
	<tr id='property-lexer.sql.allow.dotted.word'>
	<td>lexer.sql.allow.dotted.word</td>
	<td>Set to 1 to colourise recognized words with dots (recommended for Oracle PL/SQL objects).</td>
	</tr>
	<tr id='property-lexer.sql.numbersign.comment'>
	<td>lexer.sql.numbersign.comment</td>
	<td>If "lexer.sql.numbersign.comment" property is set to 0 a line beginning with '#' will not be a comment.</td>
	</tr>
	<tr id='property-lexer.xml.allow.scripts'>
	<td>lexer.xml.allow.scripts</td>
	<td>Set to 0 to disable scripts in XML.</td>
	</tr>
	<tr id='property-sql.backslash.escapes'>
	<td>sql.backslash.escapes</td>
	<td>Enables backslash as an escape character in SQL.</td>
	</tr>
	<tr id='property-styling.within.preprocessor'>
	<td>styling.within.preprocessor</td>
	<td>For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) or only from the initial # to the end of the command word(1).</td>
	</tr>
	<tr id='property-tab.timmy.whinge.level'>
	<td>tab.timmy.whinge.level</td>
	<td>For Python code, checks whether indenting is consistent. The default, 0 turns off indentation checking, 1 checks whether each line is potentially inconsistent with the previous line, 2 checks whether any space characters occur before a tab character in the indentation, 3 checks whether any spaces are in the indentation, and 4 checks for any tab characters in the indentation. 1 is a good level to use.</td>
	</tr>

<!----Autogenerated -- end of automatically generated section -->
      <tr id='property-user.shortcuts'>
        <td>
          user.shortcuts
        </td>
        <td>
        Define keys that perform commands.
        This is a '|' delimited list of keys and the commands they produce.
        The commands are either <a href="CommandValues.html">string or numeric IDs</a>.
        Numeric IDs above 2000 are Scintilla commands and are sent to the focussed pane.
        Named IDs and numeric IDs below 2000 are SciTE menu commands.
        The modifiers are Ctrl, Shift, and Alt and the named keys are Left,
        Right, Up, Down, Insert, End, Home, Enter, Space, Tab, KeypadPlus, KeypadMinus,
        KeypadMultiply, KeypadDivide, Escape, Delete, PageUp, PageDown, Slash,
        Question, Equal, Win.
        <br/>
        <div class="example">
user.shortcuts=\<br/>
Ctrl+Shift+I|IDM_OPEN|\<br/>
Ctrl+Shift+Left|IDM_CLOSE|<br/>
        </div>
	This property is only read at start up.
        <br/>
        </td>
      </tr>
      <tr id='property-user.context.menu'>
        <td>
          user.context.menu
        </td>
        <td>
        Define additional commands for the context menu.
        This is a '|' delimited list of menu items and the commands they
        produce with commands defined as in user.shortcuts. An empty
        item produces a separator.
        <br/>
        <div class="example">
user.context.menu=\<br/>
||\<br/>
Next File|IDM_NEXTFILE|\<br/>
Prev File|IDM_PREVFILE|<br/>
        </div>
        </td>
      </tr>
      <tr id='property-magnification'>
        <td>
          <a name='property-output.magnification'></a>
          magnification<br />
        output.magnification
        </td>
        <td>
          Sets the initial magnification factor of the edit and output panes. This is useful
        when you want to change the size of text globally, such as after changing the
        screen resolution without having to touch every style setting. 0 is default,
        negative values makes the size smaller and positive values make it larger.
        </td>
      </tr>
      <tr id='property-split.vertical'>
        <td>
          <a name='property-output.horizontal.size'></a><a name='property-output.vertical.size'></a><a name='property-output.initial.hide'></a>
          split.vertical<br />
        output.horizontal.size<br />
        output.vertical.size<br />
        output.initial.hide
        </td>
        <td>
          If split.vertical is set to 1 then the output pane is to the right of the editing pane,
        if set to 0 then the output pane is below the editing pane.
        The output.*.size settings determine the initial size of the output pane.
        If output.initial.hide is 1, then the output pane is hidden when SciTE first
        starts up even when output.*.size is set; otherwise the output pane is shown at
        startup.
        </td>
      </tr>
      <tr id='property-clear.before.execute'>
        <td>
          clear.before.execute
        </td>
        <td>
          If set to 1 then the output pane is cleared before any tool commands are run.
        </td>
      </tr>
      <tr id='property-horizontal.scrollbar'>
        <td>
          <a name='property-horizontal.scroll.width'></a><a name='property-horizontal.scroll.width.tracking'></a><a name='property-output.horizontal.scrollbar'></a><a name='property-output.horizontal.scroll.width'></a><a name='property-output.horizontal.scroll.width.tracking'></a><a name='property-output.scroll'></a><a name='property-end.at.last.line'></a>
          horizontal.scrollbar<br />
        horizontal.scroll.width<br />
        horizontal.scroll.width.tracking<br />
        output.horizontal.scrollbar<br />
        output.horizontal.scroll.width<br />
        output.horizontal.scroll.width.tracking<br />
        output.scroll<br />
        end.at.last.line
        </td>
        <td>
          If horizontal.scrollbar set to 0 then the edit pane's horizontal scrollbar is not displayed.<br />
          horizontal.scroll.width is the document width assumed for scrolling.<br />
          Similarly, output.horizontal.scrollbar and output.horizontal.scroll.width controls the
        horizontal scroll bar of the output pane.<br />
          The horizontal scroll bar widths can automatically grow as needed to ensure all displayed lines can be fully
        scrolled with horizontal.scroll.width.tracking and output.horizontal.scroll.width.tracking.<br />
        To stop the output pane from automatically scrolling, set output.scroll to 0.
        To have the output pane scroll and return back to the line of the executed command,
        set output.scroll to 1. If you want the output pane to scroll and remain at
        the bottom after execution, set output.scroll to 2.<br />
        The vertical scroll range is normally set so that maximum scroll position has
        the last line at the bottom of the view. Set end.at.last.line to 0 to allow
        scrolling one page below the last line.
        </td>
      </tr>
      <tr id='property-wrap'>
        <td>
          <a name='property-output.wrap'></a>
          wrap<br />
        output.wrap
        </td>
        <td>
          If wrap set to 1 then the edit pane is dynamically line wrapped.
          If output.wrap set to 1 then the output pane is dynamically line wrapped.
        These options have a high performance cost which is proportional to the amount of text
        so should be turned off for large documents on slow machines.
        </td>
      </tr>
      <tr id='property-wrap.style'>
        <td>
          wrap.style
        </td>
        <td>
          Chooses between word wrapping (1, the default) and character wrapping (2).
	Character wrapping is a better choice for Asian languages with no spaces
	between words.
        </td>
      </tr>
      <tr id='property-wrap.visual.flags'>
        <td>
          wrap.visual.flags
        </td>
        <td>
          Flags to display markers at end and begin of wrapped lines for visual identify them.
          Set to 0 to not display markers (default). Set to 1 to display markers at end of
          wrapped lines, to 2 to display markers at begin of wrapped lines and to 3 to
          display markers at begin and end.
        </td>
      </tr>
      <tr id='property-wrap.visual.flags.location'>
        <td>
          wrap.visual.flags.location
        </td>
        <td>
          Flags to set the location of the display markers (if enabled) near to text or near to border.
          Set to 0 to have begin and end markers near to border (default). Set to 1 to
          have end markers near text, to 2 to have begin markers near text and
          to 3 to have all markers near text.
        </td>
      </tr>
      <tr id='property-wrap.indent.mode'>
        <td>
          wrap.indent.mode
        </td>
        <td>
          Wrapped sublines can be indented in various ways relative to the initial subline.
          Default mode 0 indents sublines to the left of window plus wrap.visual.startindent.
          Mode 1 aligns sublines to the first subline.
          Mode 2 aligns sublines to the first subline plus one more level of indentation.
        </td>
      </tr>
      <tr id='property-wrap.visual.startindent'>
        <td>
          wrap.visual.startindent
        </td>
        <td>
          Sets the indention of continued wrapped lines to better visually identify the wrapping.
          Default is 0 (no indention). Note if wrap.visual.flags is 2 or 3 (begin marker displayed)
          the line is indented at least 1, even if wrap.visual.startindent is still 0.
        </td>
      </tr>
      <tr id='property-wrap.aware.home.end.keys'>
        <td>wrap.aware.home.end.keys</td>
        <td>
          This property changes the behaviour of the home and end keys when dynamic
          line wrapping is turned on.  When set to 0 (the default), the Home and End
          keys will move the caret to the very beginning / end of the 'logical'
          line, whether or not the line is wrapped over multiple lines in the display.
          When this property is set to 1, the caret moves to the end of the current
          'display' line if you press End once, or to the very end of the 'logical'
          line if you press End again.  Likewise, the Home key moves first to the
          beginning of the 'display' line, then on to the very beginning of the line.
          In a pane where dynamic line-wrapping is not enabled, this setting has no
          effect.
        </td>
      </tr>
      <tr id='property-cache.layout'>
        <td>
          <a name='property-output.cache.layout'></a>
        cache.layout<br />
        output.cache.layout
        </td>
        <td>
        A large proportion of the time spent in the editor is used to lay out text prior
        to drawing it. This information often stays static between repaints so can
        be cached with these settings. There are four levels of caching. 0 is no caching,
        1 caches the line that the caret is on, 2 caches the visible page as well as the caret,
        and 3 caches the whole document. The more that is cached, the greater the
        amount of memory used, with 3 using large amounts of memory, 7 times the
        size of the text in the document. However,
        level 3 dramatically speeds up dynamic wrapping by around 25 times on large
        source files so is a very good option to use when wrapping is turned on and
        memory is plentiful.
        </td>
      </tr>
      <tr id='property-open.filter'>
        <td>
          open.filter
        </td>
        <td>
          This is a complex expression used for determining the file types that will be available in
          the open file dialog. For each type of file, there is some explanatory text, a '|'
          character, some file patterns, and another '|' character. In the distributed
          SciTEGlobal.properties file, the line continuation character '\', is used to spread these
          items out, one per line. These file types appear in the "Files of type:" pull down. The
          first item is the default, so you may wish to change the first item to include the file
          types you commonly open.<br />
        </td>
      </tr>
      <tr class="windowsonly" id='property-save.filter'>
        <td>
          save.filter
        </td>
        <td>
          This is a complex expression used for determining the file types that will be available in
          the save file dialog. The structure of the property is the same as open.filter.<br />
          Does not work on GTK+.
        </td>
      </tr>
      <tr id='property-max.file.size'>
        <td>
          max.file.size
        </td>
        <td>
        To avoid accidentally loading huge files on slow media, or just to ensure SciTE is used
        only to edit human readable code, the user can set the max.file.size property to specify
        a limit to file loading.
        If unset or set to 0, there is no limit.
        If set to a given size in bytes and if a file to load exceeds this limit, the user is asked
        if the file should be loaded. If accepted, the file is read as usual. If rejected then no
        action is taken (no file loaded, no buffer created).
        </td>
      </tr>
      <tr id='property-save.deletes.first'>
        <td>
          save.deletes.first
        </td>
        <td>
          Causes files to be deleted before being opened for saving. Can be used
          to ensure saving under a different capitalisation changes the files capitalisation rather
          than silently using the old capitalisation.
        </td>
      </tr>
      <tr id='property-save.check.modified.time'>
        <td>
          save.check.modified.time
        </td>
        <td>
        With save.check.modified.time=1, when saving and the file has been modified by another
        process, check if it should be overwritten by the current contents.
        </td>
      </tr>
      <tr id='property-save.session'>
        <td>
          <a name='property-save.recent'></a><a name='property-save.position'></a>
          save.session<br />
          save.recent<br />
          save.position<br />
          save.find
        </td>
        <td>
        If you set save.session, the list of currently opened buffers will be saved on exit
        in a session file. When you start SciTE next time (without specifying a file name
        on the command line) the last session will be restored automatically.<br />
        For GTK+, the file is called ".SciTE.session" and is located in the directory
        given by the SciTE_HOME environment variable and if that is not set, the value
        of the HOME environment variable and if that is not set, the top level directory.
        For Windows, the file is called "SciTE.session" and is located in the directory
        given by the SciTE_HOME environment variable and if that is not set, the value
        of the USERPROFILE environment variable and if that is not set, the directory
        of the SciTE executable.<br />
        Setting save.recent causes the most recently used files list to be saved on
        exit in the session file and read at start up.<br />
        Setting save.position causes the SciTE window position on the desktop to be
        saved on exit in the session file and restored at start up.<br />
        Setting save.find cause the "Find what" and "Replace with" to be saved in the session file.
        </td>
      </tr>
      <tr id='property-session.bookmarks'>
        <td>
          <a name='property-session.folds'></a>
          session.bookmarks<br />
          session.folds
        </td>
        <td>
          Setting session.bookmarks causes bookmarks to be saved in session files.
        If you set session.folds then the folding state will be saved in session
        files. When loading a session file bookmarks and/or folds are restored.
        Folding states are not restored if fold.on.open is set.
        </td>
      </tr>
      <tr class="windowsonly" id='property-open.dialog.in.file.directory'>
        <td>
        open.dialog.in.file.directory
        </td>
        <td>
          Setting open.dialog.in.file.directory causes the open dialog to initially
          display the same directory as the current file. If it is not set then the
          system default is used.
        </td>
      </tr>
      <tr class="windowsonly" id='property-find.close.on.find'>
        <td>
          find.close.on.find
        </td>
        <td>
          Set to 0 to prevent the Find dialog from closing when "Find" pressed.
        </td>
      </tr>
      <tr id='property-find.replace.matchcase'>
        <td>
          <a name='property-find.replace.regexp'></a><a name='property-find.replace.wrap'></a><a name='property-find.replace.escapes'></a>
        find.replace.matchcase<br />
        find.replace.regexp<br />
        find.replace.wrap<br />
        find.replace.escapes
        </td>
        <td>
          These properties define the initial conditions for find and replace commands.
        The find.replace.matchcase property turns of the "Match case" option,
        find.replace.regexp the "Regular expression" option,
        find.replace.wrap the "Wrap around" option and
        find.replace.escapes the "Transform backslash expressions" option.<br />
        </td>
      </tr>
      <tr class="windowsonly" id='property-find.replacewith.focus'>
        <td>
        find.replacewith.focus
        </td>
        <td>
        If the find.replacewith.focus property is set, the Replace With input box is focused
	in the Replace dialog if Find What is non-empty.
        </td>
      </tr>
      <tr id='property-find.replace.regexp.posix'>
        <td>
        find.replace.regexp.posix
        </td>
        <td>
          Change behaviour of Regular expression search.
        If set to 0 (the default), characters '(' and ')' must be escaped by '\' to behave as regexp meta characters.
        If set to 1, these characters are meta characters itself.
        </td>
      </tr>
      <tr id='property-find.use.strip'>
        <td>
          <a name='property-replace.use.strip'></a>
         find.use.strip<br />
	 replace.use.strip
        </td>
        <td>
          Use in-window strips rather than dialogs for performing Find or Replace commands.
        </td>
      </tr>
      <tr class="gtkonly" id='property-strip.button.height'>
        <td>
         strip.button.height
        </td>
        <td>
          Buttons on GTK+ often contain extra spacing that makes strips take too much room.
	  This setting tries to limit the height of buttons.
	  A value of 23 or 24 may work well.
        </td>
      </tr>
      <tr id='property-find.replace.advanced'>
        <td>
         find.replace.advanced
        </td>
        <td>
          Enables Replace in Buffers command
	  <span class="windowsonly">and Search only in this style checkbox.
          If enabled, searches can be restricted to a particular style (e.g. strings).</span>
        </td>
      </tr>
      <tr class="osxonly" id='property-find.indicator'>
        <td>
         find.indicator
        </td>
        <td>
          Controls the animated golden match indicator on OS X.
	The default value, 1, shows and animates the find indicator then fades it away so surrounding text can be seen clearly.
	Use the value 0 to disable the find indicator and the value 2 to keep the find indicator displayed.
        </td>
      </tr>
      <tr id='property-find.command'>
        <td>
          find.command<br />
          <span class="windowsonly">find.input</span>
        </td>
        <td>
          The Find in Files command works in a similar way to the building commands executing a
          command line tool with output redirected to the output pane. If the command produces
          output understood by one of the error output passes, as does grep, then the F4 and
          Shift+F4 keys can be used to move through all the matches. The $(find.what),
          $(find.files), and $(find.directory) variables can be used for the values from the
          Find in Files dialog.<br />
          There are some scripts that implement this feature in Perl better than grep does
          itself
          <a href="http://jenda.krynicky.cz/#SciteFind">here</a> and
          <a href="http://www.forusers.com/forme/finder.zip">here</a>.
          This command line works with Cygwin on Windows, with modifications to suit
          the Cygwin installation directory:<br />
        <div class="example">
find.command=cmd /c c:\cygwin\bin\find "$(find.directory)"
-name "$(find.files)" -print0 |
c:\cygwin\bin\xargs -0 fgrep -G -n "$(find.what)"
          </div>
          On Windows, the find string can be given to the find command through
          its standard input stream to avoid problems with quote interpretation.
          To do this, specify find.input to be the search string, $(find.what).
          <br />
          If find.command is empty then SciTE's own search code is used. This only does a
	simple search without regular expressions and is faster than running an external program.
        </td>
      </tr>
      <tr id='property-find.files'>
        <td>
          find.files
        </td>
        <td>
          This is the default set of files to search through using the Find in Files command.
          The find.files property can contain a list of sets of files separated by '|' like
          "*.cxx *.h|*.py *.pyw|*.html" which adds three entries to the history and
          uses the first as the default value.<br />
          The evaluation of this setting is a little unusual in that each entry in the value
          from the property files is appended to the end of the history if that entry is
          not already present. This means that opening files from different directories
          will result in any local setting of find.files being added to the list.
        </td>
      </tr>
      <tr id='property-find.in.dot'>
        <td>
          find.in.dot
        </td>
        <td>
	If find.in.dot is 1 then Find in Files searches in directories that start with '.'.
	The default behaviour is to prevent SciTE finding matches in the unmodified versions of
	files kept by Subversion in .svn subdirectories.
        </td>
      </tr>
      <tr id='property-find.in.binary'>
        <td>
          find.in.binary
        </td>
        <td>
	If find.in.binary is 1 then Find in Files displays matches in binary files.
	For Find in Files, a binary file is a file that contains a NUL byte in the first 64K block read from the file.
        </td>
      </tr>
      <tr id='property-find.in.directory'>
        <td>
          find.in.directory
        </td>
        <td>
	If set then Find in Files directory will be prefilled by this value.
	If not set then Find in Files directory will be prefilled by directory of current file.
        </td>
      </tr>
      <tr class="windowsonly" id='property-find.in.files.close.on.find'>
        <td>
          find.in.files.close.on.find
        </td>
        <td>
          Set to 0 to prevent the Find in Files dialog from closing when "Find" pressed.
        </td>
      </tr>
      <tr id='property-code.page'>
        <td>
          <a name='property-output.code.page'></a>
          code.page<br />
          output.code.page
        </td>
        <td>
          To support a DBCS language such as Japanese, a code page can be set here. This ensures
          that double byte characters are always treated as a unit so the caret is never located
          between the two bytes of a double byte character.<br/><br/>
  	  <table>
	  <thead><tr><th>Code page</th><th>Value</th></tr></thead>
	  <tr><td>Default (single byte character set)</td><td align="right">0</td></tr>
	  <tr><td>UTF-8</td><td align="right">65001</td></tr>
	  <tr><td>Japanese Shift-JIS</td><td align="right">932</td></tr>
	  <tr><td>Simplified Chinese GBK</td><td align="right">936</td></tr>
	  <tr><td>Korean Wansung</td><td align="right">949</td></tr>
	  <tr><td>Traditional Chinese Big5</td><td align="right">950</td></tr>
	  <tr><td>Korean Johab</td><td align="right">1361</td></tr>
  	  </table>
        Setting code.page to 65001 starts Unicode mode and the document is treated as
        a sequence of characters expressed as UTF-8. Display is performed by converting to the
        platform's normal Unicode encoding first so characters from any language will be displayed.
        Correct glyphs may only be displayed if fonts are chosen that contain the appropriate glyphs.
        The Tahoma font contains a wide range of glyphs so may be a good choice. <br/>
        This property can <em>not</em> set a single byte character set.<br />
	If output.code.page is set then it is used for the output pane which otherwise
	matches the edit pane.
        </td>
      </tr>
      <tr id='property-character.set'>
        <td>
          character.set
        </td>
        <td>
          This setting allows changing the character set that is asked for when setting up fonts.
	Not all of the values will work on all platforms.<br/><br/>
	  <table>
	  <thead><tr><th>Character set</th><th>Value</th></tr></thead>
	  <tr><td>Default</td><td align="right">0</td></tr>
	  <tr><td>Japanese</td><td align="right">128</td></tr>
	  <tr><td>Chinese GB2312</td><td align="right">134</td></tr>
	  <tr><td>Chinese BIG5</td><td align="right">136</td></tr>
	  <tr><td>Korean</td><td align="right">129</td></tr>
	  <tr><td>Greek</td><td align="right">161</td></tr>
	  <tr><td>Eastern European</td><td align="right">238</td></tr>
	  <tr class="windowsonly"><td>Baltic</td><td align="right">186</td></tr>
	  <tr class="windowsonly"><td>Turkish</td><td align="right">162</td></tr>
	  <tr><td>Hebrew</td><td align="right">177</td></tr>
	  <tr><td>Arabic</td><td align="right">178</td></tr>
	  <tr class="windowsonly"><td>Thai</td><td align="right">222</td></tr>
	  <tr class="windowsonly"><td>Vietnamese</td><td align="right">163</td></tr>
	  <tr><td>Cyrillic (CP1251 on Windows, KOI8-R on GTK+)</td><td align="right">204</td></tr>
	  <tr class="gtkonly"><td>Cyrillic (CP1251 on GTK+)</td><td align="right">1251</td></tr>
	  <tr class="gtkonly"><td>European with Euro (ISO 8859-15)</td><td align="right">1000</td></tr>
	  </table>
        All of these values except for 1251 and 1000 should work on OS X or Windows.
        On GTK+ Baltic, Turkish, Thai and Vietnamese will probably not work.
        </td>
      </tr>
      <tr id='property-imports.include'>
        <td>
          <a name='property-imports.exclude'></a>
          imports.include<br />
          imports.exclude
        </td>
        <td>
          These settings control which files are imported by import statements.<br/>
	The imports.include property defines the names of the properties
	files that may be imported. Say you are only interested in using
	fortran and lisp, then in user properties, you could set<br />
	<div class="example">
imports.include=fortran lisp
	</div>
	The imports.exclude property is examined only if imports.include is empty or missing.
	This property stops the named files from being imported.
        </td>
      </tr>
      <tr id='property-command.discover.properties'>
        <td>
        command.discover.properties
        </td>
        <td>
        This property can be used to run a program to determine file encoding and other properties
        when a file is loaded.<br />
        The program should print a list of property=value lines for each property it wants to set.
        This is the same format as properties files.<br />
        <div class="example">
	      command.discover.properties=python /home/user/FileDetect.py "$(FilePath)"
         </div>
        A simple Python script that recognises a particular tag that indicates the file is in the Korean code page 949:<br />
        <div class="example">
<span><span class="S5">import</span><span class="S0"> </span>sys<br />
<span class="S5">if</span><span class="S0"> </span><span class="S3">"Language:Korean"</span><span class="S0"> </span><span class="S5">in</span><span class="S0"> </span>open<span class="S10">(</span>sys<span class="S10">.</span>argv<span class="S10">[</span><span class="S2">1</span><span class="S10">]).</span>read<span class="S10">():</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">print</span><span class="S10">(</span><span class="S4">'code.page=949'</span><span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">print</span><span class="S10">(</span><span class="S4">'character.set=129'</span><span class="S10">)</span><br />
<span class="S0"></span></span>
         </div>
        </td>
      </tr>
      <tr id='property-comment.block'>
        <td>
          <a name='property-comment.block.at.line.start'></a><a name='property-comment.stream.start'></a><a name='property-comment.stream.end'></a><a name='property-comment.box.start'></a><a name='property-comment.box.middle'></a><a name='property-comment.box.end'></a>
        comment.block.<i>lexer</i><br />
        comment.block.at.line.start.<i>lexer</i><br />
        comment.stream.start.<i>lexer</i><br />
        comment.stream.end.<i>lexer</i><br />
        comment.box.start.<i>lexer</i><br />
        comment.box.middle.<i>lexer</i><br />
        comment.box.end.<i>lexer</i>
        </td>
        <td>
        These settings are for the comment commands in the Edit menu and are
        defined separately for each lexer. Not all languages support
        both stream and block comments.<br />
        Block comments are comments that start with a particular string and
        continue until the end of line.
        The comment.block property sets the string to be inserted or deleted
        at the start of the selected lines when the Block Comment or Uncomment
        command is performed. To make this command perform sensibly over
        a range of text that already contains comments and other code, the string
        can be defined to contain a character such as '~' that is not used in real
        comments.<br />
        Set comment.block.at.line.start to "1" to place block comment symbols
        at the start of the lines, instead of just before the first non-blank
        character of the lines.<br />
        Stream comments start with a particular string and end with another
        particular string and may continue over line ends. These are defined
        with comment.stream.start and comment.stream.end. <br />
        Box comments are a form of stream comment that takes several lines
        and uses different strings for the start, end and other lines in the range.
        These are defined with comment.box.start,
        comment.box.middle and comment.box.end.
        </td>
      </tr>
      <tr id='property-preprocessor.symbol'>
        <td>
          <a name='property-preprocessor.start'></a><a name='property-preprocessor.middle'></a><a name='property-preprocessor.end'></a>
        preprocessor.symbol.<i>filepattern</i><br />
        preprocessor.start.<i>filepattern</i><br />
        preprocessor.middle.<i>filepattern</i><br />
        preprocessor.end.<i>filepattern</i>
        </td>
        <td>
        These settings make the preprocessor conditional movement and selection commands work.
        The character that defines preprocessor lines is defined by preprocessor.symbol.
        The preprocessor keywords that make up the start (if), middle (else), and end (endif)
        of preprocessor conditionals are defined by the other three properties.
        There may be multiple values for each of these, as, for example, C uses "if", "ifdef",
        and "ifndef" to begin preprocessor conditionals.
        </td>
      </tr>
      <tr id='property-lexer'>
        <td>
          lexer.<i>filepattern</i>
        </td>
        <td>
          A lexer splits a file up into syntactic pieces. SciTE can then display these pieces in
          different visual styles. Many lexers are included in SciTE for popular
          programming languages such as Python, Java, C/C++, JavaScript and VB. Often several file
          extensions (.cpp, .cc, .h) can map to one language (C++) and hence one lexer. These
          settings associate a file name with a lexer.<br />
          The lexers included in SciTE are written in C++ and compiled into the SciTE executable.
          Lexers can also be written as a <a href="ScriptLexer.html">Lua script</a>
          or as a Lua LPeg lexer using <a href="http://code.google.com/p/scintillua/">scintillua</a>.
        </td>
      </tr>
      <tr id='property-shbang'>
        <td>
          shbang.<i>command</i>
        </td>
        <td>
          On Unix, command files often have no extension and instead specify the interpreter
		    to use for the file in an initial line that starts with "#!". When the lexer can not be
			 otherwise determined and the file starts with "#!", the initial line is split up into words and
			 each word is prepended with "shbang.". If a property with this name exists then it is
			 treated as the extension of the file. For example, <span class="example">shbang.python=py</span> will be
			 triggered by an initial line <span class="example">#!/usr/bin/env python</span> so the file will be treated as Python.
        </td>
      </tr>
      <tr id='property-lexerpath'>
      	<td>
      	lexerpath.<i>filepattern</i>
      	</td>
      	<td>
      	Specifies the path to an external lexer module that will be loaded into Scintilla.
      	</td>
      </tr>
      <tr id='property-keywords'>
        <td>
          <a name='property-keywords2'></a><a name='property-keywords3'></a><a name='property-keywords4'></a><a name='property-keywords5'></a><a name='property-keywords6'></a><a name='property-keywords7'></a><a name='property-keywords8'></a><a name='property-keywords9'></a><a name='property-keywordclass'></a>
          keywords.<i>filepattern</i><br />
          keywords2.<i>filepattern</i><br />
          keywords3.<i>filepattern</i><br />
          keywords4.<i>filepattern</i><br />
          keywords5.<i>filepattern</i><br />
          keywords6.<i>filepattern</i><br />
          keywords7.<i>filepattern</i><br />
          keywords8.<i>filepattern</i><br />
          keywords9.<i>filepattern</i><br />
          keywordclass.<i>lexer</i>
        </td>
        <td>
          Most of the lexers differentiate between names and keywords and use the keywords
          variables to do so. To avoid repeating the keyword list for each file extension, where
          several file extensions are used for one language, a keywordclass variable is defined in
          the distributed properties file although this is just a convention. Some lexers define a
          second set of keywords which will be displayed in a different style to the first set of
          keywords. This is used in the HTML lexer to display JavaScript keywords in a different
          style to HTML tags and attributes.<br />
        Keywords can be prefix based so ^GTK_ will treat all words that start
        with GTK_ as keywords.
        </td>
      </tr>
      <tr id='property-default.file.ext'>
        <td>
          default.file.ext
        </td>
        <td>
          Defines the language mode used before the file has a name. For example, if
          default.file.ext=.py, then when the New command is used to create a new file then Python
          syntax styling is used.
        </td>
      </tr>
      <tr id='property-word.characters'>
        <td>
          word.characters.<i>filepattern</i>
        </td>
        <td>
          Defines which characters can be parts of words. The default value here is all the
          alphabetic and numeric characters and the underscore which is a reasonable value for
          languages such as C++.
        </td>
      </tr>
      <tr id='property-whitespace.characters'>
        <td>
          whitespace.characters.<i>filepattern</i>
        </td>
        <td>
          Defines which characters are considered whitespace. The default value is that initially set up
		  by Scintilla, which is space and all chars less than 0x20.  Setting this property allows you to
		  force Scintilla to consider other characters as whitespace (e.g. punctuation) during such activities
		  as cursor navigation (ctrl+left/right).
        </td>
      </tr>
      <tr id='property-style.*'>
        <td>
          style.*.<i>stylenumber</i><br />
           style.<i>lexer</i>.<i>stylenumber</i>
        </td>
        <td>
          The lexers determine a style number for each lexical type, such as keyword, comment or
          number. These settings determine the visual style to be used for each style number of
          each lexer.<br />
           The value of each setting is a set of ',' separated fields, some of which have a
          subvalue after a ':'. The fields are font, size, fore, back, italics, notitalics, bold,
          notbold, weight, eolfilled, noteolfilled, underlined, notunderlined, and case.
        The font field has a subvalue which is the name of
          the font, the fore and back have colour subvalues,
          the size field has a (fractional) numeric size subvalue,
          the weight field has a numeric size subvalue (1.. 999: 100=light, 400=normal, 700=bold),
          the case field has a subvalue of 'm', 'u', or 'l' for mixed, upper or lower case,
          and the bold, italics and eolfilled fields have no subvalue. The value
          "fore:#FF0000,font:Courier,size:14" represents 14 point, red Courier text.<br />
           A global style can be set up using style.*.<i>stylenumber</i>. Any style options set in
          the global style will be inherited by each lexer style unless overridden.<br />
	On GTK+, the font name should be prefixed with "!" such as "font:!Sans" to ensure Pango
	anti-aliased fonts are used. If this is not done, an older font system will be used which may not work well.
        </td>
      </tr>
      <tr>
        <td>
          style.<i>lexer</i>.32<br />
           style.<i>lexer</i>.33<br />
           style.<i>lexer</i>.34<br />
           style.<i>lexer</i>.35<br />
           style.<i>lexer</i>.36<br />
           style.<i>lexer</i>.37<br />
           style.<i>lexer</i>.38
        </td>
        <td>
          As well as the styles generated by the lexer, there are other numbered styles used.<br />
           Style 32 is the default style and its features will be inherited by all other styles
          unless overridden.<br />
           Style 33 is used to display line numbers in the margin.<br />
           Styles 34 and 35 are used to display matching and non-matching braces
          respectively.<br />
           Style 36 is used for displaying control characters. This is not a full style as the
          foreground and background colours for control characters are determined by their lexical
          state rather than this style.<br />
           Style 37 is used for displaying indentation guides. Only the fore and back are used.<br />
           Style 38 is used for displaying calltips. Only the font, size, fore and back are used.<br />
           A * can be used instead of a lexer to indicate a global style setting.
        </td>
      </tr>
       <tr id='property-braces.check'>
        <td>
          <a name='property-braces.sloppy'></a>
          braces.check<br />
           braces.sloppy<br />
           style.<i>lexer</i>.34<br />
           style.<i>lexer</i>.35<br />
           braces.<i>lexer</i>.style
        </td>
        <td>
          Brace highlighting is a feature that shows the range of a brace when the caret is
          positioned immediately after it. It is especially useful when complex nested braces are
          used. The characters '(', ')', '[', ']', '{', and '}' are considered braces. The feature
          defaults to off (because it slows cursor movement) unless braces.check is set to 1. If
          braces.sloppy is set to 1 then if there is no brace before the caret then the character
          after the caret is checked. The highlighting is performed by displaying the braces in
          style number 34 or in style number 35 if there is no matching brace. While this is a full
          style, to avoid partial display of the braces, it is best to make this style differ from
          the standard style of braces only in foreground and background colour. Only braces with
          style set to braces.<i>lexer</i>.style (which defaults to 0) are candidates for brace
          match highlighting.
        </td>
      </tr>
      <tr id='property-font.monospace'>
        <td>
        font.monospace
        </td>
        <td>
        Defines, with the same syntax as the style properties,
        the font name and size to be used when the Use Monospaced Font
        command is performed.
        </td>
      </tr>
      <tr id='property-command.compile'>
        <td>
          <a name='property-command.compile.subsystem'></a><a name='property-command.build'></a><a name='property-command.build.subsystem'></a><a name='property-command.build.directory'></a><a name='property-command.go'></a><a name='property-command.go.subsystem'></a>
          command.compile.<i>filepattern</i><br />
          command.compile.subsystem.<i>filepattern</i><br />
          command.build.<i>filepattern</i><br />
          command.build.subsystem.<i>filepattern</i><br />
          command.build.directory.<i>filepattern</i><br />
          command.go.<i>filepattern</i><br />
        command.go.subsystem.<i>filepattern</i>
        </td>
        <td>
          These settings choose which commands to execute when the Compile, Build or Go menu items
          are selected. The subsystem options are explained in the subsystem section.<br />
        When source files are in a different directory to that they should be built in, the
        command.build.directory property can be set to change to a particular directory before performing
        the build.
        </td>
      </tr>
      <tr id='property-command.go.needs'>
        <td>
          <a name='property-command.go.needs.subsystem'></a>
          command.go.needs.<i>filepattern</i><br />
          command.go.needs.subsystem.<i>filepattern</i>
        </td>
        <td>
          Sometimes a file must be compiled or built before it can be run. If this is the case,
          this setting indicates what command needs to be run to perform the compile or build step
          before running the file. When a file is compiled, this is noted and future runs will not
          perform a compile or build. To make a 'compile and go' Go command for .c files:
        <div class="example">
                command.go.*.c=$(FileName)<br />
                command.go.needs.*.c=g++ $(FileNameExt) -o $(FileName)<br />
         </div>
        </td>
      </tr>
      <tr>
        <td>
          command.name.<i>number</i>.<i>filepattern</i><br />
        command.<i>number</i>.<i>filepattern</i><br />
          command.is.filter.<i>number</i>.<i>filepattern</i><br />
          command.subsystem.<i>number</i>.<i>filepattern</i><br />
          command.save.before.<i>number</i>.<i>filepattern</i><br />
          <span class="windowsonly">command.input.<i>number</i>.<i>filepattern</i></span><br />
          command.replace.selection.<i>number</i>.<i>filepattern</i><br />
          <span class="windowsonly">command.quiet.<i>number</i>.<i>filepattern</i></span><br />
          command.mode.<i>number</i>.<i>filepattern</i><br />
          command.shortcut.<i>number</i>.<i>filepattern</i>
        </td>
        <td>
          Extra commands can be added to the Tools menu. For example to include the 'astyle'
          indenter, the properties file could contain
         <div class="example">command.name.0.*.cc=Indent<br />
                command.0.*.cc=astyle -taO $(FileNameExt)<br />
                command.is.filter.0.*.cc=1</div>
          The first line defines the string that will appear in the Tools menu (immediately below
          'Go'). The second line is the command string, similar to those of the compile, build, and
          go commands. The optional command.is.filter property states that the command modifies the
          current file so it may need to be read in after performing the command if
          load.on.activate is set.<br />
        If command.save.before is set to 1, SciTE automatically saves the file before execution.
        If it is set to 2, SciTE will not save the file, otherwise SciTE asks you.

        On Windows, the optional command.input property specifies text that will be piped
        to the command.  This may reference other properties; for example,
        <span class="example">command.input.0.*.cc=$(CurrentSelection)</span>
        would pipe the current selection to the command processes.
        The command.input property is only supported for subsystem 0
        (command line programs).<br />
	<br />

        The optional command.replace.selection can be used to specify that the
        command output should replace the current selection (or be inserted at the cursor
        location, if there is no selection).  This property has three available settings:
        0, the default, means do not replace the selection.  1 means replace the selection
        when the command finishes.  2 means replace the selection only if the command
        finishes with an exit code of 0.  If the user cancels the command via "Tools / Stop
        Executing", the selection will not be replaced even in mode 1.  Note, commands run
        asynchronously, so you are not prevented from modifying the document or even
        switching buffers while a command is running.  However, please bear in mind that
        command.replace.selection will send the output to whatever window is active <i>when
        the command completes</i>.<br />

        A final command property that is currently supported only on windows is command.quiet.
        A value of 1 indicates that the command I/O should not be echoed to the output pane.
        This may be useful in combination with command.input and command.replace.selection.<br />
	<br />

        The command.mode property is a comma-separated list of flags / settings.  Each mode
        setting can have an argument, separated from the setting name by a colon.  For
        most of these, the argument portion is optional; if the setting name appears without
        an argument, this works the same as "setting:yes".  If a setting is included in
        the command.mode but also appears as a separate command property, the mode property
        will be overridden.  Similarly, if a single setting appears more than once with
        different arguments, the last valid argument takes priority.  The supported
        command.mode settings are:
      <div class="example">
filter - accepts keyword arguments yes and no<br />
quiet - accepts keyword arguments yes and no<br />
replaceselection - accepts yes, no, and auto<br />
savebefore - accepts yes, no, and prompt<br />
subsystem - console, windows, shellexec, lua, director, winhelp, htmlhelp<br />
groupundo - yes or no
</div>
        Currently, all of these except groupundo are based on individual properties with
        similar names, and so are not described separately here.  The groupundo setting
        works with subsystem 3 (lua / director), and indicates that SciTE should treat any
        changes made by the command as a single undo action.  A command that uses the
        groupundo setting should not change which buffer is active in the editor.<br />

        The command.shortcut property allows you to specify a keyboard shortcut for the
        command.  By default, commands 0 to 9 have keyboard shortcuts Ctrl+0 to Ctrl+9
        respectively, but this can be overridden.  For commands numbered higher than 9,
        there is no default keyboard shortcut.  The notation used to specify keyboard
        shortcuts is the same as for the user.shortcuts property, described elsewhere
        in this document.<br />
	<br />

        If the text of a command starts with '*' then the Parameters dialog is displayed to
        prompt for parameters before executing the command. The initial '*' is not included
        in the command that is executed.<br />
	<br />

        The command number can be in the range of 0 to 49. Command numbers 0 to 9 are
        assigned Ctrl+Number shortcuts. Internally these commands use IDs starting from
        1100 (IDM_TOOLS) which can be used in user.shortcuts and user.context.menu as:
         <div class="example">user.context.menu=Indent|1100|</div>
	 If command.name is empty then no item is added to the Tools menu. This can be used
	 for commands that are only in the context menu or user shortcuts.
        </td>
      </tr>
      <tr id='property-command.help'>
        <td>
          <a name='property-command.help.subsystem'></a>
          command.help.<i>filepattern</i><br />
          command.help.subsystem.<i>filepattern</i>
        </td>
        <td>
        Defines a command to be executed when the help command is
        invoked or F1 pressed. On Windows, this often uses subsystem 4 as described above.
        On OS X or Linux, running man or a browser are common ways of displaying help.
        The word at the cursor is copied to $(CurrentWord) and this is often a good argument
        to the help application. The subsystem property works in the same way as for other
        commands.
        </td>
      </tr>
      <tr id='property-command.scite.help'>
        <td>
          <a name='property-command.scite.help.subsystem'></a>
          command.scite.help<br />
          command.scite.help.subsystem
        </td>
        <td>
        Defines a command to be executed for help on the SciTE program itself which normally
        means displaying this file in a browser.
        </td>
      </tr>
      <tr class="gtkonly" id='property-command.print'>
        <td>
          <a name='property-command.print.subsystem'></a>
          command.print.<i>filepattern</i><br />
          command.print.subsystem.<i>filepattern</i>
        </td>
        <td>
        Defines a command to be executed when print is invoked on GTK+ 2.x.
        On Windows and GTK+ 3.x, printing is performed directly by SciTE.
        </td>
      </tr>
      <tr id='property-time.commands'>
        <td>
        time.commands
        </td>
        <td>
          When a command is completed, print the time it took in seconds.
        </td>
      </tr>
      <tr id='property-print.magnification'>
        <td>
        print.magnification
        </td>
        <td>
          Printing is normally done with the same settings as screen display.
        To make the printing larger or smaller, the print.magnification
        setting is added to the size of every font when printed. To get a
        good miniaturisation of text, set print.magnification to -4.
        </td>
      </tr>
      <tr id='property-print.colour.mode'>
        <td>
        print.colour.mode
        </td>
        <td>
        Some people prefer light coloured text on a black background on
        screen but dark text on white on paper. If print.colour.mode is set
        to 1 then each colour is inverted for printing. If set to 2 then
        printing produces black text on white background. 3 forces the
        background to white and 4 forces the default background to white.
        </td>
      </tr>
      <tr class="windowsonly" id='property-print.margins'>
        <td>
        print.margins
        </td>
        <td>
        Specify the default margins on the printer on Windows in left right top bottom order.
        Units depends on your locale, either hundredths of millimetres or thousandths
        of inches. You can see which units by the units used in the page setup dialog.
        This property is only read at start up.
        </td>
      </tr>
      <tr id='property-print.header.format'>
        <td>
          <a name='property-print.footer.format'></a>
        print.header.format<br />
        print.footer.format
        </td>
        <td>
        These settings determine what will be printed if anything as headers and
        footers. Property settings can be substituted into the values using the $(property)
        syntax. There are some extra properties set up while printing:
        CurrentPage, FileTime, FileDate, CurrentDate, and CurrentTime (at start of
        printing).
        Common properties to use in headers and footers are FileNameExt and FilePath.<br />
        A header setting may look like:<br />
        <div class="example">
        print.header.format=$(FileNameExt) - Printed on $(CurrentDate),$(CurrentTime) - Page $(CurrentPage)
        </div>
        </td>
      </tr>
      <tr id='property-print.header.style'>
        <td>
          <a name='property-print.footer.style'></a>
        print.header.style<br />
        print.footer.style
        </td>
        <td>
        These settings determine the style of the header and footer using the same
        format as other styles in SciTE. Only the fore, back, font, size, bold, italics,
        and underlined attributes are supported.
        </td>
      </tr>
      <tr id='property-export.keep.ext'>
        <td>
        export.keep.ext
        </td>
        <td>
        This property determines how the file name
        (for example, LineMarker.cxx) is transformed when
        exporting to include the appropriate export format extension -
        .html for HTML and .rtf for RTF.
        If export.keep.ext is the default, 0, then the current extension is replaced
        (LineMarker.html).
        If it is 1, then the export format extension is added (LineMarker.cxx.html).
        If it is 2 then the final '.' is replaced by '_' and the
        export format extension added (LineMarker_cxx.html).
        </td>
      </tr>
      <tr id='property-export.html.wysiwyg'>
        <td>
          <a name='property-export.html.tabs'></a><a name='property-export.html.folding'></a><a name='property-export.html.styleused'></a><a name='property-export.html.title.fullpath'></a>
        export.html.wysiwyg<br />
        export.html.tabs<br />
        export.html.folding<br />
        export.html.styleused<br />
        export.html.title.fullpath
        </td>
        <td>
        When export.html.wysiwyg is set to 0 then exporting to a HTML file produces a smaller
        file but which is less completely specified so may look more different to the on screen display.
        When export.html.tabs is set to 1 and export.html.wysiwyg is set to 0 then tab characters in
        the file are exported as tab characters rather than a sequence of space characters.<br />
        The exported file can be made to fold in browsers that support CSS well (Mozilla and Internet
        Explorer) by setting export.html.folding to 1.
        Only export styles actually used when export.html.styleused set to 1.
        The full path name of the file is put in the title, instead of just the file name
        when export.html.title.fullpath set to 1.
        </td>
      </tr>
      <tr id='property-export.rtf.wysiwyg'>
        <td>
          <a name='property-export.rtf.tabs'></a><a name='property-export.rtf.font.face'></a><a name='property-export.rtf.font.size'></a><a name='property-export.rtf.tabsize'></a>
        export.rtf.wysiwyg<br />
        export.rtf.tabs<br />
        export.rtf.font.face<br />
        export.rtf.font.size<br />
        export.rtf.tabsize
        </td>
        <td>
        When export.rtf.wysiwyg is set to 0 then exporting to a RTF file produces a smaller
        file but which is less completely specified so may look more different to the on screen display.
        When export.rtf.tabs is set to 1 and export.rtf.wysiwyg is set to 0 then tab characters in
        the file are exported as tab characters rather than a sequence of space characters. <br />
        export.rtf.font.face and export.rtf.font.size can be used to select a particular font and size
        for the exported RTF file. export.rtf.tabsize can be set to use a different tab size than that
        defined by the tabsize setting.
        </td>
      </tr>
      <tr id='property-export.pdf.magnification'>
        <td>
          <a name='property-export.pdf.font'></a><a name='property-export.pdf.pagesize'></a><a name='property-export.pdf.margins'></a>
        export.pdf.magnification<br />
        export.pdf.font<br />
        export.pdf.pagesize<br />
        export.pdf.margins
        </td>
        <td>
        export.pdf.magnification is a value that is added to the font size of the default screen style in use.
        A positive value increases the PDF document's font size, and vice versa.<br />
        export.pdf.font accepts a one-word parameter that selects one of the default PDF fonts: Courier,
        Helvetica or Times. Helvetica is the default. Helvetica and Times do not line wrap, Courier line
        wraps.<br />
        export.pdf.pagesize is used to set the document's page size, using points (1/72th of an inch) as
        the unit. E.g. Letter paper (8.5 inch x 11 inch) is specified using the values 612,792.<br />
        export.pdf.margins sets the widths of the page margins. Margins defaults to 72 points,
        or 1 inch.<br />
        The PDF exporter is necessarily feature-limited because PDF is a document archival format. Supporting
        a full set of features will bloat SciTE. Wrapping Helvetica or Times adequately isn't possible without
        the complexities of font metrics and kerning. The PDF produced uses WinAnsiEncoding, so pre-encoding
        has to be done before exporting to PDF, if you want to use extended characters.
        </td>
      </tr>
      <tr id='property-export.tex.title.fullpath'>
        <td>
        export.tex.title.fullpath
        </td>
        <td>
        The full path name of the file is put in the title, instead of just the file name
        when export.tex.title.fullpath set to 1.
        </td>
      </tr>
      <tr id='property-export.xml.collapse.spaces'>
        <td>
          <a name='property-export.xml.collapse.lines'></a>
        export.xml.collapse.spaces<br />
        export.xml.collapse.lines
        </td>
        <td>
        export.xml.collapse.spaces and export.xml.collapse.lines are flags that control how empty lines
        and runs of space characters are converted into XML. The flags are enabled if set to 1. Tab
        characters are always converted by the XML exporter into spaces according to the tabsize property.
        </td>
      </tr>
      <tr id='property-fold'>
	<td>fold</td>
	<td>Folding is turned on by setting fold=1.</td>
      </tr>
      <tr id='property-fold.symbols'>
        <td>
          fold.symbols
        </td>
        <td>
        The fold.symbols setting chooses between four ways of showing folding.
        Set to 0 (the default) for MacOS style arrows to indicate contracted
        (facing right) and expanded (facing down); 1 to display contracted folds
        with "+" and expanded with "-"; 2 for a flattened tree control with round
        headers and rounded joins; 3 for a flattened tree control with square headers.
        </td>
      </tr>
      <tr id='property-fold.margin.width'>
        <td>
          fold.margin.width
        </td>
        <td>
          Sets the width of the fold margin.
        </td>
      </tr>
      <tr id='property-fold.margin.colour'>
        <td>
          <a name='property-fold.margin.highlight.colour'></a>
          fold.margin.colour<br />
          fold.margin.highlight.colour
        </td>
        <td>
          These two properties defined the fold margin colour and fold
          margin highlight colour.  If they are not defined (left commented out) the colours for the
          fold margin will default to a reasonable pair of colours.
          On Windows, the system colours are used to make the fold margin appear like the background
          of scroll bars. As an example, with <span class="example">fold.margin.colour=#FF0000</span> and
          <span class="example">fold.margin.highlight.colour=#0000FF</span>, the fold margin is a mixture of red
          and blue.
        </td>
      </tr>
      <tr id='property-fold.on.open'>
        <td>
          fold.on.open
        </td>
        <td>
        To automatically fold files as much as possible when loaded, set
        fold.on.open to 1.
        </td>
      </tr>
      <tr id='property-fold.flags'>
        <td>
          fold.flags
        </td>
        <td>
                Not really documented ;) bit flags which may go away.
        2, 4, 8, and 16 control drawing lines above and below folding lines if
        expanded or not expanded.
        Set to 64 to help debug folding by showing hexadecimal fold levels in margin.
        </td>
      </tr>
      <tr id='property-fold.compact'>
        <td>
          fold.compact<br />
        </td>
        <td>
        For HTML, XML, Lua and C++ and similar files, turning this option on leads to blank lines following the
        end of an element folding with that element. Defaults to on.
        </td>
      </tr>
      <tr id='property-fold.highlight'>
        <td>
          fold.highlight<br />
        </td>
        <td>
        Set to 1 to enable highlight for current folding block (smallest one that contains the caret).
	By default, it's disable. Note : The highlight is enabled only when fold.symbols equals
	to 2 (round headers) or 3 (square headers).
        </td>
      </tr>
      <tr id='property-fold.highlight.colour'>
        <td>
          fold.highlight.colour<br />
        </td>
        <td>
        Define the colour of highlight. The colour by default is red (#FF0000).
        </td>
      </tr>
      <tr id='property-title.full.path'>
        <td>
          title.full.path
        </td>
        <td>
                Chooses how the file name is displayed in the title bar.
        When 0 (default) the file name is displayed. When 1 the full path is displayed.
               When 2 the window title displays "filename in directory".
        </td>
      </tr>
      <tr id='property-title.show.buffers'>
        <td>
          title.show.buffers
        </td>
        <td>
                When set to 1 shows the current buffer number in the title bar.
        </td>
      </tr>
      <tr id='property-tabsize'>
        <td>
          <a name='property-tab.size'></a><a name='property-indent.size'></a><a name='property-use.tabs'></a><a name='property-indent.auto'></a><a name='property-tab.indents'></a><a name='property-backspace.unindents'></a>
          tabsize<br />
          tab.size.<i>filepattern</i><br />
        indent.size<br />
        indent.size.<i>filepattern</i><br />
          use.tabs<br />
          use.tabs.<i>filepattern</i><br />
        indent.auto<br />
        tab.indents<br />
        backspace.unindents
        </td>
        <td>
          Sets the size of a tab as a multiple of the size of a space character in the style of the
          default style definition. The indent size is the size to use when performing automatic
        indentation and may be different from the tab size. Many people use a tab size of 8 but
        4 character indentation. When creating indentation, use.tabs determines whether the
        indentation is made up purely from space characters or from a mix of tabs and spaces
        using as many tabs as possible. <br />
        The global tabsize, indent.size, and use.tabs properties can be overridden for
        files that match a pattern by using the file pattern forms: <br />
        <div class="example">
        indent.size.*.pas=3</div>
        If indent.auto is set then indent.size and use.tabs are set according to the contents
        of the opened document.<br />
        The properties file settings apply to newly opened files but remain constant once the file is open
	unless changed using the Change Indentation Settings dialog.<br />
        If tab.indents is set then pressing tab within indentation whitespace indents by indent.size
        rather than inserting a tab character. If backspace.unindents then pressing backspace
        within indentation whitespace unindents by indent.size rather than deleting the character
        before the caret.
        </td>
      </tr>
      <tr id='property-indent.automatic'>
        <td>
          <a name='property-indent.opening'></a><a name='property-indent.closing'></a><a name='property-indent.maintain'></a>
        indent.automatic<br />
        indent.opening<br />
        indent.closing<br />
        indent.maintain.<i>filepattern</i>
        </td>
        <td>
          Determines the look of automatic indentation. Automatic indentation is turned on with
          indent.automatic=1. To indent a brace line after a compound statement start set
          indent.opening=1, likewise for the terminating brace. So with both set to 0:
        <div class="example">
                if (c)<br />
                {<br />
                &nbsp;&nbsp;&nbsp;&nbsp;s;<br />
                }<br />
         </div>
         And with both set to 1:
        <div class="example">
                if (c)<br />
                &nbsp;&nbsp;&nbsp;&nbsp;{<br />
                &nbsp;&nbsp;&nbsp;&nbsp;s;<br />
                &nbsp;&nbsp;&nbsp;&nbsp;}<br />
         </div>
         Automatic indentation may be changed to simply repeat the indentation of the
         previous line for some files with indent.maintain.<i>filepattern</i>=1 which
         overrides the other language specific settings.
         </td>
      </tr>
      <tr id='property-statement.indent'>
        <td>
          <a name='property-statement.end'></a><a name='property-statement.lookback'></a><a name='property-block.start'></a><a name='property-block.end'></a>
        statement.indent.<i>filepattern</i><br />
        statement.end.<i>filepattern</i><br />
        statement.lookback.<i>filepattern</i><br />
        block.start.<i>filepattern</i><br />
        block.end.<i>filepattern</i>
        </td>
        <td>
          Each of these settings starts with a style number and then a set of words or characters
          that define how to recognise that feature. If there is a second space in the setting then
          it is a set of words, otherwise a set of characters. The set of keywords used to indicate
          the start of a compound statement is defined in statement.indent. For example:
        <div class="example">
                statement.indent.$(file.patterns.cpp)=5 if else while
         </div>
          says that for C++ the words "if", "else", and "while" in keyword style, 5, start compound
          statements which leads to the next line being indented if no other factors affect it. However,
          if a statement end is found on the same line then the next line is not indented. For C++ the
          statement end is the semicolon in the operator style, so this is defined:
         <div class="example">
                statement.end.$(file.patterns.cpp)=10 ;
         </div>
         The number of lines looked at to determine indentation can be set with statement.lookback.
         This can be used either to bound the amount of time spent on this task or to specify
         that only the last line be examined for indentation.<br />
         The block.start and block.end properties define the language elements used to bracket groups
         of statements. In C++ these are '{' and '}'.
        </td>
      </tr>
      <tr id='property-indent.python.colon'>
        <td>
        indent.python.colon
        </td>
        <td>
          For Python, automatically indent by one level if the previous line ended in a ':'
	ignoring comments and whitespace. Otherwise use the same indentation as the previous line.
	This property overrides other indentation settings.
         </td>
      </tr>
      <tr id='property-os.x.home.end.keys'>
        <td>
          os.x.home.end.keys
        </td>
        <td>
	Chooses the standard OS X behaviour for the Home and End keys which is
	to scroll the file to the start or end. This setting takes precedence over
	vc.home.key.
        </td>
      </tr>
      <tr id='property-vc.home.key'>
        <td>
          vc.home.key
        </td>
        <td>
                Chooses the behaviour of the Home and Shift+Home keys. 1, the default is like
        Visual C++ moving the caret to the end of the line indentation unless already
        there, in which case it moves to the start of the line. 0 moves to the start of the line.
        </td>
      </tr>
      <tr class="windowsonly" id='property-warning.findwrapped'>
        <td>
          <a name='property-warning.notfound'></a><a name='property-warning.wrongfile'></a><a name='property-warning.executeok'></a><a name='property-warning.executeko'></a><a name='property-warning.nootherbookmark'></a>
          warning.findwrapped<br />
          warning.notfound<br />
          warning.wrongfile<br />
          warning.executeok<br />
          warning.executeko<br />
          warning.nootherbookmark
        </td>
        <td>
                Allows for sounds to be played and the window to be flashed
        on Windows when particular events occur.
        The values consist of three items separated by ',': flash duration, sound
        and sound duration. If sound is a number then it is treated as a pitch and
        played for the duration in milliseconds.
        Otherwise it is treated as a path to a sound file
        that is played. If you do not want a flash, specify 0 for flash duration.
        For example,
        <div class="example">
        warning.wrongfile=0,C:\Windows\Media\SFX\Glass.wav
        </div>
        will play the glass sound if open selected is given a bad file name.
        The findwrapped warning occurs when a find operation wraps past
        either end of the file,
        notfound when the find or preprocessor conditional move commands
        fail to find a match,
        executeok when a command such as build
        executes successfully, executeko when a command fails, and
        nootherbookmark when there is no bookmark to find.
        </td>
      </tr>
      <tr class="gtkonly" id='property-fileselector.width'>
        <td>
          <a name='property-fileselector.height'></a>
          fileselector.width<br />
          fileselector.height
        </td>
        <td>
          For the GTK+ version determines the initial size of the file
          selector dialog invoked by the Open and Save commands.
          Setting has no effect on Windows.
        </td>
      </tr>
      <tr id='property-fileselector.show.hidden' class="osxonly">
        <td>
          fileselector.show.hidden
        </td>
        <td>
          On OS X setting this to 0 makes the file selector dialog
          invoked by the Open command not show hidden files.
        </td>
      </tr>
      <tr id='property-locale.properties'>
        <td>
        locale.properties
        </td>
        <td>
          Set the name of the localisation file. For a multi-user installation
	this allows each user to set a preferred user interface language.<br />
	On OS X, localisation files for some languages are installed in the translations
	subdirectory of the user home directory which allows setting
	the user interface to, for example, German with
		<div class="example">
		locale.properties=$(SciteUserHome)/translations/locale.de.properties
		</div>
        </td>
      </tr>
      <tr id='property-translation.missing'>
        <td>
        translation.missing
        </td>
        <td>
                When using a localised version, if a term is not found in the locale.properties
        translation file then use the value of translation.missing instead. By setting
        this to a marker such as "***" it is easier to check where terms have not been
        provided with translations.
        </td>
      </tr>
      <tr id='property-menu.language'>
        <td>
        menu.language
        </td>
        <td>
                Defines the entries in the Language menu and the file extensions they map to.
		Each menu item is defined by 3 elements, language name, extension and an optional
		keyboard equivalent. Each element is terminated by '|'. For example:<br />
		H&amp;ypertext|html|F12|<br />
		Menu items may be commented out by prefixing the name with '#'.
        </td>
      </tr>
      <tr class="gtkonly" id='property-menukey.*'>
        <td>
        menukey.*
        </td>
        <td>
                The menukey.* settings allow the user to redefine accelerator keys for menus
		without having to resort to modifying the SciTE source code.  The syntax for the setting is:
		<div class="example">
		menukey.menu_title.menu_name=&lt;modifier&gt;key
		</div>
		For example, the File | Exit command accelerator could be specifed as follows:
		<div class="example">
		menukey.file.exit=&lt;control&gt;Q
		</div>
		Note that spaces in menu titles and names must be converted to underscores,
		and trailing ellipses removed.  For example, "File | Save As...." is referenced as "menukey.file.save_as".
		<br /><br />
		Multiple modifiers may be specified, though each must be surrounded by angle brackets.  The
		recognised modifiers are the same as for the user.shortcuts setting described above.  The recognised named
		keys are also the same as for user.shortcuts, with the addition of "none" to indicate that no accelerator
		key should be defined for a particular menu.
        </td>
      </tr>
      <tr class="windowsonly" id='property-source.default.extensions'>
        <td>
          source.default.extensions
        </td>
        <td>
          If the name specified on the command line cannot be found as a directory or file - including a wild-card
          search, the contents of the property are treated as default extensions to be used to locate the file name.<br />
          An example is: .cxx|.cpp|.c|.hxx|.hpp|.h|.bat|.txt|.lua<br />
          Attempting to open win32\SciTEWin would open win32\SciTEWin.cxx since it matches before win32\SciTEWin.h
          <br />
          If the property contains an entry such as Bar.cxx|.cxx and you attempt to open win32\SciTEWin, it will open
          ScTEWinBar.cxx since that is the first match.
        </td>
      </tr>
      <tr id='property-ext.lua.startup.script'>
        <td>
          <a name='property-ext.lua.auto.reload'></a><a name='property-ext.lua.reset'></a><a name='property-extension'></a>
          ext.lua.startup.script<br />
          ext.lua.auto.reload<br />
          ext.lua.reset<br />
          extension.<i>filepattern</i>
        </td>
        <td>
          The ext.lua properties are specific to the <a href="SciTELua.html">
          SciTE Lua Scripting Extension</a>.  The extension.<i>filepattern</i> property
          is part of the generic <a href="SciTEExtension.html">SciTE Extension
          Interface</a> but is currently only used by the Lua Scripting Extension.
          <br />
          The ext.lua.startup.script property defines the filename of a Lua script that
          will be loaded when SciTE starts to set up the global state for Lua.
          The default value is $(SciteUserHome)/SciTEStartup.lua.
          You should use an absolute path for this property, but can reference the
          $(SciteDefaultHome) or $(SciteUserHome) properties.  Global event handlers,
          command functions, as well as other functions and objects can be defined here.
          <br />
          The ext.lua.auto.reload property determines what happens if you save the
          startup script, or the active extension script, from within SciTE.  If it
          is set to 0, the startup script only applied at startup time
          or when you switch buffers (depending on ext.lua.reset), and changes to the
          extension script are only applied when you switch buffers.  If
          ext.lua.auto.reload is set to 1 (the default), SciTE will re-initialize the global scope
          immediately when either script is saved from within SciTE.  <i>Even
          when ext.lua.auto.reload is enabled, SciTE will not notice if the files
          are changed from outside the current SciTE instance.  For that, see
          ext.lua.reset below.</i>
          <br />
          The ext.lua.reset property is primarily for debugging.  If ext.lua.reset
          is 0 (the default), the startup script property is checked only once -
          when SciTE starts.  If ext.lua.reset is changed to 1, SciTE will check
          the startup script property, and reload the new startup script, each
          time you switch buffers.  As such, it has a different (larger) set of
          side effects than ext.lua.auto.reload.  In some situations it will make
          sense for both auto.reload and reset to be enabled, but usually
          ext.lua.auto.reload alone will suffice.
          <br />
          Aside from ext.lua.startup.script, the extension.<i>filepattern</i> property
          provides a way to load additional functions and event handlers that may be
          specific to a given file type.  If the extension property value ends in .lua
          and names a file that exists, the Lua extension evaluates the script so that event
          handlers and commands defined in the script are available while that buffer
          is active.  Functions and objects defined through ext.lua.startup.script are
          still accessible, unless they are overridden.
          <br />
          The extension property can also define behavior that is specific to a given
          directory.  If a bare filename (no path) is specified in the extension
          property, SciTE looks for the file in the standard property file locations,
          starting with the local directory.  This can be very useful in combination
          with a local SciTE.properties file.
        </td>
      </tr>
      <tr id='property-caret.sticky'>
        <td>
          caret.sticky
        </td>
        <td>
          Controls when the last position of the caret on the line is modified.
		  When set to 1, the position is not modified when you type a character, a tab,
		  paste the clipboard content or press backspace. The default is 0 which turns
		  off this feature.
        </td>
      </tr>
	  <tr id='property-properties.directory.enable'>
        <td>
          properties.directory.enable
        </td>
        <td>
          Enables or disables the evaluation of the directory properties file.
          The default is 0 which disables the evaluation. Any other value enables
		   this properties file.
        </td>
      </tr>
    </table>
    <p>
    caret.policy.{x|y}&lt;param&gt; interaction:
    </p>
    <table cellpadding="1" cellspacing="0" border="1" summary="Caret policy">
     <tr>
      <th>slop</th>
      <th>strict</th>
      <th>jumps</th>
      <th>even</th>
      <th>Caret can go to the  margin</th>
      <th>When reaching limit<br />
      (going out of visibility or<br />
      going into the UZ)<br />
      display is...</th>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td>Yes</td>
      <td>moved to put caret on top/on right</td>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td>Yes</td>
      <td>moved by one position</td>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">0</td>
      <td>Yes</td>
      <td>moved to put caret on top/on right</td>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">1</td>
      <td>Yes</td>
      <td>centred on the caret</td>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">-</td>
      <td align="center">0</td>
      <td>Caret is always on top/on right of display</td>
      <td>-</td>
     </tr>
     <tr>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">-</td>
      <td align="center">1</td>
      <td>No, caret is always centred</td>
      <td>-</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td>Yes</td>
      <td>moved to put caret out of the asymmetrical UZ</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">0</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td>Yes</td>
      <td>moved to put caret out of the UZ</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">0</td>
      <td>Yes</td>
      <td>moved to put caret at 3UZ of the top or right margin</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td align="center">1</td>
      <td>Yes</td>
      <td>moved to put caret at 3UZ of the margin</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">1</td>
      <td align="center">-</td>
      <td align="center">0</td>
      <td>Caret is always at UZ of top/right margin</td>
      <td>-</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">1</td>
      <td align="center">0</td>
      <td align="center">1</td>
      <td>No, kept out of UZ</td>
      <td>moved by one position</td>
     </tr>
     <tr>
      <td align="center">1</td>
      <td align="center">1</td>
      <td align="center">1</td>
      <td align="center">0</td>
      <td>No, kept out of UZ</td>
      <td>moved to put caret at 3UZ of the margin</td>
     </tr>
    </table>
    <h3 id="NewLanguage">
       Supporting a new language
    </h3>
    <p>
       For languages very similar to existing supported languages, which may only differ in a minor
      feature such as the keywords used, the existing lexers can often be reused. The set of
      keywords can then be changed to suit the new language. Java and JavaScript could have
      reasonably reused the C++ lexer. The Java lexer was added only to support doc comments.
    </p>
    <p>
       For languages that can not be lexed with the existing lexers, a new lexer can be coded in
      C++.&nbsp; These can either be built into Scintilla, or put into an
		external module and loaded when SciTE runs (See lexerpath).</p>
       <a href="SciTELexer.html">Installing a lexer into SciTE</a>
    <br />
		<a href="SciTEExternalLexer.html">Creating and installing an external
		lexer</a><br />
    <p>
       The open.filter should be modified to include the file extensions used for the new language
      and entries added for command.compile, command.build, command.go and command.go.needs for the
      language.
    </p>
    <h3 id="APIFiles">
       Creating API files
    </h3>
    <p>
       The .api files can be generated by hand or by using a program.
       There are also <a href="http://code.google.com/p/scite-files/wiki/Customization">downloadable ready-to-use
       .api files.</a>
    </p>
    <p>
        For C/C++ headers, an API file can be generated using
        <a href="http://ctags.sourceforge.net/">ctags</a>
        and then the <a href="tags2api.py">
        tags2api Python script</a> (which assumes C/C++ source) on the tags file to grab complete
        multiple line function prototypes.
        Some common headers surround parameter lists with a __P macro and may have
        comments. The <a href="cleanapi.cc">cleanapi</a> utility may be used on these files.
    </p>
    <p>
        To generate an API file for Python modules, there is a
        <a href="gen_python_api.zip">gen_python script</a>.
    </p>
    <p>
        To generate an API file for Java classes, there is a
        <a href="ApiBuilder.java">ApiBuilder.java</a> program.
    </p>
    <h3 id="OpenSelected">
       Open Selected Filename
    </h3>
    <p>
       This command opens the file for the file name selected in either the edit or output pane.
       It uses the current selection or searches around the caret to try to
       find a file name based on which characters are normally used in a path.
       If there is no extension then an extension may be inferred from the current file using the
       open.suffix property which defaults to .properties in a .properties file.
       If the file name is followed by a number (in a format similar to ctags, grep output,
       or Visual Studio messages) then that line is displayed in the opened file.
       If the file name is an absolute path then it is opened directly otherwise it is looked for
       in the current directory and then in the directory specified by the openpath property.
       On Windows, web, ftp, mail and news URLs are handled by opening their
       associated application.
    </p>
    <h3 id="Translations">
       SciTE in other languages
    </h3>
    <p>
       SciTE can be and has been <a href="http://code.google.com/p/scite-files/wiki/Translations">translated into other languages</a>.
    </p>
    <h3 id="Building">
       Building SciTE
    </h3>
    <p>
       The procedure for building and installing SciTE is described in the README file in the scite
       directory.
    </p>
    <h3 id="Extending">
       Extending SciTE
    </h3>
    <p>
       There are two formal extension interfaces for SciTE, the
       <a href="SciTEExtension.html">SciTE Extension Interface</a>
       is for extending SciTE with code compiled into the SciTE executable and the
       <a href="SciTEDirector.html">SciTE Director Interface</a> is for
       manipulating SciTE on Windows from another application.
    </p>
  </body>
</html>

Added doc/SciTEDownload.html.











































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Download Scintilla and SciTE
    </title>
  <style type="text/css">
    h3 {
	background-color: #CCCCFF;
    }
  </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Download
          Scintilla and SciTE</font></a>
        </td>
      </tr>
    </table>
    <table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
      <tr>
        <td>
          <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scite325.zip?download">
	Windows</a>&nbsp;&nbsp;
	<a href="http://prdownloads.sourceforge.net/scintilla/scite325.tgz?download">
          GTK+/Linux</a>&nbsp;&nbsp;</font>
        </td>
      </tr>
    </table>
    <h2>
       Download
    </h2>
    <p>
       The <a href="License.txt">license</a> for using Scintilla or SciTE is similar to that of Python
      containing very few restrictions.
    </p>
    <h2>
       Release 3.2.5
    </h2>
    <h3>
       Source Code
    </h3>
       The source code package contains all of the source code for Scintilla and SciTE but no binary
	executable code and is available in
       <ul>
       <li><a href="http://prdownloads.sourceforge.net/scintilla/scite325.zip?download">zip format</a> (2250K) commonly used on Windows</li>
       <li><a href="http://prdownloads.sourceforge.net/scintilla/scite325.tgz?download">tgz format</a> (2000K) commonly used on Linux and compatible operating systems</li>
       </ul>
       Instructions for building on both Windows and Linux are included in the readme file.
    <h3>
       Windows
    </h3>
    <h4>
       Windows Executables
    </h4>
    <p>
       Windows executables only support Windows XP and later. It may be possible to build with older compilers for Windows 2000 but that
       is no longer tested.
    </p>
    <p>
       A <a href="http://prdownloads.sourceforge.net/scintilla/wscite325.zip?download">full download</a> (1100K) includes the SciTE executable, any required DLLs,
      configuration files and documentation. After downloading the file, unzip it, and run
      SciTE.EXE. The files required to run SciTE are SciTE.EXE, SciLexer.DLL, and
      SciTEGlobal.properties.
    </p>
    <p>
       A <a href="http://prdownloads.sourceforge.net/scintilla/Sc325.exe">single file executable called Sc1</a> (700K) does not need any DLL or
      properties files as these are linked into the executable. You may still create properties
      files if you wish.
      Sc1.exe has been compressed with the
      <a href="http://upx.sourceforge.net">UPX compressor</a>
      so that it is a fast download. It does not need to be decompressed to be used.
    </p>
    <h4>
       Windows Installer
    </h4>
    <p>
       <a href="http://opensource.ebswift.com/SciTEInstaller/">An installer</a>
       created by Troy Simpson.
    </p>
    <h3>
       GTK+ / Linux
    </h3>
    <h4>
       Linux executable for 32-bit Intel compatible processors
    </h4>
    <p>
      This binary release requires GTK+ 2.8 or later and was tested on Ubuntu 10.4.
      If you are using a Linux distribution more than a year old you may
      need to rebuild SciTE to use your installed version of GTK+.
      If the target system is 64-bit, you may also need to build SciTE from source.
    </p>
    <p>
       A <a href="http://prdownloads.sourceforge.net/scintilla/gscite325.tgz?download">full download</a> (1000K) includes the 32-bit SciTE executable,
      configuration files and documentation.
      After downloading the file, gunzip and untar it, and run
      SciTE. The files required to run SciTE are SciTE which is best located on the path
      (I put it in /usr/local/bin) 70 properties files which should be located in the
      /usr/share/scite directory, and Sci48M.png which should be copied to /usr/share/pixmaps.
    </p>
    <h4>
       Debian Packages
    </h4>
    <p>
       Official Debian Packages are available from Apt.
       There is a
       <a href="http://packages.debian.org/etch/scite">package page</a>.
    </p>
    <p>
       Contributed by Aubin Paul.
    </p>
    <h3>
       SciTE localised for other languages
    </h3>
    <p>
       SciTE can be and has been <a href="http://code.google.com/p/scite-files/wiki/Translations">translated into other languages</a>.
    </p>
    <p>
       Previous versions can be downloaded from the <a href="ScintillaHistory.html">history
      page</a>.
    </p>
  </body>
</html>

Added doc/SciTEExtension.html.































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      SciTE Extension Interface
    </title>
    <style type="text/css">
        .example {
            color: #00A000;
            font-weight: bold;
        }
        DIV.example {
            background: #F7FCF7;
            border: 1px solid #C0D7C0;
            margin: 0.3em 3em;
            padding: 0.3em 0.6em;
            font-size: 80%;
        }
    </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  SciTE Extension Interface</font></a>
        </td>
      </tr>
    </table>
    <h3>
       Purpose.
    </h3>
	<p>Some people want to create enhanced versions of the SciTE editor, while
	still receiving the benefits of new SciTE features. This could be for an
	editor designed for a particular environment such as developing games,
	to incorporate a scripting capability within SciTE or to allow SciTE to be
	controlled by another process through an IPC mechanism.</p>
	<p>There are two example extensions.
	The <a href="SciTEDirector.html">SciTE Director Interface</a> allows
	SciTE on Windows to be controlled by an external application such as a
	project manager.
	The <a href="SciTELua.html">SciTE Lua Scripting Extension</a> is an
	integration of the Lua scripting language into SciTE, done using the Extension
	interface.</p>
    <h3>
       Extension Interface.
    </h3>
    <div class="example">
	bool Initialise(ExtensionAPI *host_);<br />
	bool Finalise();<br />
	bool Clear();<br />
	bool Load(const char *filename);<br />
	bool InitBuffer(int index);<br />
	bool ActivateBuffer(int index);<br />
	bool RemoveBuffer(int index);<br />
	bool OnOpen(const char *path);<br />
	bool OnSwitchFile(const char *path);<br />
	bool OnBeforeSave(const char *path);<br />
	bool OnSave(const char *path);<br />
	bool OnChar(char ch);<br />
	bool OnExecute(const char *s);<br />
	bool OnSavePointReached();<br />
	bool OnSavePointLeft();<br />
	bool OnStyle(unsigned int, int, int, Accessor *);<br />
	bool OnDoubleClick();<br />
	bool OnUpdateUI();<br />
	bool OnMarginClick();<br />
	bool OnMacro(const char *, const char *);<br />
	bool SendProperty(const char *);<br />
	bool OnKey(int keyval, int modifiers);<br />
	bool OnDwellStart(int pos, const char *word);<br />
	bool OnClose(const char *filename);<br />
    </div>
	<p>An extension must implement the Extension interface defined in scite/src/Extender.h
	Only the first 4 methods must be implemented although an implementation can be as
	simple as just returning false. The other methods have empty default implementations.
	Methods added to this interface in the future should have default implementations so
	existing extensions will continue to compile.</p>
	<p>Each method returns a bool indicating whether the method handled all processing that
	is needed and so no additional processing is required. Normally, false is returned to indicate
	that further processing may be done.</p>
	<p>The extension should use the Initialise and Finalise methods to allocate
	and deallocate resources. The ExtensionAPI pointer should be saved in the
	Initialise method so the extension can communicate back to SciTE.</p>
	<p>The Clear and Load methods are used to support extensions that need
	to load a resource such as a script file when a file is opened. When a file is
	opened in SciTE, first the extension is asked to clear any data associated with
	the previous file through Clear. Then SciTE checks for a property called
	"extension" which matches the file name, so for x.cpp, looks for extension.*.cpp.
	A file with this name is searched for in standard property file locations and if found
	Load is called with the path as an argument.</p>
	<p>The InitBuffer, ActivateBuffer, and RemoveBuffer methods provide the necessary hooks
	so that extensions have a mechanism to associate data with a specific buffer, similar
	to the way SciTE itself remembers the monospace setting of each buffer.  InitBuffer is
	called whenever a new document is opened in a given buffer.  The buffer might be a newly
	allocated one, or it might be recycled if the maximum number of buffers has been reached.
	Once the buffer has been initialized, it will be the active buffer.  Thereafter,
	ActivateBuffer is called whenever the user switches to another loaded buffer.
	RemoveBuffer is called when an existing buffer is closed.  Thereafter, the indexes of
	the buffers that come after the removed buffer are shifted down by one.  After
	RemoveBuffer, the extension will receive an InitBuffer or ActivateBuffer to establish
	the new active buffer.</p>
	<p>OnExecute is called only when an extension command is executed. These are
	indicated in properties as subsystem 3.</p>
	<p>OnBeforeSave is called before saving the file and an extension may implement
	file saving itself and return true to prevent the default file save code from executing.</p>
	<p>Other methods are called upon events occurring in SciTE allowing an extension
	to respond to those events.</p>
    <h3>
       ExtensionAPI Interface.
    </h3>
	<div class="example">
	enum Pane { paneEditor=1, paneOutput=2, paneFindOutput=3 };<br />
	sptr_t Send(Pane p, unsigned int msg, uptr_t wParam=0, sptr_t lParam=0);<br />
	char *Range(Pane p, int start, int end);<br />
	void Remove(Pane p, int start, int end);<br />
	void Insert(Pane p, int pos, const char *s);<br />
	void Trace(const char *s);<br />
	char *Property(const char *key);<br />
	void SetProperty(const char *key, const char *val);<br />
	uptr_t GetInstance();<br />
	void ShutDown();<br />
	void Perform(const char *actions);<br />
	void DoMenuCommand(int cmdID);<br />
	void UpdateStatusBar(bool bUpdateSlowData);<br />
    	</div>
	<p>An extension can call back into SciTE using this interface which is a simplified
	way to access the functionality of SciTE.</p>
	<p>As well as the normal editor pane and output pane, this interface allows for
	a future feature where a third pane may be used for the output of search
	commands. This is currently mapped to the output pane.</p>
	<p>Send allows sending messages to the Scintilla control contained in each pane.</p>
	<p>Range retrieves text from the pane. This must be deleted with delete[].
	Remove and Insert are used to remove and insert text in a pane.</p>
	<p>Trace displays a string at the end of the output pane.</p>
	<p>SciTE's properties can be read and written with Property and
	SetProperty. The result from Property should be deleted with delete[].</p>
	<p>GetInstance is Windows specific and returns the HINSTANCE of
	the application which is needed when accessing platform facilities.</p>
	<p>ShutDown is equivalent to the user choosing the Quit menu item.
	If there are any unsaved files loaded, then the user is asked whether to save them
	and may cancel from this dialog. So under some circumstances, the application will
	continue to run after ShutDown is called.</p>
	<p>Perform takes a string containing an action, a ':' character, and an argument.
	Currently the only known action is open and then the argument is a path.
	This is used by the <a href="SciTEDirector.html">Director extension</a>
	to relay commands from another application.
	In the future more actions will be possible through this method.</p>
    <h3>
       Attaching the extension.
    </h3>
    	<p>Extensions are currently added explicitly by code in the start up function.
	On Windows, the DirectorExtension is attached with code similar to this simplified
	example:</p>
	<div class="example">
DirectorExtension director;<br />
Extension *extender = &director;<br />
//...<br />
SciTEWin MainWind(extender);
</div>
	<p>It would be better to move to an implicit attachment mechanism similar to the
	way lexers are attached to Scintilla, determining which extensions are used
	by simply linking their object files into SciTE. It would also be good to
	allow run-time attachment of extensions housed in DLLs or shared object libraries.</p>
    <h3>
       Multiplexing.
    </h3>
	<p>SciTE supports multiple extensions at a time. A multiplexer extension
	maintains a list of extensions and calls each in turn for each method. Once an extension
	returns true indicating processing should stop, the multiplexer returns without traversing
	any remaining list members. However, for some methods such as Initialise and Finalise,
	the remaining extensions are traversed regardless of the return value of the previous
	extension.</p>
    <h3>
       Thread safety.
    </h3>
	<p>In general, SciTE is a single threaded application.  However, on Windows, command
	tools call OnExecute from a separate worker thread.  The SingleThreadExtension adapter
	class can be used to wrap an extension so that OnExecute calls are marshalled to the
	main thread.  Of course, this is not necessary if your extension is thread safe, or
	if it does not implement OnExecute, or if it is a GTK-specific extension.
  </body>
</html>

Added doc/SciTEExternalLexer.html.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</html>
<body bgcolor="#FFFFFF" text="#000000">

    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0" id="table1">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  Add an external lexer to SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Lexer addition.
    </h2>
    <p>This document has been superceded by the new
    <a href="http://www.scintilla.org/nulex.html">lexer object design</a>
    </p>
</body>
</html>

Added doc/SciTEExtras.html.

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      SciTE Extras
    </title>
<style type="text/css">
        table {
            border: 1px solid black;
            border-collapse: collapse;
        }
        td {
            border: 1px solid black;
            padding: 1px 5px 1px 5px;
        }
        th {
            border: 1px solid black;
            padding: 1px 5px 1px 5px;
        }
 </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
          API files and property files for SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2 style="background: #FFB000">
        <a href="http://code.google.com/p/scite-files/wiki/Customization">The current version of this page has moved here</a>.
    </h2>
    <h3>
       This page contains various contributed files that can be used with SciTE.
    </h3>
    <h3>
       Shells
    </h3>
    <ul>
    <li><a href="http://llt.chez.tiscali.fr/">Filerx</a>
    provides project management and macro features on Windows.</li>
    <li><a href="http://www.frykholm.se/scitecmd.html">scitecmd</a>
    is a simple utility for opening files as tabs in SciTE from the command line on Windows.</li>
    </ul>
    <h3>
       APDL
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/apdl.zip">APDL properties and API</a></li>
    </ul>
    <h3>
       ASP
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/asp.api">ASP API methods</a></li>
    </ul>
    <h3>
       AutoHotkey
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/ahk.properties">AutoHotkey properties</a></li>
    </ul>
    </ul>
    <h3>
       AutoIt3
    </h3>
    <ul>
    <li><a href="http://www.autoitscript.com/autoit3/scite">SciTE4AutoIt3 Website containing AutoIt3 related properties and API files.</a></li>
    </ul>
    <h3>
       C
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/c.api">C standard library</a></li>
    </ul>
    <h3>
       C++
    </h3>
    <ul>
    <li><a href="http://www.nbk.orc.ru/scintilla/cpp.api.zip">Windows API</a></li>
    <li><a href="http://www.scintilla.org/opengl.zip">OpenGL API</a></li>
    <li><a href="http://www.scintilla.org/glut.zip">Glut API</a></li>
    </ul>
    <h3>
       C#
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/genapi.zip">C# API file and generator program.</a></li>
    </ul>
    <h3>
       CIL
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/il.properties">Properties for CIL/MSIL</a></li>
    </ul>
    <h3>
       CMake
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/cmake.api">CMake API</a></li>
    </ul>
    <h3>
       FORTRAN
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/fortran.api">Standard FORTRAN API functions</a></li>
    </ul>
    <h3>
       Java
    </h3>
    <ul>
    <li><a href="http://www.burgaud.com/scite.php">Java API and Java Help</a></li>
    </ul>
    <h3>
       Lua
    </h3>
    <ul>
    <li><a href="http://www.geocities.com/keinhong/scite/lua5api.zip">Lua 5 C API and Lua functions</a></li>
    </ul>
    <h3>
       Microsoft SQL
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/mssql.properties">Replaces sql.properties</a></li>
    </ul>
    <h3>
       MySQL
    </h3>
    <ul>
    <li><a href="http://jakub.vrana.cz/utility/scite_mysql.zip">Keywords</a></li>
    </ul>
    </ul>
    <h3>
       nncron
    </h3>
    <ul>
    <li><a href="http://www.nbk.orc.ru/scintilla/nncron.api">nncron.api</a></li>
    </ul>
    <h3>
       Oracle
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/sql.properties_ext">Extended properties file</a>
    with additional keywords and standard package names.</li>
    </ul>
    <h3>
       osCommerce
    </h3>
    <ul>
    <li><a href="http://www.rvdesign.de/index.php/SciTE">
    API. German language site.</a></li>
    </ul>
    <h3>
       Perl
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/perl.api">Perl API</a></li>
    </ul>
    <h3>
       PHP
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/html.properties">html.properties</a></li>
    <li><a href="http://www.scintilla.org/php.api">php.api for PHP 4.3.3</a></li>
    <li><a href="http://www.scintilla.org/php.properties">PHP properties</a></li>
    <li><a href="http://www.scintilla.org/phpfunctions.properties">PHP functions</a></li>
    <li><a href="http://jakub.vrana.cz/utility/scite_php_t.zip">
    Utilities for making PHP support files.</a></li>
    <li><a href="http://www.scintilla.org/phpapi.php.txt">A script for creating api file
    out of your own php source code</a></li>
    </ul>
    <h3>
       POV-Ray
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/pov.api">POV-Ray API</a></li>
    </ul>
    <h3>
       TADS3
    </h3>
    <ul>
    <li><a href="http://www.scintilla.org/tads3.properties">
    TADS3 property file</a></li>
    <li><a href="http://www.scintilla.org/TADS3.txt">
    Explanation</a></li>
    </ul>
    <h3>
       Windows Scripting
    </h3>
    <ul>
    <li><a href="http://dev.remotenetworktechnology.com/SciTE/index.htm">
    Properties files and scripts.</a></li>
    </ul>
  </body>
</html>

Added doc/SciTEFAQ.html.





















































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html" />
    <title>
      SciTE FAQ
    </title>
<style type="text/css">
        table {
            border: 1px solid #1F1F1F;
            border-collapse: collapse;
        }
        td {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        th {
            border: 1px solid #1F1F1F;
            padding: 1px 5px 1px 5px;
        }
        h4 {
            background-color: #000000;
            color: #FFFFFF;
            padding: 2px 6px;
        }
        .example {
            color: #00A000;
            font-weight: bold;
        }
        DIV.example {
            background: #F7FCF7;
            border: 1px solid #C0D7C0;
            margin: 0.3em 3em;
            padding: 0.3em 0.6em;
            font-size: 80%;
        }
 </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0"  summary="banner">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
          SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       SciTE Frequently Asked Question
    </h2>
    <ul>
    <li><a class="toc" href="#FixedWidth">
    	How do I use a fixed width font for all text?</a></li>
    <li><a class="toc" href="#Monospaced">
    	What happened to <span class="example">use.monospaced</span>?</a></li>
    <li><a class="toc" href="#LineNumbers">
    	Why doesn't my <span class="example">line.numbers</span> setting work?</a></li>
    <li><a class="toc" href="#BlackBackground">
    	How do I change SciTE to use black as the background colour?</a></li>
    <li><a class="toc" href="#OutputColour">
    	How do I change the colours of the output pane?</a></li>
    <li><a class="toc" href="#HorizontalScrollBar">
    	How do I make the horizontal scroll bar adjust to the width of text?</a></li>
    <li><a class="toc" href="#TabbedMode">
    	How do I enable tabbed window mode in SciTE?</a></li>
    <li><a class="toc" href="#Autocomplete">
    	How do I enable autocomplete?</a></li>
    <li><a class="toc" href="#CannotFindFile">
    	When I try to compile/build/run my [some language] source files, I get the following error:
        'The system cannot find the file specified'.</a></li>
    <li><a class="toc" href="#ToolsMenu">
    	How can I add [some external application] to the Tools menu on SciTE?</a></li>
    <li><a class="toc" href="#ToolsNoMenu">
    	How can I add a keyboard command without adding it to the Tools menu?</a></li>
    <li><a class="toc" href="#ReplaceInFiles">
    	Is there a command to replace a string in multiple files together?</a></li>
    <li><a class="toc" href="#SpeedUpGTK">
    	How do I make SciTE run faster on GTK+?</a></li>
    <li><a class="toc" href="#NewlineInRegEx">
    	Is it possible to use the newline character (\n) in a regular expression?</a></li>
    <li><a class="toc" href="#CompilerErrors">
    	How do I get SciTE to understand the error messages from my compiler?</a></li>
    <li><a class="toc" href="#GCCUTF8">
    	Why do GCC error messages include ugly characters?</a></li>
    <li><a class="toc" href="#WindowsSpaces">
    	How do I make Windows open a file associated with SciTE when its path contains spaces?</a></li>
    <li><a class="toc" href="#ExplicitFolds">
    	Why does a //{ comment affect folding?</a></li>
    </ul>
    <h4 id="FixedWidth">
       How do I use a fixed width font for all text?
    </h4>
    <p>
       Use these properties:</p><div class="example">
	font.base=$(font.monospace)<br />
	font.small=$(font.monospace)<br />
	font.comment=$(font.monospace)<br />
	font.text=$(font.monospace)<br />
	font.text.comment=$(font.monospace)<br />
	font.embedded.base=$(font.monospace)<br />
	font.embedded.comment=$(font.monospace)<br />
	font.vbs=$(font.monospace)</div>
    <h4 id="Monospaced">
       What happened to <span class="example">use.monospaced</span>?
    </h4>
    <p>
       The <span class="example">use.monospaced</span> property was removed as
       people were using it to ask for fixed width fonts and then
       requiring support to cope with its limitations. The correct way to
       set fixed width fonts is <a class="toc" href="#FixedWidth">here</a>.
    </p>
    <h4 id="LineNumbers">
       Why doesn't my <span class="example">line.numbers</span> setting work?
    </h4>
    <p>
       <span class="example">line.numbers</span> has been replaced with two properties: <span class="example">line.margin.visible</span>
       and <span class="example">line.margin.width</span> which are explained earlier in <a href="SciTEDoc.html">
       the main SciTE document</a>.
    </p>
    <h4 id="BlackBackground">
       How do I change SciTE to use black as the background colour?
    </h4>
    <p>
       You need to change the style settings. The main change is in the user
       options file to the global default style and caret colour but you may have
       to change other style settings to make this work well:</p><div class="example">
	style.*.32=$(font.base),back:#000000,fore:#ffffff<br />
	style.*.33=back:#C0C0C0,$(font.base)<br />
	style.*.37=fore:#939393<br />
	caret.fore=#FFFFFF<br />
	selection.alpha=75<br />
	selection.back=#FFFFFF<br />
	colour.keyword=fore:#649bff<br />
	colour.operator=fore:#727272</div>
    <h4 id="OutputColour">
       How do I change the colours of the output pane?
    </h4>
    <p>
       The output pane often lists error and warning messages and
       is styled by the "errorlist" lexer. The default errorlist styles are found
       in others.properties. To change the output pane background to black
       and the default text to white set</p><div class="example">
       style.errorlist.32=$(font.small),back:#000000<br />
       style.errorlist.0=fore:#FFFFFF</div>
    <h4 id="HorizontalScrollBar">
       How do I make the horizontal scroll bar adjust to the width of text?
    </h4>
    <p>
       To avoid slow performance the horizontal scroll bar does not automatically adjust.
       You can use the <span class="example">horizontal.scroll.width</span> property to change the horizontal scroll range.
    </p>
    <h4 id="TabbedMode">
        How do I enable tabbed window mode in SciTE?
    </h4>
    <p>
        Multiple buffers must be allocated by setting, for example, <span class="example">buffers=10</span>
        in your SciTEGlobal.properties. To have the tab bar visible upon starting
        SciTE, set <span class="example">tabbar.visible=1</span>.
        You can also set <span class="example">tabbar.hide.one=0</span> to always show tabs,
        or 1 to hide when only one file is open.
        <span class="example">tabbar.multiline=1</span> splits tabs across various lines if necessary.
    </p>
    <h4 id="Autocomplete">
        How do I enable autocomplete?
    </h4>
    <p>
        Goto Options | Open Global Options File and uncomment</p>
        <div class="example">autocompleteword.automatic=1</div>
    <h4 id="CannotFindFile">
        When I try to compile/build/run my [some language] source files, I get the following error:
        'The system cannot find the file specified'.
    </h4>
    <p>
        Make sure that the path to your compiler is set correctly on your system.
        Try to execute from console the same command you get in SciTE and see if it works.
        You can also search in your [language].properties for the compile
        commands used. If you have a different compiler or use different arguments,
        edit the commands to suit your needs.
        The lines to look for:</p><div class="example">
        command.compile.filepattern=<br />
        command.build.filepattern=<br />
        command.go.filepattern=</div>
    <h4 id="ToolsMenu">
       How can I add [some external application] to the Tools menu on SciTE?
    </h4>
    <p>
In your properties file, you'll need to add some lines:
    </p>
    <p>
<span class="example">command.name.number.filepattern</span><br />
(e.g.: <span class="example">command.name.1.$(file.patterns.web)=HTML Tidy</span>)<br />
This defines the Text that will appear on the Tools Menu.
    </p>
    <p>
<span class="example">command.number.filepattern</span><br />
(e.g.: <span class="example">command.1.$(file.patterns.web)=tidy -i -wrap 0 -m $(FilePath)</span> )<br />
This is the actual command that SciTE executes. You should provide the appropriate paths, options and parameters as you would from a command line. See SciTEDoc.html for more information on parameters and how to make SciTE prompt a Parameters Dialog.
    </p>
    <p>
<span class="example">command.is.filter.number.filepattern</span><br />
(e.g.: <span class="example">command.is.filter.1.$(file.patterns.web)=1</span>)<br />
The external application may have modified your file, so setting this to true makes SciTE reload the file after execution of the command.
    </p>
    <p>
<span class="example">command.subsystem.number.filepattern</span><br />
(e.g.: <span class="example">command.subsystem.1.$(file.patterns.web)=2</span>)<br />
This is for Windows and defines the subsystem through which the program is called. See SciTEDoc.html for more information on this.
    </p>
    <p>
You can set a command for all files using * as a file pattern. Up to 10 commands (0 - 9) can be defined in the Tools Menu at any time. Commands also get executed with Ctrl+number.
    </p>
    <h4 id="ToolsNoMenu">
       How can I add a keyboard command without adding it to the Tools menu?
    </h4>
    <p>
	This is similar to <a href="#ToolsMenu">adding to the tools menu</a> except that you set the name to be empty.
	Then the command is included in <span class="example">user.shortcuts</span> by adding 1100 to produce its command ID. For example,</p>
	<div class="example">
command.name.21.*.properties=<br />
command.21.*.properties=cmd /c echo $(FileNameExt)<br />
user.shortcuts=\<br />
Ctrl+Shift+V|1121|<br />
	</div>
    <h4 id="ReplaceInFiles">
       Is there a command to replace a string in multiple files together?
    </h4>
    <p>
     It is possible to replace a string in all opened buffers with the Replace in Buffers
     button in the Replace dialog.
     However this button is hidden by default, it can be displayed with
     <span class="example">find.replace.advanced=1</span>.
    </p>
    <h4 id="SpeedUpGTK">
       How do I make SciTE run faster on GTK+?
    </h4>
    <p>
     The default settings for SciTE were changed in version 1.63 to use the Pango font
     system and antialiased fonts. You can return to using X core fonts which are faster
     with these settings:</p><div class="example">
	font.base=font:lucidatypewriter,size:12<br />
	font.small=font:lucidatypewriter,size:10<br />
	font.comment=font:new century schoolbook,size:12<br />
	font.code.comment.box=$(font.comment)<br />
	font.code.comment.line=$(font.comment)<br />
	font.code.comment.doc=$(font.comment)<br />
	font.text=font:times,size:14<br />
	font.text.comment=font:lucidatypewriter,size:10<br />
	font.embedded.base=font:lucidatypewriter,size:12<br />
	font.embedded.comment=font:lucidatypewriter,size:12<br />
	font.monospace=font:courier,size:12<br />
	font.vbs=font:new century schoolbook,size:12<br />
     </div>
     <p>Line wrapping also slows SciTE down and this can be turned off with <span class="example">wrap=0</span>.
    </p>
    <h4 id="NewlineInRegEx">
       Is it possible to use the newline character (\n) in a regular expression?
    </h4>
    <p>
     No.
    </p>
    <p>
	 The "Transform backslash expressions" option allows using \n and \r but that option does
	 not work with regular expressions.
    </p>
    <h4 id="CompilerErrors">
       How do I get SciTE to understand the error messages from my compiler?
    </h4>
    <p>
     The set of error message formats is embedded in the Scintilla and SciTE code.
     To add support for another compiler, you will need to add a new style to
     scintilla/include/Scintilla.iface after the other SCE_ERR_* values, run HFacer.py,
     edit RecogniseErrorListLine in scintilla/src/LexOthers.cxx to recognise the error message,
     and edit DecodeMessage in scite/src/SciTEBuffers.cxx to extract the file name and line
     number.
    </p>
    <h4 id="GCCUTF8">
       Why do GCC error messages include ugly characters?
    </h4>
    <p>
	Linux distributions now often set the locale to UTF-8 by, for
	example, setting LANG=en_US.UTF-8. gcc takes this as an indication
	that it can use any Unicode character encoded as UTF-8 so quotes using
	&lsquo;these&rsquo; rather than ASCII. To see these as intended, set</p>
    <div class="example">
    output.code.page=65001</div>
    <h4 id="WindowsSpaces">
       How do I make Windows open a file associated with SciTE when its path contains spaces?
    </h4>
    <p>
	On some versions of Windows, associating a particular file type
	with SciTE does not allow paths containing spaces to work.
	To fix this, the path variable %1 needs to be surrounded by double quotes.
	This is done either directly in the registry or through the Explorer in
	Tools | Folder Options | File Types | (Select type) | Advanced | open | Edit.
	Change the "Application used to perform action" field to be similar to</p>
	<div class="example">"C:\bin\SciTE\SciTE.exe" "%1"</div>
    <h4 id="ExplicitFolds">
       Why does a //{ comment affect folding?
    </h4>
    <p>
	For C++ and similar languages, explicit folds can be added with //{ and //} .
	This feature can be turned off with</p>
    <div class="example">
    fold.comment=0</div>
  </body>
</html>

Added doc/SciTEIco.png.

cannot compute difference between binary files

Added doc/SciTEImage.html.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla and SciTE
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <br />
     <img src="SciTE224.png" />
  </body>
</html>

Added doc/SciTELexer.html.

































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Download Scintilla and SciTE
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  Add a lexer to Scintilla and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Lexer addition.
    </h2>
     <p>The process of adding a new lexer to both Scintilla and SciTE
is fairly long. Here is my response when asked how to add a lexer for
Apache CONF files to SciTE. There is more information on writing the
lexer code (steps 4 and 5, here) in the documentation for Scintilla.</p>
<p>
Don't bother about steps which are for configurations you don't
use all 6 makefiles - I'll patch them up later if you want to
contribute the lexer.</p>
    <ol>
<li>
In scintilla/include/Scintilla.iface, add a lexer ID value:<br />
val SCLEX_CONF=17
</li>
<li>
And any lexical class IDs:<br />
val SCE_CONF_DEFAULT=0<br />
val SCE_CONF_COMMENT=1
</li>
<li>
In the scintilla/include directory run HFacer.py to regenerate the
SciLexer.h file. Alternatively (if you don't want to run a Python script)
just add these values to SciLexer.h as #defines and I'll put them in
Scintilla.iface.
</li>
<li>
In the scintilla/src/LexOthers.cxx write a ColouriseConfDoc function
similar to one of the other functions such as ColouriseLatexDoc.<br />
static void ColouriseConfDoc (unsigned int startPos, int length, int
initStyle, WordList *[], Accessor &amp;styler) {
</li>
<li>
At the end of the file associate the lexer ID and name with the function:<br />
LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf");
</li>
<li>
If this is a complex lexer then it may be better off in its own file, in
which case clone one of the current files and then add the file to all of
the make files where LexOthers is currently referenced -
scintilla/win32/makefile, scintilla/win32/scintilla.mak,
scintilla/gtk/makefile, scite/win32/makefile, and scite/win32/scite.mak.
</li>
<li>
To the scite/src/others.properties add an entry to associate the file
extension with the lexer:<br />
lexer.*.conf=conf<br />
   If a new lexer file was created instead of adding to LexOthers, then a
new properties file should be created by cloning scite/src/others.properties
and modifying that file in the following steps.
</li>
<li>
Set up the styles:<br />
# Default<br />
style.conf.0=fore:#FF0000,bold<br />
# Comment<br />
style.conf.1=fore:#007F7F,$(font.comment)<br />
</li>
<li>
If on Windows (someday this may work on GTK+ too), a filter should be
added for conf files in scite/src/others.properties:
filter.conf=Configuration (.conf)|*.conf|
</li>
<li>
In scite/src/SciTEGlobal.properties add $(filter.conf) to the definition
of open.filter.
</li>
<li>
To add this language to the Language menu of SciTE, add an entry to the menu.language
property including the name of the language and the file extension used most commonly
for it.
</li>
<li>
Build both Scintilla and SciTE.
</li>
<li>
Share and enjoy
</li>
</ol>
<p>
For more extensive information on building lexers, see the
<a href ="http://www.scintilla.org/ScintillaDoc.html#BuildingScintilla">
instructions in the Scintilla documentation</a>.
</p>
  </body>
</html>

Added doc/SciTELua.html.



















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      SciTE Lua Scripting Extension
    </title>
    <style type="text/css">
        .example {
            color: #00A000;
            font-weight: bold;
        }
        DIV.example {
            background: #F7FCF7;
            border: 1px solid #C0D7C0;
            margin: 0.3em 3em;
            padding: 0.3em 0.6em;
            font-size: 80%;
        }
    </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  SciTE Lua Scripting Extension</font></a>
        </td>
      </tr>
    </table>
<h3>Lua Scripting Extension Notes</h3>
The SciTE Lua Scripting Extension uses a copy of Lua 5.1 as
its scripting engine.  Currently, all of the standard libraries are
included, although this list may be trimmed in a future revision.
<p>
Lua is Copyright (C) 1994-2007 Lua.org, PUC-Rio.  The complete Lua license
is included in <tt>luaCOPYRIGHT</tt> in the SciTE installation directory.  To
find more information about Lua, including documentation for the
language itself, visit <a href="http://www.lua.org">www.lua.org</a>.
</p><p>
For more ideas about what Lua can do, you may also want to check out
the community portal, <a href="http://lua-users.org/">lua-users.org</a>,
<a href="http://lua-users.org/wiki/UsingLuaWithScite">an introduction to using Lua with SciTE,</a>
and <a href="http://lua-users.org/wiki/SciteScripts">some example scripts</a>.
</p>
<h4>SciTE Properties and Lua Event / Command Handlers</h4>
<p>
The properties ext.lua.startup.script and extension.<i>filepattern</i>
can be used to define commands and event handlers that will be called
by the SciTE.  Other properties beginning with ext.lua may also
influence how Lua behaves.  See the <a href="SciTEDoc.html">SciTE Documentation</a>
for more details on this.
</p><p>
By defining functions in the startup script or the active extension
script, you can tailor SciTE to your needs, adding new behavior and
functionality that is tightly integrated.
</p><p>
To begin, you can handle any many of the events exposed by the
<a href="SciTEExtension.html">SciTE Extension Interface</a>.  You do
this simply by defining functions with the same name as the event.
Currently, <tt>OnOpen</tt>, <tt>OnClose</tt>, <tt>OnSwitchFile</tt>, <tt>OnSave</tt>,
<tt>OnBeforeSave</tt>, <tt>OnChar</tt>, <tt>OnKey</tt>,
<tt>OnSavePointReached</tt>, <tt>OnSavePointLeft</tt>, <tt>OnDwellStart</tt>,
<tt>OnDoubleClick</tt>, <tt>OnMarginClick</tt>,
and <tt>OnUserListSelection</tt> are supported.
</p><p>
For some of these events, SciTE will pass one or more arguments to
the event handler function: <tt>OnOpen</tt>, <tt>OnClose</tt>,
<tt>OnSwitchFile</tt>, <tt>OnSave</tt>, and
<tt>OnBeforeSave</tt> will receive the filename of the affected buffer as
their first argument.
An <tt>OnChar</tt> handler should expect a single-character string argument.
An <tt>OnKey</tt> handler should expect an integer keycode and boolean
shift, control, and alt arguments. The keycode is currently a platform specific value
but this may change in future.
<tt>OnDwellStart</tt> will receive the position of the mouse and the
word under the mouse as arguments and the word will be empty when the mouse starts moving.
<tt>OnUserListSelection</tt> receives two arguments: a number
indicating the list type, and a string indicating the selected
item text.  The other event handlers will not be passed any arguments.
</p><p>
Event handlers return a boolean value to indicate whether SciTE should
continue processing the event.  Return a true value to indicate that
the event has been fully handled, and that no further handlers should
be called.  Return a false value to give other extensions a chance to
process the same event.  In many but not all cases, a well behaved
event handler will return false.  Remember that, in Lua, the only
non-true values are <tt>false</tt> and <tt>nil</tt>.  Unlike in C++, Python and many
other languages, 0 evaluates to <tt>true</tt>.
</p><p>
There is one additional event handler, <tt>OnClear</tt>, that is not
expressly defined in the Extension interface, but is exposed to Lua.
Whenever SciTE re-reads the properties (which occurs every time you
switch buffers or open a new file, but can also occur at other times),
the Lua Extension removes any globals that were created since the last
time properties were read, and restores any globals that were
overwritten. Then, if the startup script defines a function
<tt>OnClear</tt>, that function will be called so that scripts have a
chance to clean up other changes they might have made outside of the
Lua global scope (e.g. dynamic properties modified through the props
object; see below) and/or to tailor the Lua environment according to
local properties for the current buffer.
</p><p>
After this, SciTE reads the properties and ultimately loads the
extension script, if one is defined.  However, at the time when the
<tt>OnClear</tt> event fires, the extension script is not yet loaded.
Thus, <tt>OnClear</tt> can only be defined in the startup script,
not in an extension script.
</p><p>
In addition to event handlers, you can also use define new commands
that are available through the Tools menu or through keyboard shortcuts.
To specify that a command that will be handled by Lua, specify
subsystem 3 for the command.  Then, to implement the command using Lua,
just define a global function.  The command name is the function name.
</p><p>
You can also use predefined functions like <tt>dofile</tt> and <tt>dostring</tt> as tool
commands.
</p><p>
Anything specified after the command name is passed to the Lua function
as a single string argument.  An example of a command, using the
built-in dofile command, is shown below.
</p>
<div class="example">
  command.name.1.*=Run My Script<br />
  command.subsystem.1.*=3<br />
  command.1.*=dofile $(SciteDefaultHome)/My Script.lua<br />
</div>
<p>
Note that the command line is &quot;not&quot; evaluated directly
as a Lua script.
</p><p>
If there is no function matching the command name, no error will be
displayed.  This is because Lua assumes in this case that the command
is meant for some other extension, such as the <a href="SciTEDirector.html">SciTE Director
Extension</a>.  However, if the command function is found, but fails
to execute, an error is reported.
</p>
<h4>Multiple handlers</h4>
<p>
<a href="http://lua-users.org/wiki/SciteExtMan">Scite Ext Man</a> can help in
more complex applications where you have
multiple scripts needing to handle an event.
</p>
<hr noshade="noshade" width="80%" align="left" />
<h4>Predefined Lua Functions and Objects:</h4>
<p>
Within Lua scripts you can use the following functions / objects:
</p><pre><tt>  trace(s) - writes s to the output pane (no prefix, no newlines)
  dostring(s) - executes s as a Lua string, like Lua 4&#39;s dostring
  editor - the editor pane
  output - the output pane
  props - a pseudo-table representing the SciTE properties
  buffer - a table associated with the current buffer or document
  scite - a namespace for functions which control SciTE.
</tt></pre><p>
In addition, all constants defined in Scintilla.iface are exposed as
Lua globals variables. Function names are exposed as their block
capital equivalents, with the SCI_ prefix.
</p><p>
All functions and objects defined in the Lua standard library are also
available.  Although dostring was deprecated in Lua 5, it is restored
since some have said it would be useful in tool commands.
</p><p>
A function <tt>_ALERT()</tt> is also defined to be an alias for the built-in
<tt>print()</tt>, which prints the alert message (plus a newline) to the window.
This provides a reasonable way for Lua to present error messages to
the user.  You are free to override <tt>_ALERT</tt> with a different definition
if you prefer.
</p><p>
The props pseudo-table allows you to read or write properties by name
using normal Lua table-access semantics, e.g. <tt>props["property.name"]</tt>.
As with Lua tables, you can also un-set a property by assigning nil to its key.
</p><p>
When you assign a value to a property from Lua, this overrides any values
specified in the configuration files for that setting.  The underlying file
properties are not changed.  If you later assign nil to the same property
from Lua, this removes the run-time setting, allowing any file-based
property setting to show through once again.
</p><p>
The editor and output panes support the following properties and
methods:
</p><pre><tt>  textrange(startPos, endPos) - gets the text in the specified range

  findtext(text, [flags], [startPos, [endPos]])
    - returns the start and end of the first match, or nil if no match
    - flags can be 0 (the default), or a combination of <a href="http://www.scintilla.org/ScintillaDoc.html#searchFlags">SCFIND constants</a>
      such as SCFIND_WHOLEWORD, SCFIND_MATCHCASE, and SCFIND_REGEXP

  match(text, [flags], [startPos])
    - returns a generator that allows you to loop over the matches
      i.e. for m in editor:match(text, flags) do ... end
    - the match object (i.e. the loop counter m in the above
      example) supports read-only properties pos, len, and text;
      and also supports a function replace(replaceText) to
      support search and replace.
    - while looping through matches, if the document is modified
      by any method other than the loop counter's replace method,
      this may cause the match generator to lose its place.
    - also, do not attempt to store the match object for later
      access outside the loop; it will not be useable.

  append(text) - appends text to the end of the document
  insert(pos, text) - inserts text at the specified position
  remove(startPos, endPos) - removes the text in the range
</tt></pre><p>
Most of the functions defined in Scintilla.iface are also be exposed
as pane methods. Those functions having simple parameters (string,
boolean, and numeric types) are fully supported. For example,
<tt>editor:InsertText(pos, text)</tt> does practically the same thing as
<tt>editor:insert(pos, text)</tt>. Functions having a stringresult parameter
will include a string in the return value.  For both strings and
stringresults, if the function is documented as expecting a length
as its first parameter, you do not pass the length from Lua. Instead,
it is inferred from the context.
</p><p>
The keymod parameter type has partial support. When an iface function
is declared as taking a keymod, the Lua equivalent expects two
numbers: first the key code (e.g. <tt>SCK_LEFT</tt> or <tt>string.byte("'")</tt>, and
second the modifiers (e.g. <tt>SCMOD_CTRL</tt>).
</p><p>
Functions that have more complex parameters are not supported.
</p><p>
Functions that are declared to return a numeric type have the result
added to their return value.  If the function also has a stringresult,
that comes first, followed by the numeric return value.
</p><p>
Some functions are declared as 'get' or 'set' rather than 'fun' in
the iface file.  These are generally exposed to Lua as properties,
e.g. <tt>editor.TabSize = 8</tt>.  Some of the getters and setters also have
a parameter.  Where possible, these are exposed to Lua as indexed
properties, e.g. <tt>editor.StyleBold[SCE_PROPS_DEFAULT] = true</tt>.
However, if an iface function is declared as get / set but cannot be
mapped to a Lua property, it is exposed as a Lua function instead.
</p><p>
The possible Scintilla calls are listed as the
<a href="http://www.scintilla.org/PaneAPI.html">Pane API</a> and in
<a href="http://scite-files.googlecode.com/svn-history/trunk/extras/SciTELua.api">API file format.</a>
The Scintilla API is described in
<a href="http://www.scintilla.org/ScintillaDoc.html">ScintillaDoc</a>.
</p>
<p>
The <tt>scite</tt> namespace includes the following functions:
</p><pre><tt>  scite.Open(filename)
    - opens a file in a new buffer
    - activates the file's buffer if it is already opened.

  scite.SendEditor(SCI_constant, ...)
    - sends a message to the editor pane
    - equivalent to the corresponding iface function or property

  scite.SendOutput(SCI_constant, ...)
    - sends a message to the output pane

  scite.ConstantName(number)
    - returns the symbolic name of a Scintilla / SciTE constant

  scite.MenuCommand(IDM_constant)
    - equivalent to the corresponding IDM_ command defined in SciTE.h
</tt></pre><p>
<tt>Open</tt> requires special care.  When the buffer changes in SciTE, the
Lua global namespace is reset to its initial state, and any extension
script associated with the new buffer is loaded.  Thus, when you call
Open, this may change the environment in which your current script is
running.  When possible, you can avoid confusion by simply returning
after scite.Open, but when that is not possible, just bear in mind
that there are side effects.  Local variables, unlike globals, will
be retained after the buffer change until your script returns.
</p><p>
The <tt>SendEditor</tt> and <tt>SendOuput</tt> functions duplicate the
functionality of the editor and output objects, providing access to these
through an interface that is more familiar to Scintilla C++ developers.
This may be useful for prototyping C++ code using Lua.  Internally,
<tt>SendEditor</tt> and <tt>SendOutput</tt> are translated to the
corresponding iface function or property, so their arguments and
return types are identical.  (Although the calling convention for
properties is obviously different.)
</p><p>
The <tt>ConstantName</tt> function may be useful when generating debug messages,
or if extending the SciTE LuaExtension to support macro recording.
</p><p>
The <tt>MenuCommand</tt> function enables usage of SciTE's menu commands
as defined in SciTE.h.
</p>

<h4>Scripting user interfaces with strips</h4>
<p>Simple user interfaces may be defined from Lua as strips similar to
the find and replace strips. An example looks like<br />
<img src="http://scintilla.org/UserStrip.png"></img></p>

<p>Strips are shown with StripShow which takes a string describing
the user interface then builds and displays it as a strip at the
bottom of the application window. There are 5 supported elements:
labels, editable text, combo boxes, buttons and default buttons. These are
surrounded by different indicator strings: ' for labels; []
for editable text; {} for combo boxes; () for buttons; and (()) for default buttons.
There can also be a newline to start a new line and a ! to show a close box on
Windows only.</p>
<p>A default button looks like ((OK)) and can be triggered by pressing the Enter key.
Buttons may include accelerator keys prefixed with &amp;.
On Windows and GTK+ but not OS X, labels may also define accelerator keys
which cause focus to move to the next element which accepts focus.
Literal ampersands are defined with &amp;&amp;.

  For example, the code<pre><tt>       scite.StripShow("!'Explanation:'{}(&amp;Search)\n'Name:'[Name](OK)(Cancel)")
</tt></pre>
  shows the strip displayed in the picture. The strip can be closed
by passing an empty string.</p>

<p>On GTK+ a table is used for layout and the approach was copied to the other
platforms. It is not yet as capable on the other platforms yet as on
GTK+ - columns containing editable text and combo boxes can expand and
other columns are fixed to the their natural width of their widest
element.</p>

<p>Events from the user are communicated back to the script through
the OnStrip function which takes an element number (starting at 0 and
including static text elements) and a change type (clicked=1,
change=2, focusIn=3, focusOut=4). 'clicked' is for button presses,
'change' for changes to editable text or the editable text part of a
combo boxes and 'focusIn' and 'focusOut' are when the user moves focus
between elements. The value of editable text or combo boxes can be
retrieved with StripValue(element).</p>

<p>There are some bugs and limitations with these events currently.
Focus events may not occur or may occur only when text is edited.
Selecting an item from the list in a combo box may not send a 'change'
event.</p>

<p>The editable part of combo boxes and editable text can be set with
StripSet(element, value) and the list part of combo boxes can be set
with StripSetList(element, value) where the items in 'value' are
separated with new lines.</p>

<h4>Lua 5.1</h4>
<pre>
Despite some of the big changes in Lua 5.1 dealing with changes
in the language, most of the compatibility options have been
turned on.
Compatibilities:
- table.getn still works, but the '#' operator should be used
- Lua 5.0's varargs are still available
- Lua 5.0's math.mod is still available, as well as 5.1's
math.fmod
- Lua 5.0's string.gfind is still available, as well as 5.1's
string.gmatch
- [C API] Lua 5.0's luaL_openlib behavior is still available
Changes:
- table.setn was deprecated
- loadlib was moved into the package table (package.loadlib)
- Lua 5.0's long string nesting throws an error
</pre>

<hr noshade="noshade" width="80%" align="left" />

<h4>Disabling Lua</h4>
<p>
Lua is currently loaded just-in-time, before it is first used.  The
ways that Lua can become are through the ext.lua.startup.script
property, by naming a lua file named in the extension.<i>filepattern</i>
property, or by using the extension mechanism to define tool commands
(i.e. subsystem 3).  If you do not do any of these things, the Lua
scripting engine is not loaded, and for all practical purposes, SciTE
should behave as it did before Lua was added.
</p><p>
Nevertheless, it is still possible to build SciTE without the Lua
support. To do this, simply define the variable <tt>NO_LUA</tt> when you build
it, e.g. for MSVC, <tt>nmake -f scite.mak -DNO_LUA</tt>; or with GNU tools,
<tt>make NO_LUA=1</tt>.
</p>
</body>
</html>

Added doc/SciTERegEx.html.

















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      SciTE Regular Expressions
    </title>
<style type="text/css">
        h3 {
            background-color: #FEC;
        }
        .ref {
            color: #80C;
        }
        code {
            font-weight: bold;
        }
        dt {
            margin-top: 15px;
        }
 </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
          Regular Expressions</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Regular Expressions in SciTE
    </h2>
    <h3>Purpose</h3>
    <p>
      Regular expressions can be used for searching for patterns
      rather than literals. For example, it is possible to
      search for variables in SciTE property files,
      which look like $(name.subname) with the regular expression:<br />
      <code>\$([a-z.]+)</code> (or <code>\$\([a-z.]+\)</code> in posix mode).
    </p>
    <p>
      Replacement with regular expressions allows complex
      transformations with the use of tagged expressions.
      For example, pairs of numbers separated by a ',' could
      be reordered by replacing the regular expression:<br />
      <code>\([0-9]+\),\([0-9]+\)</code> (or <code>([0-9]+),([0-9]+)</code>
      in posix mode, or even <code>(\d+),(\d+)</code>)<br />
      with:<br />
      <code>\2,\1</code>
    </p>
    <h3>Syntax</h3>
    <p>
      Regular expression syntax depends on a parameter:  find.replace.regexp.posix<br />
      If set to 0, syntax uses the old Unix style where <code>\(</code> and <code>\)</code>
      mark capturing sections while <code>(</code> and <code>)</code> are themselves.<br />
      If set to 1, syntax uses the more common style where <code>(</code> and <code>)</code>
      mark capturing sections while <code>\(</code> and <code>\)</code> are plain parentheses.
    </p>
    <dl><dt><span class="ref">[1]</span> char</dt>
    <dd>matches itself, unless it is a special character
    (metachar): <code>. \ [ ] * + ? ^ $</code> and <code>( )</code> in posix mode.
    </dd><dt><span class="ref">[2]</span> <code>.</code></dt>
    <dd>matches any character.
    </dd><dt><span class="ref">[3]</span> <code>\</code></dt>
    <dd>matches the character following it, except:
    <ul><li><code>\a</code>, <code>\b</code>, <code>\f</code>,
    <code>\n</code>, <code>\r</code>, <code>\t</code>, <code>\v</code>
    match the corresponding C escape char,
    respectively BEL, BS, FF, LF, CR, TAB and VT;<br />
    Note that <code>\r</code> and <code>\n</code> are never matched because in Scintilla,
    regular expression searches are made line per line (stripped of end-of-line chars).
    </li><li>if not in posix mode, when followed by a left or right round bracket (see <span class="ref">[8]</span>);
    </li><li>when followed by a digit 1 to 9 (see <span class="ref">[9]</span>);
    </li><li>when followed by a left or right angle bracket (see <span class="ref">[10]</span>);
    </li><li>when followed by d, D, s, S, w or W (see <span class="ref">[11]</span>);
    </li><li>when followed by x and two hexa digits (see <span class="ref">[12]</span>);
    </li></ul>
    Backslash is used as an escape character for all other meta-characters, and itself.
    </dd><dt><span class="ref">[4]</span> <code>[</code>set<code>]</code></dt>
    <dd>matches one of the characters in the set.
    If the first character in the set is <code>^</code>, it matches the characters NOT in the set,
    i.e. complements the set. A shorthand <code>S-E</code> (start dash end) is
    used to specify a set of characters S up to E, inclusive. The special characters <code>]</code> and
    <code>-</code> have no special meaning if they appear as the first chars in the set. To include both,
    put - first: <code>[-]A-Z]</code> (or just backslash them).
    <table><tr><td>example</td><td>match</td></tr>
      <tr><td><code>[-]|]</code></td><td>matches these 3 chars,</td></tr>
      <tr><td><code>[]-|]</code></td><td>matches from ] to | chars</td></tr>
      <tr><td><code>[a-z]</code></td><td>any lowercase alpha</td></tr>
      <tr><td><code>[^-]]</code></td><td>any char except - and ]</td></tr>
      <tr><td><code>[^A-Z]</code></td><td>any char except uppercase alpha</td></tr>
      <tr><td><code>[a-zA-Z]</code></td><td>any alpha</td></tr>
    </table>
    </dd><dt><span class="ref">[5]</span> <code>*</code></dt>
    <dd>any regular expression form <span class="ref">[1]</span> to <span class="ref">[4]</span>
    (except <span class="ref">[8]</span>, <span class="ref">[9]</span> and <span class="ref">[10]</span>
    forms of <span class="ref">[3]</span>),
    followed by closure char (<code>*</code>) matches zero or more matches of that form.
    </dd><dt><span class="ref">[6]</span> <code>+</code></dt>
    <dd>same as <span class="ref">[5]</span>, except it matches one or more.
    </dd><dt><span class="ref">[5-6]</span></dt>
    <dd>Both <span class="ref">[5]</span> and <span class="ref">[6]</span> are greedy (they match as much as possible)
    unless they are followed by the 'lazy' quantifier (<code>?</code>)
    in which case both <span class="ref">[5]</span> and <span class="ref">[6]</span> try to match as little as possible.
    </dd><dt><span class="ref">[7]</span> <code>?</code></dt>
    <dd>same as <span class="ref">[5]</span>, except it matches zero or one.
    </dd><dt><span class="ref">[8]</span></dt>
    <dd>a regular expression in the form <span class="ref">[1]</span> to <span class="ref">[13]</span>, enclosed
    as <code>\(<i>form</i>\)</code> (or <code>(<i>form</i>)</code> with posix flag) matches
    what <i>form</i> matches.
    The enclosure creates a set of tags, used for <span class="ref">[9]</span> and for
    pattern substitution. The tagged forms are numbered starting from 1.
    </dd><dt><span class="ref">[9]</span></dt>
    <dd>a <code>\</code> followed by a digit 1 to 9 matches whatever a
    previously tagged regular expression (<span class="ref">[8]</span>) matched.
    </dd><dt><span class="ref">[10]</span> <code>\&lt; \&gt;</code></dt>
    <dd>a regular expression starting with a <code>\&lt;</code> construct
    and/or ending with a <code>\&gt;</code> construct, restricts the
    pattern matching to the beginning of a word, and/or
    the end of a word. A word is defined to be a character
    string beginning and/or ending with the characters
    A-Z a-z 0-9 and _. Scintilla extends this definition
    by user setting. The word must also be preceded and/or
    followed by any character outside those mentioned.
    </dd><dt><span class="ref">[11]</span> <code>\l</code></dt>
    <dd>a backslash followed by d, D, s, S, w or W,
    becomes a character class (both inside and outside sets []).
    <ul><li>d: decimal digits
    </li><li>D: any char except decimal digits
    </li><li>s: whitespace (space, \t \n \r \f \v)
    </li><li>S: any char except whitespace (see above)
    </li><li>w: alphanumeric &amp; underscore (changed by user setting)
    </li><li>W: any char except alphanumeric &amp; underscore (see above)
    </li></ul>
    </dd><dt><span class="ref">[12]</span> <code>\xHH</code></dt>
    <dd>a backslash followed by x and two hexa digits,
    becomes the character whose Ascii code is equal
    to these digits. If not followed by two digits,
    it is 'x' char itself.
    </dd><dt><span class="ref">[13]</span></dt>
    <dd>a composite regular expression xy where x and y
    are in the form <span class="ref">[1]</span> to <span class="ref">[12]</span> matches the longest
    match of x followed by a match for y.
    </dd><dt><span class="ref">[14]</span> <code>^ $</code></dt>
    <dd>a regular expression starting with a ^ character
    and/or ending with a $ character, restricts the
    pattern matching to the beginning of the line,
    or the end of line. [anchors] Elsewhere in the
    pattern, ^ and $ are treated as ordinary characters.
    </dd></dl>
    <h3>Acknowledgments</h3>
    <p>
    Most of this documentation was originally written by Ozan S. Yigit.<br />
    Additions by Neil Hodgson and Philippe Lhoste.<br />
    All of this document is in the public domain.
    </p>
  </body>
</html>


Added doc/SciTEWord.jpg.

cannot compute difference between binary files

Added doc/SciWord.jpg.

cannot compute difference between binary files

Added doc/ScintillaDoc.html.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator"
    content="HTML Tidy for Windows (vers 1st August 2002), see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

    <title>Scintilla Documentation</title>

    <style type="text/css">
<!--
/*<![CDATA[*/
	CODE { font-weight: bold; font-family: Consolas,Bitstream Vera Sans Mono,Courier New,monospace; }
	A:visited { color: blue; }
	A:hover { text-decoration: underline ! important; }
	A.message { text-decoration: none; font-weight: bold; font-family: Consolas,Bitstream Vera Sans Mono,Courier New,monospace; }
	A.toc { text-decoration: none; }
	A.jump { text-decoration: none; }
	.S0 {
		color: #808080;
	}
	.S2 {
		font-family: 'Comic Sans MS';
		color: #007F00;
		font-size: 9pt;
	}
	.S3 {
		font-family: 'Comic Sans MS';
		color: #3F703F;
		font-size: 9pt;
	}
	.S4 {
		color: #007F7F;
	}
	.S5 {
		font-weight: bold;
		color: #00007F;
	}
	.S9 {
		color: #7F7F00;
	}
	.S10 {
		font-weight: bold;
		color: #000000;
	}
	.S17 {
		font-family: 'Comic Sans MS';
		color: #3060A0;
		font-size: 9pt;
	}
	DIV.highlighted {
		background: #F7FCF7;
		border: 1px solid #C0D7C0;
		margin: 0.3em 3em;
		padding: 0.3em 0.6em;
		font-family: 'Verdana';
		color: #000000;
		font-size: 10pt;
	}
	.provisional {
		background: #FFB000;
        }
/*]]>*/
-->
    </style>
  </head>

  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0"
    summary="Banner">
      <tr>
        <td><img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" /></td>

        <td><a href="index.html"
        style="color:white;text-decoration:none;font-size:200%">Scintilla</a></td>
      </tr>
    </table>

    <h1>Scintilla Documentation</h1>

    <p>Last edited 18/January/2013 NH</p>

    <p>There is <a class="jump" href="Design.html">an overview of the internal design of
    Scintilla</a>.<br />
     <a class="jump" href="ScintillaUsage.html">Some notes on using Scintilla</a>.<br />
     <a class="jump" href="Steps.html">How to use the Scintilla Edit Control on Windows</a>.<br />
     <a class="jump" href="http://www.scintilla.org/dmapp.zip">A simple sample using Scintilla from
    C++ on Windows</a>.<br />
     <a class="jump" href="http://www.scintilla.org/SciTry.vb">A simple sample using Scintilla from
    Visual Basic</a>.<br />
     <a class="jump" href="http://www.scintilla.org/bait.zip">Bait is a tiny sample using Scintilla
     on GTK+</a>.<br />
     <a class="jump" href="Lexer.txt">A detailed description of how to write a lexer, including a
    discussion of folding</a>.<br />
     <a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-container_lexer.html">
     How to implement a lexer in the container</a>.<br />
     <a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-folding.html">
     How to implement folding</a>.<br />
     The <a class="jump" href="SciCoding.html">coding style</a> used in Scintilla and SciTE is
    worth following if you want to contribute code to Scintilla but is not compulsory.</p>

    <h2>Introduction</h2>

    <p>The Windows version of Scintilla is a Windows Control. As such, its primary programming
    interface is through Windows messages. Early versions of Scintilla emulated much of the API
    defined by the standard Windows Edit and RichEdit controls but those APIs are now deprecated in
    favour of Scintilla's own, more consistent API. In addition to messages performing the actions
    of a normal Edit control, Scintilla allows control of syntax styling, folding, markers, autocompletion
    and call tips.</p>

    <p>The GTK+ version also uses messages in a similar way to the Windows version. This is
    different to normal GTK+ practice but made it easier to implement rapidly.</p>

    <p>Scintilla does not properly support right-to-left languages like Arabic and Hebrew.
    While text in these languages may appear correct, it is not possible to interact with this text
    as is normal with other editing components.</p>

    <p>This documentation describes the individual messages and notifications used by Scintilla. It
    does not describe how to link them together to form a useful editor. For now, the best way to
    work out how to develop using Scintilla is to see how SciTE uses it. SciTE exercises most of
    Scintilla's facilities.</p>

    <p>In the descriptions that follow, the messages are described as function calls with zero, one
    or two arguments. These two arguments are the standard <code>wParam</code> and
    <code>lParam</code> familiar to Windows programmers. These parameters are integers that
    are large enough to hold pointers, and the return value is also an integer large enough to contain a
    pointer.
    Although the commands only use the
    arguments described, because all messages have two arguments whether Scintilla uses them or
    not, it is strongly recommended that any unused arguments are set to 0. This allows future
    enhancement of messages without the risk of breaking existing code. Common argument types
    are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Common argument types">
      <tbody valign="top">
        <tr>
          <th align="left">bool</th>

          <td>Arguments expect the values 0 for <code>false</code> and 1 for
          <code>true</code>.</td>
        </tr>

        <tr>
          <th align="left">int</th>

          <td>Arguments are 32-bit signed integers.</td>
        </tr>

        <tr>
          <th align="left">const&nbsp;char&nbsp;*</th>

          <td>Arguments point at text that is being passed to Scintilla but not modified. The text
          may be zero terminated or another argument may specify the character count, the
          description will make this clear.</td>
        </tr>

        <tr>
          <th align="left">char *</th>

          <td>Arguments point at text buffers that Scintilla will fill with text. In some cases,
          another argument will tell Scintilla the buffer size. In others, you must make sure that
          the buffer is big enough to hold the requested text. If a NULL pointer (0) is passed
          then, for SCI_* calls, the length that should be allocated is returned.</td>
        </tr>

        <tr>
          <th align="left" id="colour">colour</th>

          <td>Colours are set using the RGB format (Red, Green, Blue). The intensity of each colour
          is set in the range 0 to 255. If you have three such intensities, they are combined as:
          red | (green &lt;&lt; 8) | (blue &lt;&lt; 16). If you set all intensities to 255, the
          colour is white. If you set all intensities to 0, the colour is black. When you set a
          colour, you are making a request. What you will get depends on the capabilities of the
          system and the current screen mode.</td>
        </tr>

        <tr>
          <th align="left" id="alpha">alpha</th>

          <td>Translucency is set using an alpha value.
                        Alpha ranges from 0 (SC_ALPHA_TRANSPARENT) which is completely transparent to
                               255 (SC_ALPHA_OPAQUE) which is opaque. The value 256 (SC_ALPHA_NOALPHA)
                               is opaque and uses code that is not alpha-aware and may be faster. Not all platforms support
                               translucency and only some Scintilla features implement translucency.
                               The default alpha value for most features is SC_ALPHA_NOALPHA.</td>
        </tr>

        <tr>
          <th align="left">&lt;unused&gt;</th>

          <td>This is an unused argument. Setting it to 0 will ensure compatibility with future
          enhancements.</td>
        </tr>
      </tbody>
    </table>

    <h2 id="MessageCategories">Contents</h2>

    <table cellpadding="4" cellspacing="2" border="0" summary="Message categories">
      <tbody>
        <tr>
          <td>o <a class="toc" href="#TextRetrievalAndModification">Text retrieval and
          modification</a></td>

          <td>o <a class="toc" href="#Searching">Searching and replacing</a></td>

          <td>o <a class="toc" href="#Overtype">Overtype</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#CutCopyAndPaste">Cut, copy and paste</a></td>

          <td>o <a class="toc" href="#ErrorHandling">Error handling</a></td>

          <td>o <a class="toc" href="#UndoAndRedo">Undo and Redo</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#SelectionAndInformation">Selection and information</a></td>

          <td>o <a class="toc" href="#MultipleSelectionAndVirtualSpace">Multiple Selection and Virtual Space</a></td>

          <td>o <a class="toc" href="#ScrollingAndAutomaticScrolling">Scrolling and automatic
          scrolling</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#WhiteSpace">White space</a></td>

          <td>o <a class="toc" href="#Cursor">Cursor</a></td>

          <td>o <a class="toc" href="#MouseCapture">Mouse capture</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#LineEndings">Line endings</a></td>

          <td>o <a class="toc" href="#Styling">Styling</a></td>

          <td>o <a class="toc" href="#StyleDefinition">Style definition</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#CaretAndSelectionStyles">Caret, selection, and hotspot styles</a></td>

          <td>o <a class="toc" href="#Margins">Margins</a></td>

          <td>o <a class="toc" href="#Annotations">Annotations</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#OtherSettings">Other settings</a></td>

          <td>o <a class="toc" href="#BraceHighlighting">Brace highlighting</a></td>

          <td>o <a class="toc" href="#TabsAndIndentationGuides">Tabs and Indentation
          Guides</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#Markers">Markers</a></td>

          <td>o <a class="toc" href="#Indicators">Indicators</a></td>

	<td>o <a class="toc" href="#Autocompletion">Autocompletion</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#UserLists">User lists</a></td>

          <td>o <a class="toc" href="#CallTips">Call tips</a></td>

	<td>o <a class="toc" href="#KeyboardCommands">Keyboard commands</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#KeyBindings">Key bindings</a></td>

          <td>o <a class="toc" href="#PopupEditMenu">Popup edit menu</a></td>

          <td>o <a class="toc" href="#MacroRecording">Macro recording</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#Printing">Printing</a></td>

          <td>o <a class="toc" href="#DirectAccess">Direct access</a></td>

          <td>o <a class="toc" href="#MultipleViews">Multiple views</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#BackgroundLoadSave">Background loading and saving</a></td>

          <td>o <a class="toc" href="#Folding">Folding</a></td>

          <td>o <a class="toc" href="#LineWrapping">Line wrapping</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#Zooming">Zooming</a></td>

          <td>o <a class="toc" href="#LongLines">Long lines</a></td>

          <td>o <a class="toc" href="#Lexer">Lexer</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#LexerObjects">Lexer objects</a></td>

          <td>o <a class="toc" href="#Notifications">Notifications</a></td>

          <td>o <a class="toc" href="#Images">Images</a></td>
        </tr>

        <tr>
          <td>o <a class="toc" href="#GTK">GTK+</a></td>

          <td>o <a class="toc" href="#ProvisionalMessages"><span class="provisional">Provisional messages</span></a></td>

          <td>o <a class="toc" href="#DeprecatedMessages">Deprecated messages</a></td>
	  
        </tr>

        <tr>
          <td>o <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never
          supported by Scintilla</a></td>

          <td>o <a class="toc" href="#BuildingScintilla">Building Scintilla</a></td>

        </tr>
      </tbody>
    </table>

    <p>Messages with names of the form <code>SCI_SETxxxxx</code> often have a companion
    <code>SCI_GETxxxxx</code>. To save tedious repetition, if the <code>SCI_GETxxxxx</code> message
    returns the value set by the <code>SCI_SETxxxxx</code> message, the <code>SET</code> routine is
    described and the <code>GET</code> routine is left to your imagination.</p>

    <h2 id="TextRetrievalAndModification">Text retrieval and modification</h2>

    <p>Each byte in a Scintilla document is followed by an associated byte of styling
    information. The combination of a character byte and a style byte is called a cell. Style bytes
    are interpreted an index into an array of styles.
    Style bytes may be split into an index and a set of indicator bits
    but this use is discouraged and indicators should now use
    <a class="message" href ="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE</a>
    and related calls.
    The default split is with the index in the low 5 bits and 3 high bits as <a class="jump"
    href="#Indicators">indicators</a>. This allows 32 fundamental styles, which is enough for most
    languages, and three independent indicators so that, for example, syntax errors, deprecated
    names and bad indentation could all be displayed at once. The number of bits used for styles
    can be altered with <a class="message"
    href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> up to a maximum of 8 bits.
    The remaining bits can be used for indicators.</p>

    <p>In this document, 'character' normally refers to a byte even when multi-byte characters are used.
    Lengths measure the numbers of bytes, not the amount of characters in those bytes.</p>

    <p>Positions within the Scintilla document refer to a character or the gap before that
    character. The first character in a document is 0, the second 1 and so on. If a document
    contains <code>nLen</code> characters, the last character is numbered <code>nLen</code>-1.
    The caret exists between character positions and can be located from before the first character (0)
    to after the last character (<code>nLen</code>).</p>

    <p>There are places where the caret can not go where two character bytes make up one character.
    This occurs when a DBCS character from a language like Japanese is included in the document or
    when line ends are marked with the CP/M standard of a carriage return followed by a line feed.
    The <code>INVALID_POSITION</code> constant (-1) represents an invalid position within the
    document.</p>

    <p>All lines of text in Scintilla are the same height, and this height is calculated from the
    largest font in any current style. This restriction is for performance; if lines differed in
    height then calculations involving positioning of text would require the text to be styled
    first.</p>
    <code><a class="message" href="#SCI_GETTEXT">SCI_GETTEXT(int length, char *text)</a><br />
     <a class="message" href="#SCI_SETTEXT">SCI_SETTEXT(&lt;unused&gt;, const char *text)</a><br />
     <a class="message" href="#SCI_SETSAVEPOINT">SCI_SETSAVEPOINT</a><br />
     <a class="message" href="#SCI_GETLINE">SCI_GETLINE(int line, char *text)</a><br />
     <a class="message" href="#SCI_REPLACESEL">SCI_REPLACESEL(&lt;unused&gt;, const char
    *text)</a><br />
     <a class="message" href="#SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</a><br />
     <a class="message" href="#SCI_GETREADONLY">SCI_GETREADONLY</a><br />
     <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, Sci_TextRange
    *tr)</a><br />
     <a class="message" href="#SCI_ALLOCATE">SCI_ALLOCATE(int bytes, &lt;unused&gt;)</a><br />
     <a class="message" href="#SCI_ADDTEXT">SCI_ADDTEXT(int length, const char *s)</a><br />
     <a class="message" href="#SCI_ADDSTYLEDTEXT">SCI_ADDSTYLEDTEXT(int length, cell *s)</a><br />
     <a class="message" href="#SCI_APPENDTEXT">SCI_APPENDTEXT(int length, const char *s)</a><br />
     <a class="message" href="#SCI_INSERTTEXT">SCI_INSERTTEXT(int pos, const char *text)</a><br />
     <a class="message" href="#SCI_CLEARALL">SCI_CLEARALL</a><br />
     <a class="message" href="#SCI_DELETERANGE">SCI_DELETERANGE(int pos, int deleteLength)</a><br />
     <a class="message" href="#SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</a><br />
     <a class="message" href="#SCI_GETCHARAT">SCI_GETCHARAT(int position)</a><br />
     <a class="message" href="#SCI_GETSTYLEAT">SCI_GETSTYLEAT(int position)</a><br />
     <a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(&lt;unused&gt;, Sci_TextRange
    *tr)</a><br />
     <a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS(int bits)</a><br />
     <a class="message" href="#SCI_GETSTYLEBITS">SCI_GETSTYLEBITS</a><br />
     <a class="message" href="#SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</a><br />
     <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles)</a><br />
     <a class="message" href="#SCI_TARGETASUTF8">SCI_TARGETASUTF8(&lt;unused&gt;, char *s)</a><br />
     <a class="message" href="#SCI_ENCODEDFROMUTF8">SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)</a><br />
     <a class="message" href="#SCI_SETLENGTHFORENCODE">SCI_SETLENGTHFORENCODE(int bytes)</a><br />
    </code>

    <p><b id="SCI_GETTEXT">SCI_GETTEXT(int length, char *text)</b><br />
     This returns <code>length</code>-1 characters of text from the start of the document plus one
    terminating 0 character. To collect all the text in a document, use <code>SCI_GETLENGTH</code>
    to get the number of characters in the document (<code>nLen</code>), allocate a character
    buffer of length <code>nLen+1</code> bytes, then call <code>SCI_GETTEXT(nLen+1, char
    *text)</code>. If the text argument is 0 then the length that should be allocated to store the
    entire document is returned.
    If you then save the text, you should use <code>SCI_SETSAVEPOINT</code> to mark
    the text as unmodified.</p>

    <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
    class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
    href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
    href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
    href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a></code></p>

    <p><b id="SCI_SETTEXT">SCI_SETTEXT(&lt;unused&gt;, const char *text)</b><br />
     This replaces all the text in the document with the zero terminated text string you pass
    in.</p>

    <p><b id="SCI_SETSAVEPOINT">SCI_SETSAVEPOINT</b><br />
     This message tells Scintilla that the current state of the document is unmodified. This is
    usually done when the file is saved or loaded, hence the name "save point". As Scintilla
    performs undo and redo operations, it notifies the container that it has entered or left the
    save point with <code><a class="message"
    href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a></code> and <code><a class="message"
    href="#SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</a></code> <a class="jump"
    href="#Notifications">notification messages</a>, allowing the container to know if the file
    should be considered dirty or not.</p>

    <p>See also: <code><a class="message" href="#SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</a>, <a
    class="message" href="#SCI_GETMODIFY">SCI_GETMODIFY</a></code></p>

    <p><b id="SCI_GETLINE">SCI_GETLINE(int line, char *text)</b><br />
     This fills the buffer defined by text with the contents of the nominated line (lines start at
    0). The buffer is not terminated by a 0 character. It is up to you to make sure that the buffer
    is long enough for the text, use <a class="message"
    href="#SCI_LINELENGTH"><code>SCI_LINELENGTH(int line)</code></a>. The returned value is the
    number of characters copied to the buffer. The returned text includes any end of line
    characters. If you ask for a line number outside the range of lines in the document, 0
    characters are copied. If the text argument is 0 then the length that should be allocated
    to store the entire line is returned.</p>

    <p>See also: <code><a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a
    class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a class="message"
    href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>, <a class="message"
    href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
    href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>

    <p><b id="SCI_REPLACESEL">SCI_REPLACESEL(&lt;unused&gt;, const char *text)</b><br />
     The currently selected text between the <a class="jump" href="#SelectionAndInformation">anchor
    and the current position</a> is replaced by the 0 terminated text string. If the anchor and
    current position are the same, the text is inserted at the caret position. The caret is
    positioned after the inserted text and the caret is scrolled into view.</p>

    <p><b id="SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</b><br />
     <b id="SCI_GETREADONLY">SCI_GETREADONLY</b><br />
     These messages set and get the read-only flag for the document. If you mark a document as read
    only, attempts to modify the text cause the <a class="message"
    href="#SCN_MODIFYATTEMPTRO"><code>SCN_MODIFYATTEMPTRO</code></a> notification.</p>

    <p><b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, <a class="jump"
    href="#Sci_TextRange">Sci_TextRange</a> *tr)</b><br />
     This collects the text between the positions <code>cpMin</code> and <code>cpMax</code> and
    copies it to <code>lpstrText</code> (see <code>struct Sci_TextRange</code> in
    <code>Scintilla.h</code>). If <code>cpMax</code> is -1, text is returned to the end of the
    document. The text is 0 terminated, so you must supply a buffer that is at least 1 character
    longer than the number of characters you wish to read. The return value is the length of the
    returned text not including the terminating 0.</p>

    <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
    class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
    href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
    href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
    href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>

    <p><b id="SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(&lt;unused&gt;, <a class="jump"
    href="#Sci_TextRange">Sci_TextRange</a> *tr)</b><br />
     This collects styled text into a buffer using two bytes for each cell, with the character at
    the lower address of each pair and the style byte at the upper address. Characters between the
    positions <code>cpMin</code> and <code>cpMax</code> are copied to <code>lpstrText</code> (see
    <code>struct Sci_TextRange</code> in <code>Scintilla.h</code>). Two 0 bytes are added to the end of
    the text, so the buffer that <code>lpstrText</code> points at must be at least
    <code>2*(cpMax-cpMin)+2</code> bytes long. No check is made for sensible values of
    <code>cpMin</code> or <code>cpMax</code>. Positions outside the document return character codes
    and style bytes of 0.</p>

    <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
    class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
    href="#SCI_GETCURLINE">SCI_GETCURLINE</a>, <a class="message"
    href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>, <a class="message"
    href="#SCI_GETTEXT">SCI_GETTEXT</a></code></p>

    <p><b id="SCI_ALLOCATE">SCI_ALLOCATE(int bytes, &lt;unused&gt;)</b><br />
     Allocate a document buffer large enough to store a given number of bytes.
     The document will not be made smaller than its current contents.</p>

    <p><b id="SCI_ADDTEXT">SCI_ADDTEXT(int length, const char *s)</b><br />
     This inserts the first <code>length</code> characters from the string <code>s</code>
    at the current position. This will include any 0's in the string that you might have expected
    to stop the insert operation. The current position is set at the end of the inserted text,
    but it is not scrolled into view.</p>

    <p><b id="SCI_ADDSTYLEDTEXT">SCI_ADDSTYLEDTEXT(int length, cell *s)</b><br />
     This behaves just like <code>SCI_ADDTEXT</code>, but inserts styled text.</p>

    <p><b id="SCI_APPENDTEXT">SCI_APPENDTEXT(int length, const char *s)</b><br />
     This adds the first <code>length</code> characters from the string <code>s</code> to the end
    of the document. This will include any 0's in the string that you might have expected to stop
    the operation. The current selection is not changed and the new text is not scrolled into
    view.</p>

    <p><b id="SCI_INSERTTEXT">SCI_INSERTTEXT(int pos, const char *text)</b><br />
     This inserts the zero terminated <code>text</code> string at position <code>pos</code> or at
    the current position if <code>pos</code> is -1. If the current position is after the insertion point
    then it is moved along with its surrounding text but no scrolling is performed.</p>

    <p><b id="SCI_CLEARALL">SCI_CLEARALL</b><br />
     Unless the document is read-only, this deletes all the text.</p>

    <p><b id="SCI_DELETERANGE">SCI_DELETERANGE(int pos, int deleteLength)</b><br />
     Deletes a range of text in the document.</p>

    <p><b id="SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</b><br />
     When wanting to completely restyle the document, for example after choosing a lexer, the
    <code>SCI_CLEARDOCUMENTSTYLE</code> can be used to clear all styling information and reset the
    folding state.</p>

    <p><b id="SCI_GETCHARAT">SCI_GETCHARAT(int pos)</b><br />
     This returns the character at <code>pos</code> in the document or 0 if <code>pos</code> is
    negative or past the end of the document.</p>

    <p><b id="SCI_GETSTYLEAT">SCI_GETSTYLEAT(int pos)</b><br />
     This returns the style at <code>pos</code> in the document, or 0 if <code>pos</code> is
    negative or past the end of the document.</p>

    <p><b id="SCI_SETSTYLEBITS">SCI_SETSTYLEBITS(int bits)</b><br />
     <b id="SCI_GETSTYLEBITS">SCI_GETSTYLEBITS</b><br />
     This pair of routines sets and reads back the number of bits in each cell to use for styling,
    to a maximum of 8 style bits. The remaining bits can be used as indicators. The standard
    setting is <code>SCI_SETSTYLEBITS(5)</code>.
    The number of styling bits needed by the current lexer can be found with
    <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a>.</p>

    <p><b id="SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</b><br />
    <b id="SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles)</b><br />
     Extended styles are used for features like textual margins and annotations as well as internally by Scintilla.
     They are outside the range 0..255 used for the styles bytes associated with document bytes.
     These functions manage the use of extended styles to ensures that components cooperate in defining styles.
     <code>SCI_RELEASEALLEXTENDEDSTYLES</code> releases any extended styles allocated by the container.
     <code>SCI_ALLOCATEEXTENDEDSTYLES</code> allocates a range of style numbers after the byte style values and returns
     the number of the first allocated style.
     Ranges for margin and annotation styles should be allocated before calling 
     <a class="message" href="#SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET</a> or
     <a class="message" href="#SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET</a>.</p>

    <p><b id="Sci_TextRange">Sci_TextRange</b> and <b id="Sci_CharacterRange">Sci_CharacterRange</b><br />
     These structures are defined to be exactly the same shape as the Win32 <code>TEXTRANGE</code>
    and <code>CHARRANGE</code>, so that older code that treats Scintilla as a RichEdit will
    work.</p>
<pre>
struct Sci_CharacterRange {
    long cpMin;
    long cpMax;
};

struct Sci_TextRange {
    struct Sci_CharacterRange chrg;
    char *lpstrText;
};
</pre>

    <h3 id="EncodedAccess">GTK+-specific: Access to encoded text</h3>

    <p><b id="SCI_TARGETASUTF8">SCI_TARGETASUTF8(&lt;unused&gt;, char *s)</b><br />
     This method retrieves the value of the target encoded as UTF-8 which is the default
     encoding of GTK+ so is useful for retrieving text for use in other parts of the user interface,
     such as find and replace dialogs. The length of the encoded text in bytes is returned.
    </p>

    <p><b id="SCI_ENCODEDFROMUTF8">SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)</b><br />
     <b id="SCI_SETLENGTHFORENCODE">SCI_SETLENGTHFORENCODE(int bytes)</b><br />
     <code>SCI_ENCODEDFROMUTF8</code> converts a UTF-8 string into the document's
     encoding which is useful for taking the results of a find dialog, for example, and receiving
     a string of bytes that can be searched for in the document. Since the text can contain nul bytes,
     the <code>SCI_SETLENGTHFORENCODE</code> method can be used to set the
     length that will be converted. If set to -1, the length is determined by finding a nul byte.
     The length of the converted string is returned.
    </p>


    <h2 id="Searching">Searching</h2>
    <p>
    There are methods to search for text and for regular expressions. The regular expression support
    is limited and should only be used for simple cases and initial development. A different regular expression
    library can be <a class="jump" href="#AlternativeRegEx">integrated into Scintilla</a>
    or can be called from the container using direct access to the buffer contents through
    <a class="message" href="#SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</a>.
    </p>
    <code><a class="message" href="#SCI_FINDTEXT">SCI_FINDTEXT(int flags, Sci_TextToFind
    *ttf)</a><br />
     <a class="message" href="#SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</a><br />
     <a class="message" href="#SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char
    *text)</a><br />
     <a class="message" href="#SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char
    *text)</a><br />
     <a class="jump" href="#SearchAndReplaceUsingTheTarget">Search and replace using the
    target</a><br />
    </code>

    <p><b id="searchFlags"><code>searchFlags</code></b><br />
     Several of the search routines use flag options, which include a simple regular expression
    search. Combine the flag options by adding them:</p>

    <table border="0" summary="Search flags">
      <tbody>
        <tr>
          <td><code>SCFIND_MATCHCASE</code></td>

          <td>A match only occurs with text that matches the case of the search string.</td>
        </tr>

        <tr>
          <td><code>SCFIND_WHOLEWORD</code></td>

          <td>A match only occurs if the characters before and after are not word characters.</td>
        </tr>

        <tr>
          <td><code>SCFIND_WORDSTART</code></td>

          <td>A match only occurs if the character before is not a word character.</td>
        </tr>

        <tr>
          <td><code>SCFIND_REGEXP</code></td>

          <td>The search string should be interpreted as a regular expression.</td>
        </tr>
        <tr>
          <td><code>SCFIND_POSIX</code></td>

          <td>Treat regular expression in a more POSIX compatible manner
            by interpreting bare ( and ) for tagged sections rather than \( and \).</td>
        </tr>
      </tbody>
    </table>

    <p>You can
    search backwards to find the previous occurrence of a search string by setting the end of the
    search range before the start.</p>

    <p>In a regular expression, special characters interpreted are:</p>

    <table border="0" summary="Regular expression synopsis">
      <tbody>
        <tr>
          <td><code>.</code></td>

          <td>Matches any character</td>
        </tr>

        <tr>
          <td><code>\(</code></td>

          <td>This marks the start of a region for tagging a match.</td>
        </tr>

        <tr>
          <td><code>\)</code></td>

          <td>This marks the end of a tagged region.</td>
        </tr>

        <tr>
          <td><code>\n</code></td>

          <td>Where <code>n</code> is 1 through 9 refers to the first through ninth tagged region
          when replacing. For example, if the search string was <code>Fred\([1-9]\)XXX</code> and
          the replace string was <code>Sam\1YYY</code>, when applied to <code>Fred2XXX</code> this
          would generate <code>Sam2YYY</code>.
	  <code>\0</code> refers to all of the matching text.</td>
        </tr>

        <tr>
          <td><code>\&lt;</code></td>

          <td>This matches the start of a word using Scintilla's definitions of words.</td>
        </tr>

        <tr>
          <td><code>\&gt;</code></td>

          <td>This matches the end of a word using Scintilla's definition of words.</td>
        </tr>

        <tr>
          <td><code>\x</code></td>

          <td>This allows you to use a character x that would otherwise have a special meaning. For
          example, \[ would be interpreted as [ and not as the start of a character set.</td>
        </tr>

        <tr>
          <td><code>[...]</code></td>

          <td>This indicates a set of characters, for example, [abc] means any of the characters a,
          b or c. You can also use ranges, for example [a-z] for any lower case character.</td>
        </tr>

        <tr>
          <td><code>[^...]</code></td>

          <td>The complement of the characters in the set. For example, [^A-Za-z] means any
          character except an alphabetic character.</td>
        </tr>

        <tr>
          <td><code>^</code></td>

          <td>This matches the start of a line (unless used inside a set, see above).</td>
        </tr>

        <tr>
          <td><code>$</code></td>

          <td>This matches the end of a line.</td>
        </tr>

        <tr>
          <td><code>*</code></td>

          <td>This matches 0 or more times. For example, <code>Sa*m</code> matches <code>Sm</code>,
          <code>Sam</code>, <code>Saam</code>, <code>Saaam</code> and so on.</td>
        </tr>

        <tr>
          <td><code>+</code></td>

          <td>This matches 1 or more times. For example, <code>Sa+m</code> matches
          <code>Sam</code>, <code>Saam</code>, <code>Saaam</code> and so on.</td>
        </tr>
      </tbody>
    </table>

    <p>Regular expressions will only match ranges within a single line, never matching over multiple lines.</p>

    <p><b id="SCI_FINDTEXT">SCI_FINDTEXT(int searchFlags, <a class="jump"
    href="#Sci_TextToFind">Sci_TextToFind</a> *ttf)</b><br />
     This message searches for text in the document. It does not use or move the current selection.
    The <a class="jump" href="#searchFlags"><code>searchFlags</code></a> argument controls the
    search type, which includes regular expression searches.</p>

    <p>The <code>Sci_TextToFind</code> structure is defined in <code>Scintilla.h</code>; set
    <code>chrg.cpMin</code> and <code>chrg.cpMax</code> with the range of positions in the document
    to search. You can search backwards by
    setting <code>chrg.cpMax</code> less than <code>chrg.cpMin</code>.
    Set the <code>lpstrText</code> member of <code>Sci_TextToFind</code> to point at a zero terminated
    text string holding the search pattern. If your language makes the use of <code>Sci_TextToFind</code>
    difficult, you should consider using <code>SCI_SEARCHINTARGET</code> instead.</p>

    <p>The return value is -1 if the search fails or the position of the start of the found text if
    it succeeds. The <code>chrgText.cpMin</code> and <code>chrgText.cpMax</code> members of
    <code>Sci_TextToFind</code> are filled in with the start and end positions of the found text.</p>

    <p>See also: <code><a class="message"
    href="#SCI_SEARCHINTARGET">SCI_SEARCHINTARGET</a></code></p>

    <p><b id="Sci_TextToFind">Sci_TextToFind</b><br />
     This structure is defined to have exactly the same shape as the Win32 structure
    <code>FINDTEXTEX</code> for old code that treated Scintilla as a RichEdit control.</p>
<pre>
struct Sci_TextToFind {
    struct <a class="jump" href="#Sci_CharacterRange">Sci_CharacterRange</a> chrg;     // range to search
    char *lpstrText;                // the search pattern (zero terminated)
    struct Sci_CharacterRange chrgText; // returned as position of matching text
};
</pre>

    <p><b id="SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</b><br />
     <b id="SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char *text)</b><br />
     <b id="SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text)</b><br />
     These messages provide relocatable search support. This allows multiple incremental
    interactive searches to be macro recorded while still setting the selection to found text so
    the find/select operation is self-contained. These three messages send <a class="message"
    href="#SCN_MACRORECORD"><code>SCN_MACRORECORD</code></a> <a class="jump"
    href="#Notifications">notifications</a> if macro recording is enabled.</p>

    <p><code>SCI_SEARCHANCHOR</code> sets the search start point used by
    <code>SCI_SEARCHNEXT</code> and <code>SCI_SEARCHPREV</code> to the start of the current
    selection, that is, the end of the selection that is nearer to the start of the document. You
    should always call this before calling either of <code>SCI_SEARCHNEXT</code> or
    <code>SCI_SEARCHPREV</code>.</p>

    <p><code>SCI_SEARCHNEXT</code> and <code>SCI_SEARCHPREV</code> search for the next and previous
    occurrence of the zero terminated search string pointed at by text. The search is modified by
    the <a class="jump" href="#searchFlags"><code>searchFlags</code></a>. </p>

    <p>The return value is -1 if nothing is found, otherwise the return value is the start position
    of the matching text. The selection is updated to show the matched text, but is not scrolled
    into view.</p>

    <p>See also: <a class="message" href="#SCI_SEARCHINTARGET"><code>SCI_SEARCHINTARGET</code></a>,
    <a class="message" href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a></p>

    <h3 id="SearchAndReplaceUsingTheTarget">Search and replace using the target</h3>

    <p>Using <a class="message" href="#SCI_REPLACESEL"><code>SCI_REPLACESEL</code></a>,
    modifications cause scrolling and other visible changes, which may take some time and cause
    unwanted display updates. If performing many changes, such as a replace all command, the target
    can be used instead. First, set the target, ie. the range to be replaced. Then call
    <code>SCI_REPLACETARGET</code> or <code>SCI_REPLACETARGETRE</code>.</p>

    <p>Searching can be performed within the target range with <code>SCI_SEARCHINTARGET</code>,
    which uses a counted string to allow searching for null characters. It returns the
    position of the start of the matching text range or -1 for failure, in which case the target is not moved. The flags used by
    <code>SCI_SEARCHINTARGET</code> such as <code>SCFIND_MATCHCASE</code>,
    <code>SCFIND_WHOLEWORD</code>, <code>SCFIND_WORDSTART</code>, and <code>SCFIND_REGEXP</code>
    can be set with <code>SCI_SETSEARCHFLAGS</code>. <code>SCI_SEARCHINTARGET</code> may be simpler
    for some clients to use than <a class="message"
    href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a>, as that requires using a pointer to a
    structure.</p>
    <code><a class="message" href="#SCI_SETTARGETSTART">SCI_SETTARGETSTART(int pos)</a><br />
     <a class="message" href="#SCI_GETTARGETSTART">SCI_GETTARGETSTART</a><br />
     <a class="message" href="#SCI_SETTARGETEND">SCI_SETTARGETEND(int pos)</a><br />
     <a class="message" href="#SCI_GETTARGETEND">SCI_GETTARGETEND</a><br />
     <a class="message" href="#SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</a><br />
     <a class="message" href="#SCI_SETSEARCHFLAGS">SCI_SETSEARCHFLAGS(int searchFlags)</a><br />
     <a class="message" href="#SCI_GETSEARCHFLAGS">SCI_GETSEARCHFLAGS</a><br />
     <a class="message" href="#SCI_SEARCHINTARGET">SCI_SEARCHINTARGET(int length, const char
    *text)</a><br />
     <a class="message" href="#SCI_REPLACETARGET">SCI_REPLACETARGET(int length, const char
    *text)</a><br />
     <a class="message" href="#SCI_REPLACETARGETRE">SCI_REPLACETARGETRE(int length, const char
    *text)</a><br />
     <a class="message" href="#SCI_GETTAG">SCI_GETTAG(int tagNumber, char *tagValue)</a><br />
    </code>

    <p><b id="SCI_SETTARGETSTART">SCI_SETTARGETSTART(int pos)</b><br />
     <b id="SCI_GETTARGETSTART">SCI_GETTARGETSTART</b><br />
     <b id="SCI_SETTARGETEND">SCI_SETTARGETEND(int pos)</b><br />
     <b id="SCI_GETTARGETEND">SCI_GETTARGETEND</b><br />
     These functions set and return the start and end of the target. When searching in non-regular
    expression mode, you can set start greater than end to find the last matching text in the
    target rather than the first matching text. The target is also set by a successful
    <code>SCI_SEARCHINTARGET</code>.</p>

     <p><b id="SCI_TARGETFROMSELECTION">SCI_TARGETFROMSELECTION</b><br />
     Set the target start and end to the start and end positions of the selection.</p>

    <p><b id="SCI_SETSEARCHFLAGS">SCI_SETSEARCHFLAGS(int searchFlags)</b><br />
     <b id="SCI_GETSEARCHFLAGS">SCI_GETSEARCHFLAGS</b><br />
     These get and set the <a class="jump" href="#searchFlags"><code>searchFlags</code></a> used by
    <code>SCI_SEARCHINTARGET</code>. There are several option flags including a simple regular
    expression search.</p>

    <p><b id="SCI_SEARCHINTARGET">SCI_SEARCHINTARGET(int length, const char *text)</b><br />
     This searches for the first occurrence of a text string in the target defined by
    <code>SCI_SETTARGETSTART</code> and <code>SCI_SETTARGETEND</code>. The text string is not zero
    terminated; the size is set by <code>length</code>. The search is modified by the search flags
    set by <code>SCI_SETSEARCHFLAGS</code>. If the search succeeds, the target is set to the found
    text and the return value is the position of the start of the matching text. If the search
    fails, the result is -1.</p>

    <p><b id="SCI_REPLACETARGET">SCI_REPLACETARGET(int length, const char *text)</b><br />
     If <code>length</code> is -1, <code>text</code> is a zero terminated string, otherwise
    <code>length</code> sets the number of character to replace the target with.
           After replacement, the target range refers to the replacement text.
           The return value
    is the length of the replacement string.<br />
    Note that the recommended way to delete text in the document is to set the target to the text to be removed,
    and to perform a replace target with an empty string.</p>

    <p><b id="SCI_REPLACETARGETRE">SCI_REPLACETARGETRE(int length, const char *text)</b><br />
     This replaces the target using regular expressions. If <code>length</code> is -1,
    <code>text</code> is a zero terminated string, otherwise <code>length</code> is the number of
    characters to use. The replacement string is formed from the text string with any sequences of
    <code>\1</code> through <code>\9</code> replaced by tagged matches from the most recent regular
    expression search. <code>\0</code> is replaced with all the matched text from the most recent search.
           After replacement, the target range refers to the replacement text.
           The return value is the length of the replacement string.</p>

    <p><b id="SCI_GETTAG">SCI_GETTAG(int tagNumber, char *tagValue)</b><br />
     Discover what text was matched by tagged expressions in a regular expression search.
     This is useful if the application wants to interpret the replacement string itself.</p>

    <p>See also: <a class="message" href="#SCI_FINDTEXT"><code>SCI_FINDTEXT</code></a></p>

    <h2 id="Overtype">Overtype</h2>

    <p><b id="SCI_SETOVERTYPE">SCI_SETOVERTYPE(bool overType)</b><br />
     <b id="SCI_GETOVERTYPE">SCI_GETOVERTYPE</b><br />
     When overtype is enabled, each typed character replaces the character to the right of the text
    caret. When overtype is disabled, characters are inserted at the caret.
    <code>SCI_GETOVERTYPE</code> returns <code>TRUE</code> (1) if overtyping is active, otherwise
    <code>FALSE</code> (0) will be returned. Use <code>SCI_SETOVERTYPE</code> to set the overtype
    mode.</p>

    <h2 id="CutCopyAndPaste">Cut, copy and paste</h2>

    <code><a class="message" href="#SCI_CUT">SCI_CUT</a><br />
     <a class="message" href="#SCI_COPY">SCI_COPY</a><br />
     <a class="message" href="#SCI_PASTE">SCI_PASTE</a><br />
     <a class="message" href="#SCI_CLEAR">SCI_CLEAR</a><br />
     <a class="message" href="#SCI_CANPASTE">SCI_CANPASTE</a><br />
     <a class="message" href="#SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</a><br />
     <a class="message" href="#SCI_COPYTEXT">SCI_COPYTEXT(int length,
     const char *text)</a><br />
     <a class="message" href="#SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</a><br />
     <a class="message" href="#SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</a><br />
     <a class="message" href="#SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS</a><br />
    </code>

    <p><b id="SCI_CUT">SCI_CUT</b><br />
     <b id="SCI_COPY">SCI_COPY</b><br />
     <b id="SCI_PASTE">SCI_PASTE</b><br />
     <b id="SCI_CLEAR">SCI_CLEAR</b><br />
     <b id="SCI_CANPASTE">SCI_CANPASTE</b><br />
     <b id="SCI_COPYALLOWLINE">SCI_COPYALLOWLINE</b><br />
     These commands perform the standard tasks of cutting and copying data to the clipboard,
    pasting from the clipboard into the document, and clearing the document.
    <code>SCI_CANPASTE</code> returns non-zero if the document isn't read-only and if the selection
    doesn't contain protected text. If you need a "can copy" or "can cut", use
    <code>SCI_GETSELECTIONEMPTY()</code>, which will be zero if there are any non-empty
    selection ranges implying that a copy or cut to the clipboard should work.</p>

    <p>GTK+ does not really support <code>SCI_CANPASTE</code> and always returns <code>TRUE</code>
    unless the document is read-only.</p>

    <p>On X, the clipboard is asynchronous and may require several messages between
    the destination and source applications. Data from SCI_PASTE will not arrive in the
    document immediately.</p>

    <p><code>SCI_COPYALLOWLINE</code> works the same as SCI_COPY except that if the
    selection is empty then the current line is copied. On Windows, an extra "MSDEVLineSelect" marker
    is added to the clipboard which is then used in <code>SCI_PASTE</code> to paste
    the whole line before the current line.</p>

     <b id="SCI_COPYRANGE">SCI_COPYRANGE(int start, int end)</b><br />
     <b id="SCI_COPYTEXT">SCI_COPYTEXT(int length, const char *text)</b><br />
    <p><code>SCI_COPYRANGE</code> copies a range of text from the document to
    the system clipboard and <code>SCI_COPYTEXT</code> copies a supplied piece of
    text to the system clipboard.</p>

    <p><b id="SCI_SETPASTECONVERTENDINGS">SCI_SETPASTECONVERTENDINGS(bool convert)</b><br />
     <b id="SCI_GETPASTECONVERTENDINGS">SCI_GETPASTECONVERTENDINGS</b><br />
     If this property is set then when text is pasted any line ends are converted to match the document's
     end of line mode as set with
     <a class="message" href="#SCI_SETEOLMODE">SCI_SETEOLMODE</a>.
     Currently only changeable on Windows. On GTK+ pasted text is always converted.</p>

    <h2 id="ErrorHandling">Error handling</h2>

    <p><b id="SCI_SETSTATUS">SCI_SETSTATUS(int status)</b><br />
     <b id="SCI_GETSTATUS">SCI_GETSTATUS</b><br />
     If an error occurs, Scintilla may set an internal error number that can be retrieved with
    <code>SCI_GETSTATUS</code>.
    To clear the error status call <code>SCI_SETSTATUS(0)</code>.
    The currently defined statuses are:
    </p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Status values">
      <tbody valign="top">
        <tr>
          <th align="left">SC_STATUS_OK</th>
          <td>0</td>
          <td>No failures</td>
        </tr>

        <tr>
          <th align="left">SC_STATUS_FAILURE</th>
          <td>1</td>
          <td>Generic failure</td>
        </tr>

        <tr>
          <th align="left">SC_STATUS_BADALLOC</th>
          <td>2</td>
          <td>Memory is exhausted</td>
        </tr>

      </tbody>
    </table>

    <h2 id="UndoAndRedo">Undo and Redo</h2>

    <p>Scintilla has multiple level undo and redo. It will continue to collect undoable actions
    until memory runs out. Scintilla saves actions that change the document. Scintilla does not
    save caret and selection movements, view scrolling and the like. Sequences of typing or
    deleting are compressed into single transactions to make it easier to undo and redo at a sensible
    level of detail. Sequences of actions can be combined into transactions that are undone as a unit.
    These sequences occur between <code>SCI_BEGINUNDOACTION</code> and
    <code>SCI_ENDUNDOACTION</code> messages. These transactions can be nested and only the top-level
    sequences are undone as units.</p>
    <code><a class="message" href="#SCI_UNDO">SCI_UNDO</a><br />
     <a class="message" href="#SCI_CANUNDO">SCI_CANUNDO</a><br />
     <a class="message" href="#SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</a><br />
     <a class="message" href="#SCI_REDO">SCI_REDO</a><br />
     <a class="message" href="#SCI_CANREDO">SCI_CANREDO</a><br />
     <a class="message" href="#SCI_SETUNDOCOLLECTION">SCI_SETUNDOCOLLECTION(bool
    collectUndo)</a><br />
     <a class="message" href="#SCI_GETUNDOCOLLECTION">SCI_GETUNDOCOLLECTION</a><br />
     <a class="message" href="#SCI_BEGINUNDOACTION">SCI_BEGINUNDOACTION</a><br />
     <a class="message" href="#SCI_ENDUNDOACTION">SCI_ENDUNDOACTION</a><br />
     <a class="message" href="#SCI_ADDUNDOACTION">SCI_ADDUNDOACTION(int token, int flags)</a><br />
    </code>

    <p><b id="SCI_UNDO">SCI_UNDO</b><br />
     <b id="SCI_CANUNDO">SCI_CANUNDO</b><br />
     <code>SCI_UNDO</code> undoes one action, or if the undo buffer has reached a
    <code>SCI_ENDUNDOACTION</code> point, all the actions back to the corresponding
    <code>SCI_BEGINUNDOACTION</code>.</p>

    <p><code>SCI_CANUNDO</code> returns 0 if there is nothing to undo, and 1 if there is. You would
    typically use the result of this message to enable/disable the Edit menu Undo command.</p>

    <p><b id="SCI_REDO">SCI_REDO</b><br />
     <b id="SCI_CANREDO">SCI_CANREDO</b><br />
     <code>SCI_REDO</code> undoes the effect of the last <code>SCI_UNDO</code> operation.</p>

    <p><code>SCI_CANREDO</code> returns 0 if there is no action to redo and 1 if there are undo
    actions to redo. You could typically use the result of this message to enable/disable the Edit
    menu Redo command.</p>

    <p><b id="SCI_EMPTYUNDOBUFFER">SCI_EMPTYUNDOBUFFER</b><br />
     This command tells Scintilla to forget any saved undo or redo history. It also sets the save
    point to the start of the undo buffer, so the document will appear to be unmodified. This does
    not cause the <code><a class="message"
    href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a></code> notification to be sent to the
    container.</p>

    <p>See also: <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a></p>

    <p><b id="SCI_SETUNDOCOLLECTION">SCI_SETUNDOCOLLECTION(bool collectUndo)</b><br />
     <b id="SCI_GETUNDOCOLLECTION">SCI_GETUNDOCOLLECTION</b><br />
     You can control whether Scintilla collects undo information with
    <code>SCI_SETUNDOCOLLECTION</code>. Pass in <code>true</code> (1) to collect information and
    <code>false</code> (0) to stop collecting. If you stop collection, you should also use
    <code>SCI_EMPTYUNDOBUFFER</code> to avoid the undo buffer being unsynchronized with the data in
    the buffer.</p>

    <p>You might wish to turn off saving undo information if you use the Scintilla to store text
    generated by a program (a Log view) or in a display window where text is often deleted and
    regenerated.</p>

    <p><b id="SCI_BEGINUNDOACTION">SCI_BEGINUNDOACTION</b><br />
     <b id="SCI_ENDUNDOACTION">SCI_ENDUNDOACTION</b><br />
     Send these two messages to Scintilla to mark the beginning and end of a set of operations that
    you want to undo all as one operation but that you have to generate as several operations.
    Alternatively, you can use these to mark a set of operations that you do not want to have
    combined with the preceding or following operations if they are undone.</p>

    <p><b id="SCI_ADDUNDOACTION">SCI_ADDUNDOACTION(int token, int flags)</b><br />
     The container can add its own actions into the undo stack by calling
     <code>SCI_ADDUNDOACTION</code> and an <code>SCN_MODIFIED</code>
     notification will be sent to the container with the
     <a class="message" href="#SC_MOD_CONTAINER"><code>SC_MOD_CONTAINER</code></a>
     flag when it is time to undo (<code>SC_PERFORMED_UNDO</code>) or
     redo (<code>SC_PERFORMED_REDO</code>) the action. The token argument supplied is
     returned in the <code>token</code> field of the notification.</p>
     <p>For example, if the container wanted to allow undo and redo of a 'toggle bookmark' command then
     it could call <code>SCI_ADDUNDOACTION(line, 0)</code> each time the command is performed.
     Then when it receives a notification to undo or redo it toggles a bookmark on the line given by
     the token field. If there are different types of commands or parameters that need to be stored into the undo
     stack then the container should maintain a stack of its own for the document and use the current
     position in that stack as the argument to <code>SCI_ADDUNDOACTION(line)</code>.
     <code>SCI_ADDUNDOACTION</code> commands are not combined together
     into a single undo transaction unless grouped with <code>SCI_BEGINUNDOACTION</code>
     and <code>SCI_ENDUNDOACTION</code>.</p>

     <p>The flags argument can be <code>UNDO_MAY_COALESCE</code> (1) if the container action may be
     coalesced along with any insertion and deletion actions into a single compound action, otherwise 0.
     Coalescing treats coalescible container actions as transparent so will still only group together insertions that
     look like typing or deletions that look like multiple uses of the Backspace or Delete keys.
     </p>
    <h2 id="SelectionAndInformation">Selection and information</h2>

    <p>Scintilla maintains a selection that stretches between two points, the anchor and the
    current position. If the anchor and the current position are the same, there is no selected
    text. Positions in the document range from 0 (before the first character), to the document size
    (after the last character). If you use messages, there is nothing to stop you setting a
    position that is in the middle of a CRLF pair, or in the middle of a 2 byte character. However,
    keyboard commands will not move the caret into such positions.</p>
    <code><a class="message" href="#SCI_GETTEXTLENGTH">SCI_GETTEXTLENGTH</a><br />
     <a class="message" href="#SCI_GETLENGTH">SCI_GETLENGTH</a><br />
     <a class="message" href="#SCI_GETLINECOUNT">SCI_GETLINECOUNT</a><br />
     <a class="message" href="#SCI_SETFIRSTVISIBLELINE">SCI_SETFIRSTVISIBLELINE(int lineDisplay)</a><br />
     <a class="message" href="#SCI_GETFIRSTVISIBLELINE">SCI_GETFIRSTVISIBLELINE</a><br />
     <a class="message" href="#SCI_LINESONSCREEN">SCI_LINESONSCREEN</a><br />
     <a class="message" href="#SCI_GETMODIFY">SCI_GETMODIFY</a><br />
     <a class="message" href="#SCI_SETSEL">SCI_SETSEL(int anchorPos, int currentPos)</a><br />
     <a class="message" href="#SCI_GOTOPOS">SCI_GOTOPOS(int position)</a><br />
     <a class="message" href="#SCI_GOTOLINE">SCI_GOTOLINE(int line)</a><br />
     <a class="message" href="#SCI_SETCURRENTPOS">SCI_SETCURRENTPOS(int position)</a><br />
     <a class="message" href="#SCI_GETCURRENTPOS">SCI_GETCURRENTPOS</a><br />
     <a class="message" href="#SCI_SETANCHOR">SCI_SETANCHOR(int position)</a><br />
     <a class="message" href="#SCI_GETANCHOR">SCI_GETANCHOR</a><br />
     <a class="message" href="#SCI_SETSELECTIONSTART">SCI_SETSELECTIONSTART(int position)</a><br />
     <a class="message" href="#SCI_GETSELECTIONSTART">SCI_GETSELECTIONSTART</a><br />
     <a class="message" href="#SCI_SETSELECTIONEND">SCI_SETSELECTIONEND(int position)</a><br />
     <a class="message" href="#SCI_GETSELECTIONEND">SCI_GETSELECTIONEND</a><br />
     <a class="message" href="#SCI_SETEMPTYSELECTION">SCI_SETEMPTYSELECTION(int pos)</a><br />
     <a class="message" href="#SCI_SELECTALL">SCI_SELECTALL</a><br />
     <a class="message" href="#SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION(int position)</a><br />
     <a class="message" href="#SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE(int line)</a><br />
     <a class="message" href="#SCI_GETLINEENDPOSITION">SCI_GETLINEENDPOSITION(int line)</a><br />
     <a class="message" href="#SCI_LINELENGTH">SCI_LINELENGTH(int line)</a><br />
     <a class="message" href="#SCI_GETCOLUMN">SCI_GETCOLUMN(int position)</a><br />
     <a class="message" href="#SCI_FINDCOLUMN">SCI_FINDCOLUMN(int line, int column)</a><br />
     <a class="message" href="#SCI_POSITIONFROMPOINT">SCI_POSITIONFROMPOINT(int x, int y)</a><br />
     <a class="message" href="#SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE(int x, int
    y)</a><br />
     <a class="message" href="#SCI_CHARPOSITIONFROMPOINT">SCI_CHARPOSITIONFROMPOINT(int x, int y)</a><br />
     <a class="message" href="#SCI_CHARPOSITIONFROMPOINTCLOSE">SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int
    y)</a><br />
     <a class="message" href="#SCI_POINTXFROMPOSITION">SCI_POINTXFROMPOSITION(&lt;unused&gt;, int
    position)</a><br />
     <a class="message" href="#SCI_POINTYFROMPOSITION">SCI_POINTYFROMPOSITION(&lt;unused&gt;, int
    position)</a><br />
     <a class="message" href="#SCI_HIDESELECTION">SCI_HIDESELECTION(bool hide)</a><br />
     <a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT(&lt;unused&gt;, char *text)</a><br />
     <a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE(int textLen, char *text)</a><br />
     <a class="message" href="#SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE</a><br />
     <a class="message" href="#SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int mode)</a><br />
     <a class="message" href="#SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE</a><br />
     <a class="message" href="#SCI_GETLINESELSTARTPOSITION">SCI_GETLINESELSTARTPOSITION(int line)</a><br />
     <a class="message" href="#SCI_GETLINESELENDPOSITION">SCI_GETLINESELENDPOSITION(int line)</a><br />
     <a class="message" href="#SCI_MOVECARETINSIDEVIEW">SCI_MOVECARETINSIDEVIEW</a><br />
     <a class="message" href="#SCI_WORDENDPOSITION">SCI_WORDENDPOSITION(int position, bool
    onlyWordCharacters)</a><br />
     <a class="message" href="#SCI_WORDSTARTPOSITION">SCI_WORDSTARTPOSITION(int position, bool
    onlyWordCharacters)</a><br />
     <a class="message" href="#SCI_POSITIONBEFORE">SCI_POSITIONBEFORE(int position)</a><br />
     <a class="message" href="#SCI_POSITIONAFTER">SCI_POSITIONAFTER(int position)</a><br />
     <a class="message" href="#SCI_COUNTCHARACTERS">SCI_COUNTCHARACTERS(int startPos, int endPos)</a><br />
     <a class="message" href="#SCI_TEXTWIDTH">SCI_TEXTWIDTH(int styleNumber, const char *text)</a><br />
     <a class="message" href="#SCI_TEXTHEIGHT">SCI_TEXTHEIGHT(int line)</a><br />
     <a class="message" href="#SCI_CHOOSECARETX">SCI_CHOOSECARETX</a><br />
     <a class="message" href="#SCI_MOVESELECTEDLINESUP">SCI_MOVESELECTEDLINESUP</a><br />
     <a class="message" href="#SCI_MOVESELECTEDLINESDOWN">SCI_MOVESELECTEDLINESDOWN</a><br />
    </code>

    <p><b id="SCI_GETTEXTLENGTH">SCI_GETTEXTLENGTH</b><br />
     <b id="SCI_GETLENGTH">SCI_GETLENGTH</b><br />
     Both these messages return the length of the document in bytes.</p>

    <p><b id="SCI_GETLINECOUNT">SCI_GETLINECOUNT</b><br />
     This returns the number of lines in the document. An empty document contains 1 line. A
    document holding only an end of line sequence has 2 lines.</p>

    <p><b id="SCI_SETFIRSTVISIBLELINE">SCI_SETFIRSTVISIBLELINE(int lineDisplay)</b><br />
     <b id="SCI_GETFIRSTVISIBLELINE">SCI_GETFIRSTVISIBLELINE</b><br />
     These messages retrieve and set the line number of the first visible line in the Scintilla view. The first line
    in the document is numbered 0. The value is a visible line rather than a document line.</p>

    <p><b id="SCI_LINESONSCREEN">SCI_LINESONSCREEN</b><br />
     This returns the number of complete lines visible on the screen. With a constant line height,
    this is the vertical space available divided by the line separation. Unless you arrange to size
    your window to an integral number of lines, there may be a partial line visible at the bottom
    of the view.</p>

    <p><b id="SCI_GETMODIFY">SCI_GETMODIFY</b><br />
     This returns non-zero if the document is modified and 0 if it is unmodified. The modified
    status of a document is determined by the undo position relative to the save point. The save
    point is set by <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a>,
    usually when you have saved data to a file.</p>

    <p>If you need to be notified when the document becomes modified, Scintilla notifies the
    container that it has entered or left the save point with the <a class="message"
    href="#SCN_SAVEPOINTREACHED"><code>SCN_SAVEPOINTREACHED</code></a> and <a class="message"
    href="#SCN_SAVEPOINTLEFT"><code>SCN_SAVEPOINTLEFT</code></a> <a class="jump"
    href="#Notifications">notification messages</a>.</p>

    <p><b id="SCI_SETSEL">SCI_SETSEL(int anchorPos, int currentPos)</b><br />
     This message sets both the anchor and the current position. If <code>currentPos</code> is
    negative, it means the end of the document. If <code>anchorPos</code> is negative, it means
    remove any selection (i.e. set the anchor to the same position as <code>currentPos</code>). The
    caret is scrolled into view after this operation.</p>

    <p><b id="SCI_GOTOPOS">SCI_GOTOPOS(int pos)</b><br />
     This removes any selection, sets the caret at <code>pos</code> and scrolls the view to make
    the caret visible, if necessary. It is equivalent to
    <code>SCI_SETSEL(pos, pos)</code>. The anchor position is set the same as the current
    position.</p>

    <p><b id="SCI_GOTOLINE">SCI_GOTOLINE(int line)</b><br />
     This removes any selection and sets the caret at the start of line number <code>line</code>
    and scrolls the view (if needed) to make it visible. The anchor position is set the same as the
    current position. If <code>line</code> is outside the lines in the document (first line is 0),
    the line set is the first or last.</p>

    <p><b id="SCI_SETCURRENTPOS">SCI_SETCURRENTPOS(int pos)</b><br />
     This sets the current position and creates a selection between the anchor and the current
    position. The caret is not scrolled into view.</p>

    <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>

    <p><b id="SCI_GETCURRENTPOS">SCI_GETCURRENTPOS</b><br />
     This returns the current position.</p>

    <p><b id="SCI_SETANCHOR">SCI_SETANCHOR(int pos)</b><br />
     This sets the anchor position and creates a selection between the anchor position and the
    current position. The caret is not scrolled into view.</p>

    <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>

    <p><b id="SCI_GETANCHOR">SCI_GETANCHOR</b><br />
     This returns the current anchor position.</p>

    <p><b id="SCI_SETSELECTIONSTART">SCI_SETSELECTIONSTART(int pos)</b><br />
     <b id="SCI_SETSELECTIONEND">SCI_SETSELECTIONEND(int pos)</b><br />
     These set the selection based on the assumption that the anchor position is less than the
    current position. They do not make the caret visible. The table shows the positions of the
    anchor and the current position after using these messages.</p>

    <table cellpadding="3" cellspacing="0" border="1" summary="SetSelection caret positioning">
      <thead align="center">
        <tr>
          <th>
          </th>

          <th>anchor</th>

          <th>current</th>
        </tr>
      </thead>

      <tbody align="center">
        <tr>
          <th><code>SCI_SETSELECTIONSTART</code></th>

          <td><code>pos</code></td>

          <td><code>Max(pos, current)</code></td>
        </tr>

        <tr>
          <th><code>SCI_SETSELECTIONEND</code></th>

          <td><code>Min(anchor, pos)</code></td>

          <td><code>pos</code></td>
        </tr>
      </tbody>
    </table>

    <p>See also: <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a></p>

    <p><b id="SCI_GETSELECTIONSTART">SCI_GETSELECTIONSTART</b><br />
     <b id="SCI_GETSELECTIONEND">SCI_GETSELECTIONEND</b><br />
     These return the start and end of the selection without regard to which end is the current
    position and which is the anchor. <code>SCI_GETSELECTIONSTART</code> returns the smaller of the
    current position or the anchor position. <code>SCI_GETSELECTIONEND</code> returns the larger of
    the two values.</p>

    <p><b id="SCI_SETEMPTYSELECTION">SCI_SETEMPTYSELECTION(int pos)</b><br />
     This removes any selection and sets the caret at <code>pos</code>. The caret is not scrolled into view.</p>

    <p><b id="SCI_SELECTALL">SCI_SELECTALL</b><br />
     This selects all the text in the document. The current position is not scrolled into view.</p>

    <p><b id="SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION(int pos)</b><br />
     This message returns the line that contains the position <code>pos</code> in the document. The
    return value is 0 if <code>pos</code> &lt;= 0. The return value is the last line if
    <code>pos</code> is beyond the end of the document.</p>

    <p><b id="SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE(int line)</b><br />
     This returns the document position that corresponds with the start of the line. If
    <code>line</code> is negative, the position of the line holding the start of the selection is
    returned. If <code>line</code> is greater than the lines in the document, the return value is
    -1. If <code>line</code> is equal to the number of lines in the document (i.e. 1 line past the
    last line), the return value is the end of the document.</p>

    <p><b id="SCI_GETLINEENDPOSITION">SCI_GETLINEENDPOSITION(int line)</b><br />
     This returns the position at the end of the line, before any line end characters. If <code>line</code>
    is the last line in the document (which does not have any end of line characters), the result is the size of the
    document. If <code>line</code> is negative or <code>line</code> &gt;= <a class="message"
    href="#SCI_GETLINECOUNT"><code>SCI_GETLINECOUNT()</code></a>, the result is undefined.</p>

    <p><b id="SCI_LINELENGTH">SCI_LINELENGTH(int line)</b><br />
     This returns the length of the line, including any line end characters. If <code>line</code>
    is negative or beyond the last line in the document, the result is 0. If you want the length of
    the line not including any end of line characters, use <a class="message"
    href="#SCI_GETLINEENDPOSITION"><code>SCI_GETLINEENDPOSITION(line)</code></a> - <a class="message"
    href="#SCI_POSITIONFROMLINE"><code>SCI_POSITIONFROMLINE(line)</code></a>.</p>

    <p><b id="SCI_GETSELTEXT">SCI_GETSELTEXT(&lt;unused&gt;, char *text)</b><br />
     This copies the currently selected text and a terminating 0 byte to the <code>text</code>
    buffer. The buffer size should be determined by calling with a NULL pointer for the <code>text</code> argument
    <code>SCI_GETSELTEXT(0,0)</code>.
    This allows for rectangular and discontiguous selections as well as simple selections.
    See <a class="toc" href="#MultipleSelectionAndVirtualSpace">Multiple Selection</a> for information on
    how multiple and rectangular selections and virtual space are copied.</p>

    <p>See also: <code><a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE</a>,
    <a class="message" href="#SCI_GETLINE">SCI_GETLINE</a>,
    <a class="message" href="#SCI_GETTEXT">SCI_GETTEXT</a>,
    <a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>,
    <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a>
    </code></p>

    <p><b id="SCI_GETCURLINE">SCI_GETCURLINE(int textLen, char *text)</b><br />
     This retrieves the text of the line containing the caret and returns the position within the
    line of the caret. Pass in <code>char* text</code> pointing at a buffer large enough to hold
    the text you wish to retrieve and a terminating 0 character.
    Set <code>textLen</code> to the
    length of the buffer which must be at least 1 to hold the terminating 0 character.
    If the text argument is 0 then the length that should be allocated
    to store the entire current line is returned.</p>

    <p>See also: <code><a class="message" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>, <a
    class="message" href="#SCI_GETLINE">SCI_GETLINE</a>, <a class="message"
    href="#SCI_GETTEXT">SCI_GETTEXT</a>, <a class="message"
    href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT</a>, <a class="message"
    href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE</a></code></p>

    <p><b id="SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE</b><br />
     This returns 1 if the current selection is in rectangle mode, 0 if not.</p>

    <p><b id="SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int mode)</b><br />
    <b id="SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE</b><br />
    The two functions set and get the selection mode, which can be
     stream (<code>SC_SEL_STREAM</code>=0) or
     rectangular (<code>SC_SEL_RECTANGLE</code>=1) or
     by lines (<code>SC_SEL_LINES</code>=2)
     or thin rectangular (<code>SC_SEL_THIN</code>=3).
     When set in these modes, regular caret moves will extend or reduce the selection,
     until the mode is cancelled by a call with same value or with <code>SCI_CANCEL</code>.
     The get function returns the current mode even if the selection was made by mouse
     or with regular extended moves.
     <code>SC_SEL_THIN</code> is the mode after a rectangular selection has been typed into and ensures
     that no characters are selected.</p>

    <p><b id="SCI_GETLINESELSTARTPOSITION">SCI_GETLINESELSTARTPOSITION(int line)</b><br />
    <b id="SCI_GETLINESELENDPOSITION">SCI_GETLINESELENDPOSITION(int line)</b><br />
    Retrieve the position of the start and end of the selection at the given line with
    INVALID_POSITION returned if no selection on this line.</p>

    <p><b id="SCI_MOVECARETINSIDEVIEW">SCI_MOVECARETINSIDEVIEW</b><br />
     If the caret is off the top or bottom of the view, it is moved to the nearest line that is
    visible to its current position. Any selection is lost.</p>

    <p><b id="SCI_WORDENDPOSITION">SCI_WORDENDPOSITION(int position, bool
    onlyWordCharacters)</b><br />
     <b id="SCI_WORDSTARTPOSITION">SCI_WORDSTARTPOSITION(int position, bool
    onlyWordCharacters)</b><br />
     These messages return the start and end of words using the same definition of words as used
    internally within Scintilla. You can set your own list of characters that count as words with
    <a class="message" href="#SCI_SETWORDCHARS"><code>SCI_SETWORDCHARS</code></a>. The position
    sets the start or the search, which is forwards when searching for the end and backwards when
    searching for the start.</p>

    <p>Set <code>onlyWordCharacters</code> to <code>true</code> (1) to stop searching at the first
    non-word character in the search direction. If <code>onlyWordCharacters</code> is
    <code>false</code> (0), the first character in the search direction sets the type of the search
    as word or non-word and the search stops at the first non-matching character. Searches are also
    terminated by the start or end of the document.</p>

    <p>If "w" represents word characters and "." represents non-word characters and "|" represents
    the position and <code>true</code> or <code>false</code> is the state of
    <code>onlyWordCharacters</code>:</p>

    <table cellpadding="3" cellspacing="0" border="1" summary="Word start and end positions">
      <thead align="center">
        <tr>
          <th>Initial state</th>

          <th>end, true</th>

          <th>end, false</th>

          <th>start, true</th>

          <th>start, false</th>
        </tr>
      </thead>

      <tbody align="center">
        <tr>
          <td>..ww..|..ww..</td>

          <td>..ww..|..ww..</td>

          <td>..ww....|ww..</td>

          <td>..ww..|..ww..</td>

          <td>..ww|....ww..</td>
        </tr>

        <tr>
          <td>....ww|ww....</td>

          <td>....wwww|....</td>

          <td>....wwww|....</td>

          <td>....|wwww....</td>

          <td>....|wwww....</td>
        </tr>

        <tr>
          <td>..ww|....ww..</td>

          <td>..ww|....ww..</td>

          <td>..ww....|ww..</td>

          <td>..|ww....ww..</td>

          <td>..|ww....ww..</td>
        </tr>

        <tr>
          <td>..ww....|ww..</td>

          <td>..ww....ww|..</td>

          <td>..ww....ww|..</td>

          <td>..ww....|ww..</td>

          <td>..ww|....ww..</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_POSITIONBEFORE">SCI_POSITIONBEFORE(int position)</b><br />
     <b id="SCI_POSITIONAFTER">SCI_POSITIONAFTER(int position)</b><br />
     These messages return the position before and after another position
     in the document taking into account the current code page. The minimum
     position returned is 0 and the maximum is the last position in the document.
     If called with a position within a multi byte character will return the position
     of the start/end of that character.</p>

    <p><b id="SCI_COUNTCHARACTERS">SCI_COUNTCHARACTERS(int startPos, int endPos)</b><br />
     Returns the number of whole characters between two positions..</p>

    <p><b id="SCI_TEXTWIDTH">SCI_TEXTWIDTH(int styleNumber, const char *text)</b><br />
     This returns the pixel width of a string drawn in the given <code>styleNumber</code> which can
    be used, for example, to decide how wide to make the line number margin in order to display a
    given number of numerals.</p>

    <p><b id="SCI_TEXTHEIGHT">SCI_TEXTHEIGHT(int line)</b><br />
     This returns the height in pixels of a particular line. Currently all lines are the same
    height.</p>

    <p><b id="SCI_GETCOLUMN">SCI_GETCOLUMN(int pos)</b><br />
     This message returns the column number of a position <code>pos</code> within the document
    taking the width of tabs into account. This returns the column number of the last tab on the
    line before <code>pos</code>, plus the number of characters between the last tab and
    <code>pos</code>. If there are no tab characters on the line, the return value is the number of
    characters up to the position on the line. In both cases, double byte characters count as a
    single character. This is probably only useful with monospaced fonts.</p>

    <p><b id="SCI_FINDCOLUMN">SCI_FINDCOLUMN(int line, int column)</b><br />
     This message returns the position of a <code>column</code> on a <code>line</code>
    taking the width of tabs into account. It treats a multi-byte character as a single column.
    Column numbers, like lines start at 0.</p>

    <p><b id="SCI_POSITIONFROMPOINT">SCI_POSITIONFROMPOINT(int x, int y)</b><br />
     <b id="SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE(int x, int y)</b><br />
     <code>SCI_POSITIONFROMPOINT</code> finds the closest character position to a point and
    <code>SCI_POSITIONFROMPOINTCLOSE</code> is similar but returns -1 if the point is outside the
    window or not close to any characters.</p>

    <p><b id="SCI_CHARPOSITIONFROMPOINT">SCI_CHARPOSITIONFROMPOINT(int x, int y)</b><br />
     <b id="SCI_CHARPOSITIONFROMPOINTCLOSE">SCI_CHARPOSITIONFROMPOINTCLOSE(int x, int y)</b><br />
     <code>SCI_CHARPOSITIONFROMPOINT</code> finds the closest character to a point and
    <code>SCI_CHARPOSITIONFROMPOINTCLOSE</code> is similar but returns -1 if the point is outside the
    window or not close to any characters. This is similar to the previous methods but finds characters rather than
    inter-character positions.</p>

    <p><b id="SCI_POINTXFROMPOSITION">SCI_POINTXFROMPOSITION(&lt;unused&gt;, int pos)</b><br />
     <b id="SCI_POINTYFROMPOSITION">SCI_POINTYFROMPOSITION(&lt;unused&gt;, int pos)</b><br />
     These messages return the x and y display pixel location of text at position <code>pos</code>
    in the document.</p>

    <p><b id="SCI_HIDESELECTION">SCI_HIDESELECTION(bool hide)</b><br />
     The normal state is to make the selection visible by drawing it as set by <a class="message"
    href="#SCI_SETSELFORE"><code>SCI_SETSELFORE</code></a> and <a class="message"
    href="#SCI_SETSELBACK"><code>SCI_SETSELBACK</code></a>. However, if you hide the selection, it
    is drawn as normal text.</p>

    <p><b id="SCI_CHOOSECARETX">SCI_CHOOSECARETX</b><br />
     Scintilla remembers the x value of the last position horizontally moved to explicitly by the
    user and this value is then used when moving vertically such as by using the up and down keys.
    This message sets the current x position of the caret as the remembered value.</p>

    <p><b id="SCI_MOVESELECTEDLINESUP">SCI_MOVESELECTEDLINESUP</b><br />
     Move the selected lines up one line, shifting the line above after the selection.
     The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line.
     If nothing was selected, the line the cursor is currently at will be selected.</p>

    <p><b id="SCI_MOVESELECTEDLINESDOWN">SCI_MOVESELECTEDLINESDOWN</b><br />
     Move the selected lines down one line, shifting the line below before the selection.
     The selection will be automatically extended to the beginning of the selection's first line and the end of the seletion's last line.
     If nothing was selected, the line the cursor is currently at will be selected.</p>

    <h2 id="MultipleSelectionAndVirtualSpace">Multiple Selection and Virtual Space</h2>

    <code>
     <a class="message" href="#SCI_SETMULTIPLESELECTION">SCI_SETMULTIPLESELECTION(bool multipleSelection)</a><br />
     <a class="message" href="#SCI_GETMULTIPLESELECTION">SCI_GETMULTIPLESELECTION</a><br />
     <a class="message" href="#SCI_SETADDITIONALSELECTIONTYPING">SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)</a><br />
     <a class="message" href="#SCI_GETADDITIONALSELECTIONTYPING">SCI_GETADDITIONALSELECTIONTYPING</a><br />
     <a class="message" href="#SCI_SETMULTIPASTE">SCI_SETMULTIPASTE(int multiPaste)</a><br />
     <a class="message" href="#SCI_GETMULTIPASTE">SCI_GETMULTIPASTE</a><br />
     <a class="message" href="#SCI_SETVIRTUALSPACEOPTIONS">SCI_SETVIRTUALSPACEOPTIONS(int virtualSpaceOptions)</a><br />
     <a class="message" href="#SCI_GETVIRTUALSPACEOPTIONS">SCI_GETVIRTUALSPACEOPTIONS</a><br />
     <a class="message" href="#SCI_SETRECTANGULARSELECTIONMODIFIER">SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)</a><br />
     <a class="message" href="#SCI_GETRECTANGULARSELECTIONMODIFIER">SCI_GETRECTANGULARSELECTIONMODIFIER</a><br />
     <br />

     <a class="message" href="#SCI_GETSELECTIONS">SCI_GETSELECTIONS</a><br />
     <a class="message" href="#SCI_GETSELECTIONEMPTY">SCI_GETSELECTIONEMPTY</a><br />
     <a class="message" href="#SCI_CLEARSELECTIONS">SCI_CLEARSELECTIONS</a><br />
     <a class="message" href="#SCI_SETSELECTION">SCI_SETSELECTION(int caret, int anchor)</a><br />
     <a class="message" href="#SCI_ADDSELECTION">SCI_ADDSELECTION(int caret, int anchor)</a><br />
     <a class="message" href="#SCI_SETMAINSELECTION">SCI_SETMAINSELECTION(int selection)</a><br />
     <a class="message" href="#SCI_GETMAINSELECTION">SCI_GETMAINSELECTION</a><br />
     <br />

     <a class="message" href="#SCI_SETSELECTIONNCARET">SCI_SETSELECTIONNCARET(int selection, int pos)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNCARET">SCI_GETSELECTIONNCARET(int selection)</a><br />
     <a class="message" href="#SCI_SETSELECTIONNCARETVIRTUALSPACE">SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNCARETVIRTUALSPACE">SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)</a><br />
     <a class="message" href="#SCI_SETSELECTIONNANCHOR">SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNANCHOR">SCI_GETSELECTIONNANCHOR(int selection)</a><br />
     <a class="message" href="#SCI_SETSELECTIONNANCHORVIRTUALSPACE">SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNANCHORVIRTUALSPACE">SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)</a><br />
     <a class="message" href="#SCI_SETSELECTIONNSTART">SCI_SETSELECTIONNSTART(int selection, int pos)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNSTART">SCI_GETSELECTIONNSTART(int selection)</a><br />
     <a class="message" href="#SCI_SETSELECTIONNEND">SCI_SETSELECTIONNEND(int selection, int pos)</a><br />
     <a class="message" href="#SCI_GETSELECTIONNEND">SCI_GETSELECTIONNEND(int selection)</a><br />
     <br />

     <a class="message" href="#SCI_SETRECTANGULARSELECTIONCARET">SCI_SETRECTANGULARSELECTIONCARET(int pos)</a><br />
     <a class="message" href="#SCI_GETRECTANGULARSELECTIONCARET">SCI_GETRECTANGULARSELECTIONCARET</a><br />
     <a class="message" href="#SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)</a><br />
     <a class="message" href="#SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE</a><br />
     <a class="message" href="#SCI_SETRECTANGULARSELECTIONANCHOR">SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)</a><br />
     <a class="message" href="#SCI_GETRECTANGULARSELECTIONANCHOR">SCI_GETRECTANGULARSELECTIONANCHOR</a><br />
     <a class="message" href="#SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)</a><br />
     <a class="message" href="#SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE</a><br />
     <br />

     <a class="message" href="#SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(int alpha)</a><br />
     <a class="message" href="#SCI_GETADDITIONALSELALPHA">SCI_GETADDITIONALSELALPHA</a><br />
     <a class="message" href="#SCI_SETADDITIONALSELFORE">SCI_SETADDITIONALSELFORE(int colour)</a><br />
     <a class="message" href="#SCI_SETADDITIONALSELBACK">SCI_SETADDITIONALSELBACK(int colour)</a><br />
     <a class="message" href="#SCI_SETADDITIONALCARETFORE">SCI_SETADDITIONALCARETFORE(int colour)</a><br />
     <a class="message" href="#SCI_GETADDITIONALCARETFORE">SCI_GETADDITIONALCARETFORE</a><br />
     <a class="message" href="#SCI_SETADDITIONALCARETSBLINK">SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)</a><br />
     <a class="message" href="#SCI_GETADDITIONALCARETSBLINK">SCI_GETADDITIONALCARETSBLINK</a><br />
     <a class="message" href="#SCI_SETADDITIONALCARETSVISIBLE">SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)</a><br />
     <a class="message" href="#SCI_GETADDITIONALCARETSVISIBLE">SCI_GETADDITIONALCARETSVISIBLE</a><br />
     <br />

     <a class="message" href="#SCI_SWAPMAINANCHORCARET">SCI_SWAPMAINANCHORCARET</a><br />
     <a class="message" href="#SCI_ROTATESELECTION">SCI_ROTATESELECTION</a><br />
    </code>

    <p>
    There may be multiple selections active at one time.
    More selections are made by holding down the Ctrl key while dragging with the mouse.
    The most recent selection is the main selection and determines which part of the document is shown automatically.
    Any selection apart from the main selection is called an additional selection.
    The calls in the previous section operate on the main selection.
    There is always at least one selection.
    </p>

    <p>
    Rectangular selections are handled as multiple selections although the original rectangular range is remembered so that
    subsequent operations may be handled differently for rectangular selections. For example, pasting a rectangular selection
    places each piece in a vertical column.
    </p>

    <p>
    Virtual space is space beyond the end of each line. The caret may be moved into virtual space but no real space will be
    added to the document until there is some text typed or some other text insertion command is used.
    </p>

    <p>When discontiguous selections are copied to the clipboard, each selection is added to the clipboard text
    in order with no delimiting characters.
    For rectangular selections the document's line end is added after each line's text. Rectangular selections
    are always copied from top line to bottom, not in the in order of selection.Virtual space is not copied.</p>

    <p>
    <b id="SCI_SETMULTIPLESELECTION">SCI_SETMULTIPLESELECTION(bool multipleSelection)</b><br />
    <b id="SCI_GETMULTIPLESELECTION">SCI_GETMULTIPLESELECTION</b><br />
     Enable or disable multiple selection. When multiple selection is disabled, it is not possible to select
     multiple ranges by holding down the Ctrl key while dragging with the mouse.</p>

    <p>
    <b id="SCI_SETADDITIONALSELECTIONTYPING">SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)</b><br />
    <b id="SCI_GETADDITIONALSELECTIONTYPING">SCI_GETADDITIONALSELECTIONTYPING</b><br />
     Whether typing, backspace, or delete works with multiple selections simultaneously.</p>

    <p>
    <b id="SCI_SETMULTIPASTE">SCI_SETMULTIPASTE(int multiPaste)</b><br />
    <b id="SCI_GETMULTIPASTE">SCI_GETMULTIPASTE</b><br />
     When pasting into multiple selections, the pasted text can go into just the main selection with <code>SC_MULTIPASTE_ONCE</code>=0
     or into each selection with <code>SC_MULTIPASTE_EACH</code>=1. <code>SC_MULTIPASTE_ONCE</code> is the default.</p>

    <p>
    <b id="SCI_SETVIRTUALSPACEOPTIONS">SCI_SETVIRTUALSPACEOPTIONS(int virtualSpace)</b><br />
    <b id="SCI_GETVIRTUALSPACEOPTIONS">SCI_GETVIRTUALSPACEOPTIONS</b><br />
     Virtual space can be enabled or disabled for rectangular selections or in other circumstances or in both.
     There are two bit flags <code>SCVS_RECTANGULARSELECTION</code>=1 and
     <code>SCVS_USERACCESSIBLE</code>=2 which can be set independently.
     <code>SCVS_NONE</code>=0, the default, disables all use of virtual space.</p>

    <p>
    <b id="SCI_SETRECTANGULARSELECTIONMODIFIER">SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)</b><br />
    <b id="SCI_GETRECTANGULARSELECTIONMODIFIER">SCI_GETRECTANGULARSELECTIONMODIFIER</b><br />
     On GTK+, the key used to indicate that a rectangular selection should be created when combined with a mouse drag can be set.
     The three possible values are <code>SCMOD_CTRL</code>=2 (default), <code>SCMOD_ALT</code>=4 or <code>SCMOD_SUPER</code>=8.
     Since <code>SCMOD_ALT</code> is often already used by a window manager, the window manager may need configuring to allow this choice.
     <code>SCMOD_SUPER</code> is often a system dependent modifier key such as the Left Windows key on a Windows keyboard or the
     Command key on a Mac.</p>

    <p>
    <b id="SCI_GETSELECTIONS">SCI_GETSELECTIONS</b><br />
     Return the number of selections currently active.</p>

    <p>
    <b id="SCI_GETSELECTIONEMPTY">SCI_GETSELECTIONEMPTY</b><br />
     Return 1 if every selected range is empty else 0.</p>

    <p>
    <b id="SCI_CLEARSELECTIONS">SCI_CLEARSELECTIONS</b><br />
     Set a single empty selection at 0 as the only selection.</p>

    <p>
    <b id="SCI_SETSELECTION">SCI_SETSELECTION(int caret, int anchor)</b><br />
     Set a single selection from <code>anchor</code> to <code>caret</code> as the only selection.</p>

    <p>
    <b id="SCI_ADDSELECTION">SCI_ADDSELECTION(int caret, int anchor)</b><br />
     Add a new selection from <code>anchor</code> to <code>caret</code> as the main selection retaining all other
     selections as additional selections.
     Since there is always at least one selection, to set a list of selections, the first selection should be
     added with <code>SCI_SETSELECTION</code> and later selections added with <code>SCI_ADDSELECTION</code></p>

    <p>
    <b id="SCI_SETMAINSELECTION">SCI_SETMAINSELECTION(int selection)</b><br />
    <b id="SCI_GETMAINSELECTION">SCI_GETMAINSELECTION</b><br />
     One of the selections is the main selection which is used to determine what range of text is automatically visible.
     The main selection may be displayed in different colours or with a differently styled caret.
     Only an already existing selection can be made main.</p>

    <p>
     <b id="SCI_SETSELECTIONNCARET">SCI_SETSELECTIONNCARET(int selection, int pos)</b><br />
     <b id="SCI_GETSELECTIONNCARET">SCI_GETSELECTIONNCARET(int selection)</b><br />
     <b id="SCI_SETSELECTIONNCARETVIRTUALSPACE">SCI_SETSELECTIONNCARETVIRTUALSPACE(int selection, int space)</b><br />
     <b id="SCI_GETSELECTIONNCARETVIRTUALSPACE">SCI_GETSELECTIONNCARETVIRTUALSPACE(int selection)</b><br />
     <b id="SCI_SETSELECTIONNANCHOR">SCI_SETSELECTIONNANCHOR(int selection, int posAnchor)</b><br />
     <b id="SCI_GETSELECTIONNANCHOR">SCI_GETSELECTIONNANCHOR(int selection)</b><br />
     <b id="SCI_SETSELECTIONNANCHORVIRTUALSPACE">SCI_SETSELECTIONNANCHORVIRTUALSPACE(int selection, int space)</b><br />
     <b id="SCI_GETSELECTIONNANCHORVIRTUALSPACE">SCI_GETSELECTIONNANCHORVIRTUALSPACE(int selection)</b><br />
     Set or query the position and amount of virtual space for the caret and anchor of each already existing selection.</p>

    <p>
     <b id="SCI_SETSELECTIONNSTART">SCI_SETSELECTIONNSTART(int selection, int pos)</b><br />
     <b id="SCI_GETSELECTIONNSTART">SCI_GETSELECTIONNSTART(int selection)</b><br />
     <b id="SCI_SETSELECTIONNEND">SCI_SETSELECTIONNEND(int selection, int pos)</b><br />
     <b id="SCI_GETSELECTIONNEND">SCI_GETSELECTIONNEND(int selection)</b><br />
     Set or query the start and end position of each already existing selection.
     Mostly of use to query each range for its text.</p>

    <p>
     <b id="SCI_SETRECTANGULARSELECTIONCARET">SCI_SETRECTANGULARSELECTIONCARET(int pos)</b><br />
     <b id="SCI_GETRECTANGULARSELECTIONCARET">SCI_GETRECTANGULARSELECTIONCARET</b><br />
     <b id="SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE(int space)</b><br />
     <b id="SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE</b><br />
     <b id="SCI_SETRECTANGULARSELECTIONANCHOR">SCI_SETRECTANGULARSELECTIONANCHOR(int posAnchor)</b><br />
     <b id="SCI_GETRECTANGULARSELECTIONANCHOR">SCI_GETRECTANGULARSELECTIONANCHOR</b><br />
     <b id="SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE(int space)</b><br />
     <b id="SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE</b><br />
     Set or query the position and amount of virtual space for the caret and anchor of the rectangular selection.
     After setting the rectangular selection, this is broken down into multiple selections, one for each line.</p>

    <p>
     <b id="SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(int alpha)</b><br />
     <b id="SCI_GETADDITIONALSELALPHA">SCI_GETADDITIONALSELALPHA</b><br />
     <b id="SCI_SETADDITIONALSELFORE">SCI_SETADDITIONALSELFORE(int <a class="jump" href="#colour">colour</a>)</b><br />
     <b id="SCI_SETADDITIONALSELBACK">SCI_SETADDITIONALSELBACK(int <a class="jump" href="#colour">colour</a>)</b><br />
     Modify the appearence of additional selections so that they can be differentiated from the main selection which has its appearence set with
     <a class="message" href="#SCI_SETSELALPHA"><code>SCI_SETSELALPHA</code></a>,
     <a class="message" href="#SCI_GETSELALPHA"><code>SCI_GETSELALPHA</code></a>,
     <a class="message" href="#SCI_SETSELFORE"><code>SCI_SETSELFORE</code></a>, and
     <a class="message" href="#SCI_SETSELBACK"><code>SCI_SETSELBACK</code></a>.</p>

    <p>
     <b id="SCI_SETADDITIONALCARETFORE">SCI_SETADDITIONALCARETFORE(int <a class="jump" href="#colour">colour</a>)</b><br />
     <b id="SCI_GETADDITIONALCARETFORE">SCI_GETADDITIONALCARETFORE</b><br />
     <b id="SCI_SETADDITIONALCARETSBLINK">SCI_SETADDITIONALCARETSBLINK(bool additionalCaretsBlink)</b><br />
     <b id="SCI_GETADDITIONALCARETSBLINK">SCI_GETADDITIONALCARETSBLINK</b><br />
     Modify the appearence of additional carets so that they can be differentiated from the main caret which has its appearence set with
     <a class="message" href="#SCI_SETCARETFORE"><code>SCI_SETCARETFORE</code></a>,
     <a class="message" href="#SCI_GETCARETFORE"><code>SCI_GETCARETFORE</code></a>,
     <a class="message" href="#SCI_SETCARETPERIOD"><code>SCI_SETCARETPERIOD</code></a>, and
     <a class="message" href="#SCI_GETCARETPERIOD"><code>SCI_GETCARETPERIOD</code></a>.</p>

    <p>
     <b id="SCI_SETADDITIONALCARETSVISIBLE">SCI_SETADDITIONALCARETSVISIBLE(bool additionalCaretsVisible)</b><br />
     <b id="SCI_GETADDITIONALCARETSVISIBLE">SCI_GETADDITIONALCARETSVISIBLE</b><br />
     Determine whether to show additional carets (defaults to <code>true</code>).</p>

    <p>
     <b id="SCI_SWAPMAINANCHORCARET">SCI_SWAPMAINANCHORCARET</b><br />
     <b id="SCI_ROTATESELECTION">SCI_ROTATESELECTION</b><br />
     These commands may be assigned to keys to make it possible to manipulate multiple selections.
     <code>SCI_SWAPMAINANCHORCARET</code> moves the caret to the opposite end of the main selection.
     <code>SCI_ROTATESELECTION</code> makes the next selection be the main selection.
     </p>

    <h2 id="ScrollingAndAutomaticScrolling">Scrolling and automatic scrolling</h2>
    <code><a class="message" href="#SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</a><br />
     <a class="message" href="#SCI_SCROLLCARET">SCI_SCROLLCARET</a><br />
     <a class="message" href="#SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</a><br />
     <a class="message" href="#SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int
    caretSlop)</a><br />
     <a class="message" href="#SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int
    caretSlop)</a><br />
     <a class="message" href="#SCI_SETVISIBLEPOLICY">SCI_SETVISIBLEPOLICY(int caretPolicy, int
    caretSlop)</a><br />
     <a class="message" href="#SCI_SETHSCROLLBAR">SCI_SETHSCROLLBAR(bool visible)</a><br />
     <a class="message" href="#SCI_GETHSCROLLBAR">SCI_GETHSCROLLBAR</a><br />
     <a class="message" href="#SCI_SETVSCROLLBAR">SCI_SETVSCROLLBAR(bool visible)</a><br />
     <a class="message" href="#SCI_GETVSCROLLBAR">SCI_GETVSCROLLBAR</a><br />
     <a class="message" href="#SCI_GETXOFFSET">SCI_GETXOFFSET</a><br />
     <a class="message" href="#SCI_SETXOFFSET">SCI_SETXOFFSET(int xOffset)</a><br />
     <a class="message" href="#SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH(int pixelWidth)</a><br />
     <a class="message" href="#SCI_GETSCROLLWIDTH">SCI_GETSCROLLWIDTH</a><br />
     <a class="message" href="#SCI_SETSCROLLWIDTHTRACKING">SCI_SETSCROLLWIDTHTRACKING(bool tracking)</a><br />
     <a class="message" href="#SCI_GETSCROLLWIDTHTRACKING">SCI_GETSCROLLWIDTHTRACKING</a><br />
     <a class="message" href="#SCI_SETENDATLASTLINE">SCI_SETENDATLASTLINE(bool
    endAtLastLine)</a><br />
     <a class="message" href="#SCI_GETENDATLASTLINE">SCI_GETENDATLASTLINE</a><br />
    </code>

    <p><b id="SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</b><br />
     This will attempt to scroll the display by the number of columns and lines that you specify.
    Positive line values increase the line number at the top of the screen (i.e. they move the text
    upwards as far as the user is concerned), Negative line values do the reverse.</p>

    <p>The column measure is the width of a space in the default style. Positive values increase
    the column at the left edge of the view (i.e. they move the text leftwards as far as the user
    is concerned). Negative values do the reverse.</p>

    <p>See also: <a class="message" href="#SCI_SETXOFFSET"><code>SCI_SETXOFFSET</code></a></p>

    <p><b id="SCI_SCROLLCARET">SCI_SCROLLCARET</b><br />
     If the current position (this is the caret if there is no selection) is not visible, the view
    is scrolled to make it visible according to the current caret policy.</p>

    <p><b id="SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</b><br />
     Scroll the argument positions and the range between them into view giving
     priority to the primary position then the secondary position.
     The behaviour is similar to <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a>
     with the primary position used instead of the caret. An effort is then made to ensure that the secondary
     position and range between are also visible.
     This may be used to make a search match visible.</p>

    <p><b id="SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
     <b id="SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
     These set the caret policy. The value of <code>caretPolicy</code> is a combination of
    <code>CARET_SLOP</code>, <code>CARET_STRICT</code>, <code>CARET_JUMPS</code> and
    <code>CARET_EVEN</code>.</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Caret policy">
      <tbody valign="top">
        <tr>
          <th align="left"><code>CARET_SLOP</code></th>

          <td>If set, we can define a slop value: <code>caretSlop</code>. This value defines an
          unwanted zone (UZ) where the caret is... unwanted. This zone is defined as a number of
          pixels near the vertical margins, and as a number of lines near the horizontal margins.
          By keeping the caret away from the edges, it is seen within its context. This makes it
          likely that the identifier that the caret is on can be completely seen, and that the
          current line is seen with some of the lines following it, which are often dependent on
          that line.</td>
        </tr>

        <tr>
          <th align="left"><code>CARET_STRICT</code></th>

          <td>If set, the policy set by <code>CARET_SLOP</code> is enforced... strictly. The caret
          is centred on the display if <code>caretSlop</code> is not set, and cannot go in the UZ
          if <code>caretSlop</code> is set.</td>
        </tr>

        <tr>
          <th align="left"><code>CARET_JUMPS</code></th>

          <td>If set, the display is moved more energetically so the caret can move in the same
          direction longer before the policy is applied again. '3UZ' notation is used to indicate
          three time the size of the UZ as a distance to the margin.</td>
        </tr>

        <tr>
          <th align="left"><code>CARET_EVEN</code></th>

          <td>If not set, instead of having symmetrical UZs, the left and bottom UZs are extended
          up to right and top UZs respectively. This way, we favour the displaying of useful
          information: the beginning of lines, where most code reside, and the lines after the
          caret, for example, the body of a function.</td>
        </tr>
      </tbody>
    </table>

    <table cellpadding="3" cellspacing="0" border="1" summary="Caret positioning">
      <thead align="center">
        <tr>
          <th>slop</th>

          <th>strict</th>

          <th>jumps</th>

          <th>even</th>

          <th>Caret can go to the margin</th>

          <th>On reaching limit (going out of visibility<br />
           or going into the UZ) display is...</th>
        </tr>
      </thead>

      <tbody align="center">
        <tr>
          <td>0</td>

          <td>0</td>

          <td>0</td>

          <td>0</td>

          <td>Yes</td>

          <td>moved to put caret on top/on right</td>
        </tr>

        <tr>
          <td>0</td>

          <td>0</td>

          <td>0</td>

          <td>1</td>

          <td>Yes</td>

          <td>moved by one position</td>
        </tr>

        <tr>
          <td>0</td>

          <td>0</td>

          <td>1</td>

          <td>0</td>

          <td>Yes</td>

          <td>moved to put caret on top/on right</td>
        </tr>

        <tr>
          <td>0</td>

          <td>0</td>

          <td>1</td>

          <td>1</td>

          <td>Yes</td>

          <td>centred on the caret</td>
        </tr>

        <tr>
          <td>0</td>

          <td>1</td>

          <td>-</td>

          <td>0</td>

          <td>Caret is always on top/on right of display</td>

          <td>-</td>
        </tr>

        <tr>
          <td>0</td>

          <td>1</td>

          <td>-</td>

          <td>1</td>

          <td>No, caret is always centred</td>

          <td>-</td>
        </tr>

        <tr>
          <td>1</td>

          <td>0</td>

          <td>0</td>

          <td>0</td>

          <td>Yes</td>

          <td>moved to put caret out of the asymmetrical UZ</td>
        </tr>

        <tr>
          <td>1</td>

          <td>0</td>

          <td>0</td>

          <td>1</td>

          <td>Yes</td>

          <td>moved to put caret out of the UZ</td>
        </tr>

        <tr>
          <td>1</td>

          <td>0</td>

          <td>1</td>

          <td>0</td>

          <td>Yes</td>

          <td>moved to put caret at 3UZ of the top or right margin</td>
        </tr>

        <tr>
          <td>1</td>

          <td>0</td>

          <td>1</td>

          <td>1</td>

          <td>Yes</td>

          <td>moved to put caret at 3UZ of the margin</td>
        </tr>

        <tr>
          <td>1</td>

          <td>1</td>

          <td>-</td>

          <td>0</td>

          <td>Caret is always at UZ of top/right margin</td>

          <td>-</td>
        </tr>

        <tr>
          <td>1</td>

          <td>1</td>

          <td>0</td>

          <td>1</td>

          <td>No, kept out of UZ</td>

          <td>moved by one position</td>
        </tr>

        <tr>
          <td>1</td>

          <td>1</td>

          <td>1</td>

          <td>0</td>

          <td>No, kept out of UZ</td>

          <td>moved to put caret at 3UZ of the margin</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETVISIBLEPOLICY">SCI_SETVISIBLEPOLICY(int caretPolicy, int caretSlop)</b><br />
     This determines how the vertical positioning is determined when <a class="message"
    href="#SCI_ENSUREVISIBLEENFORCEPOLICY"><code>SCI_ENSUREVISIBLEENFORCEPOLICY</code></a> is
    called. It takes <code>VISIBLE_SLOP</code> and <code>VISIBLE_STRICT</code> flags for the policy
    parameter. It is similar in operation to <a class="message"
    href="#SCI_SETYCARETPOLICY"><code>SCI_SETYCARETPOLICY(int caretPolicy, int
    caretSlop)</code></a>.</p>

    <p><b id="SCI_SETHSCROLLBAR">SCI_SETHSCROLLBAR(bool visible)</b><br />
     <b id="SCI_GETHSCROLLBAR">SCI_GETHSCROLLBAR</b><br />
     The horizontal scroll bar is only displayed if it is needed for the assumed width.
     If you never wish to see it, call
    <code>SCI_SETHSCROLLBAR(0)</code>. Use <code>SCI_SETHSCROLLBAR(1)</code> to enable it again.
    <code>SCI_GETHSCROLLBAR</code> returns the current state. The default state is to display it
    when needed.</p>
    <p>See also: <a class="message" href="#SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH</a>.</p>

    <p><b id="SCI_SETVSCROLLBAR">SCI_SETVSCROLLBAR(bool visible)</b><br />
     <b id="SCI_GETVSCROLLBAR">SCI_GETVSCROLLBAR</b><br />
     By default, the vertical scroll bar is always displayed when required. You can choose to hide
    or show it with <code>SCI_SETVSCROLLBAR</code> and get the current state with
    <code>SCI_GETVSCROLLBAR</code>.</p>

    <p><b id="SCI_SETXOFFSET">SCI_SETXOFFSET(int xOffset)</b><br />
     <b id="SCI_GETXOFFSET">SCI_GETXOFFSET</b><br />
     The <code>xOffset</code> is the horizontal scroll position in pixels of the start of the text
    view. A value of 0 is the normal position with the first text column visible at the left of the
    view.</p>

    <p>See also: <a class="message" href="#SCI_LINESCROLL"><code>SCI_LINESCROLL</code></a></p>

    <p><b id="SCI_SETSCROLLWIDTH">SCI_SETSCROLLWIDTH(int pixelWidth)</b><br />
     <b id="SCI_GETSCROLLWIDTH">SCI_GETSCROLLWIDTH</b><br />
     For performance, Scintilla does not measure the display width of the document to determine
     the properties of the horizontal scroll bar. Instead, an assumed width is used.
     These messages set and get the document width in pixels assumed by Scintilla.
     The default value is 2000.
     To ensure the width of the currently visible lines can be scrolled use
     <a class="message" href="#SCI_SETSCROLLWIDTHTRACKING"><code>SCI_SETSCROLLWIDTHTRACKING</code></a></p>

    <p><b id="SCI_SETSCROLLWIDTHTRACKING">SCI_SETSCROLLWIDTHTRACKING(bool tracking)</b><br />
     <b id="SCI_GETSCROLLWIDTHTRACKING">SCI_GETSCROLLWIDTHTRACKING</b><br />
     If scroll width tracking is enabled then the scroll width is adjusted to ensure that all of the lines currently
     displayed can be completely scrolled. This mode never adjusts the scroll width to be narrower.</p>

    <p><b id="SCI_SETENDATLASTLINE">SCI_SETENDATLASTLINE(bool endAtLastLine)</b><br />
     <b id="SCI_GETENDATLASTLINE">SCI_GETENDATLASTLINE</b><br />
     <code>SCI_SETENDATLASTLINE</code> sets the scroll range so that maximum scroll position has
    the last line at the bottom of the view (default). Setting this to <code>false</code> allows
    scrolling one page below the last line.</p>

    <h2 id="WhiteSpace">White space</h2>
    <code><a class="message" href="#SCI_SETVIEWWS">SCI_SETVIEWWS(int wsMode)</a><br />
     <a class="message" href="#SCI_GETVIEWWS">SCI_GETVIEWWS</a><br />
     <a class="message" href="#SCI_SETWHITESPACEFORE">SCI_SETWHITESPACEFORE(bool
    useWhitespaceForeColour, int colour)</a><br />
     <a class="message" href="#SCI_SETWHITESPACEBACK">SCI_SETWHITESPACEBACK(bool
    useWhitespaceBackColour, int colour)</a><br />
     <a class="message" href="#SCI_SETWHITESPACESIZE">SCI_SETWHITESPACESIZE(int
    size)</a><br />
     <a class="message" href="#SCI_GETWHITESPACESIZE">SCI_GETWHITESPACESIZE</a><br />
     <a class="message" href="#SCI_SETEXTRAASCENT">SCI_SETEXTRAASCENT(int extraAscent)</a><br />
     <a class="message" href="#SCI_GETEXTRAASCENT">SCI_GETEXTRAASCENT</a><br />
     <a class="message" href="#SCI_SETEXTRADESCENT">SCI_SETEXTRADESCENT(int extraDescent)</a><br />
     <a class="message" href="#SCI_GETEXTRADESCENT">SCI_GETEXTRADESCENT</a><br />
    </code>

    <p><b id="SCI_SETVIEWWS">SCI_SETVIEWWS(int wsMode)</b><br />
     <b id="SCI_GETVIEWWS">SCI_GETVIEWWS</b><br />
     White space can be made visible which may be useful for languages in which white space is
    significant, such as Python. Space characters appear as small centred dots and tab characters
    as light arrows pointing to the right. There are also ways to control the display of <a
    class="jump" href="#LineEndings">end of line characters</a>. The two messages set and get the
    white space display mode. The <code>wsMode</code> argument can be one of:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="White space policy">
      <tbody valign="top">
        <tr>
          <th align="left"><code>SCWS_INVISIBLE</code></th>

          <td>0</td>

          <td>The normal display mode with white space displayed as an empty background
          colour.</td>
        </tr>

        <tr>
          <th align="left"><code>SCWS_VISIBLEALWAYS</code></th>

          <td>1</td>

          <td>White space characters are drawn as dots and arrows,</td>
        </tr>

        <tr>
          <th align="left"><code>SCWS_VISIBLEAFTERINDENT</code></th>

          <td>2</td>

          <td>White space used for indentation is displayed normally but after the first visible
          character, it is shown as dots and arrows.</td>
        </tr>
      </tbody>
    </table>

    <p>The effect of using any other <code>wsMode</code> value is undefined.</p>

    <p><b id="SCI_SETWHITESPACEFORE">SCI_SETWHITESPACEFORE(bool useWhitespaceForeColour, int <a
    class="jump" href="#colour">colour</a>)</b><br />
     <b id="SCI_SETWHITESPACEBACK">SCI_SETWHITESPACEBACK(bool useWhitespaceBackColour, int <a
    class="jump" href="#colour">colour</a>)</b><br />
     By default, the colour of visible white space is determined by the lexer in use. The
    foreground and/or background colour of all visible white space can be set globally, overriding
    the lexer's colours with <code>SCI_SETWHITESPACEFORE</code> and
    <code>SCI_SETWHITESPACEBACK</code>.</p>

     <p><b id="SCI_SETWHITESPACESIZE">SCI_SETWHITESPACESIZE(int size)</b><br />
     <b id="SCI_GETWHITESPACESIZE">SCI_GETWHITESPACESIZE</b><br />
     <code>SCI_SETWHITESPACESIZE</code> sets the size of the dots used for mark space characters.
     The <code>SCI_GETWHITESPACESIZE</code> message retrieves the current size.
    </p>

    <p>
     <b id="SCI_SETEXTRAASCENT">SCI_SETEXTRAASCENT(int extraAscent)</b><br />
     <b id="SCI_GETEXTRAASCENT">SCI_GETEXTRAASCENT</b><br />
     <b id="SCI_SETEXTRADESCENT">SCI_SETEXTRADESCENT(int extraDescent)</b><br />
     <b id="SCI_GETEXTRADESCENT">SCI_GETEXTRADESCENT</b><br />
     Text is drawn with the base of each character on a 'baseline'. The height of a line is found from the maximum
     that any style extends above the baseline (its 'ascent'), added to the maximum that any style extends below the
     baseline (its 'descent').
     Space may be added to the maximum ascent (<code>SCI_SETEXTRAASCENT</code>) and the
     maximum descent (<code>SCI_SETEXTRADESCENT</code>) to allow for more space between lines.
     This may done to make the text easier to read or to accomodate underlines or highlights.
    </p>

    <h2 id="Cursor">Cursor</h2>

    <p><b id="SCI_SETCURSOR">SCI_SETCURSOR(int curType)</b><br />
     <b id="SCI_GETCURSOR">SCI_GETCURSOR</b><br />
     The cursor is normally chosen in a context sensitive way, so it will be different over the
    margin than when over the text. When performing a slow action, you may wish to change to a wait
    cursor. You set the cursor type with <code>SCI_SETCURSOR</code>. The <code>curType</code>
    argument can be:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Mouse cursors">
      <tbody valign="top">
        <tr>
          <th align="left"><code>SC_CURSORNORMAL</code></th>

          <td>-1</td>

          <td>The normal cursor is displayed.</td>
        </tr>

        <tr>
          <th align="left"><code>SC_CURSORWAIT</code></th>

          <td>&nbsp;4</td>

          <td>The wait cursor is displayed when the mouse is over or owned by the Scintilla
          window.</td>
        </tr>
      </tbody>
    </table>

    <p>Cursor values 1 through 7 have defined cursors, but only <code>SC_CURSORWAIT</code> is
    usefully controllable. Other values of <code>curType</code> cause a pointer to be displayed.
    The <code>SCI_GETCURSOR</code> message returns the last cursor type you set, or
    <code>SC_CURSORNORMAL</code> (-1) if you have not set a cursor type.</p>

    <h2 id="MouseCapture">Mouse capture</h2>

    <p><b id="SCI_SETMOUSEDOWNCAPTURES">SCI_SETMOUSEDOWNCAPTURES(bool captures)</b><br />
     <b id="SCI_GETMOUSEDOWNCAPTURES">SCI_GETMOUSEDOWNCAPTURES</b><br />
     When the mouse is pressed inside Scintilla, it is captured so future mouse movement events are
    sent to Scintilla. This behavior may be turned off with
    <code>SCI_SETMOUSEDOWNCAPTURES(0)</code>.</p>

    <h2 id="LineEndings">Line endings</h2>

    <p>Scintilla can handle the major line end conventions <span class="provisional">and, depending on settings and
    the current lexer also support additional Unicode line ends</span>.</p>
    
    <p>Scintilla can interpret any of the Macintosh (\r), Unix (\n) and Windows (\r\n)
    line ends.
    When the user presses the Enter key, one of these line
    end strings is inserted into the buffer. The default is \r\n in Windows and \n in Unix, but
    this can be changed with the <code>SCI_SETEOLMODE</code> message. You can also convert the
    entire document to one of these line endings with <code>SCI_CONVERTEOLS</code>. Finally, you
    can choose to display the line endings with <code>SCI_SETVIEWEOL</code>.</p>

<div  class="provisional">
    <p>For the UTF-8 encoding, three additional Unicode line ends,
    Next Line (<code>NEL=U+0085</code>), Line Separator (<code>LS=U+2028</code>), and Paragraph Separator (<code>PS=U+2029</code>)
    may optionally be interpreted when Unicode line ends is turned on and the current lexer also supports
    Unicode line ends.</p>
</div>

    <code><a class="message" href="#SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</a><br />
     <a class="message" href="#SCI_GETEOLMODE">SCI_GETEOLMODE</a><br />
     <a class="message" href="#SCI_CONVERTEOLS">SCI_CONVERTEOLS(int eolMode)</a><br />
     <a class="message" href="#SCI_SETVIEWEOL">SCI_SETVIEWEOL(bool visible)</a><br />
     <a class="message" href="#SCI_GETVIEWEOL">SCI_GETVIEWEOL</a><br />

<div  class="provisional">
     <a class="message" href="#SCI_GETLINEENDTYPESSUPPORTED">SCI_GETLINEENDTYPESSUPPORTED</a><br />
     <a class="message" href="#SCI_SETLINEENDTYPESALLOWED">SCI_SETLINEENDTYPESALLOWED(int lineEndBitSet)</a><br />
     <a class="message" href="#SCI_GETLINEENDTYPESALLOWED">SCI_GETLINEENDTYPESALLOWED</a><br />
     <a class="message" href="#SCI_GETLINEENDTYPESACTIVE">SCI_GETLINEENDTYPESACTIVE</a><br />
</div>
    </code>

    <p><b id="SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</b><br />
     <b id="SCI_GETEOLMODE">SCI_GETEOLMODE</b><br />
     <code>SCI_SETEOLMODE</code> sets the characters that are added into the document when the user
    presses the Enter key. You can set <code>eolMode</code> to one of <code>SC_EOL_CRLF</code> (0),
    <code>SC_EOL_CR</code> (1), or <code>SC_EOL_LF</code> (2). The <code>SCI_GETEOLMODE</code>
    message retrieves the current state.</p>

    <p><b id="SCI_CONVERTEOLS">SCI_CONVERTEOLS(int eolMode)</b><br />
     This message changes all the end of line characters in the document to match
    <code>eolMode</code>. Valid values are: <code>SC_EOL_CRLF</code> (0), <code>SC_EOL_CR</code>
    (1), or <code>SC_EOL_LF</code> (2).</p>

    <p><b id="SCI_SETVIEWEOL">SCI_SETVIEWEOL(bool visible)</b><br />
     <b id="SCI_GETVIEWEOL">SCI_GETVIEWEOL</b><br />
     Normally, the end of line characters are hidden, but <code>SCI_SETVIEWEOL</code> allows you to
    display (or hide) them by setting <code>visible</code> <code>true</code> (or
    <code>false</code>). The visible rendering of the end of line characters is similar to
    <code>(CR)</code>, <code>(LF)</code>, or <code>(CR)(LF)</code>. <code>SCI_GETVIEWEOL</code>
    returns the current state.</p>

<div  class="provisional">
    <a href="#ProvisionalMessages">These features are provisional</a><br />

    <p><b id="SCI_GETLINEENDTYPESSUPPORTED">SCI_GETLINEENDTYPESSUPPORTED</b><br />
     <code>SCI_GETLINEENDTYPESSUPPORTED</code> reports the different types of line ends supported
     by the current lexer. This is a bit set although there is currently only a single choice
     with either <code>SC_LINE_END_TYPE_DEFAULT</code> (0) or <code>SC_LINE_END_TYPE_UNICODE</code> (1).
     These values are also used by the other messages concerned with Unicode line ends.</p>

    <p><b id="SCI_SETLINEENDTYPESALLOWED">SCI_SETLINEENDTYPESALLOWED(int lineEndBitSet)</b><br />
     <b id="SCI_GETLINEENDTYPESALLOWED">SCI_GETLINEENDTYPESALLOWED</b><br />
     By default, only the ASCII line ends are interpreted. Unicode line ends may be requested with
     <code>SCI_SETLINEENDTYPESALLOWED(SC_LINE_END_TYPE_UNICODE)</code>
     but this will be ineffective unless the lexer also allows you Unicode line ends.
    <code>SCI_GETLINEENDTYPESALLOWED</code> returns the current state.</p>

    <p><b id="SCI_GETLINEENDTYPESACTIVE">SCI_GETLINEENDTYPESACTIVE</b><br />
     <code>SCI_GETLINEENDTYPESACTIVE</code> reports the set of line ends currently interpreted
     by Scintilla. It is <code>SCI_GETLINEENDTYPESSUPPORTED &amp; SCI_GETLINEENDTYPESALLOWED</code>.</p>
</div>

    <h2 id="Styling">Styling</h2>

    <p>The styling messages allow you to assign styles to text. The standard Scintilla settings
    divide the 8 style bits available for each character into 5 bits (0 to 4 = <a class="jump"
    href="#StyleDefinition">styles 0 to 31</a>) that set a style and three bits (5 to 7) that
    define <a class="jump" href="#Indicators">indicators</a>. You can change the balance between
    styles and indicators with <a class="message"
    href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a>. If your styling needs can be met by
    one of the standard lexers, or if you can write your own, then a lexer is probably the easiest
    way to style your document. If you choose to use the container to do the styling you can use
    the <a class="message" href="#SCI_SETLEXER"><code>SCI_SETLEXER</code></a> command to select
    <code>SCLEX_CONTAINER</code>, in which case the container is sent a <a class="message"
    href="#SCN_STYLENEEDED"><code>SCN_STYLENEEDED</code></a> <a class="jump"
    href="#Notifications">notification</a> each time text needs styling for display. As another
    alternative, you might use idle time to style the document. Even if you use a lexer, you might
    use the styling commands to mark errors detected by a compiler. The following commands can be
    used.</p>
    <code><a class="message" href="#SCI_GETENDSTYLED">SCI_GETENDSTYLED</a><br />
     <a class="message" href="#SCI_STARTSTYLING">SCI_STARTSTYLING(int position, int mask)</a><br />
     <a class="message" href="#SCI_SETSTYLING">SCI_SETSTYLING(int length, int style)</a><br />
     <a class="message" href="#SCI_SETSTYLINGEX">SCI_SETSTYLINGEX(int length, const char
    *styles)</a><br />
     <a class="message" href="#SCI_SETLINESTATE">SCI_SETLINESTATE(int line, int value)</a><br />
     <a class="message" href="#SCI_GETLINESTATE">SCI_GETLINESTATE(int line)</a><br />
     <a class="message" href="#SCI_GETMAXLINESTATE">SCI_GETMAXLINESTATE</a><br />
    </code>

    <p><b id="SCI_GETENDSTYLED">SCI_GETENDSTYLED</b><br />
     Scintilla keeps a record of the last character that is likely to be styled correctly. This is
    moved forwards when characters after it are styled and moved backwards if changes are made to
    the text of the document before it. Before drawing text, this position is checked to see if any
    styling is needed and, if so, a <code><a class="message"
    href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a></code> notification message is sent to the
    container. The container can send <code>SCI_GETENDSTYLED</code> to work out where it needs to
    start styling. Scintilla will always ask to style whole lines.</p>

    <p><b id="SCI_STARTSTYLING">SCI_STARTSTYLING(int pos, int mask)</b><br />
     This prepares for styling by setting the styling position <code>pos</code> to start at and a
    <code>mask</code> indicating which bits of the style bytes can be set. The mask allows styling
    to occur over several passes, with, for example, basic styling done on an initial pass to
    ensure that the text of the code is seen quickly and correctly, and then a second slower pass,
    detecting syntax errors and using indicators to show where these are. For example, with the
    standard settings of 5 style bits and 3 indicator bits, you would use a <code>mask</code> value
    of 31 (0x1f) if you were setting text styles and did not want to change the indicators. After
    <code>SCI_STARTSTYLING</code>, send multiple <code>SCI_SETSTYLING</code> messages for each
    lexical entity to style.</p>

    <p><b id="SCI_SETSTYLING">SCI_SETSTYLING(int length, int style)</b><br />
     This message sets the style of <code>length</code> characters starting at the styling position
    and then increases the styling position by <code>length</code>, ready for the next call. If
    <code>sCell</code> is the style byte, the operation is:<br />
     <code>if ((sCell &amp; mask) != style) sCell = (sCell &amp; ~mask) | (style &amp;
    mask);</code><br />
    </p>

    <p><b id="SCI_SETSTYLINGEX">SCI_SETSTYLINGEX(int length, const char *styles)</b><br />
     As an alternative to <code>SCI_SETSTYLING</code>, which applies the same style to each byte,
    you can use this message which specifies the styles for each of <code>length</code> bytes from
    the styling position and then increases the styling position by <code>length</code>, ready for
    the next call. The <code>length</code> styling bytes pointed at by <code>styles</code> should
    not contain any bits not set in mask.</p>

    <p><b id="SCI_SETLINESTATE">SCI_SETLINESTATE(int line, int value)</b><br />
     <b id="SCI_GETLINESTATE">SCI_GETLINESTATE(int line)</b><br />
     As well as the 8 bits of lexical state stored for each character there is also an integer
    stored for each line. This can be used for longer lived parse states such as what the current
    scripting language is in an ASP page. Use <code>SCI_SETLINESTATE</code> to set the integer
    value and <code>SCI_GETLINESTATE</code> to get the value.
    Changing the value produces a <a class="message" href="#SC_MOD_CHANGELINESTATE">SC_MOD_CHANGELINESTATE</a> notification.
    </p>

    <p><b id="SCI_GETMAXLINESTATE">SCI_GETMAXLINESTATE</b><br />
     This returns the last line that has any line state.</p>

    <h2 id="StyleDefinition">Style definition</h2>

    <p>While the style setting messages mentioned above change the style numbers associated with
    text, these messages define how those style numbers are interpreted visually. There are 256
    lexer styles that can be set, numbered 0 to <code>STYLE_MAX</code> (255). Unless you use <a
    class="message" href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> to change the number
    of style bits, styles 0 to 31 are used to set the text attributes. There are also some
    predefined numbered styles starting at 32, The following <code>STYLE_</code>* constants are
    defined.</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Preset styles">
      <tbody valign="top">
        <tr>
          <th align="left"><code>STYLE_DEFAULT</code></th>

          <td>32</td>

          <td>This style defines the attributes that all styles receive when the
          <code>SCI_STYLECLEARALL</code> message is used.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_LINENUMBER</code></th>

          <td>33</td>

          <td>This style sets the attributes of the text used to display line numbers in a line
          number margin. The background colour set for this style also sets the background colour
          for all margins that do not have any folding mask bits set. That is, any margin for which
          <code>mask &amp; SC_MASK_FOLDERS</code> is 0. See <a class="message"
          href="#SCI_SETMARGINMASKN"><code>SCI_SETMARGINMASKN</code></a> for more about masks.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_BRACELIGHT</code></th>

          <td>34</td>

          <td>This style sets the attributes used when highlighting braces with the <a
          class="message" href="#BraceHighlighting"><code>SCI_BRACEHIGHLIGHT</code></a> message and
          when highlighting the corresponding indentation with <a class="message"
          href="#SCI_SETHIGHLIGHTGUIDE"><code>SCI_SETHIGHLIGHTGUIDE</code></a>.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_BRACEBAD</code></th>

          <td>35</td>

          <td>This style sets the display attributes used when marking an unmatched brace with the
          <a class="message" href="#BraceHighlighting"><code>SCI_BRACEBADLIGHT</code></a>
          message.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_CONTROLCHAR</code></th>

          <td>36</td>

          <td>This style sets the font used when drawing control characters.
            Only the font, size, bold, italics, and character set attributes are used and not
            the colour attributes. See
          also: <a class="message"
          href="#SCI_SETCONTROLCHARSYMBOL"><code>SCI_SETCONTROLCHARSYMBOL</code></a>.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_INDENTGUIDE</code></th>

          <td>37</td>

          <td>This style sets the foreground and background colours used when drawing the
          indentation guides.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_CALLTIP</code></th>

          <td>38</td>

          <td> Call tips normally use the font attributes defined by <code>STYLE_DEFAULT</code>.
          Use of <a class="message" href="#SCI_CALLTIPUSESTYLE"><code>SCI_CALLTIPUSESTYLE</code></a>
            causes call tips to use this style instead. Only the font face name, font size,
          foreground and background colours and character set attributes are used.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_LASTPREDEFINED</code></th>

          <td>39</td>

          <td>To make it easier for client code to discover the range of styles that are
          predefined, this is set to the style number of the last predefined style. This is
          currently set to 39 and the last style with an identifier is 38, which reserves space
          for one future predefined style.</td>
        </tr>

        <tr>
          <th align="left"><code>STYLE_MAX</code></th>

          <td>255</td>

          <td>This is not a style but is the number of the maximum style that can be set. Styles
          between <code>STYLE_LASTPREDEFINED</code> and <code>STYLE_MAX</code> would be appropriate
          if you used <a class="message" href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a>
          to set more than 5 style bits.</td>
        </tr>
      </tbody>
    </table>

    <p>For each style you can set the font name, size and use of bold, italic and underline,
    foreground and background colour and the character set. You can also choose to hide text with a
    given style, display all characters as upper or lower case and fill from the last character on
    a line to the end of the line (for embedded languages). There is also an experimental attribute
    to make text read-only.</p>

    <p>It is entirely up to you how you use styles. If you want to use syntax colouring you might
    use style 0 for white space, style 1 for numbers, style 2 for keywords, style 3 for strings,
    style 4 for preprocessor, style 5 for operators, and so on.</p>
    <code><a class="message" href="#SCI_STYLERESETDEFAULT">SCI_STYLERESETDEFAULT</a><br />
    <a class="message" href="#SCI_STYLECLEARALL">SCI_STYLECLEARALL</a><br />
    <a class="message" href="#SCI_STYLESETFONT">SCI_STYLESETFONT(int styleNumber, char
    *fontName)</a><br />
    <a class="message" href="#SCI_STYLEGETFONT">SCI_STYLEGETFONT(int styleNumber, char *fontName)</a><br />
    <a class="message" href="#SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int
    sizeInPoints)</a><br />
    <a class="message" href="#SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETSIZEFRACTIONAL">SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int
    sizeInHundredthPoints)</a><br />
    <a class="message" href="#SCI_STYLEGETSIZEFRACTIONAL">SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool
    bold)</a><br />
    <a class="message" href="#SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETWEIGHT">SCI_STYLESETWEIGHT(int styleNumber, int
    weight)</a><br />
    <a class="message" href="#SCI_STYLEGETWEIGHT">SCI_STYLEGETWEIGHT(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool
    italic)</a><br />
    <a class="message" href="#SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETUNDERLINE">SCI_STYLESETUNDERLINE(int styleNumber, bool
    underline)</a><br />
    <a class="message" href="#SCI_STYLEGETUNDERLINE">SCI_STYLEGETUNDERLINE(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETFORE">SCI_STYLESETFORE(int styleNumber, int
    colour)</a><br />
    <a class="message" href="#SCI_STYLEGETFORE">SCI_STYLEGETFORE(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETBACK">SCI_STYLESETBACK(int styleNumber, int
    colour)</a><br />
    <a class="message" href="#SCI_STYLEGETBACK">SCI_STYLEGETBACK(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETEOLFILLED">SCI_STYLESETEOLFILLED(int styleNumber, bool
    eolFilled)</a><br />
    <a class="message" href="#SCI_STYLEGETEOLFILLED">SCI_STYLEGETEOLFILLED(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETCHARACTERSET">SCI_STYLESETCHARACTERSET(int styleNumber,
    int charSet)</a><br />
    <a class="message" href="#SCI_STYLEGETCHARACTERSET">SCI_STYLEGETCHARACTERSET(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETCASE">SCI_STYLESETCASE(int styleNumber, int
    caseMode)</a><br />
    <a class="message" href="#SCI_STYLEGETCASE">SCI_STYLEGETCASE(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETVISIBLE">SCI_STYLESETVISIBLE(int styleNumber, bool
    visible)</a><br />
    <a class="message" href="#SCI_STYLEGETVISIBLE">SCI_STYLEGETVISIBLE(int styleNumber)</a><br />
    <a class="message" href="#SCI_STYLESETCHANGEABLE">SCI_STYLESETCHANGEABLE(int styleNumber, bool
    changeable)</a><br />
    <a class="message" href="#SCI_STYLEGETCHANGEABLE">SCI_STYLEGETCHANGEABLE(int styleNumber)</a><br />
     <a class="message" href="#SCI_STYLESETHOTSPOT">SCI_STYLESETHOTSPOT(int styleNumber, bool
    hotspot)</a><br />
    <a class="message" href="#SCI_STYLEGETHOTSPOT">SCI_STYLEGETHOTSPOT(int styleNumber)</a><br />
    </code>

    <p><b id="SCI_STYLERESETDEFAULT">SCI_STYLERESETDEFAULT</b><br />
     This message resets <code>STYLE_DEFAULT</code> to its state when Scintilla was
    initialised.</p>

    <p><b id="SCI_STYLECLEARALL">SCI_STYLECLEARALL</b><br />
     This message sets all styles to have the same attributes as <code>STYLE_DEFAULT</code>. If you
    are setting up Scintilla for syntax colouring, it is likely that the lexical styles you set
    will be very similar. One way to set the styles is to:<br />
     1. Set <code>STYLE_DEFAULT</code> to the common features of all styles.<br />
     2. Use <code>SCI_STYLECLEARALL</code> to copy this to all styles.<br />
     3. Set the style attributes that make your lexical styles different.</p>

    <p><b id="SCI_STYLESETFONT">SCI_STYLESETFONT(int styleNumber, const char *fontName)</b><br />
    <b id="SCI_STYLEGETFONT">SCI_STYLEGETFONT(int styleNumber, char *fontName)</b><br />
    <b id="SCI_STYLESETSIZE">SCI_STYLESETSIZE(int styleNumber, int sizeInPoints)</b><br />
    <b id="SCI_STYLEGETSIZE">SCI_STYLEGETSIZE(int styleNumber)</b><br />
    <b id="SCI_STYLESETSIZEFRACTIONAL">SCI_STYLESETSIZEFRACTIONAL(int styleNumber, int sizeInHundredthPoints)</b><br />
    <b id="SCI_STYLEGETSIZEFRACTIONAL">SCI_STYLEGETSIZEFRACTIONAL(int styleNumber)</b><br />
    <b id="SCI_STYLESETBOLD">SCI_STYLESETBOLD(int styleNumber, bool bold)</b><br />
    <b id="SCI_STYLEGETBOLD">SCI_STYLEGETBOLD(int styleNumber)</b><br />
    <b id="SCI_STYLESETWEIGHT">SCI_STYLESETWEIGHT(int styleNumber, int weight)</b><br />
    <b id="SCI_STYLEGETWEIGHT">SCI_STYLEGETWEIGHT(int styleNumber)</b><br />
    <b id="SCI_STYLESETITALIC">SCI_STYLESETITALIC(int styleNumber, bool italic)</b><br />
    <b id="SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</b><br />
     These messages (plus <a class="message"
    href="#SCI_STYLESETCHARACTERSET"><code>SCI_STYLESETCHARACTERSET</code></a>) set the font
    attributes that are used to match the fonts you request to those available. The
    <code>fontName</code> is a zero terminated string holding the name of a font. Under Windows,
    only the first 32 characters of the name are used and the name is not case sensitive. For
    internal caching, Scintilla tracks fonts by name and does care about the casing of font names,
    so please be consistent. On GTK+, Pango is used to display text.</p>
    <p>Sizes can be set to a whole number of points with <code>SCI_STYLESETSIZE</code>
    or to a fractional point size in hundredths of a point with <code>SCI_STYLESETSIZEFRACTIONAL</code>
    by multiplying the size by 100 (<code>SC_FONT_SIZE_MULTIPLIER</code>).
    For example, a text size of 9.4 points is set with <code>SCI_STYLESETSIZEFRACTIONAL(&lt;style&gt;, 940)</code>.
    </p>
    <p>The weight or boldness of a font can be set with <code>SCI_STYLESETBOLD</code>
    or <code>SCI_STYLESETWEIGHT</code>. The weight is a number between 1 and 999 with 1 being very light
    and 999 very heavy. While any value can be used, fonts often only support between 2 and 4 weights with three weights
    being common enough to have symbolic names: 
    <code>SC_WEIGHT_NORMAL</code> (400),
    <code>SC_WEIGHT_SEMIBOLD</code> (600), and
    <code>SC_WEIGHT_BOLD</code> (700).
    The <code>SCI_STYLESETBOLD</code> message takes a boolean argument with 0 choosing <code>SC_WEIGHT_NORMAL</code>
    and 1 <code>SC_WEIGHT_BOLD</code>.
    </p>

    <p><b id="SCI_STYLESETUNDERLINE">SCI_STYLESETUNDERLINE(int styleNumber, bool
    underline)</b><br />
    <b id="SCI_STYLEGETUNDERLINE">SCI_STYLEGETUNDERLINE(int styleNumber)</b><br />
    You can set a style to be underlined. The underline is drawn in the foreground colour. All
    characters with a style that includes the underline attribute are underlined, even if they are
    white space.</p>

    <p><b id="SCI_STYLESETFORE">SCI_STYLESETFORE(int styleNumber, int <a class="jump"
    href="#colour">colour</a>)</b><br />
    <b id="SCI_STYLEGETFORE">SCI_STYLEGETFORE(int styleNumber)</b><br />
    <b id="SCI_STYLESETBACK">SCI_STYLESETBACK(int styleNumber, int <a class="jump"
    href="#colour">colour</a>)</b><br />
    <b id="SCI_STYLEGETBACK">SCI_STYLEGETBACK(int styleNumber)</b><br />
    Text is drawn in the foreground colour. The space in each character cell that is not occupied
    by the character is drawn in the background colour.</p>

    <p><b id="SCI_STYLESETEOLFILLED">SCI_STYLESETEOLFILLED(int styleNumber, bool
    eolFilled)</b><br />
    <b id="SCI_STYLEGETEOLFILLED">SCI_STYLEGETEOLFILLED(int styleNumber)</b><br />
    If the last character in the line has a style with this attribute set, the remainder of the
    line up to the right edge of the window is filled with the background colour set for the last
    character. This is useful when a document contains embedded sections in another language such
    as HTML pages with embedded JavaScript. By setting <code>eolFilled</code> to <code>true</code>
    and a consistent background colour (different from the background colour set for the HTML
    styles) to all JavaScript styles then JavaScript sections will be easily distinguished from
    HTML.</p>

    <p><b id="SCI_STYLESETCHARACTERSET">SCI_STYLESETCHARACTERSET(int styleNumber, int
    charSet)</b><br />
    <b id="SCI_STYLEGETCHARACTERSET">SCI_STYLEGETCHARACTERSET(int styleNumber)</b><br />
    You can set a style to use a different character set than the default. The places where such
    characters sets are likely to be useful are comments and literal strings. For example,
    <code>SCI_STYLESETCHARACTERSET(SCE_C_STRING, SC_CHARSET_RUSSIAN)</code> would ensure that
    strings in Russian would display correctly in C and C++ (<code>SCE_C_STRING</code> is the style
    number used by the C and C++ lexer to display literal strings; it has the value 6). This
    feature works differently on Windows and GTK+.</p>

    <p>The character sets supported on Windows are:<br />
     <code>SC_CHARSET_ANSI</code>, <code>SC_CHARSET_ARABIC</code>, <code>SC_CHARSET_BALTIC</code>,
    <code>SC_CHARSET_CHINESEBIG5</code>, <code>SC_CHARSET_DEFAULT</code>,
    <code>SC_CHARSET_EASTEUROPE</code>, <code>SC_CHARSET_GB2312</code>,
    <code>SC_CHARSET_GREEK</code>, <code>SC_CHARSET_HANGUL</code>, <code>SC_CHARSET_HEBREW</code>,
    <code>SC_CHARSET_JOHAB</code>, <code>SC_CHARSET_MAC</code>, <code>SC_CHARSET_OEM</code>,
    <code>SC_CHARSET_RUSSIAN</code> (code page 1251),
    <code>SC_CHARSET_SHIFTJIS</code>, <code>SC_CHARSET_SYMBOL</code>, <code>SC_CHARSET_THAI</code>,
    <code>SC_CHARSET_TURKISH</code>, and <code>SC_CHARSET_VIETNAMESE</code>.</p>

    <p>The character sets supported on GTK+ are:<br />
     <code>SC_CHARSET_ANSI</code>, <code>SC_CHARSET_CYRILLIC</code> (code page 1251),
     <code>SC_CHARSET_EASTEUROPE</code>,
    <code>SC_CHARSET_GB2312</code>, <code>SC_CHARSET_HANGUL</code>,
    <code>SC_CHARSET_RUSSIAN</code> (KOI8-R), <code>SC_CHARSET_SHIFTJIS</code>, and
    <code>SC_CHARSET_8859_15</code>.</p>

    <p><b id="SCI_STYLESETCASE">SCI_STYLESETCASE(int styleNumber, int caseMode)</b><br />
    <b id="SCI_STYLEGETCASE">SCI_STYLEGETCASE(int styleNumber)</b><br />
    The value of caseMode determines how text is displayed. You can set upper case
    (<code>SC_CASE_UPPER</code>, 1) or lower case (<code>SC_CASE_LOWER</code>, 2) or display
    normally (<code>SC_CASE_MIXED</code>, 0). This does not change the stored text, only how it is
    displayed.</p>

    <p><b id="SCI_STYLESETVISIBLE">SCI_STYLESETVISIBLE(int styleNumber, bool visible)</b><br />
    <b id="SCI_STYLEGETVISIBLE">SCI_STYLEGETVISIBLE(int styleNumber)</b><br />
    Text is normally visible. However, you can completely hide it by giving it a style with the
    <code>visible</code> set to 0. This could be used to hide embedded formatting instructions or
    hypertext keywords in HTML or XML.</p>

    <p><b id="SCI_STYLESETCHANGEABLE">SCI_STYLESETCHANGEABLE(int styleNumber, bool
    changeable)</b><br />
    <b id="SCI_STYLEGETCHANGEABLE">SCI_STYLEGETCHANGEABLE(int styleNumber)</b><br />
    This is an experimental and incompletely implemented style attribute. The default setting is
    <code>changeable</code> set <code>true</code> but when set <code>false</code> it makes text
    read-only. Currently it only stops the caret from being within not-changeable text and does not
    yet stop deleting a range that contains not-changeable text.</p>

    <p><b id="SCI_STYLESETHOTSPOT">SCI_STYLESETHOTSPOT(int styleNumber, bool
    hotspot)</b><br />
    <b id="SCI_STYLEGETHOTSPOT">SCI_STYLEGETHOTSPOT(int styleNumber)</b><br />
    This style is used to mark ranges of text that can detect mouse clicks.
    The cursor changes to a hand over hotspots, and the foreground, and background colours
    may change and an underline appear to indicate that these areas are sensitive to clicking.
    This may be used to allow hyperlinks to other documents.</p>

    <h2 id="CaretAndSelectionStyles">Caret, selection, and hotspot styles</h2>

    <p>The selection is shown by changing the foreground and/or background colours. If one of these
    is not set then that attribute is not changed for the selection. The default is to show the
    selection by changing the background to light gray and leaving the foreground the same as when
    it was not selected. When there is no selection, the current insertion point is marked by the
    text caret. This is a vertical line that is normally blinking on and off to attract the users
    attention.</p>
    <code><a class="message" href="#SCI_SETSELFORE">SCI_SETSELFORE(bool useSelectionForeColour, int colour)</a><br />
    <a class="message" href="#SCI_SETSELBACK">SCI_SETSELBACK(bool useSelectionBackColour, int colour)</a><br />
    <a class="message" href="#SCI_SETSELALPHA">SCI_SETSELALPHA(int alpha)</a><br />
    <a class="message" href="#SCI_GETSELALPHA">SCI_GETSELALPHA</a><br />
    <a class="message" href="#SCI_SETSELEOLFILLED">SCI_SETSELEOLFILLED(bool filled)</a><br />
    <a class="message" href="#SCI_GETSELEOLFILLED">SCI_GETSELEOLFILLED</a><br />
    <a class="message" href="#SCI_SETCARETFORE">SCI_SETCARETFORE(int colour)</a><br />
    <a class="message" href="#SCI_GETCARETFORE">SCI_GETCARETFORE</a><br />
    <a class="message" href="#SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</a><br />
    <a class="message" href="#SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE</a><br />
    <a class="message" href="#SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(int colour)</a><br />
    <a class="message" href="#SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK</a><br />
    <a class="message" href="#SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(int alpha)</a><br />
    <a class="message" href="#SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA</a><br />
    <a class="message" href="#SCI_SETCARETLINEVISIBLEALWAYS">SCI_SETCARETLINEVISIBLEALWAYS(bool alwaysVisible)</a><br />
    <a class="message" href="#SCI_GETCARETLINEVISIBLEALWAYS">SCI_GETCARETLINEVISIBLEALWAYS</a><br />
    <a class="message" href="#SCI_SETCARETPERIOD">SCI_SETCARETPERIOD(int milliseconds)</a><br />
    <a class="message" href="#SCI_GETCARETPERIOD">SCI_GETCARETPERIOD</a><br />
    <a class="message" href="#SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</a><br />
    <a class="message" href="#SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</a><br />
    <a class="message" href="#SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</a><br />
    <a class="message" href="#SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</a><br />
    <a class="message" href="#SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useSetting, int colour)</a><br />
    <a class="message" href="#SCI_GETHOTSPOTACTIVEFORE">SCI_GETHOTSPOTACTIVEFORE</a><br />
    <a class="message" href="#SCI_SETHOTSPOTACTIVEBACK">SCI_SETHOTSPOTACTIVEBACK(bool useSetting, int colour)</a><br />
    <a class="message" href="#SCI_GETHOTSPOTACTIVEBACK">SCI_GETHOTSPOTACTIVEBACK</a><br />
    <a class="message" href="#SCI_SETHOTSPOTACTIVEUNDERLINE">SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)</a><br />
    <a class="message" href="#SCI_GETHOTSPOTACTIVEUNDERLINE">SCI_GETHOTSPOTACTIVEUNDERLINE</a><br />
    <a class="message" href="#SCI_SETHOTSPOTSINGLELINE">SCI_SETHOTSPOTSINGLELINE(bool singleLine)</a><br />
    <a class="message" href="#SCI_GETHOTSPOTSINGLELINE">SCI_GETHOTSPOTSINGLELINE</a><br />
    <a class="message" href="#SCI_SETCONTROLCHARSYMBOL">SCI_SETCONTROLCHARSYMBOL(int symbol)</a><br />
     <a class="message" href="#SCI_GETCONTROLCHARSYMBOL">SCI_GETCONTROLCHARSYMBOL</a><br />
     <a class="message" href="#SCI_SETCARETSTICKY">SCI_SETCARETSTICKY(int useCaretStickyBehaviour)</a><br />
     <a class="message" href="#SCI_GETCARETSTICKY">SCI_GETCARETSTICKY</a><br />
     <a class="message" href="#SCI_TOGGLECARETSTICKY">SCI_TOGGLECARETSTICKY</a><br />
    </code>

    <p><b id="SCI_SETSELFORE">SCI_SETSELFORE(bool useSelectionForeColour, int <a class="jump"
    href="#colour">colour</a>)</b><br />
     <b id="SCI_SETSELBACK">SCI_SETSELBACK(bool useSelectionBackColour, int <a class="jump"
    href="#colour">colour</a>)</b><br />
     You can choose to override the default selection colouring with these two messages. The colour
    you provide is used if you set <code>useSelection*Colour</code> to <code>true</code>. If it is
    set to <code>false</code>, the default styled colouring is used and the <code>colour</code>
    argument has no effect.</p>
     <p><b id="SCI_SETSELALPHA">SCI_SETSELALPHA(int <a class="jump" href="#alpha">alpha</a>)</b><br />
     <b id="SCI_GETSELALPHA">SCI_GETSELALPHA</b><br />
     The selection can be drawn translucently in the selection background colour by
     setting an alpha value.</p>

     <p><b id="SCI_SETSELEOLFILLED">SCI_SETSELEOLFILLED(bool filled)</b><br />
     <b id="SCI_GETSELEOLFILLED">SCI_GETSELEOLFILLED</b><br />
     The selection can be drawn up to the right hand border by setting this property.</p>

    <p><b id="SCI_SETCARETFORE">SCI_SETCARETFORE(int <a class="jump"
    href="#colour">colour</a>)</b><br />
     <b id="SCI_GETCARETFORE">SCI_GETCARETFORE</b><br />
     The colour of the caret can be set with <code>SCI_SETCARETFORE</code> and retrieved with
    <code>SCI_GETCARETFORE</code>.</p>

    <p><b id="SCI_SETCARETLINEVISIBLE">SCI_SETCARETLINEVISIBLE(bool show)</b><br />
     <b id="SCI_GETCARETLINEVISIBLE">SCI_GETCARETLINEVISIBLE</b><br />
     <b id="SCI_SETCARETLINEBACK">SCI_SETCARETLINEBACK(int <a class="jump"
    href="#colour">colour</a>)</b><br />
     <b id="SCI_GETCARETLINEBACK">SCI_GETCARETLINEBACK</b><br />
     <b id="SCI_SETCARETLINEBACKALPHA">SCI_SETCARETLINEBACKALPHA(int <a class="jump" href="#alpha">alpha</a>)</b><br />
     <b id="SCI_GETCARETLINEBACKALPHA">SCI_GETCARETLINEBACKALPHA</b><br />
     You can choose to make the background colour of the line containing the caret different with
    these messages. To do this, set the desired background colour with
    <code>SCI_SETCARETLINEBACK</code>, then use <code>SCI_SETCARETLINEVISIBLE(true)</code> to
    enable the effect. You can cancel the effect with <code>SCI_SETCARETLINEVISIBLE(false)</code>.
    The two <code>SCI_GETCARET*</code> functions return the state and the colour. This form of
    background colouring has highest priority when a line has markers that would otherwise change
    the background colour.
           The caret line may also be drawn translucently which allows other background colours to show
           through. This is done by setting the alpha (translucency) value by calling
           SCI_SETCARETLINEBACKALPHA. When the alpha is not SC_ALPHA_NOALPHA,
           the caret line is drawn after all other features so will affect the colour of all other features.
          </p>

    <p><b id="SCI_SETCARETLINEVISIBLEALWAYS">SCI_SETCARETLINEVISIBLEALWAYS(bool alwaysVisible)</b><br />
     <b id="SCI_GETCARETLINEVISIBLEALWAYS">SCI_GETCARETLINEVISIBLEALWAYS</b><br />
     Choose to make the caret line always visible even when the window is not in focus.
     Default behaviour <code>SCI_SETCARETLINEVISIBLEALWAYS(false)</code> the caret line is only visible when the window is in focus.
          </p>

    <p><b id="SCI_SETCARETPERIOD">SCI_SETCARETPERIOD(int milliseconds)</b><br />
     <b id="SCI_GETCARETPERIOD">SCI_GETCARETPERIOD</b><br />
     The rate at which the caret blinks can be set with <code>SCI_SETCARETPERIOD</code> which
    determines the time in milliseconds that the caret is visible or invisible before changing
    state. Setting the period to 0 stops the caret blinking. The default value is 500 milliseconds.
    <code>SCI_GETCARETPERIOD</code> returns the current setting.</p>

    <p><b id="SCI_SETCARETSTYLE">SCI_SETCARETSTYLE(int style)</b><br />
     <b id="SCI_GETCARETSTYLE">SCI_GETCARETSTYLE</b><br />
     The style of the caret can be set with <code>SCI_SETCARETSTYLE</code> to be a line caret
    (CARETSTYLE_LINE=1), a block caret (CARETSTYLE_BLOCK=2) or to not draw at all
    (CARETSTYLE_INVISIBLE=0). The default value is the line caret (CARETSTYLE_LINE=1).
    You can determine the current caret style setting using <code>SCI_GETCARETSTYLE</code>.</p>

    <p>The block character draws most combining and multibyte character sequences successfully,
    though some fonts like Thai Fonts (and possibly others) can sometimes appear strange when
    the cursor is positioned at these characters, which may result in only drawing a part of the
    cursor character sequence. This is most notable on Windows platforms.</p>

    <p><b id="SCI_SETCARETWIDTH">SCI_SETCARETWIDTH(int pixels)</b><br />
     <b id="SCI_GETCARETWIDTH">SCI_GETCARETWIDTH</b><br />
     The width of the line caret can be set with <code>SCI_SETCARETWIDTH</code> to a value of
    0, 1, 2 or 3 pixels. The default width is 1 pixel. You can read back the current width with
    <code>SCI_GETCARETWIDTH</code>. A width of 0 makes the caret invisible (added at version
    1.50), similar to setting the caret style to CARETSTYLE_INVISIBLE (though not interchangable).
    This setting only affects the width of the cursor when the cursor style is set to line caret
    mode, it does not affect the width for a block caret.</p>

    <p><b id="SCI_SETHOTSPOTACTIVEFORE">SCI_SETHOTSPOTACTIVEFORE(bool useHotSpotForeColour, int <a class="jump"
    href="#colour">colour</a>)</b><br />
    <b id="SCI_GETHOTSPOTACTIVEFORE">SCI_GETHOTSPOTACTIVEFORE</b><br />
    <b id="SCI_SETHOTSPOTACTIVEBACK">SCI_SETHOTSPOTACTIVEBACK(bool useHotSpotBackColour, int <a class="jump"
    href="#colour">colour</a>)</b><br />
    <b id="SCI_GETHOTSPOTACTIVEBACK">SCI_GETHOTSPOTACTIVEBACK</b><br />
    <b id="SCI_SETHOTSPOTACTIVEUNDERLINE">SCI_SETHOTSPOTACTIVEUNDERLINE(bool underline)</b><br />
     <b id="SCI_GETHOTSPOTACTIVEUNDERLINE">SCI_GETHOTSPOTACTIVEUNDERLINE</b><br />
    <b id="SCI_SETHOTSPOTSINGLELINE">SCI_SETHOTSPOTSINGLELINE(bool singleLine)</b><br />
     <b id="SCI_GETHOTSPOTSINGLELINE">SCI_GETHOTSPOTSINGLELINE</b><br />
    While the cursor hovers over text in a style with the hotspot attribute set,
    the default colouring can be modified and an underline drawn with these settings.
    Single line mode stops a hotspot from wrapping onto next line.</p>

    <p><b id="SCI_SETCONTROLCHARSYMBOL">SCI_SETCONTROLCHARSYMBOL(int symbol)</b><br />
     <b id="SCI_GETCONTROLCHARSYMBOL">SCI_GETCONTROLCHARSYMBOL</b><br />
     By default, Scintilla displays control characters (characters with codes less than 32) in a
    rounded rectangle as ASCII mnemonics: "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
    "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK",
    "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US". These mnemonics come from the
    early days of signaling, though some are still used (LF = Line Feed, BS = Back Space, CR =
    Carriage Return, for example).</p>

    <p>You can choose to replace these mnemonics by a nominated symbol with an ASCII code in the
    range 32 to 255. If you set a symbol value less than 32, all control characters are displayed
    as mnemonics. The symbol you set is rendered in the font of the style set for the character.
    You can read back the current symbol with the <code>SCI_GETCONTROLCHARSYMBOL</code> message.
    The default symbol value is 0.</p>

    <p><b id="SCI_SETCARETSTICKY">SCI_SETCARETSTICKY(int useCaretStickyBehaviour)</b><br />
    <b id="SCI_GETCARETSTICKY">SCI_GETCARETSTICKY</b><br />
    <b id="SCI_TOGGLECARETSTICKY">SCI_TOGGLECARETSTICKY</b><br />
    These messages set, get or toggle the caretSticky setting which controls when the last position
    of the caret on the line is saved.</p>

    <p>When set to <code>SC_CARETSTICKY_OFF</code> (0), the sticky flag is off; all text changes
    (and all caret position changes) will remember the
    caret's new horizontal position when moving to different lines. This is the default.</p>

    <p>When set to <code>SC_CARETSTICKY_ON</code> (1), the sticky flag is on, and the only thing which will cause the editor to remember the
    horizontal caret position is moving the caret with mouse or keyboard (left/right arrow keys, home/end keys, etc). </p>

    <p>When set to <code>SC_CARETSTICKY_WHITESPACE</code> (2), the caret acts like mode 0 (sticky off) except under one
    special case; when space or tab characters are inserted. (Including pasting <b>only space/tabs</b> -- undo, redo,
    etc. do not exhibit this behavior..).</p>

    <p><code>SCI_TOGGLECARETSTICKY</code> switches from <code>SC_CARETSTICKY_ON</code> and <code>SC_CARETSTICKY_WHITESPACE</code>
    to <code>SC_CARETSTICKY_OFF</code> and from <code>SC_CARETSTICKY_OFF</code> to <code>SC_CARETSTICKY_ON</code>.</p>

    <h2 id="Margins">Margins</h2>

    <p>There may be up to five margins, numbered 0 to <code>SC_MAX_MARGIN</code> (4)
    to the left of the text display, plus a gap either side of
    the text. Each margin can be set to display only symbols, line numbers, or text with <a
    class="message" href="#SCI_SETMARGINTYPEN"><code>SCI_SETMARGINTYPEN</code></a>.
    Textual margins may also display symbols.
    The markers
    that can be displayed in each margin are set with <a class="message"
    href="#SCI_SETMARGINMASKN"><code>SCI_SETMARGINMASKN</code></a>. Any markers not associated with
    a visible margin will be displayed as changes in background colour in the text. A width in
    pixels can be set for each margin. Margins with a zero width are ignored completely. You can
    choose if a mouse click in a margin sends a <a class="message"
    href="#SCN_MARGINCLICK"><code>SCN_MARGINCLICK</code></a> notification to the container or
    selects a line of text.</p>

    <p>The margins are numbered 0 to 4. Using a margin number outside the valid range has no
    effect. By default, margin 0 is set to display line numbers, but is given a width of 0, so it
    is hidden. Margin 1 is set to display non-folding symbols and is given a width of 16 pixels, so
    it is visible. Margin 2 is set to display the folding symbols, but is given a width of 0, so it
    is hidden. Of course, you can set the margins to be whatever you wish.</p>

    <p>Styled text margins used to show revision and blame information:</p>
    <p><img src="styledmargin.png" alt="Styled text margins used to show revision and blame information" /></p>

    <code><a class="message" href="#SCI_SETMARGINTYPEN">SCI_SETMARGINTYPEN(int margin, int
    type)</a><br />
     <a class="message" href="#SCI_GETMARGINTYPEN">SCI_GETMARGINTYPEN(int margin)</a><br />
     <a class="message" href="#SCI_SETMARGINWIDTHN">SCI_SETMARGINWIDTHN(int margin, int
    pixelWidth)</a><br />
     <a class="message" href="#SCI_GETMARGINWIDTHN">SCI_GETMARGINWIDTHN(int margin)</a><br />
     <a class="message" href="#SCI_SETMARGINMASKN">SCI_SETMARGINMASKN(int margin, int
    mask)</a><br />
     <a class="message" href="#SCI_GETMARGINMASKN">SCI_GETMARGINMASKN(int margin)</a><br />
     <a class="message" href="#SCI_SETMARGINSENSITIVEN">SCI_SETMARGINSENSITIVEN(int margin, bool
    sensitive)</a><br />
     <a class="message" href="#SCI_GETMARGINSENSITIVEN">SCI_GETMARGINSENSITIVEN(int
    margin)</a><br />
     <a class="message" href="#SCI_SETMARGINCURSORN">SCI_SETMARGINCURSORN(int margin, int
    cursor)</a><br />
     <a class="message" href="#SCI_GETMARGINCURSORN">SCI_GETMARGINCURSORN(int
    margin)</a><br />
     <a class="message" href="#SCI_SETMARGINLEFT">SCI_SETMARGINLEFT(&lt;unused&gt;, int
    pixels)</a><br />
     <a class="message" href="#SCI_GETMARGINLEFT">SCI_GETMARGINLEFT</a><br />
     <a class="message" href="#SCI_SETMARGINRIGHT">SCI_SETMARGINRIGHT(&lt;unused&gt;, int
    pixels)</a><br />
     <a class="message" href="#SCI_GETMARGINRIGHT">SCI_GETMARGINRIGHT</a><br />
     <a class="message" href="#SCI_SETFOLDMARGINCOLOUR">SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)</a><br />
     <a class="message" href="#SCI_SETFOLDMARGINHICOLOUR">SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)</a><br />
     <a class="message" href="#SCI_MARGINSETTEXT">SCI_MARGINSETTEXT(int line, char *text)</a><br />
     <a class="message" href="#SCI_MARGINGETTEXT">SCI_MARGINGETTEXT(int line, char *text)</a><br />
     <a class="message" href="#SCI_MARGINSETSTYLE">SCI_MARGINSETSTYLE(int line, int style)</a><br />
     <a class="message" href="#SCI_MARGINGETSTYLE">SCI_MARGINGETSTYLE(int line)</a><br />
     <a class="message" href="#SCI_MARGINSETSTYLES">SCI_MARGINSETSTYLES(int line, char *styles)</a><br />
     <a class="message" href="#SCI_MARGINGETSTYLES">SCI_MARGINGETSTYLES(int line, char *styles)</a><br />
     <a class="message" href="#SCI_MARGINTEXTCLEARALL">SCI_MARGINTEXTCLEARALL</a><br />
     <a class="message" href="#SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET(int style)</a><br />
     <a class="message" href="#SCI_MARGINGETSTYLEOFFSET">SCI_MARGINGETSTYLEOFFSET</a><br />
     <a class="message" href="#SCI_SETMARGINOPTIONS">SCI_SETMARGINOPTIONS(int marginOptions)</a><br />
     <a class="message" href="#SCI_GETMARGINOPTIONS">SCI_GETMARGINOPTIONS</a><br />
    </code>

    <p><b id="SCI_SETMARGINTYPEN">SCI_SETMARGINTYPEN(int margin, int iType)</b><br />
     <b id="SCI_GETMARGINTYPEN">SCI_GETMARGINTYPEN(int margin)</b><br />
     These two routines set and get the type of a margin. The margin argument should be 0, 1, 2, 3 or 4.
    You can use the predefined constants <code>SC_MARGIN_SYMBOL</code> (0) and
    <code>SC_MARGIN_NUMBER</code> (1) to set a margin as either a line number or a symbol margin.
    A margin with application defined text may use <code>SC_MARGIN_TEXT</code> (4) or
    <code>SC_MARGIN_RTEXT</code> (5) to right justify the text.
    By convention, margin 0 is used for line numbers and the next two are used for symbols. You can
    also use the constants <code>SC_MARGIN_BACK</code> (2) and <code>SC_MARGIN_FORE</code> (3) for
    symbol margins that set their background colour to match the STYLE_DEFAULT background and
    foreground colours.</p>

    <p><b id="SCI_SETMARGINWIDTHN">SCI_SETMARGINWIDTHN(int margin, int pixelWidth)</b><br />
     <b id="SCI_GETMARGINWIDTHN">SCI_GETMARGINWIDTHN(int margin)</b><br />
     These routines set and get the width of a margin in pixels. A margin with zero width is
    invisible. By default, Scintilla sets margin 1 for symbols with a width of 16 pixels, so this
    is a reasonable guess if you are not sure what would be appropriate. Line number margins widths
    should take into account the number of lines in the document and the line number style. You
    could use something like <a class="message"
    href="#SCI_TEXTWIDTH"><code>SCI_TEXTWIDTH(STYLE_LINENUMBER, "_99999")</code></a> to get a
    suitable width.</p>

    <p><b id="SCI_SETMARGINMASKN">SCI_SETMARGINMASKN(int margin, int mask)</b><br />
     <b id="SCI_GETMARGINMASKN">SCI_GETMARGINMASKN(int margin)</b><br />
     The mask is a 32-bit value. Each bit corresponds to one of 32 logical symbols that can be
    displayed in a margin that is enabled for symbols. There is a useful constant,
    <code>SC_MASK_FOLDERS</code> (0xFE000000 or -33554432), that is a mask for the 7 logical
    symbols used to denote folding. You can assign a wide range of symbols and colours to each of
    the 32 logical symbols, see <a href="#Markers">Markers</a> for more information. If <code>(mask
    &amp; SC_MASK_FOLDERS)==0</code>, the margin background colour is controlled by style 33 (<a
    class="message" href="#StyleDefinition"><code>STYLE_LINENUMBER</code></a>).</p>

    <p>You add logical markers to a line with <a class="message"
    href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. If a line has an associated marker that
    does not appear in the mask of any margin with a non-zero width, the marker changes the
    background colour of the line. For example, suppose you decide to use logical marker 10 to mark
    lines with a syntax error and you want to show such lines by changing the background colour.
    The mask for this marker is 1 shifted left 10 times (1&lt;&lt;10) which is 0x400. If you make
    sure that no symbol margin includes 0x400 in its mask, any line with the marker gets the
    background colour changed.</p>

    <p>To set a non-folding margin 1 use <code>SCI_SETMARGINMASKN(1, ~SC_MASK_FOLDERS)</code>
    which is the default set by Scintilla.
    To set a folding margin 2 use <code>SCI_SETMARGINMASKN(2, SC_MASK_FOLDERS)</code>.
    <code>~SC_MASK_FOLDERS</code> is 0x1FFFFFF in hexadecimal or 33554431
    decimal. Of course, you may need to display all 32 symbols in a margin, in which case use
    <code>SCI_SETMARGINMASKN(margin, -1)</code>.</p>

    <p><b id="SCI_SETMARGINSENSITIVEN">SCI_SETMARGINSENSITIVEN(int margin, bool
    sensitive)</b><br />
     <b id="SCI_GETMARGINSENSITIVEN">SCI_GETMARGINSENSITIVEN(int margin)</b><br />
     Each of the five margins can be set sensitive or insensitive to mouse clicks. A click in a
    sensitive margin sends a <a class="message"
    href="#SCN_MARGINCLICK"><code>SCN_MARGINCLICK</code></a> <a class="jump"
    href="#Notifications">notification</a> to the container. Margins that are not sensitive act as
    selection margins which make it easy to select ranges of lines. By default, all margins are
    insensitive.</p>

    <p><b id="SCI_SETMARGINCURSORN">SCI_SETMARGINCURSORN(int margin, int
    cursor)</b><br />
     <b id="SCI_GETMARGINCURSORN">SCI_GETMARGINCURSORN(int margin)</b><br />
     A reversed arrow cursor is normally shown over all margins. This may be changed to a normal arrow with
     <code>SCI_SETMARGINCURSORN(margin, SC_CURSORARROW)</code> or restored to a
     reversed arrow with
     <code>SCI_SETMARGINCURSORN(margin, SC_CURSORREVERSEARROW)</code>.</p>

    <p><b id="SCI_SETMARGINLEFT">SCI_SETMARGINLEFT(&lt;unused&gt;, int pixels)</b><br />
     <b id="SCI_GETMARGINLEFT">SCI_GETMARGINLEFT</b><br />
     <b id="SCI_SETMARGINRIGHT">SCI_SETMARGINRIGHT(&lt;unused&gt;, int pixels)</b><br />
     <b id="SCI_GETMARGINRIGHT">SCI_GETMARGINRIGHT</b><br />
     These messages set and get the width of the blank margin on both sides of the text in pixels.
    The default is to one pixel on each side.</p>

    <p><b id="SCI_SETFOLDMARGINCOLOUR">SCI_SETFOLDMARGINCOLOUR(bool useSetting, int colour)</b><br />
     <b id="SCI_SETFOLDMARGINHICOLOUR">SCI_SETFOLDMARGINHICOLOUR(bool useSetting, int colour)</b><br />
     These messages allow changing the colour of the fold margin and fold margin highlight.
     On Windows the fold margin colour defaults to ::GetSysColor(COLOR_3DFACE) and the fold margin highlight
     colour to ::GetSysColor(COLOR_3DHIGHLIGHT).</p>

    <p>
     <b id="SCI_MARGINSETTEXT">SCI_MARGINSETTEXT(int line, char *text)</b><br />
     <b id="SCI_MARGINGETTEXT">SCI_MARGINGETTEXT(int line, char *text)</b><br />
     <b id="SCI_MARGINSETSTYLE">SCI_MARGINSETSTYLE(int line, int style)</b><br />
     <b id="SCI_MARGINGETSTYLE">SCI_MARGINGETSTYLE(int line)</b><br />
     <b id="SCI_MARGINSETSTYLES">SCI_MARGINSETSTYLES(int line, char *styles)</b><br />
     <b id="SCI_MARGINGETSTYLES">SCI_MARGINGETSTYLES(int line, char *styles)</b><br />
     <b id="SCI_MARGINTEXTCLEARALL">SCI_MARGINTEXTCLEARALL</b><br />
     Text margins are created with the type SC_MARGIN_TEXT or SC_MARGIN_RTEXT.
     A different string may be set for each line with <code>SCI_MARGINSETTEXT</code>.
     The whole of the text margin on a line may be displayed in a particular style with
     <code>SCI_MARGINSETSTYLE</code> or each character may be individually styled with
     <code>SCI_MARGINSETSTYLES</code> which uses an array of bytes with each byte setting the style
     of the corresponding text byte similar to <code>SCI_SETSTYLINGEX</code>.
     Setting a text margin will cause a
     <a class="message" href="#SC_MOD_CHANGEMARGIN"><code>SC_MOD_CHANGEMARGIN</code></a>
     notification to be sent.
    </p>
    <p>
    Only some style attributes are active in text margins: font, size/sizeFractional, bold/weight, italics, fore, back, and characterSet.
    </p>
    <p>
     <b id="SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET(int style)</b><br />
     <b id="SCI_MARGINGETSTYLEOFFSET">SCI_MARGINGETSTYLEOFFSET</b><br />
    Margin styles may be completely separated from standard text styles by setting a style offset. For example,
    <code>SCI_MARGINSETSTYLEOFFSET(256)</code> would allow the margin styles to be numbered from
    256 upto 511 so they do not overlap styles set by lexers. Each style number set with <code>SCI_MARGINSETSTYLE</code>
    or <code>SCI_MARGINSETSTYLES</code> has the offset added before looking up the style.
    </p>
    <p>
    Always call <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES</a>
    before <code>SCI_MARGINSETSTYLEOFFSET</code> and use the result as the argument to <code>SCI_MARGINSETSTYLEOFFSET</code>.
    </p>
    <p>
     <b id="SCI_SETMARGINOPTIONS">SCI_SETMARGINOPTIONS(int marginOptions)</b><br />
     <b id="SCI_GETMARGINOPTIONS">SCI_GETMARGINOPTIONS</b><br />
    Define margin options by enabling appropriate bit flags. At the moment, only one flag is available 
    <code>SC_MARGINOPTION_SUBLINESELECT</code>=1, which controls how wrapped lines are selected when clicking 
    on margin in front of them. If <code>SC_MARGINOPTION_SUBLINESELECT</code> is set only sub line of wrapped 
    line is selected, otherwise whole wrapped line is selected. Margin options are set to 
    <code>SC_MARGINOPTION_NONE</code>=0 by default.
    </p>

    <h2 id="Annotations">Annotations</h2>

    <p>Annotations are read-only lines of text underneath each line of editable text.
    An annotation may consist of multiple lines separated by '\n'.
    Annotations can be used to display an assembler version of code for debugging or to show diagnostic messages inline or to
    line up different versions of text in a merge tool.</p>
    <p>Annotations count as display lines for the methods
    <a class="message" href="#SCI_VISIBLEFROMDOCLINE"><code>SCI_VISIBLEFROMDOCLINE</code></a> and
    <a class="message" href="#SCI_DOCLINEFROMVISIBLE"><code>SCI_DOCLINEFROMVISIBLE</code></a></p>
    <p>Annotations used for inline diagnostics:</p>
    <p><img src="annotations.png" alt="Annotations used for inline diagnostics" /></p>

    <code>
     <a class="message" href="#SCI_ANNOTATIONSETTEXT">SCI_ANNOTATIONSETTEXT(int line, char *text)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETTEXT">SCI_ANNOTATIONGETTEXT(int line, char *text)</a><br />
     <a class="message" href="#SCI_ANNOTATIONSETSTYLE">SCI_ANNOTATIONSETSTYLE(int line, int style)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETSTYLE">SCI_ANNOTATIONGETSTYLE(int line)</a><br />
     <a class="message" href="#SCI_ANNOTATIONSETSTYLES">SCI_ANNOTATIONSETSTYLES(int line, char *styles)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETSTYLES">SCI_ANNOTATIONGETSTYLES(int line, char *styles)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETLINES">SCI_ANNOTATIONGETLINES(int line)</a><br />
     <a class="message" href="#SCI_ANNOTATIONCLEARALL">SCI_ANNOTATIONCLEARALL</a><br />
     <a class="message" href="#SCI_ANNOTATIONSETVISIBLE">SCI_ANNOTATIONSETVISIBLE(int visible)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETVISIBLE">SCI_ANNOTATIONGETVISIBLE</a><br />
     <a class="message" href="#SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET(int style)</a><br />
     <a class="message" href="#SCI_ANNOTATIONGETSTYLEOFFSET">SCI_ANNOTATIONGETSTYLEOFFSET</a><br />
    </code>

    <p>
     <b id="SCI_ANNOTATIONSETTEXT">SCI_ANNOTATIONSETTEXT(int line, char *text)</b><br />
     <b id="SCI_ANNOTATIONGETTEXT">SCI_ANNOTATIONGETTEXT(int line, char *text)</b><br />
     <b id="SCI_ANNOTATIONSETSTYLE">SCI_ANNOTATIONSETSTYLE(int line, int style)</b><br />
     <b id="SCI_ANNOTATIONGETSTYLE">SCI_ANNOTATIONGETSTYLE(int line)</b><br />
     <b id="SCI_ANNOTATIONSETSTYLES">SCI_ANNOTATIONSETSTYLES(int line, char *styles)</b><br />
     <b id="SCI_ANNOTATIONGETSTYLES">SCI_ANNOTATIONGETSTYLES(int line, char *styles)</b><br />
     <b id="SCI_ANNOTATIONGETLINES">SCI_ANNOTATIONGETLINES(int line)</b><br />
     <b id="SCI_ANNOTATIONCLEARALL">SCI_ANNOTATIONCLEARALL</b><br />
     A different string may be set for each line with <code>SCI_ANNOTATIONSETTEXT</code>.
     To clear annotations call <code>SCI_ANNOTATIONSETTEXT</code> with a NULL pointer.
     The whole of the text ANNOTATION on a line may be displayed in a particular style with
     <code>SCI_ANNOTATIONSETSTYLE</code> or each character may be individually styled with
     <code>SCI_ANNOTATIONSETSTYLES</code> which uses an array of bytes with each byte setting the style
     of the corresponding text byte similar to <code>SCI_SETSTYLINGEX</code>. The text must be set first as it
     specifies how long the annotation is so how many bytes of styling to read.
     Setting an annotation will cause a
     <a class="message" href="#SC_MOD_CHANGEANNOTATION"><code>SC_MOD_CHANGEANNOTATION</code></a>
     notification to be sent.
    </p>
    <p>
    The number of lines annotating a line can be retrieved with <code>SCI_ANNOTATIONGETLINES</code>.
    All the lines can be cleared of annotations with <code>SCI_ANNOTATIONCLEARALL</code>
    which is equivalent to clearing each line (setting to 0) and then deleting other memory used for this feature.
    </p>
    <p>
    Only some style attributes are active in annotations: font, size/sizeFractional, bold/weight, italics, fore, back, and characterSet.
    </p>
    <p>
     <b id="SCI_ANNOTATIONSETVISIBLE">SCI_ANNOTATIONSETVISIBLE(int visible)</b><br />
     <b id="SCI_ANNOTATIONGETVISIBLE">SCI_ANNOTATIONGETVISIBLE</b><br />
     Annotations can be made visible in a view and there is a choice of display style when visible.
     The two messages set and get the annotation display mode. The <code>visible</code>
     argument can be one of:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Annotation visibility">
      <tbody valign="top">
        <tr>
          <th align="left"><code>ANNOTATION_HIDDEN</code></th>

          <td>0</td>

          <td>Annotations are not displayed.</td>
        </tr>

        <tr>
          <th align="left"><code>ANNOTATION_STANDARD</code></th>

          <td>1</td>

          <td>Annotations are drawn left justified with no adornment.</td>
        </tr>

        <tr>
          <th align="left"><code>ANNOTATION_BOXED</code></th>

          <td>2</td>

          <td>Annotations are indented to match the text and are surrounded by a box.</td>
        </tr>
      </tbody>
    </table>

    <p>
     <b id="SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET(int style)</b><br />
     <b id="SCI_ANNOTATIONGETSTYLEOFFSET">SCI_ANNOTATIONGETSTYLEOFFSET</b><br />
    Annotation styles may be completely separated from standard text styles by setting a style offset. For example,
    <code>SCI_ANNOTATIONSETSTYLEOFFSET(512)</code> would allow the annotation styles to be numbered from
    512 upto 767 so they do not overlap styles set by lexers (or margins if margins offset is 256).
    Each style number set with <code>SCI_ANNOTATIONSETSTYLE</code>
    or <code>SCI_ANNOTATIONSETSTYLES</code> has the offset added before looking up the style.
    </p>
    <p>
    Always call <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES</a>
    before <code>SCI_ANNOTATIONSETSTYLEOFFSET</code> and use the result as the argument to <code>SCI_ANNOTATIONSETSTYLEOFFSET</code>.
    </p>

    <h2 id="OtherSettings">Other settings</h2>
    <code><a class="message" href="#SCI_SETUSEPALETTE">SCI_SETUSEPALETTE(bool
    allowPaletteUse)</a><br />
     <a class="message" href="#SCI_GETUSEPALETTE">SCI_GETUSEPALETTE</a><br />
     <a class="message" href="#SCI_SETBUFFEREDDRAW">SCI_SETBUFFEREDDRAW(bool isBuffered)</a><br />
     <a class="message" href="#SCI_GETBUFFEREDDRAW">SCI_GETBUFFEREDDRAW</a><br />
     <a class="message" href="#SCI_SETTWOPHASEDRAW">SCI_SETTWOPHASEDRAW(bool twoPhase)</a><br />
     <a class="message" href="#SCI_GETTWOPHASEDRAW">SCI_GETTWOPHASEDRAW</a><br />
     <a class="message" href="#SCI_SETTECHNOLOGY">SCI_SETTECHNOLOGY(int technology)</a><br />
     <a class="message" href="#SCI_GETTECHNOLOGY">SCI_GETTECHNOLOGY</a><br />
     <a class="message" href="#SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</a><br />
     <a class="message" href="#SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</a><br />
     <a class="message" href="#SCI_SETCODEPAGE">SCI_SETCODEPAGE(int codePage)</a><br />
     <a class="message" href="#SCI_GETCODEPAGE">SCI_GETCODEPAGE</a><br />
     <a class="message" href="#SCI_SETKEYSUNICODE">SCI_SETKEYSUNICODE(bool keysUnicode)</a><br />
     <a class="message" href="#SCI_GETKEYSUNICODE">SCI_GETKEYSUNICODE</a><br />
     <a class="message" href="#SCI_SETWORDCHARS">SCI_SETWORDCHARS(&lt;unused&gt;, const char *characters)</a><br />
     <a class="message" href="#SCI_GETWORDCHARS">SCI_GETWORDCHARS(&lt;unused&gt;, char *characters)</a><br />
     <a class="message" href="#SCI_SETWHITESPACECHARS">SCI_SETWHITESPACECHARS(&lt;unused&gt;, const char *characters)</a><br />
     <a class="message" href="#SCI_GETWHITESPACECHARS">SCI_GETWHITESPACECHARS(&lt;unused&gt;, char *characters)</a><br />
     <a class="message" href="#SCI_SETPUNCTUATIONCHARS">SCI_SETPUNCTUATIONCHARS(&lt;unused&gt;, const char *characters)</a><br />
     <a class="message" href="#SCI_GETPUNCTUATIONCHARS">SCI_GETPUNCTUATIONCHARS(&lt;unused&gt;, char *characters)</a><br />
     <a class="message" href="#SCI_SETCHARSDEFAULT">SCI_SETCHARSDEFAULT</a><br />
     <a class="message" href="#SCI_GRABFOCUS">SCI_GRABFOCUS</a><br />
     <a class="message" href="#SCI_SETFOCUS">SCI_SETFOCUS(bool focus)</a><br />
     <a class="message" href="#SCI_GETFOCUS">SCI_GETFOCUS</a><br />
    </code>

    <p>To forward a message <code>(WM_XXXX, WPARAM, LPARAM)</code> to Scintilla, you can use
    <code>SendMessage(hScintilla, WM_XXXX, WPARAM, LPARAM)</code> where <code>hScintilla</code> is
    the handle to the Scintilla window you created as your editor.</p>

    <p>While we are on the subject of forwarding messages in Windows, the top level window should
    forward any <code>WM_SETTINGCHANGE</code> messages to Scintilla (this is currently used to
    collect changes to mouse settings, but could be used for other user interface items in the
    future).</p>

    <p><b id="SCI_SETBUFFEREDDRAW">SCI_SETBUFFEREDDRAW(bool isBuffered)</b><br />
     <b id="SCI_GETBUFFEREDDRAW">SCI_GETBUFFEREDDRAW</b><br />
     These messages turn buffered drawing on or off and report the buffered drawing state. Buffered
    drawing draws each line into a bitmap rather than directly to the screen and then copies the
    bitmap to the screen. This avoids flickering although it does take longer. The default is for
    drawing to be buffered.</p>

    <p><b id="SCI_SETTWOPHASEDRAW">SCI_SETTWOPHASEDRAW(bool twoPhase)</b><br />
     <b id="SCI_GETTWOPHASEDRAW">SCI_GETTWOPHASEDRAW</b><br />
     Two phase drawing is a better but slower way of drawing text.
     In single phase drawing each run of characters in one style is drawn along with its background.
     If a character overhangs the end of a run, such as in "<i>V</i>_" where the
     "<i>V</i>" is in a different style from the "_", then this can cause the right hand
     side of the "<i>V</i>" to be overdrawn by the background of the "_" which
     cuts it off. Two phase drawing
     fixes this by drawing all the backgrounds first and then drawing the text in
     transparent mode. Two phase drawing may flicker more than single phase
     unless buffered drawing is on. The default is for drawing to be two phase.</p>

    <p><b id="SCI_SETTECHNOLOGY">SCI_SETTECHNOLOGY(int technology)</b><br />
     <b id="SCI_GETTECHNOLOGY">SCI_GETTECHNOLOGY</b><br />
    The technology property allows choosing between different drawing APIs and options.
    On most platforms, the only choice is <code>SC_TECHNOLOGY_DEFAULT</code> (0).
    On Windows Vista or later, <code>SC_TECHNOLOGY_DIRECTWRITE</code> (1)
    can be chosen to use the Direct2D and DirectWrite APIs for higher quality antialiased drawing.
    Since Direct2D buffers drawing, Scintilla's buffering can be turned off with
    <code>SCI_SETBUFFEREDDRAW(0)</code>.</p>

    <p><b id="SCI_SETFONTQUALITY">SCI_SETFONTQUALITY(int fontQuality)</b><br />
     <b id="SCI_GETFONTQUALITY">SCI_GETFONTQUALITY</b><br />
     Manage font quality (antialiasing method). Currently, the following values are available on Windows:
     <code>SC_EFF_QUALITY_DEFAULT</code> (backward compatible),
     <code>SC_EFF_QUALITY_NON_ANTIALIASED</code>,
     <code>SC_EFF_QUALITY_ANTIALIASED</code>,
     <code>SC_EFF_QUALITY_LCD_OPTIMIZED</code>.</p>
     <p>In case it is necessary to squeeze more options into this property, only a limited number of bits defined
     by SC_EFF_QUALITY_MASK (0xf) will be used for quality.</p>

    <p><b id="SCI_SETCODEPAGE">SCI_SETCODEPAGE(int codePage)</b><br />
     <b id="SCI_GETCODEPAGE">SCI_GETCODEPAGE</b><br />
     Scintilla has some support for Japanese, Chinese and Korean DBCS. Use this message with
    <code>codePage</code> set to the code page number to set Scintilla to use code page information
    to ensure double byte characters are treated as one character rather than two. This also stops
    the caret from moving between the two bytes in a double byte character.
    Do not use this message to choose between different single byte character sets: it doesn't do that.
    Call with
    <code>codePage</code> set to zero to disable DBCS support. The default is
    <code>SCI_SETCODEPAGE(0)</code>.</p>

    <p>Code page <code>SC_CP_UTF8</code> (65001) sets Scintilla into Unicode mode with the document
    treated as a sequence of characters expressed in UTF-8. The text is converted to the platform's
    normal Unicode encoding before being drawn by the OS and thus can display Hebrew, Arabic,
    Cyrillic, and Han characters. Languages which can use two characters stacked vertically in one
    horizontal space, such as Thai, will mostly work but there are some issues where the characters
    are drawn separately leading to visual glitches. Bi-directional text is not supported. </p>

    <p>Code page can be set to 932 (Japanese Shift-JIS), 936 (Simplified Chinese GBK),
    949 (Korean Unified Hangul Code), 950 (Traditional Chinese Big5), or 1361 (Korean Johab)
    although these may require installation of language specific support.</p>

    <p><b id="SCI_SETKEYSUNICODE">SCI_SETKEYSUNICODE(bool keysUnicode)</b><br />
     <b id="SCI_GETKEYSUNICODE">SCI_GETKEYSUNICODE</b><br />
     On Windows, character keys are normally handled differently depending on whether Scintilla is a wide
     or narrow character window with character messages treated as Unicode when wide and as 8 bit otherwise.
     Set this property to always treat as Unicode. This option is needed for Delphi.</p>

    <p><b id="SCI_SETWORDCHARS">SCI_SETWORDCHARS(&lt;unused&gt;, const char *characters)</b><br />
     Scintilla has several functions that operate on words, which are defined to be contiguous
    sequences of characters from a particular set of characters. This message defines which
    characters are members of that set. The character sets are set to default values before processing this
    function.
    For example, if you don't allow '_' in your set of characters
    use:<br />
     <code>SCI_SETWORDCHARS(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")</code>;</p>

    <p><b id="SCI_GETWORDCHARS">SCI_GETWORDCHARS(&lt;unused&gt;, char *characters)</b><br />
     This fills the characters parameter with all the characters included in words.
     The characters parameter must be large enough to hold all of the characters. 
     If the characters parameter is 0 then the length that should be allocated
     to store the entire set is returned.</p>

    <p><b id="SCI_SETWHITESPACECHARS">SCI_SETWHITESPACECHARS(&lt;unused&gt;, const char *characters)</b><br />
    <b id="SCI_GETWHITESPACECHARS">SCI_GETWHITESPACECHARS(&lt;unused&gt;, char *characters)</b><br />
     Similar to <code>SCI_SETWORDCHARS</code>, this message allows the user to define which chars Scintilla considers
          as whitespace.  Setting the whitespace chars allows the user to fine-tune Scintilla's behaviour doing
          such things as moving the cursor to the start or end of a word; for example, by defining punctuation chars
          as whitespace, they will be skipped over when the user presses ctrl+left or ctrl+right.
          This function should be called after <code>SCI_SETWORDCHARS</code> as it will
          reset the whitespace characters to the default set.
	  <code>SCI_GETWHITESPACECHARS</code> behaves similarly to <code>SCI_GETWORDCHARS</code>.</p>

    <p><b id="SCI_SETPUNCTUATIONCHARS">SCI_SETPUNCTUATIONCHARS(&lt;unused&gt;, const char *characters)</b><br />
    <b id="SCI_GETPUNCTUATIONCHARS">SCI_GETPUNCTUATIONCHARS(&lt;unused&gt;, char *characters)</b><br />
     Similar to <code>SCI_SETWORDCHARS</code> and <code>SCI_SETWHITESPACECHARS</code>, this message
     allows the user to define which chars Scintilla considers as punctuation.
	  <code>SCI_GETPUNCTUATIONCHARS</code> behaves similarly to <code>SCI_GETWORDCHARS</code>.</p>

    <p><b id="SCI_SETCHARSDEFAULT">SCI_SETCHARSDEFAULT</b><br />
     Use the default sets of word and whitespace characters. This sets whitespace to space, tab and other
     characters with codes less than 0x20, with word characters set to alphanumeric and '_'.
    </p>


    <p><b id="SCI_GRABFOCUS">SCI_GRABFOCUS</b><br />
     <b id="SCI_SETFOCUS">SCI_SETFOCUS(bool focus)</b><br />
     <b id="SCI_GETFOCUS">SCI_GETFOCUS</b><br />
     Scintilla can be told to grab the focus with this message. This is needed more on GTK+ where
           focus handling is more complicated than on Windows.</p>

    <p>The internal focus flag can be set with <code>SCI_SETFOCUS</code>. This is used by clients
    that have complex focus requirements such as having their own window that gets the real focus
    but with the need to indicate that Scintilla has the logical focus.</p>

    <h2 id="BraceHighlighting">Brace highlighting</h2>
    <code><a class="message" href="#SCI_BRACEHIGHLIGHT">SCI_BRACEHIGHLIGHT(int pos1, int
    pos2)</a><br />
     <a class="message" href="#SCI_BRACEBADLIGHT">SCI_BRACEBADLIGHT(int pos1)</a><br />
     <a class="message" href="#SCI_BRACEHIGHLIGHTINDICATOR">SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)</a><br />
     <a class="message" href="#SCI_BRACEBADLIGHTINDICATOR">SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)</a><br />
     <a class="message" href="#SCI_BRACEMATCH">SCI_BRACEMATCH(int position, int
    maxReStyle)</a><br />
    </code>

    <p><b id="SCI_BRACEHIGHLIGHT">SCI_BRACEHIGHLIGHT(int pos1, int pos2)</b><br />
     Up to two characters can be highlighted in a 'brace highlighting style', which is defined as
    style number <a class="message" href="#StyleDefinition"><code>STYLE_BRACELIGHT</code></a> (34).
    If you have enabled indent guides, you may also wish to highlight the indent that corresponds
    with the brace. You can locate the column with <a class="message"
    href="#SCI_GETCOLUMN"><code>SCI_GETCOLUMN</code></a> and highlight the indent with <a
    class="message" href="#SCI_SETHIGHLIGHTGUIDE"><code>SCI_SETHIGHLIGHTGUIDE</code></a>.</p>

    <p><b id="SCI_BRACEBADLIGHT">SCI_BRACEBADLIGHT(int pos1)</b><br />
     If there is no matching brace then the <a class="jump" href="#StyleDefinition">brace
    badlighting style</a>, style <code>STYLE_BRACEBAD</code> (35), can be used to show the brace
    that is unmatched. Using a position of <code>INVALID_POSITION</code> (-1) removes the
    highlight.</p>

    <p><b id="#SCI_BRACEHIGHLIGHTINDICATOR">SCI_BRACEHIGHLIGHTINDICATOR(bool useBraceHighlightIndicator, int indicatorNumber)</b><br />
     Use specified indicator to highlight matching braces instead of changing their style.</p>

    <p><b id="#SCI_BRACEBADLIGHTINDICATOR">SCI_BRACEBADLIGHTINDICATOR(bool useBraceBadLightIndicator, int indicatorNumber)</b><br />
     Use specified indicator to highlight non matching brace instead of changing its style.</p>

    <p><b id="SCI_BRACEMATCH">SCI_BRACEMATCH(int pos, int maxReStyle)</b><br />
     The <code>SCI_BRACEMATCH</code> message finds a corresponding matching brace given
    <code>pos</code>, the position of one brace. The brace characters handled are '(', ')', '[',
    ']', '{', '}', '&lt;', and '&gt;'. The search is forwards from an opening brace and backwards
    from a closing brace. If the character at position is not a brace character, or a matching
    brace cannot be found, the return value is -1. Otherwise, the return value is the position of
    the matching brace.</p>

    <p>A match only occurs if the style of the matching brace is the same as the starting brace or
    the matching brace is beyond the end of styling. Nested braces are handled correctly. The
    <code>maxReStyle</code> parameter must currently be 0 - it may be used in the future to limit
    the length of brace searches.</p>

    <h2 id="TabsAndIndentationGuides">Tabs and Indentation Guides</h2>

    <p>Indentation (the white space at the start of a line) is often used by programmers to clarify
    program structure and in some languages, for example Python, it may be part of the language
    syntax. Tabs are normally used in editors to insert a tab character or to pad text with spaces
    up to the next tab.</p>

    <p>Scintilla can be set to treat tab and backspace in the white space at the start of a line in
    a special way: inserting a tab indents the line to the next indent position rather than just
    inserting a tab at the current character position and backspace unindents the line rather than
    deleting a character. Scintilla can also display indentation guides (vertical lines) to help
    you to generate code.</p>
    <code><a class="message" href="#SCI_SETTABWIDTH">SCI_SETTABWIDTH(int widthInChars)</a><br />
     <a class="message" href="#SCI_GETTABWIDTH">SCI_GETTABWIDTH</a><br />
     <a class="message" href="#SCI_SETUSETABS">SCI_SETUSETABS(bool useTabs)</a><br />
     <a class="message" href="#SCI_GETUSETABS">SCI_GETUSETABS</a><br />
     <a class="message" href="#SCI_SETINDENT">SCI_SETINDENT(int widthInChars)</a><br />
     <a class="message" href="#SCI_GETINDENT">SCI_GETINDENT</a><br />
     <a class="message" href="#SCI_SETTABINDENTS">SCI_SETTABINDENTS(bool tabIndents)</a><br />
     <a class="message" href="#SCI_GETTABINDENTS">SCI_GETTABINDENTS</a><br />
     <a class="message" href="#SCI_SETBACKSPACEUNINDENTS">SCI_SETBACKSPACEUNINDENTS(bool
    bsUnIndents)</a><br />
     <a class="message" href="#SCI_GETBACKSPACEUNINDENTS">SCI_GETBACKSPACEUNINDENTS</a><br />
     <a class="message" href="#SCI_SETLINEINDENTATION">SCI_SETLINEINDENTATION(int line, int
    indentation)</a><br />
     <a class="message" href="#SCI_GETLINEINDENTATION">SCI_GETLINEINDENTATION(int line)</a><br />
     <a class="message" href="#SCI_GETLINEINDENTPOSITION">SCI_GETLINEINDENTPOSITION(int
    line)</a><br />
     <a class="message" href="#SCI_SETINDENTATIONGUIDES">SCI_SETINDENTATIONGUIDES(int indentView)</a><br />
     <a class="message" href="#SCI_GETINDENTATIONGUIDES">SCI_GETINDENTATIONGUIDES</a><br />
     <a class="message" href="#SCI_SETHIGHLIGHTGUIDE">SCI_SETHIGHLIGHTGUIDE(int column)</a><br />
     <a class="message" href="#SCI_GETHIGHLIGHTGUIDE">SCI_GETHIGHLIGHTGUIDE</a><br />
    </code>

    <p><b id="SCI_SETTABWIDTH">SCI_SETTABWIDTH(int widthInChars)</b><br />
     <b id="SCI_GETTABWIDTH">SCI_GETTABWIDTH</b><br />
     <code>SCI_SETTABWIDTH</code> sets the size of a tab as a multiple of the size of a space
    character in <code>STYLE_DEFAULT</code>. The default tab width is 8 characters. There are no
    limits on tab sizes, but values less than 1 or large values may have undesirable effects.</p>

    <p><b id="SCI_SETUSETABS">SCI_SETUSETABS(bool useTabs)</b><br />
     <b id="SCI_GETUSETABS">SCI_GETUSETABS</b><br />
     <code>SCI_SETUSETABS</code> determines whether indentation should be created out of a mixture
    of tabs and spaces or be based purely on spaces. Set <code>useTabs</code> to <code>false</code>
    (0) to create all tabs and indents out of spaces. The default is <code>true</code>. You can use
    <a class="message" href="#SCI_GETCOLUMN"><code>SCI_GETCOLUMN</code></a> to get the column of a
    position taking the width of a tab into account.</p>
    <p><b id="SCI_SETINDENT">SCI_SETINDENT(int widthInChars)</b><br />
     <b id="SCI_GETINDENT">SCI_GETINDENT</b><br />
     <code>SCI_SETINDENT</code> sets the size of indentation in terms of the width of a space in <a
    class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>. If you set a width of
    0, the indent size is the same as the tab size. There are no limits on indent sizes, but values
    less than 0 or large values may have undesirable effects.
    </p>

    <p><b id="SCI_SETTABINDENTS">SCI_SETTABINDENTS(bool tabIndents)</b><br />
     <b id="SCI_GETTABINDENTS">SCI_GETTABINDENTS</b><br />
     <b id="SCI_SETBACKSPACEUNINDENTS">SCI_SETBACKSPACEUNINDENTS(bool bsUnIndents)</b><br />
     <b id="SCI_GETBACKSPACEUNINDENTS">SCI_GETBACKSPACEUNINDENTS</b><br />
    </p>

    <p>Inside indentation white space, the tab and backspace keys can be made to indent and
    unindent rather than insert a tab character or delete a character with the
    <code>SCI_SETTABINDENTS</code> and <code>SCI_SETBACKSPACEUNINDENTS</code> functions.</p>

    <p><b id="SCI_SETLINEINDENTATION">SCI_SETLINEINDENTATION(int line, int indentation)</b><br />
     <b id="SCI_GETLINEINDENTATION">SCI_GETLINEINDENTATION(int line)</b><br />
     The amount of indentation on a line can be discovered and set with
    <code>SCI_GETLINEINDENTATION</code> and <code>SCI_SETLINEINDENTATION</code>. The indentation is
    measured in character columns, which correspond to the width of space characters.</p>

    <p><b id="SCI_GETLINEINDENTPOSITION">SCI_GETLINEINDENTPOSITION(int line)</b><br />
     This returns the position at the end of indentation of a line.</p>

    <p><b id="SCI_SETINDENTATIONGUIDES">SCI_SETINDENTATIONGUIDES(int indentView)</b><br />
     <b id="SCI_GETINDENTATIONGUIDES">SCI_GETINDENTATIONGUIDES</b><br />
     Indentation guides are dotted vertical lines that appear within indentation white space every
    indent size columns. They make it easy to see which constructs line up especially when they
    extend over multiple pages. Style <a class="message"
    href="#StyleDefinition"><code>STYLE_INDENTGUIDE</code></a> (37) is used to specify the
    foreground and background colour of the indentation guides.</p>

    <p>There are 4 indentation guide views.
    SC_IV_NONE turns the feature off but the other 3 states determine how far the guides appear on
    empty lines. </p>
    <table border="0" summary="Search flags">
      <tbody>
        <tr>
          <td><code>SC_IV_NONE</code></td>
          <td>No indentation guides are shown.</td>
        </tr>

        <tr>
          <td><code>SC_IV_REAL</code></td>
          <td>Indentation guides are shown inside real indentation white space.</td>
        </tr>

        <tr>
          <td><code>SC_IV_LOOKFORWARD</code></td>
          <td>Indentation guides are shown beyond the actual indentation up to the level of the
          next non-empty line.
          If the previous non-empty line was a fold header then indentation guides are shown for
          one more level of indent than that line. This setting is good for Python.</td>
        </tr>

        <tr>
          <td><code>SC_IV_LOOKBOTH</code></td>
          <td>Indentation guides are shown beyond the actual indentation up to the level of the
          next non-empty line or previous non-empty line whichever is the greater.
          This setting is good for most languages.</td>
        </tr>

      </tbody>
    </table>

    <p><b id="SCI_SETHIGHLIGHTGUIDE">SCI_SETHIGHLIGHTGUIDE(int column)</b><br />
     <b id="SCI_GETHIGHLIGHTGUIDE">SCI_GETHIGHLIGHTGUIDE</b><br />
     When brace highlighting occurs, the indentation guide corresponding to the braces may be
    highlighted with the brace highlighting style, <a class="message"
    href="#StyleDefinition"><code>STYLE_BRACELIGHT</code></a> (34). Set <code>column</code> to 0 to
    cancel this highlight.</p>

    <h2 id="Markers">Markers</h2>

    <p>There are 32 markers, numbered 0 to <code>MARKER_MAX</code> (31), and you can assign any combination of them to each
    line in the document. Markers appear in the <a class="jump" href="#Margins">selection
    margin</a> to the left of the text. If the selection margin is set to zero width, the
    background colour of the whole line is changed instead. Marker numbers 25 to 31 are used by
    Scintilla in folding margins, and have symbolic names of the form <code>SC_MARKNUM_</code>*,
    for example <code>SC_MARKNUM_FOLDEROPEN</code>.</p>

    <p>Marker numbers 0 to 24 have no pre-defined function; you can use them to mark syntax errors
    or the current point of execution, break points, or whatever you need marking. If you do not
    need folding, you can use all 32 for any purpose you wish.</p>

    <p>Each marker number has a symbol associated with it. You can also set the foreground and
    background colour for each marker number, so you can use the same symbol more than once with
    different colouring for different uses. Scintilla has a set of symbols you can assign
    (<code>SC_MARK_</code>*) or you can use characters. By default, all 32 markers are set to
    <code>SC_MARK_CIRCLE</code> with a black foreground and a white background.</p>

    <p>The markers are drawn in the order of their numbers, so higher numbered markers appear on
    top of lower numbered ones. Markers try to move with their text by tracking where the start of
    their line moves. When a line is deleted, its markers are combined, by an <code>OR</code>
    operation, with the markers of the previous line.</p>
    <code><a class="message" href="#SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int
    markerSymbols)</a><br />
     <a class="message" href="#SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber,
    const char *xpm)</a><br />
     <a class="message" href="#SCI_RGBAIMAGESETWIDTH">SCI_RGBAIMAGESETWIDTH(int width)</a><br />
     <a class="message" href="#SCI_RGBAIMAGESETHEIGHT">SCI_RGBAIMAGESETHEIGHT(int height)</a><br />
     <a class="message" href="#SCI_RGBAIMAGESETSCALE">SCI_RGBAIMAGESETSCALE(int scalePercent)</a><br />
     <a class="message" href="#SCI_MARKERDEFINERGBAIMAGE">SCI_MARKERDEFINERGBAIMAGE(int markerNumber,
    const char *pixels)</a><br />
     <a class="message" href="#SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)
     </a><br />
     <a class="message" href="#SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int
    colour)</a><br />
     <a class="message" href="#SCI_MARKERSETBACK">SCI_MARKERSETBACK(int markerNumber, int
    colour)</a><br />
    <a class="message" href="#SCI_MARKERSETBACKSELECTED">SCI_MARKERSETBACKSELECTED(int markerNumber, int
    colour)</a><br />
    <a class="message" href="#SCI_MARKERENABLEHIGHLIGHT">SCI_MARKERENABLEHIGHLIGHT(int enabled)</a><br />
     <a class="message" href="#SCI_MARKERSETALPHA">SCI_MARKERSETALPHA(int markerNumber, int
    alpha)</a><br />
     <a class="message" href="#SCI_MARKERADD">SCI_MARKERADD(int line, int markerNumber)</a><br />
     <a class="message" href="#SCI_MARKERADDSET">SCI_MARKERADDSET(int line, int markerMask)</a><br />
     <a class="message" href="#SCI_MARKERDELETE">SCI_MARKERDELETE(int line, int
    markerNumber)</a><br />
     <a class="message" href="#SCI_MARKERDELETEALL">SCI_MARKERDELETEALL(int markerNumber)</a><br />
     <a class="message" href="#SCI_MARKERGET">SCI_MARKERGET(int line)</a><br />
     <a class="message" href="#SCI_MARKERNEXT">SCI_MARKERNEXT(int lineStart, int
    markerMask)</a><br />
     <a class="message" href="#SCI_MARKERPREVIOUS">SCI_MARKERPREVIOUS(int lineStart, int
    markerMask)</a><br />
     <a class="message" href="#SCI_MARKERLINEFROMHANDLE">SCI_MARKERLINEFROMHANDLE(int
    handle)</a><br />
     <a class="message" href="#SCI_MARKERDELETEHANDLE">SCI_MARKERDELETEHANDLE(int handle)</a><br />
    </code>

    <p><b id="SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int markerSymbols)</b><br />
     This message associates a marker number in the range 0 to 31 with one of the marker symbols or
    an ASCII character. The general-purpose marker symbols currently available are:<br />
     <code>SC_MARK_CIRCLE</code>, <code>SC_MARK_ROUNDRECT</code>, <code>SC_MARK_ARROW</code>,
    <code>SC_MARK_SMALLRECT</code>, <code>SC_MARK_SHORTARROW</code>, <code>SC_MARK_EMPTY</code>,
    <code>SC_MARK_ARROWDOWN</code>, <code>SC_MARK_MINUS</code>, <code>SC_MARK_PLUS</code>,
    <code>SC_MARK_ARROWS</code>, <code>SC_MARK_DOTDOTDOT</code>,
    <code>SC_MARK_BACKGROUND</code>, <code>SC_MARK_LEFTRECT</code>,
    <code>SC_MARK_FULLRECT</code>, and <code>SC_MARK_UNDERLINE</code>.</p>

    <p>The <code>SC_MARK_BACKGROUND</code> marker changes the background colour of the line only.
          The <code>SC_MARK_FULLRECT</code> symbol mirrors this, changing only the margin background colour.
          <code>SC_MARK_UNDERLINE</code> draws an underline across the text.
    The <code>SC_MARK_EMPTY</code> symbol is invisible, allowing client code to track the movement
    of lines. You would also use it if you changed the folding style and wanted one or more of the
    <code>SC_FOLDERNUM_</code>* markers to have no associated symbol.</p>

    <p>Applications may use the marker symbol <code>SC_MARK_AVAILABLE</code> to indicate that
    plugins may allocate that marker number.
    </p>

    <p>There are also marker symbols designed for use in the folding margin in a flattened tree
    style.<br />
     <code>SC_MARK_BOXMINUS</code>, <code>SC_MARK_BOXMINUSCONNECTED</code>,
    <code>SC_MARK_BOXPLUS</code>, <code>SC_MARK_BOXPLUSCONNECTED</code>,
    <code>SC_MARK_CIRCLEMINUS</code>, <code>SC_MARK_CIRCLEMINUSCONNECTED</code>,
    <code>SC_MARK_CIRCLEPLUS</code>, <code>SC_MARK_CIRCLEPLUSCONNECTED</code>,
    <code>SC_MARK_LCORNER</code>, <code>SC_MARK_LCORNERCURVE</code>, <code>SC_MARK_TCORNER</code>,
    <code>SC_MARK_TCORNERCURVE</code>, and <code>SC_MARK_VLINE</code>.</p>
     Characters can be used as markers by adding the ASCII value of the character to
    <code>SC_MARK_CHARACTER</code> (10000). For example, to use 'A' (ASCII code 65) as marker
    number 1 use:<br />
     <code>SCI_MARKERDEFINE(1, SC_MARK_CHARACTER+65)</code>. <br />

    <p>The marker numbers <code>SC_MARKNUM_FOLDER</code> and <code>SC_MARKNUM_FOLDEROPEN</code> are
    used for showing that a fold is present and open or closed. Any symbols may be assigned for
    this purpose although the (<code>SC_MARK_PLUS</code>, <code>SC_MARK_MINUS</code>) pair or the
    (<code>SC_MARK_ARROW</code>, <code>SC_MARK_ARROWDOWN</code>) pair are good choices. As well as
    these two, more assignments are needed for the flattened tree style:
    <code>SC_MARKNUM_FOLDEREND</code>, <code>SC_MARKNUM_FOLDERMIDTAIL</code>,
    <code>SC_MARKNUM_FOLDEROPENMID</code>, <code>SC_MARKNUM_FOLDERSUB</code>, and
    <code>SC_MARKNUM_FOLDERTAIL</code>. The bits used for folding are specified by
    <code>SC_MASK_FOLDERS</code>, which is commonly used as an argument to
    <code>SCI_SETMARGINMASKN</code> when defining a margin to be used for folding.</p>

    <p>This table shows which <code>SC_MARK_</code>* symbols should be assigned to which
    <code>SC_MARKNUM_</code>* marker numbers to obtain four folding styles: Arrow (mimics
    Macintosh), plus/minus shows folded lines as '+' and opened folds as '-', Circle tree, Box
    tree.</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Markers used for folding">
      <thead align="left">
        <tr>
          <th><code>SC_MARKNUM_</code>*</th>

          <th>Arrow</th>

          <th>Plus/minus</th>

          <th>Circle tree</th>

          <th>Box tree</th>
        </tr>
      </thead>

      <tbody valign="top">
        <tr>
          <th align="left"><code>FOLDEROPEN</code></th>

          <td><code>ARROWDOWN</code></td>

          <td><code>MINUS</code></td>

          <td><code>CIRCLEMINUS</code></td>

          <td><code>BOXMINUS</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDER</code></th>

          <td><code>ARROW</code></td>

          <td><code>PLUS</code></td>

          <td><code>CIRCLEPLUS</code></td>

          <td><code>BOXPLUS</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDERSUB</code></th>

          <td><code>EMPTY</code></td>

          <td><code>EMPTY</code></td>

          <td><code>VLINE</code></td>

          <td><code>VLINE</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDERTAIL</code></th>

          <td><code>EMPTY</code></td>

          <td><code>EMPTY</code></td>

          <td><code>LCORNERCURVE</code></td>

          <td><code>LCORNER</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDEREND</code></th>

          <td><code>EMPTY</code></td>

          <td><code>EMPTY</code></td>

          <td><code>CIRCLEPLUSCONNECTED</code></td>

          <td><code>BOXPLUSCONNECTED</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDEROPENMID</code></th>

          <td><code>EMPTY</code></td>

          <td><code>EMPTY</code></td>

          <td><code>CIRCLEMINUSCONNECTED</code></td>

          <td><code>BOXMINUSCONNECTED</code></td>
        </tr>

        <tr>
          <th align="left"><code>FOLDERMIDTAIL</code></th>

          <td><code>EMPTY</code></td>

          <td><code>EMPTY</code></td>

          <td><code>TCORNERCURVE</code></td>

          <td><code>TCORNER</code></td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_MARKERDEFINEPIXMAP">SCI_MARKERDEFINEPIXMAP(int markerNumber, const char
    *xpm)</b><br />
     Markers can be set to pixmaps with this message. The 
     <a class="jump" href="#XPM">XPM format</a> is used for the pixmap.
    Pixmaps use the <code>SC_MARK_PIXMAP</code> marker symbol. </p>

    <p>
    <b id="SCI_RGBAIMAGESETWIDTH">SCI_RGBAIMAGESETWIDTH(int width)</b><br />
    <b id="SCI_RGBAIMAGESETHEIGHT">SCI_RGBAIMAGESETHEIGHT(int height)</b><br />
    <b id="SCI_RGBAIMAGESETSCALE">SCI_RGBAIMAGESETSCALE(int scalePercent)</b><br />
    <b id="SCI_MARKERDEFINERGBAIMAGE">SCI_MARKERDEFINERGBAIMAGE(int markerNumber, const char *pixels)</b><br />
     Markers can be set to translucent pixmaps with this message. The 
     <a class="jump" href="#RGBA">RGBA format</a> is used for the pixmap.
     The width and height must previously been set with the <code>SCI_RGBAIMAGESETWIDTH</code> and 
     <code>SCI_RGBAIMAGESETHEIGHT</code> messages.</p>
     <p>A scale factor in percent may be set with <code>SCI_RGBAIMAGESETSCALE</code>. This is useful on OS X with
     a retina display where each display unit is 2 pixels: use a factor of 200 so that each image pixel is dsplayed using a screen pixel.
     The default scale, 100, will stretch each image pixel to cover 4 screen pixels on a retina display.</p>
    <p>Pixmaps use the <code>SC_MARK_RGBAIMAGE</code> marker symbol. </p>

    <p><b id="SCI_MARKERSYMBOLDEFINED">SCI_MARKERSYMBOLDEFINED(int markerNumber)</b><br />
     Returns the symbol defined for a markerNumber with <code>SCI_MARKERDEFINE</code>
     or <code>SC_MARK_PIXMAP</code> if defined with <code>SCI_MARKERDEFINEPIXMAP</code>
     or <code>SC_MARK_RGBAIMAGE</code> if defined with <code>SCI_MARKERDEFINERGBAIMAGE</code>.</p>

    <p><b id="SCI_MARKERSETFORE">SCI_MARKERSETFORE(int markerNumber, int <a class="jump"
    href="#colour">colour</a>)</b><br />
     <b id="SCI_MARKERSETBACK">SCI_MARKERSETBACK(int markerNumber, int <a class="jump"
    href="#colour">colour</a>)</b><br />
     These two messages set the foreground and background colour of a marker number.<br />
     <b id="SCI_MARKERSETBACKSELECTED">SCI_MARKERSETBACKSELECTED(int markerNumber, int <a class="jump"
    href="#colour">colour</a>)</b><br />
     This message sets the highlight background colour of a marker number when its folding block is selected. The default colour is #FF0000.</p>
     <p><b id="SCI_MARKERENABLEHIGHLIGHT">SCI_MARKERENABLEHIGHLIGHT(bool enabled)</b><br />
     This message allows to enable/disable the highlight folding block when it is selected. (i.e. block that contains the caret)</p>
     <p><b id="SCI_MARKERSETALPHA">SCI_MARKERSETALPHA(int markerNumber, int <a class="jump"
    href="#alpha">alpha</a>)</b><br />
     When markers are drawn in the content area, either because there is no margin for them or
     they are of <code>SC_MARK_BACKGROUND</code> or <code>SC_MARK_UNDERLINE</code> types, they may be drawn translucently by
     setting an alpha value.</p>

    <p><b id="SCI_MARKERADD">SCI_MARKERADD(int line, int markerNumber)</b><br />
     This message adds marker number <code>markerNumber</code> to a line. The message returns -1 if
    this fails (illegal line number, out of memory) or it returns a marker handle number that
    identifies the added marker. You can use this returned handle with <a class="message"
    href="#SCI_MARKERLINEFROMHANDLE"><code>SCI_MARKERLINEFROMHANDLE</code></a> to find where a
    marker is after moving or combining lines and with <a class="message"
    href="#SCI_MARKERDELETEHANDLE"><code>SCI_MARKERDELETEHANDLE</code></a> to delete the marker
    based on its handle. The message does not check the value of markerNumber, nor does it
    check if the line already contains the marker.</p>

    <p><b id="SCI_MARKERADDSET">SCI_MARKERADDSET(int line, int markerMask)</b><br />
     This message can add one or more markers to a line with a single call, specified in the same "one-bit-per-marker" 32-bit integer format returned by
    <a class="message" href="#SCI_MARKERGET"><code>SCI_MARKERGET</code></a>
    (and used by the mask-based marker search functions
    <a class="message" href="#SCI_MARKERNEXT"><code>SCI_MARKERNEXT</code></a> and
    <a class="message" href="#SCI_MARKERPREVIOUS"><code>SCI_MARKERPREVIOUS</code></a>).
    As with
    <a class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>, no check is made
    to see if any of the markers are already present on the targeted line.</p>

    <p><b id="SCI_MARKERDELETE">SCI_MARKERDELETE(int line, int markerNumber)</b><br />
     This searches the given line number for the given marker number and deletes it if it is
    present. If you added the same marker more than once to the line, this will delete one copy
    each time it is used. If you pass in a marker number of -1, all markers are deleted from the
    line.</p>

    <p><b id="SCI_MARKERDELETEALL">SCI_MARKERDELETEALL(int markerNumber)</b><br />
     This removes markers of the given number from all lines. If markerNumber is -1, it deletes all
    markers from all lines.</p>

    <p><b id="SCI_MARKERGET">SCI_MARKERGET(int line)</b><br />
     This returns a 32-bit integer that indicates which markers were present on the line. Bit 0 is
    set if marker 0 is present, bit 1 for marker 1 and so on.</p>

    <p><b id="SCI_MARKERNEXT">SCI_MARKERNEXT(int lineStart, int markerMask)</b><br />
     <b id="SCI_MARKERPREVIOUS">SCI_MARKERPREVIOUS(int lineStart, int markerMask)</b><br />
     These messages search efficiently for lines that include a given set of markers. The search
    starts at line number <code>lineStart</code> and continues forwards to the end of the file
    (<code>SCI_MARKERNEXT</code>) or backwards to the start of the file
    (<code>SCI_MARKERPREVIOUS</code>). The <code>markerMask</code> argument should have one bit set
    for each marker you wish to find. Set bit 0 to find marker 0, bit 1 for marker 1 and so on. The
    message returns the line number of the first line that contains one of the markers in
    <code>markerMask</code> or -1 if no marker is found.</p>

    <p><b id="SCI_MARKERLINEFROMHANDLE">SCI_MARKERLINEFROMHANDLE(int markerHandle)</b><br />
     The <code>markerHandle</code> argument is an identifier for a marker returned by <a
    class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. This function searches
    the document for the marker with this handle and returns the line number that contains it or -1
    if it is not found.</p>

    <p><b id="SCI_MARKERDELETEHANDLE">SCI_MARKERDELETEHANDLE(int markerHandle)</b><br />
     The <code>markerHandle</code> argument is an identifier for a marker returned by <a
    class="message" href="#SCI_MARKERADD"><code>SCI_MARKERADD</code></a>. This function searches
    the document for the marker with this handle and deletes the marker if it is found.</p>

    <h2 id="Indicators">Indicators</h2>

    <p>Indicators are used to display additional information over the top of styling.
    They can be used to show, for example, syntax errors, deprecated names and bad indentation
    by drawing underlines under text or boxes around text. Originally, Scintilla stored indicator information in
    the style bytes but this has proved limiting, so now up to 32 separately stored indicators may be used.
    While style byte indicators currently still work, they will soon be removed so all the bits in each style
    byte can be used for lexical states.</p>

    <p>Indicators may be displayed as simple underlines, squiggly underlines, a
    line of small 'T' shapes, a line of diagonal hatching, a strike-out or a rectangle around the text.</p>

    <p>The <code>SCI_INDIC*</code> messages allow you to get and set the visual appearance of the
    indicators. They all use an <code>indicatorNumber</code> argument in the range 0 to INDIC_MAX(31)
    to set the indicator to style. To prevent interference the set of indicators is divided up into a range for use
    by lexers (0..7) and a range for use by containers
    (8=<code>INDIC_CONTAINER</code> .. 31=<code>INDIC_MAX</code>).</p>

    <code><a class="message" href="#SCI_INDICSETSTYLE">SCI_INDICSETSTYLE(int indicatorNumber, int
    indicatorStyle)</a><br />
     <a class="message" href="#SCI_INDICGETSTYLE">SCI_INDICGETSTYLE(int indicatorNumber)</a><br />
     <a class="message" href="#SCI_INDICSETFORE">SCI_INDICSETFORE(int indicatorNumber, int
    colour)</a><br />
     <a class="message" href="#SCI_INDICGETFORE">SCI_INDICGETFORE(int indicatorNumber)</a><br />
     <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA(int indicatorNumber, int alpha)</a><br />
     <a class="message" href="#SCI_INDICGETALPHA">SCI_INDICGETALPHA(int indicatorNumber)</a><br />
     <a class="message" href="#SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)</a><br />
     <a class="message" href="#SCI_INDICGETOUTLINEALPHA">SCI_INDICGETOUTLINEALPHA(int indicatorNumber)</a><br />
     <a class="message" href="#SCI_INDICSETUNDER">SCI_INDICSETUNDER(int indicatorNumber, bool under)</a><br />
     <a class="message" href="#SCI_INDICGETUNDER">SCI_INDICGETUNDER(int indicatorNumber)</a><br />

     <a class="message" href="#SCI_SETINDICATORCURRENT">SCI_SETINDICATORCURRENT(int indicator)</a><br />
     <a class="message" href="#SCI_GETINDICATORCURRENT">SCI_GETINDICATORCURRENT</a><br />
     <a class="message" href="#SCI_SETINDICATORVALUE">SCI_SETINDICATORVALUE(int value)</a><br />
     <a class="message" href="#SCI_GETINDICATORVALUE">SCI_GETINDICATORVALUE</a><br />
     <a class="message" href="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE(int position, int fillLength)</a><br />
     <a class="message" href="#SCI_INDICATORCLEARRANGE">SCI_INDICATORCLEARRANGE(int position, int clearLength)</a><br />
     <a class="message" href="#SCI_INDICATORALLONFOR">SCI_INDICATORALLONFOR(int position)</a><br />
     <a class="message" href="#SCI_INDICATORVALUEAT">SCI_INDICATORVALUEAT(int indicator, int position)</a><br />
     <a class="message" href="#SCI_INDICATORSTART">SCI_INDICATORSTART(int indicator, int position)</a><br />
     <a class="message" href="#SCI_INDICATOREND">SCI_INDICATOREND(int indicator, int position)</a><br />

     <a class="message" href="#SCI_FINDINDICATORSHOW">SCI_FINDINDICATORSHOW(int start, int end)</a><br />
     <a class="message" href="#SCI_FINDINDICATORFLASH">SCI_FINDINDICATORFLASH(int start, int end)</a><br />
     <a class="message" href="#SCI_FINDINDICATORHIDE">SCI_FINDINDICATORHIDE</a><br />
    </code>

    <p><b id="SCI_INDICSETSTYLE">SCI_INDICSETSTYLE(int indicatorNumber, int
    indicatorStyle)</b><br />
     <b id="SCI_INDICGETSTYLE">SCI_INDICGETSTYLE(int indicatorNumber)</b><br />
     These two messages set and get the style for a particular indicator. The indicator styles
    currently available are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Indicators">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Visual effect</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>INDIC_PLAIN</code></td>

          <td align="center">0</td>

          <td>Underlined with a single, straight line.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_SQUIGGLE</code></td>

          <td align="center">1</td>

          <td>A squiggly underline. Requires 3 pixels of descender space.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_TT</code></td>

          <td align="center">2</td>

          <td>A line of small T shapes.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_DIAGONAL</code></td>

          <td align="center">3</td>

          <td>Diagonal hatching.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_STRIKE</code></td>

          <td align="center">4</td>

          <td>Strike out.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_HIDDEN</code></td>

          <td align="center">5</td>

          <td>An indicator with no visual effect.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_BOX</code></td>

          <td align="center">6</td>

          <td>A rectangle around the text.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_ROUNDBOX</code></td>

          <td align="center">7</td>

          <td>A rectangle with rounded corners around the text using translucent drawing with the
              interior usually more transparent than the border. You can use
              <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA</a> and
			  <a class="message" href="#SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA</a>
              to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_STRAIGHTBOX</code></td>

          <td align="center">8</td>

          <td>A rectangle around the text using translucent drawing with the
              interior usually more transparent than the border. You can use
              <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA</a> and
			  <a class="message" href="#SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA</a>
              to control the alpha transparency values. The default alpha values are 30 for fill colour and 50 for outline colour.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_DASH</code></td>

          <td align="center">9</td>

          <td>A dashed underline.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_DOTS</code></td>

          <td align="center">10</td>

          <td>A dotted underline.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_SQUIGGLELOW</code></td>

          <td align="center">11</td>

          <td>Similar to <code>INDIC_SQUIGGLE</code> but only using 2 vertical pixels
	  so will fit under small fonts.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_DOTBOX</code></td>

          <td align="center">12</td>

          <td>A dotted rectangle around the text using translucent drawing.
          Translucency alternates between the alpha and outline alpha settings with the top-left pixel using the alpha setting.
              <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA</a> and
              <a class="message" href="#SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA</a>
              control the alpha transparency values. The default values are 30 for alpha and 50 for outline alpha.
              To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels.
              Not available for OS X Carbon.</td>
        </tr>

        <tr>
          <td align="left"><code>INDIC_SQUIGGLEPIXMAP</code></td>

          <td align="center">13</td>

          <td>A version of <code>INDIC_SQUIGGLE</code> that draws using a pixmap instead of
	  as a series of line segments for performance.
	  Measured to be between 3 and 6 times faster than <code>INDIC_SQUIGGLE</code> on GTK+.
	  Apperance will not be as good as <code>INDIC_SQUIGGLE</code> on OS X in HiDPI mode.</td>
        </tr>

      </tbody>
    </table>

    <p>The default indicator styles are equivalent to:<br />
     <code>SCI_INDICSETSTYLE(0, INDIC_SQUIGGLE);</code><br />
     <code>SCI_INDICSETSTYLE(1, INDIC_TT);</code><br />
     <code>SCI_INDICSETSTYLE(2, INDIC_PLAIN);</code></p>

    <p><b id="SCI_INDICSETFORE">SCI_INDICSETFORE(int indicatorNumber, int <a class="jump" href="#colour">colour</a>)</b><br />
     <b id="SCI_INDICGETFORE">SCI_INDICGETFORE(int indicatorNumber)</b><br />
     These two messages set and get the colour used to draw an indicator. The default indicator
    colours are equivalent to:<br />
     <code>SCI_INDICSETFORE(0, 0x007f00);</code> (dark green)<br />
     <code>SCI_INDICSETFORE(1, 0xff0000);</code> (light blue)<br />
     <code>SCI_INDICSETFORE(2, 0x0000ff);</code> (light red)</p>

    <p><b id="SCI_INDICSETALPHA">SCI_INDICSETALPHA(int indicatorNumber, int alpha)</b><br />
     <b id="SCI_INDICGETALPHA">SCI_INDICGETALPHA(int indicatorNumber)</b><br />
     These two messages set and get the alpha transparency used for drawing the
     fill colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from
     0 (completely transparent) to 255 (no transparency).
     </p>

    <p><b id="SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA(int indicatorNumber, int alpha)</b><br />
     <b id="SCI_INDICGETOUTLINEALPHA">SCI_INDICGETOUTLINEALPHA(int indicatorNumber)</b><br />
     These two messages set and get the alpha transparency used for drawing the
     outline colour of the INDIC_ROUNDBOX and INDIC_STRAIGHTBOX rectangle. The alpha value can range from
     0 (completely transparent) to 255 (no transparency).
     </p>

    <p><b id="SCI_INDICSETUNDER">SCI_INDICSETUNDER(int indicatorNumber, bool under)</b><br />
     <b id="SCI_INDICGETUNDER">SCI_INDICGETUNDER(int indicatorNumber)</b><br />
     These two messages set and get whether an indicator is drawn under text or over(default).
     Drawing under text works only for modern indicators when <a class="message" href="#SCI_SETTWOPHASEDRAW">two phase drawing</a>
     is enabled.</p>

    <h3 id="ModernIndicators">Modern Indicators</h3>

    <p>Modern indicators are stored in a format similar to run length encoding which is efficient in both
    speed and storage for sparse information.</p>
    <p>An indicator may store different values for each range but currently all values are drawn the same.
    In the future, it may be possible to draw different values in different styles.</p>
    <p>
    <b id="SCI_SETINDICATORCURRENT">SCI_SETINDICATORCURRENT(int indicator)</b><br />
    <b id="SCI_GETINDICATORCURRENT">SCI_GETINDICATORCURRENT</b><br />
    These two messages set and get the indicator that will be affected by calls to
    <a class="message" href="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE(int position, int fillLength)</a> and
    <a class="message" href="#SCI_INDICATORCLEARRANGE">SCI_INDICATORCLEARRANGE(int position, int clearLength)</a>.
    </p>

    <p>
    <b id="SCI_SETINDICATORVALUE">SCI_SETINDICATORVALUE(int value)</b><br />
    <b id="SCI_GETINDICATORVALUE">SCI_GETINDICATORVALUE</b><br />
    These two messages set and get the value that will be set by calls to
    <a class="message" href="#SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE</a>.
    </p>

    <p>
    <b id="SCI_INDICATORFILLRANGE">SCI_INDICATORFILLRANGE(int position, int fillLength)</b><br />
    <b id="SCI_INDICATORCLEARRANGE">SCI_INDICATORCLEARRANGE(int position, int clearLength)</b><br />
    These two messages fill or clear a range for the current indicator.
    <code>SCI_INDICATORFILLRANGE</code> fills with the
    the current value.
    </p>

    <p>
    <b id="SCI_INDICATORALLONFOR">SCI_INDICATORALLONFOR(int position)</b><br />
    Retrieve a bitmap value representing which indicators are non-zero at a position.
    </p>

    <p>
    <b id="SCI_INDICATORVALUEAT">SCI_INDICATORVALUEAT(int indicator, int position)</b><br />
    Retrieve the value of a particular indicator at a position.
    </p>

    <p>
    <b id="SCI_INDICATORSTART">SCI_INDICATORSTART(int indicator, int position)</b><br />
    <b id="SCI_INDICATOREND">SCI_INDICATOREND(int indicator, int position)</b><br />
    Find the start or end of a range with one value from a position within the range.
    Can be used to iterate through the document to discover all the indicator positions.
    </p>

    <h3 id="FindIndicators">OS X Find Indicator</h3>

    <p>On OS X search matches are highlighted with an animated gold rounded rectangle.
    The indicator shows, then briefly grows 25% and shrinks to the original size to draw the user's attention.
    While this feature is currently only implemented on OS X, it may be implemented on other platforms
    in the future.</p>

    <p><b id="SCI_FINDINDICATORSHOW">SCI_FINDINDICATORSHOW(int start, int end)</b><br />
     <b id="SCI_FINDINDICATORFLASH">SCI_FINDINDICATORFLASH(int start, int end)</b><br />
     These two messages show and animate the find indicator. The indicator remains visible with
     <code>SCI_FINDINDICATORSHOW</code> and fades out after showing for half a second with 
     <code>SCI_FINDINDICATORFLASH</code>.
     <code>SCI_FINDINDICATORSHOW</code> behaves similarly to the OS X TextEdit and Safari applications
     and is best suited to editing documentation where the search target is often a word.
     <code>SCI_FINDINDICATORFLASH</code> is similar to Xcode and is suited to editing source code
     where the match will often be located next to operators which would otherwise be hidden under the indicator's
     padding.
     </p>

    <p><b id="SCI_FINDINDICATORHIDE">SCI_FINDINDICATORHIDE</b><br />
     This message hides the find indicator.
     </p>

    <h3 id="StyleByteIndicators">Style Byte Indicators (deprecated)</h3>
    <p>By default, Scintilla organizes the style byte associated with each text byte as 5 bits of
    style information (for 32 styles) and 3 bits of indicator information for 3 independent
    indicators so that, for example, syntax errors, deprecated names and bad indentation could all
    be displayed at once.</p>

    <p>The indicators are set using <a class="message"
    href="#SCI_STARTSTYLING"><code>SCI_STARTSTYLING</code></a> with a <code>INDICS_MASK</code> mask
    and <a class="message" href="#SCI_SETSTYLING"><code>SCI_SETSTYLING</code></a> with the values
    <code>INDIC0_MASK</code>, <code>INDIC1_MASK</code> and <code>INDIC2_MASK</code>.</p>

          <p>If you are using indicators in a buffer that has a lexer active
          (see <a class="message" href="#SCI_SETLEXER"><code>SCI_SETLEXER</code></a>),
          you must save lexing state information before setting any indicators and restore it afterwards.
          Use <a class="message" href="#SCI_GETENDSTYLED"><code>SCI_GETENDSTYLED</code></a>
          to retrieve the current "styled to" position and
          <a class="message" href="#SCI_STARTSTYLING"><code>SCI_STARTSTYLING</code></a>
        to reset the styling position and mask (<code>0x1f </code> in the default layout of 5 style bits and 3 indicator bits)
        when you are done.</p>

    <p>The number of bits used for styles can be altered with <a class="message"
    href="#SCI_SETSTYLEBITS"><code>SCI_SETSTYLEBITS</code></a> from 0 to 8 bits. The remaining bits
    can be used for indicators, so there can be from 1 to 8 indicators. However, the
    <code>INDIC*_MASK</code> constants defined in <code>Scintilla.h</code> all assume 5 bits of
    styling information and 3 indicators. If you use a different arrangement, you must define your
    own constants.</p>


    <h2 id="Autocompletion">Autocompletion</h2>

    <p>Autocompletion displays a list box showing likely identifiers based upon the user's typing.
    The user chooses the currently selected item by pressing the tab character or another character
    that is a member of the fillup character set defined with <code>SCI_AUTOCSETFILLUPS</code>.
    Autocompletion is triggered by your application. For example, in C if you detect that the user
    has just typed <code>fred.</code> you could look up <code>fred</code>, and if it has a known
    list of members, you could offer them in an autocompletion list. Alternatively, you could
    monitor the user's typing and offer a list of likely items once their typing has narrowed down
    the choice to a reasonable list. As yet another alternative, you could define a key code to
    activate the list.</p>

    <p>When the user makes a selection from the list the container is sent a <code><a class="message"
    href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a></code> <a class="jump"
    href="#Notifications">notification message</a>. On return from the notification Scintilla will insert
     the selected text unless the autocompletion list has been cancelled, for example by the container sending
     <code><a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a></code>.</p>

    <p>To make use of autocompletion you must monitor each character added to the document. See
    <code>SciTEBase::CharAdded()</code> in SciTEBase.cxx for an example of autocompletion.</p>
    <code><a class="message" href="#SCI_AUTOCSHOW">SCI_AUTOCSHOW(int lenEntered, const char
    *list)</a><br />
     <a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a><br />
     <a class="message" href="#SCI_AUTOCACTIVE">SCI_AUTOCACTIVE</a><br />
     <a class="message" href="#SCI_AUTOCPOSSTART">SCI_AUTOCPOSSTART</a><br />
     <a class="message" href="#SCI_AUTOCCOMPLETE">SCI_AUTOCCOMPLETE</a><br />
     <a class="message" href="#SCI_AUTOCSTOPS">SCI_AUTOCSTOPS(&lt;unused&gt;, const char
    *chars)</a><br />
     <a class="message" href="#SCI_AUTOCSETSEPARATOR">SCI_AUTOCSETSEPARATOR(char
    separator)</a><br />
     <a class="message" href="#SCI_AUTOCGETSEPARATOR">SCI_AUTOCGETSEPARATOR</a><br />
     <a class="message" href="#SCI_AUTOCSELECT">SCI_AUTOCSELECT(&lt;unused&gt;, const char
    *select)</a><br />
     <a class="message" href="#SCI_AUTOCGETCURRENT">SCI_AUTOCGETCURRENT</a><br />
     <a class="message" href="#SCI_AUTOCGETCURRENTTEXT">SCI_AUTOCGETCURRENTTEXT(&lt;unused&gt;,
     char *text)</a><br />
     <a class="message" href="#SCI_AUTOCSETCANCELATSTART">SCI_AUTOCSETCANCELATSTART(bool
    cancel)</a><br />
     <a class="message" href="#SCI_AUTOCGETCANCELATSTART">SCI_AUTOCGETCANCELATSTART</a><br />
     <a class="message" href="#SCI_AUTOCSETFILLUPS">SCI_AUTOCSETFILLUPS(&lt;unused&gt;, const char
    *chars)</a><br />
     <a class="message" href="#SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE(bool
    chooseSingle)</a><br />
     <a class="message" href="#SCI_AUTOCGETCHOOSESINGLE">SCI_AUTOCGETCHOOSESINGLE</a><br />
     <a class="message" href="#SCI_AUTOCSETIGNORECASE">SCI_AUTOCSETIGNORECASE(bool
    ignoreCase)</a><br />
     <a class="message" href="#SCI_AUTOCGETIGNORECASE">SCI_AUTOCGETIGNORECASE</a><br />
     <a class="message" href="#SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR(int behaviour)</a><br>
     <a class="message" href="#SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR</a><br>
     <a class="message" href="#SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</a><br />
     <a class="message" href="#SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</a><br />
     <a class="message" href="#SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool
    dropRestOfWord)</a><br />
     <a class="message" href="#SCI_AUTOCGETDROPRESTOFWORD">SCI_AUTOCGETDROPRESTOFWORD</a><br />
     <a class="message" href="#SCI_REGISTERIMAGE">SCI_REGISTERIMAGE(int type, const char *xpmData)</a><br />
     <a class="message" href="#SCI_REGISTERRGBAIMAGE">SCI_REGISTERRGBAIMAGE(int type, const char *pixels)</a><br />
     <a class="message" href="#SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</a><br />
     <a class="message" href="#SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</a><br />
     <a class="message" href="#SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</a><br />
     <a class="message" href="#SCI_AUTOCSETMAXHEIGHT">SCI_AUTOCSETMAXHEIGHT(int rowCount)</a><br />
     <a class="message" href="#SCI_AUTOCGETMAXHEIGHT">SCI_AUTOCGETMAXHEIGHT</a><br />
     <a class="message" href="#SCI_AUTOCSETMAXWIDTH">SCI_AUTOCSETMAXWIDTH(int characterCount)</a><br />
     <a class="message" href="#SCI_AUTOCGETMAXWIDTH">SCI_AUTOCGETMAXWIDTH</a><br />
    </code>

    <p><b id="SCI_AUTOCSHOW">SCI_AUTOCSHOW(int lenEntered, const char *list)</b><br />
     This message causes a list to be displayed. <code>lenEntered</code> is the number of
    characters of the word already entered and <code>list</code> is the list of words separated by
    separator characters. The initial separator character is a space but this can be set or got
    with <a class="message" href="#SCI_AUTOCSETSEPARATOR"><code>SCI_AUTOCSETSEPARATOR</code></a>
    and <a class="message"
    href="#SCI_AUTOCGETSEPARATOR"><code>SCI_AUTOCGETSEPARATOR</code></a>.</p>

    <p>The list of words should be in sorted order. If set to ignore case mode with <a class="message" href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>, then
    strings are matched after being converted to upper case. One result of this is that the list
    should be sorted with the punctuation characters '[', '\', ']', '^', '_', and '`' sorted after
    letters.</p>

    <p><b id="SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</b><br />
     This message cancels any displayed autocompletion list. When in autocompletion mode, the list
    should disappear when the user types a character that can not be part of the autocompletion,
    such as '.', '(' or '[' when typing an identifier. A set of characters that will cancel
    autocompletion can be specified with <a class="message"
    href="#SCI_AUTOCSTOPS"><code>SCI_AUTOCSTOPS</code></a>.</p>

    <p><b id="SCI_AUTOCACTIVE">SCI_AUTOCACTIVE</b><br />
     This message returns non-zero if there is an active autocompletion list and zero if there is
    not.</p>

    <p><b id="SCI_AUTOCPOSSTART">SCI_AUTOCPOSSTART</b><br />
     This returns the value of the current position when <code>SCI_AUTOCSHOW</code> started display
    of the list.</p>

    <p><b id="SCI_AUTOCCOMPLETE">SCI_AUTOCCOMPLETE</b><br />
     This message triggers autocompletion. This has the same effect as the tab key.</p>

    <p><b id="SCI_AUTOCSTOPS">SCI_AUTOCSTOPS(&lt;unused&gt;, const char *chars)</b><br />
     The <code>chars</code> argument is a string containing a list of characters that will
    automatically cancel the autocompletion list. When you start the editor, this list is
    empty.</p>

    <p><b id="SCI_AUTOCSETSEPARATOR">SCI_AUTOCSETSEPARATOR(char separator)</b><br />
     <b id="SCI_AUTOCGETSEPARATOR">SCI_AUTOCGETSEPARATOR</b><br />
     These two messages set and get the separator character used to separate words in the
    <code>SCI_AUTOCSHOW</code> list. The default is the space character.</p>

    <p><b id="SCI_AUTOCSELECT">SCI_AUTOCSELECT(&lt;unused&gt;, const char *select)</b><br />
     <b id="SCI_AUTOCGETCURRENT">SCI_AUTOCGETCURRENT</b><br />
     This message selects an item in the autocompletion list. It searches the list of words for the
    first that matches <code>select</code>. By default, comparisons are case sensitive, but you can
    change this with <a class="message"
    href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>. The match is character
    by character for the length of the <code>select</code> string. That is, if select is "Fred" it
    will match "Frederick" if this is the first item in the list that begins with "Fred". If an
    item is found, it is selected. If the item is not found, the autocompletion list closes if
    auto-hide is true (see <a class="message"
    href="#SCI_AUTOCSETAUTOHIDE"><code>SCI_AUTOCSETAUTOHIDE</code></a>).<br />
    The current selection index can be retrieved with <code>SCI_AUTOCGETCURRENT</code>.</p>

    <p><b id="SCI_AUTOCGETCURRENTTEXT">SCI_AUTOCGETCURRENTTEXT(&lt;unused&gt;, char *text)</b><br />
     This message retrieves the current selected text in the autocompletion list. Normally the
    <a class="message" href="#SCN_AUTOCSELECTION"><code>SCN_AUTOCSELECTION</code></a> notification
    is used instead.</p>

    <p>The value is copied to the <code>text</code> buffer, returning the length (not including the
    terminating 0). If not found, an empty string is copied to the buffer and 0 is returned.</p>

    <p>If the value argument is 0 then the length that should be allocated to store the value is
    returned; again, the terminating 0 is not included.</p>

    <p><b id="SCI_AUTOCSETCANCELATSTART">SCI_AUTOCSETCANCELATSTART(bool cancel)</b><br />
     <b id="SCI_AUTOCGETCANCELATSTART">SCI_AUTOCGETCANCELATSTART</b><br />
     The default behavior is for the list to be cancelled if the caret moves to the location it
    was at when the list was displayed. By calling this message with a <code>false</code> argument,
    the list is not cancelled until the caret moves at least one character before the word being
    completed.</p>

    <p><b id="SCI_AUTOCSETFILLUPS">SCI_AUTOCSETFILLUPS(&lt;unused&gt;, const char *chars)</b><br />
     If a fillup character is typed with an autocompletion list active, the currently selected item
    in the list is added into the document, then the fillup character is added. Common fillup
    characters are '(', '[' and '.' but others are possible depending on the language. By default,
    no fillup characters are set.</p>

    <p><b id="SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE(bool chooseSingle)</b><br />
     <b id="SCI_AUTOCGETCHOOSESINGLE">SCI_AUTOCGETCHOOSESINGLE</b><br />
     If you use <code>SCI_AUTOCSETCHOOSESINGLE(1)</code> and a list has only one item, it is
    automatically added and no list is displayed. The default is to display the list even if there
    is only a single item.</p>

    <p><b id="SCI_AUTOCSETIGNORECASE">SCI_AUTOCSETIGNORECASE(bool ignoreCase)</b><br />
     <b id="SCI_AUTOCGETIGNORECASE">SCI_AUTOCGETIGNORECASE</b><br />
     By default, matching of characters to list members is case sensitive. These messages let you
    set and get case sensitivity.</p>

    <p><b id="SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR(int behaviour)</b><br>
    <b id="SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR</b><br>
    When autocompletion is set to ignore case (<code>SCI_AUTOCSETIGNORECASE</code>), by default it will
    nonetheless select the first list member that matches in a case sensitive way to entered characters.
    This corresponds to a behaviour property of <code>SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE</code> (0).
    If you want autocompletion to ignore case at all, choose <code>SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE</code> (1).</p>

    <p><b id="SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</b><br />
     <b id="SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</b><br />
     By default, the list is cancelled if there are no viable matches (the user has typed
    characters that no longer match a list entry). If you want to keep displaying the original
    list, set <code>autoHide</code> to <code>false</code>. This also effects <a class="message"
    href="#SCI_AUTOCSELECT"><code>SCI_AUTOCSELECT</code></a>.</p>

    <p><b id="SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool dropRestOfWord)</b><br />
     <b id="SCI_AUTOCGETDROPRESTOFWORD">SCI_AUTOCGETDROPRESTOFWORD</b><br />
     When an item is selected, any word characters following the caret are first erased if
    <code>dropRestOfWord</code> is set <code>true</code>. The default is <code>false</code>.</p>

    <p>
      <b id="SCI_REGISTERIMAGE">SCI_REGISTERIMAGE(int type, const char *xpmData)</b><br />
      <b id="SCI_REGISTERRGBAIMAGE">SCI_REGISTERRGBAIMAGE(int type, const char *pixels)</b><br />
      <b id="SCI_CLEARREGISTEREDIMAGES">SCI_CLEARREGISTEREDIMAGES</b><br />
      <b id="SCI_AUTOCSETTYPESEPARATOR">SCI_AUTOCSETTYPESEPARATOR(char separatorCharacter)</b><br />
      <b id="SCI_AUTOCGETTYPESEPARATOR">SCI_AUTOCGETTYPESEPARATOR</b><br />

      Autocompletion list items may display an image as well as text. Each image is first registered with an integer
      type. Then this integer is included in the text of the list separated by a '?' from the text. For example,
      "fclose?2 fopen" displays image 2 before the string "fclose" and no image before "fopen".
      The images are in either the <a class="jump" href="#XPM">XPM format</a> (<code>SCI_REGISTERIMAGE</code>) or 
      <a class="jump" href="#RGBA">RGBA format</a> (<code>SCI_REGISTERRGBAIMAGE</code>).
      For <code>SCI_REGISTERRGBAIMAGE</code> the width and height must previously been set with
      the <a class="message" href="#SCI_RGBAIMAGESETWIDTH"><code>SCI_RGBAIMAGESETWIDTH</code></a> and 
      <a class="message" href="#SCI_RGBAIMAGESETHEIGHT"><code>SCI_RGBAIMAGESETHEIGHT</code></a> messages.
      The set of registered images can be cleared with <code>SCI_CLEARREGISTEREDIMAGES</code> and the '?' separator changed
      with <code>SCI_AUTOCSETTYPESEPARATOR</code>.
    </p>

    <p>
      <b id="SCI_AUTOCSETMAXHEIGHT">SCI_AUTOCSETMAXHEIGHT(int rowCount)</b><br />
      <b id="SCI_AUTOCGETMAXHEIGHT">SCI_AUTOCGETMAXHEIGHT</b><br />

      Get or set the maximum number of rows that will be visible in an autocompletion list. If there are more rows in the list, then a vertical
      scrollbar is shown. The default is 5.
     </p>

    <p>
      <b id="SCI_AUTOCSETMAXWIDTH">SCI_AUTOCSETMAXWIDTH(int characterCount)</b><br />
      <b id="SCI_AUTOCGETMAXWIDTH">SCI_AUTOCGETMAXWIDTH</b><br />

      Get or set the maximum width of an autocompletion list expressed as the number of characters in the longest item that will be totally visible.
      If zero (the default) then the list's width is calculated to fit the item with the most characters. Any items that cannot be fully displayed within
      the available width are indicated by the presence of ellipsis.
     </p>

    <h2 id="UserLists">User lists</h2>

    <p>User lists use the same internal mechanisms as autocompletion lists, and all the calls
    listed for autocompletion work on them; you cannot display a user list at the same time as an
    autocompletion list is active. They differ in the following respects:</p>

    <p>o The <code><a class="message"
    href="#SCI_AUTOCSETCHOOSESINGLE">SCI_AUTOCSETCHOOSESINGLE</a></code> message has no
    effect.<br />
     o When the user makes a selection you are sent a <code><a class="message"
    href="#SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</a></code> <a class="jump"
    href="#Notifications">notification message</a> rather than <code><a class="message"
    href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a></code>.</p>

    <p>BEWARE: if you have set fillup characters or stop characters, these will still be active
    with the user list, and may result in items being selected or the user list cancelled due to
    the user typing into the editor.</p>

    <p><b id="SCI_USERLISTSHOW">SCI_USERLISTSHOW(int listType, const char *list)</b><br />
     The <code>listType</code> parameter is returned to the container as the <code>wParam</code>
    field of the <a class="message" href="#SCNotification"><code>SCNotification</code></a>
    structure. It must be greater than 0 as this is how Scintilla tells the difference between an
    autocompletion list and a user list. If you have different types of list, for example a list of
    buffers and a list of macros, you can use <code>listType</code> to tell which one has returned
    a selection. </p>

    <h2 id="CallTips">Call tips</h2>

    <p>Call tips are small windows displaying the arguments to a function and are displayed after
    the user has typed the name of the function. They normally display characters using the font
    facename, size and character set defined by
    <code><a class="message" href="#StyleDefinition">STYLE_DEFAULT</a></code>. You can choose to
    use <code><a class="message" href="#StyleDefinition">STYLE_CALLTIP</a></code> to define the
    facename, size, foreground and background colours and character set with
    <code><a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE</a></code>.
    This also enables support for Tab characters.

    There is some interaction between call tips and autocompletion lists in that showing a
    call tip cancels any active autocompletion list, and vice versa.</p>

    <p>Call tips can highlight part of the text within them. You could use this to highlight the
    current argument to a function by counting the number of commas (or whatever separator your
    language uses). See <code>SciTEBase::CharAdded()</code> in <code>SciTEBase.cxx</code> for an
    example of call tip use.</p>

    <p>The mouse may be clicked on call tips and this causes a
    <code><a class="message" href="#SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</a></code>
    notification to be sent to the container. Small up and down arrows may be displayed within
    a call tip by, respectively, including the characters '\001', or '\002'. This is useful
    for showing that there are overloaded variants of one function name and that the user can
    click on the arrows to cycle through the overloads.</p>

    <p>Alternatively, call tips can be displayed when you leave the mouse pointer for a while over
    a word in response to the <code><a class="message"
    href="#SCN_DWELLSTART">SCN_DWELLSTART</a></code> <a class="jump"
    href="#Notifications">notification</a> and cancelled in response to <code><a class="message"
    href="#SCN_DWELLEND">SCN_DWELLEND</a></code>. This method could be used in a debugger to give
    the value of a variable, or during editing to give information about the word under the
    pointer.</p>
    <code><a class="message" href="#SCI_CALLTIPSHOW">SCI_CALLTIPSHOW(int posStart, const char
    *definition)</a><br />
     <a class="message" href="#SCI_CALLTIPCANCEL">SCI_CALLTIPCANCEL</a><br />
     <a class="message" href="#SCI_CALLTIPACTIVE">SCI_CALLTIPACTIVE</a><br />
     <a class="message" href="#SCI_CALLTIPPOSSTART">SCI_CALLTIPPOSSTART</a><br />
     <a class="message" href="#SCI_CALLTIPSETHLT">SCI_CALLTIPSETHLT(int highlightStart, int
    highlightEnd)</a><br />
     <a class="message" href="#SCI_CALLTIPSETBACK">SCI_CALLTIPSETBACK(int colour)</a><br />
     <a class="message" href="#SCI_CALLTIPSETFORE">SCI_CALLTIPSETFORE(int colour)</a><br />
     <a class="message" href="#SCI_CALLTIPSETFOREHLT">SCI_CALLTIPSETFOREHLT(int colour)</a><br />
     <a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE(int tabsize)</a><br />
     <a class="message" href="#SCI_CALLTIPSETPOSITION">SCI_CALLTIPSETPOSITION(bool above)</a><br />
    </code>

    <p><b id="SCI_CALLTIPSHOW">SCI_CALLTIPSHOW(int posStart, const char *definition)</b><br />
     This message starts the process by displaying the call tip window. If a call tip is already
    active, this has no effect.<br />
     <code>posStart</code> is the position in the document at which to align the call tip. The call
    tip text is aligned to start 1 line below this character unless you have included up and/or
    down arrows in the call tip text in which case the tip is aligned to the right-hand edge of
    the rightmost arrow. The assumption is that you will start the text with something like
    "\001 1 of 3 \002".<br />
     <code>definition</code> is the call tip text. This can contain multiple lines separated by
    '\n' (Line Feed, ASCII code 10) characters. Do not include '\r' (Carriage Return, ASCII
     code 13), as this will most likely print as an empty box. '\t' (Tab, ASCII code 9) is
     supported if you set a tabsize with
    <code><a class="message" href="#SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE</a></code>.<br /></p>

    <p><b id="SCI_CALLTIPCANCEL">SCI_CALLTIPCANCEL</b><br />
     This message cancels any displayed call tip. Scintilla will also cancel call tips for you if
    you use any keyboard commands that are not compatible with editing the argument list of a
    function.</p>

    <p><b id="SCI_CALLTIPACTIVE">SCI_CALLTIPACTIVE</b><br />
     This returns 1 if a call tip is active and 0 if it is not active.</p>

    <p><b id="SCI_CALLTIPPOSSTART">SCI_CALLTIPPOSSTART</b><br />
     This message returns the value of the current position when <code>SCI_CALLTIPSHOW</code>
    started to display the tip.</p>

    <p><b id="SCI_CALLTIPSETHLT">SCI_CALLTIPSETHLT(int hlStart, int hlEnd)</b><br />
     This sets the region of the call tips text to display in a highlighted style.
    <code>hlStart</code> is the zero-based index into the string of the first character to
    highlight and <code>hlEnd</code> is the index of the first character after the highlight.
    <code>hlEnd</code> must be greater than <code>hlStart</code>; <code>hlEnd-hlStart</code> is the
    number of characters to highlight. Highlights can extend over line ends if this is
    required.</p>

    <p>Unhighlighted text is drawn in a mid gray. Selected text is drawn in a dark blue. The
    background is white. These can be changed with
    <code>SCI_CALLTIPSETBACK</code>,
    <code>SCI_CALLTIPSETFORE</code>, and
    <code>SCI_CALLTIPSETFOREHLT</code>.
    </p>

    <p><b id="SCI_CALLTIPSETBACK">SCI_CALLTIPSETBACK(int colour)</b><br />
     The background colour of call tips can be set with this message; the default colour is white.
    It is not a good idea to set a dark colour as the background as the default colour for normal
    calltip text is mid gray and the defaultcolour for highlighted text is dark blue. This also
    sets the background colour of <code>STYLE_CALLTIP</code>.</p>

    <p><b id="SCI_CALLTIPSETFORE">SCI_CALLTIPSETFORE(int colour)</b><br />
     The colour of call tip text can be set with this message; the default colour is mid gray.
    This also sets the foreground colour of <code>STYLE_CALLTIP</code>.</p>

    <p><b id="SCI_CALLTIPSETFOREHLT">SCI_CALLTIPSETFOREHLT(int colour)</b><br />
     The colour of highlighted call tip text can be set with this message; the default colour
    is dark blue.</p>

    <p><b id="SCI_CALLTIPUSESTYLE">SCI_CALLTIPUSESTYLE(int tabsize)</b><br />
     This message changes the style used for call tips from <code>STYLE_DEFAULT</code> to
    <code>STYLE_CALLTIP</code> and sets a tab size in screen pixels. If <code>tabsize</code> is
    less than 1, Tab characters are not treated specially. Once this call has been used, the
    call tip foreground and background colours are also taken from the style.</p>

    <p><b id="SCI_CALLTIPSETPOSITION">SCI_CALLTIPSETPOSITION(bool above)</b><br />
     By default the calltip is displayed below the text, setting above to <code>true</code>
    (1) will display it above the text.</p>
    

    <h2 id="KeyboardCommands">Keyboard commands</h2>

    <p>To allow the container application to perform any of the actions available to the user with
    keyboard, all the keyboard actions are messages. They do not take any parameters. These
    commands are also used when redefining the key bindings with the <a class="message"
    href="#SCI_ASSIGNCMDKEY"><code>SCI_ASSIGNCMDKEY</code></a> message.</p>

    <table border="0" summary="Keyboard commands">
      <tbody>
        <tr>
          <td><code>SCI_LINEDOWN</code></td>

          <td><code>SCI_LINEDOWNEXTEND</code></td>

          <td><code>SCI_LINEDOWNRECTEXTEND</code></td>

          <td><code>SCI_LINESCROLLDOWN</code></td>
        </tr>

        <tr>
          <td><code>SCI_LINEUP</code></td>

          <td><code>SCI_LINEUPEXTEND</code></td>

          <td><code>SCI_LINEUPRECTEXTEND</code></td>

          <td><code>SCI_LINESCROLLUP</code></td>
        </tr>

        <tr>
          <td><code>SCI_PARADOWN</code></td>

          <td><code>SCI_PARADOWNEXTEND</code></td>

          <td><code>SCI_PARAUP</code></td>

          <td><code>SCI_PARAUPEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_CHARLEFT</code></td>

          <td><code>SCI_CHARLEFTEXTEND</code></td>

          <td><code>SCI_CHARLEFTRECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_CHARRIGHT</code></td>

          <td><code>SCI_CHARRIGHTEXTEND</code></td>

          <td><code>SCI_CHARRIGHTRECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_WORDLEFT</code></td>

          <td><code>SCI_WORDLEFTEXTEND</code></td>

          <td><code>SCI_WORDRIGHT</code></td>

          <td><code>SCI_WORDRIGHTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_WORDLEFTEND</code></td>

          <td><code>SCI_WORDLEFTENDEXTEND</code></td>

          <td><code>SCI_WORDRIGHTEND</code></td>

          <td><code>SCI_WORDRIGHTENDEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_WORDPARTLEFT</code></td>

          <td><code>SCI_WORDPARTLEFTEXTEND</code></td>

          <td><code>SCI_WORDPARTRIGHT</code></td>

          <td><code>SCI_WORDPARTRIGHTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_HOME</code></td>

          <td><code>SCI_HOMEEXTEND</code></td>

          <td><code>SCI_HOMERECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_HOMEDISPLAY</code></td>

          <td><code>SCI_HOMEDISPLAYEXTEND</code></td>

          <td><code>SCI_HOMEWRAP</code></td>

          <td><code>SCI_HOMEWRAPEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_VCHOME</code></td>

          <td><code>SCI_VCHOMEEXTEND</code></td>

          <td><code>SCI_VCHOMERECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_VCHOMEWRAP</code></td>

          <td><code>SCI_VCHOMEWRAPEXTEND</code></td>

          <td><code>SCI_VCHOMEDISPLAY</code></td>

          <td><code>SCI_VCHOMEDISPLAYEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_LINEEND</code></td>

          <td><code>SCI_LINEENDEXTEND</code></td>

          <td><code>SCI_LINEENDRECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_LINEENDDISPLAY</code></td>

          <td><code>SCI_LINEENDDISPLAYEXTEND</code></td>

          <td><code>SCI_LINEENDWRAP</code></td>

          <td><code>SCI_LINEENDWRAPEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_DOCUMENTSTART</code></td>

          <td><code>SCI_DOCUMENTSTARTEXTEND</code></td>

          <td><code>SCI_DOCUMENTEND</code></td>

          <td><code>SCI_DOCUMENTENDEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_PAGEUP</code></td>

          <td><code>SCI_PAGEUPEXTEND</code></td>

          <td><code>SCI_PAGEUPRECTEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_PAGEDOWN</code></td>

          <td><code>SCI_PAGEDOWNEXTEND</code></td>

          <td><code>SCI_PAGEDOWNRECTEXTEND</code></td>
        </tr>


        <tr>
          <td><code>SCI_STUTTEREDPAGEUP</code></td>

          <td><code>SCI_STUTTEREDPAGEUPEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_STUTTEREDPAGEDOWN</code></td>

          <td><code>SCI_STUTTEREDPAGEDOWNEXTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_DELETEBACK</code></td>

          <td><code>SCI_DELETEBACKNOTLINE</code></td>
        </tr>

        <tr>
          <td><code>SCI_DELWORDLEFT</code></td>

          <td><code>SCI_DELWORDRIGHT</code></td>

          <td><code>SCI_DELWORDRIGHTEND</code></td>
        </tr>

        <tr>
          <td><code>SCI_DELLINELEFT</code></td>

          <td><code>SCI_DELLINERIGHT</code></td>

          <td><code>SCI_LINEDELETE</code></td>
        </tr>

        <tr>
          <td><code>SCI_LINECUT</code></td>

          <td><code>SCI_LINECOPY</code></td>

          <td><code>SCI_LINETRANSPOSE</code></td>

          <td><code>SCI_LINEDUPLICATE</code></td>
        </tr>

        <tr>
          <td><code>SCI_LOWERCASE</code></td>

          <td><code>SCI_UPPERCASE</code></td>

          <td><code>SCI_CANCEL</code></td>

          <td><code>SCI_EDITTOGGLEOVERTYPE</code></td>
        </tr>

        <tr>
          <td><code>SCI_NEWLINE</code></td>

          <td><code>SCI_FORMFEED</code></td>

          <td><code>SCI_TAB</code></td>

          <td><code>SCI_BACKTAB</code></td>
        </tr>

        <tr>
          <td><code>SCI_SELECTIONDUPLICATE</code></td>

          <td><code>SCI_VERTICALCENTRECARET</code></td>

        </tr>

        <tr>
          <td><code>SCI_MOVESELECTEDLINESUP</code></td>

          <td><code>SCI_MOVESELECTEDLINESDOWN</code></td>
        </tr>

        <tr>
          <td><code>SCI_SCROLLTOSTART</code></td>

          <td><code>SCI_SCROLLTOEND</code></td>
        </tr>
     </tbody>
    </table>

    <p>The <code>SCI_*EXTEND</code> messages extend the selection.</p>

    <p>The <code>SCI_*RECTEXTEND</code> messages extend the rectangular selection
    (and convert regular selection to rectangular one, if any).</p>

    <p>The <code>SCI_WORDPART*</code> commands are used to move between word segments marked by
    capitalisation (aCamelCaseIdentifier) or underscores (an_under_bar_ident).</p>

    <p>The <code>SCI_HOME*</code> commands move the caret to the start of the line, while the
    <code>SCI_VCHOME*</code> commands move the caret to the first non-blank character of the line
    (ie. just after the indentation) unless it is already there; in this case, it acts as SCI_HOME*.</p>

    <p>The <code>SCI_[HOME|LINEEND]DISPLAY*</code> commands are used when in line wrap mode to
    allow movement to the start or end of display lines as opposed to the normal
    <code>SCI_[HOME|LINEEND]</code> commands which move to the start or end of document lines.</p>

    <p>The <code>SCI_[[VC]HOME|LINEEND]WRAP*</code> commands are like their namesakes
    <code>SCI_[[VC]HOME|LINEEND]*</code> except they behave differently when word-wrap is enabled:
     They go first to the start / end of the display line, like <code>SCI_[HOME|LINEEND]DISPLAY*</code>,
     but if the cursor is already at the point, it goes on to the start or end of the document line,
     as appropriate for <code>SCI_[[VC]HOME|LINEEND]*</code>.
     </p>

    <p>The <code>SCI_SCROLLTO[START|END]</code> commands scroll the document to the start
    or end without changing the selection. These commands match OS X platform conventions for the behaviour of the
    <code>home</code> and <code>end</code> keys. Scintilla can be made to match OS X applications
    by binding the <code>home</code> and <code>end</code> keys to these commands.
     </p>

    <h2 id="KeyBindings">Key bindings</h2>

    <p>There is a default binding of keys to commands that is defined in the Scintilla source in
    the file <code>KeyMap.cxx</code> by the constant <code>KeyMap::MapDefault[]</code>. This table
    maps key definitions to <code>SCI_*</code> messages with no parameters (mostly the <a
    class="jump" href="#KeyboardCommands">keyboard commands</a> discussed above, but any Scintilla
    command that has no arguments can be mapped). You can change the mapping to suit your own
    requirements.</p>
    <code><a class="message" href="#SCI_ASSIGNCMDKEY">SCI_ASSIGNCMDKEY(int keyDefinition, int
    sciCommand)</a><br />
     <a class="message" href="#SCI_CLEARCMDKEY">SCI_CLEARCMDKEY(int keyDefinition)</a><br />
     <a class="message" href="#SCI_CLEARALLCMDKEYS">SCI_CLEARALLCMDKEYS</a><br />
     <a class="message" href="#SCI_NULL">SCI_NULL</a><br />
    </code>

    <p><b id="keyDefinition">keyDefinition</b><br />
     A key definition contains the key code in the low 16-bits and the key modifiers in the high
    16-bits. To combine <code>keyCode</code> and <code>keyMod</code> set:<br />
    <br />
     <code>keyDefinition = keyCode + (keyMod &lt;&lt; 16)</code></p>

    <p>The key code is a visible or control character or a key from the <code>SCK_*</code>
    enumeration, which contains:<br />
     <code>SCK_ADD</code>, <code>SCK_BACK</code>, <code>SCK_DELETE</code>, <code>SCK_DIVIDE</code>,
    <code>SCK_DOWN</code>, <code>SCK_END</code>, <code>SCK_ESCAPE</code>, <code>SCK_HOME</code>,
    <code>SCK_INSERT</code>, <code>SCK_LEFT</code>, <code>SCK_MENU</code>, <code>SCK_NEXT</code> (Page Down),
    <code>SCK_PRIOR</code> (Page Up), <code>SCK_RETURN</code>, <code>SCK_RIGHT</code>,
    <code>SCK_RWIN</code>,
    <code>SCK_SUBTRACT</code>, <code>SCK_TAB</code>, <code>SCK_UP</code>, and
    <code>SCK_WIN</code>.</p>

    <p>The modifiers are a combination of zero or more of <code>SCMOD_ALT</code>,
    <code>SCMOD_CTRL</code>, <code>SCMOD_SHIFT</code>, and <code>SCMOD_META</code>.
    On OS X, the Command key is mapped to <code>SCMOD_CTRL</code> and the Control key to 
    <code>SCMOD_META</code>.
    If you are building a table, you might
    want to use <code>SCMOD_NORM</code>, which has the value 0, to mean no modifiers.</p>

    <p><b id="SCI_ASSIGNCMDKEY">SCI_ASSIGNCMDKEY(int <a class="jump"
    href="#keyDefinition">keyDefinition</a>, int sciCommand)</b><br />
     This assigns the given key definition to a Scintilla command identified by
    <code>sciCommand</code>. <code>sciCommand</code> can be any <code>SCI_*</code> command that has
    no arguments.</p>

    <p><b id="SCI_CLEARCMDKEY">SCI_CLEARCMDKEY(int <a class="jump"
    href="#keyDefinition">keyDefinition</a>)</b><br />
     This makes the given key definition do nothing by assigning the action <code>SCI_NULL</code>
    to it.</p>

    <p><b id="SCI_CLEARALLCMDKEYS">SCI_CLEARALLCMDKEYS</b><br />
     This command removes all keyboard command mapping by setting an empty mapping table.</p>

    <p><b id="SCI_NULL">SCI_NULL</b><br />
     The <code>SCI_NULL</code> does nothing and is the value assigned to keys that perform no
    action. SCI_NULL ensures that keys do not propagate to the parent window as that may
    cause focus to move. If you want the standard platform behaviour use the constant 0 instead.</p>

    <h2 id="PopupEditMenu">Popup edit menu</h2>

    <p><b id="SCI_USEPOPUP">SCI_USEPOPUP(bool bEnablePopup)</b><br />
     Clicking the wrong button on the mouse pops up a short default editing menu. This may be
    turned off with <code>SCI_USEPOPUP(0)</code>. If you turn it off, context menu commands (in
    Windows, <code>WM_CONTEXTMENU</code>) will not be handled by Scintilla, so the parent of the
    Scintilla window will have the opportunity to handle the message.</p>

    <h2 id="MacroRecording">Macro recording</h2>

    <p>Start and stop macro recording mode. In macro recording mode, actions are reported to the
    container through <code><a class="message" href="#SCN_MACRORECORD">SCN_MACRORECORD</a></code>
    <a class="jump" href="#Notifications">notifications</a>. It is then up to the container to
    record these actions for future replay.</p>

    <p><b id="SCI_STARTRECORD">SCI_STARTRECORD</b><br />
     <b id="SCI_STOPRECORD">SCI_STOPRECORD</b><br />
     These two messages turn macro recording on and off.</p>

    <h2 id="Printing">Printing</h2>

    <p><code>SCI_FORMATRANGE</code> can be used to draw the text onto a display surface
    which can include a printer display surface. Printed output shows text styling as on the
    screen, but it hides all margins except a line number margin. All special marker effects are
    removed and the selection and caret are hidden.</p>

    <p>Different platforms use different display surface ID types to print on. On Windows, these are
    <code>HDC</code>s., on GTK+ 3.x <code>cairo_t *</code>,
    and on Cocoa <code>CGContextRef</code> is used.</p>

    <code><a class="message" href="#SCI_FORMATRANGE">SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat
    *pfr)</a><br />
     <a class="message" href="#SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int
    magnification)</a><br />
     <a class="message" href="#SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION</a><br />
     <a class="message" href="#SCI_SETPRINTCOLOURMODE">SCI_SETPRINTCOLOURMODE(int mode)</a><br />
     <a class="message" href="#SCI_GETPRINTCOLOURMODE">SCI_GETPRINTCOLOURMODE</a><br />
     <a class="message" href="#SCI_SETPRINTWRAPMODE">SCI_SETPRINTWRAPMODE</a><br />
     <a class="message" href="#SCI_GETPRINTWRAPMODE">SCI_GETPRINTWRAPMODE</a><br />
    </code>

    <p><b id="SCI_FORMATRANGE">SCI_FORMATRANGE(bool bDraw, Sci_RangeToFormat *pfr)</b><br />
     This call renders a range of text into a device context. If you use
    this for printing, you will probably want to arrange a page header and footer; Scintilla does
    not do this for you. See <code>SciTEWin::Print()</code> in <code>SciTEWinDlg.cxx</code> for an
    example. Each use of this message renders a range of text into a rectangular area and returns
    the position in the document of the next character to print.</p>

    <p><code>bDraw</code> controls if any output is done. Set this to false if you are paginating
    (for example, if you use this with MFC you will need to paginate in
    <code>OnBeginPrinting()</code> before you output each page.</p>
<pre>
struct Sci_Rectangle { int left; int top; int right; int bottom; };

struct Sci_RangeToFormat {
    Sci_SurfaceID hdc;        // The Surface ID we print to
    Sci_SurfaceID hdcTarget;  // The Surface ID we use for measuring (may be same as hdc)
    Sci_Rectangle rc;         // Rectangle in which to print
    Sci_Rectangle rcPage;     // Physically printable page size
    Sci_CharacterRange chrg;  // Range of characters to print
};
</pre>

    <p>On Windows, <code>hdc</code> and <code>hdcTarget</code> should both be set to the device context handle
    of the output device (usually a printer). If you print to a metafile these will not be the same
    as Windows metafiles (unlike extended metafiles) do not implement the full API for returning
    information. In this case, set <code>hdcTarget</code> to the screen DC.<br />
     <code>rcPage</code> is the rectangle <code>{0, 0, maxX, maxY}</code> where <code>maxX+1</code>
    and <code>maxY+1</code> are the number of physically printable pixels in x and y.<br />
     <code>rc</code> is the rectangle to render the text in (which will, of course, fit within the
    rectangle defined by rcPage).<br />
     <code>chrg.cpMin</code> and <code>chrg.cpMax</code> define the start position and maximum
    position of characters to output. All of each line within this character range is drawn.</p>

    <p>On Cocoa, the surface IDs for printing (<code>bDraw=1</code>) should be the graphics port of the current context
    (<code>(CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]</code>) when the view's drawRect method is called.
    The Surface IDs are not really used for measurement (<code>bDraw=0</code>) but can be set
    to a bitmap context (created with <code>CGBitmapContextCreate</code>) to avoid runtime warnings.</p>

    <p>On GTK+, the surface IDs to use can be found from the printing context with 
    <code>gtk_print_context_get_cairo_context(context)</code>.</p>

     <code>chrg.cpMin</code> and <code>chrg.cpMax</code> define the start position and maximum
    position of characters to output. All of each line within this character range is drawn.</p>

    <p>When printing, the most tedious part is always working out what the margins should be to
    allow for the non-printable area of the paper and printing a header and footer. If you look at
    the printing code in SciTE, you will find that most of it is taken up with this. The loop that
    causes Scintilla to render text is quite simple if you strip out all the margin, non-printable
    area, header and footer code.</p>

    <p><b id="SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int magnification)</b><br />
     <b id="SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION</b><br />
     <code>SCI_GETPRINTMAGNIFICATION</code> lets you to print at a different size than the screen
    font. <code>magnification</code> is the number of points to add to the size of each screen
    font. A value of -3 or -4 gives reasonably small print. You can get this value with
    <code>SCI_GETPRINTMAGNIFICATION</code>.</p>

    <p><b id="SCI_SETPRINTCOLOURMODE">SCI_SETPRINTCOLOURMODE(int mode)</b><br />
     <b id="SCI_GETPRINTCOLOURMODE">SCI_GETPRINTCOLOURMODE</b><br />
     These two messages set and get the method used to render coloured text on a printer that is
    probably using white paper. It is especially important to consider the treatment of colour if
    you use a dark or black screen background. Printing white on black uses up toner and ink very
    many times faster than the other way around. You can set the mode to one of:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Colour printing modes">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Purpose</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_PRINT_NORMAL</code></td>

          <td align="center">0</td>

          <td>Print using the current screen colours. This is the default.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PRINT_INVERTLIGHT</code></td>

          <td align="center">1</td>

          <td>If you use a dark screen background this saves ink by inverting the light value of
          all colours and printing on a white background.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PRINT_BLACKONWHITE</code></td>

          <td align="center">2</td>

          <td>Print all text as black on a white background.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PRINT_COLOURONWHITE</code></td>

          <td align="center">3</td>

          <td>Everything prints in its own colour on a white background.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PRINT_COLOURONWHITEDEFAULTBG</code></td>

          <td align="center">4</td>

          <td>Everything prints in its own colour on a white background except that line numbers
          use their own background colour.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETPRINTWRAPMODE">SCI_SETPRINTWRAPMODE(int wrapMode)</b><br />
     <b id="SCI_GETPRINTWRAPMODE">SCI_GETPRINTWRAPMODE</b><br />
     These two functions get and set the printer wrap mode. <code>wrapMode</code> can be
     set to <code>SC_WRAP_NONE</code> (0), <code>SC_WRAP_WORD</code> (1) or
     <code>SC_WRAP_CHAR</code> (2). The default is
     <code>SC_WRAP_WORD</code>, which wraps printed output so that all characters fit
     into the print rectangle. If you set <code>SC_WRAP_NONE</code>, each line of text
     generates one line of output and the line is truncated if it is too long to fit
     into the print area.<br />
     <code>SC_WRAP_WORD</code> tries to wrap only between words as indicated by
     white space or style changes although if a word is longer than a line, it will be wrapped before
     the line end. <code>SC_WRAP_CHAR</code> is preferred to
     <code>SC_WRAP_WORD</code> for Asian languages where there is no white space
     between words.</p>

    <h2 id="DirectAccess">Direct access</h2>
    <code><a class="message" href="#SCI_GETDIRECTFUNCTION">SCI_GETDIRECTFUNCTION</a><br />
     <a class="message" href="#SCI_GETDIRECTPOINTER">SCI_GETDIRECTPOINTER</a><br />
     <a class="message" href="#SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</a><br />
     <a class="message" href="#SCI_GETRANGEPOINTER">SCI_GETRANGEPOINTER(int position, int rangeLength)</a><br />
     <a class="message" href="#SCI_GETGAPPOSITION">SCI_GETGAPPOSITION</a><br />
    </code>

    <p>On Windows, the message-passing scheme used to communicate between the container and
    Scintilla is mediated by the operating system <code>SendMessage</code> function and can lead to
    bad performance when calling intensively. To avoid this overhead, Scintilla provides messages
    that allow you to call the Scintilla message function directly. The code to do this in C/C++ is
    of the form:</p>
<pre>
#include "Scintilla.h"
SciFnDirect pSciMsg = (SciFnDirect)SendMessage(hSciWnd, SCI_GETDIRECTFUNCTION, 0, 0);
sptr_t pSciWndData = (sptr_t)SendMessage(hSciWnd, SCI_GETDIRECTPOINTER, 0, 0);

// now a wrapper to call Scintilla directly
sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
    return pSciMsg(pSciWndData, iMessage, wParam, lParam);
}
</pre>

    <p><code>SciFnDirect</code>, <code>sptr_t</code> and <code>uptr_t</code> are declared in
    <code>Scintilla.h</code>. <code>hSciWnd</code> is the window handle returned when you created
    the Scintilla window.</p>

    <p>While faster, this direct calling will cause problems if performed from a different thread
    to the native thread of the Scintilla window in which case <code>SendMessage(hSciWnd, SCI_*,
    wParam, lParam)</code> should be used to synchronize with the window's thread.</p>

    <p>This feature also works on GTK+ but has no significant impact on speed.</p>

    <p>From version 1.47 on Windows, Scintilla exports a function called
    <code>Scintilla_DirectFunction</code> that can be used the same as the function returned by
    <code>SCI_GETDIRECTFUNCTION</code>. This saves you the call to
    <code>SCI_GETDIRECTFUNCTION</code> and the need to call Scintilla indirectly via the function
    pointer.</p>

    <p><b id="SCI_GETDIRECTFUNCTION">SCI_GETDIRECTFUNCTION</b><br />
     This message returns the address of the function to call to handle Scintilla messages without
    the overhead of passing through the Windows messaging system. You need only call this once,
    regardless of the number of Scintilla windows you create.</p>

    <p><b id="SCI_GETDIRECTPOINTER">SCI_GETDIRECTPOINTER</b><br />
     This returns a pointer to data that identifies which Scintilla window is in use. You must call
    this once for each Scintilla window you create. When you call the direct function, you must
    pass in the direct pointer associated with the target window.</p>

    <p><b id="SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</b><br />
    <b id="SCI_GETRANGEPOINTER">SCI_GETRANGEPOINTER(int position, int rangeLength)</b><br />
    <b id="SCI_GETGAPPOSITION">SCI_GETGAPPOSITION</b><br />
     Grant temporary direct read-only access to the memory used by Scintilla to store
     the document.</p>
     <p><code>SCI_GETCHARACTERPOINTER</code> moves the gap within Scintilla so that the
     text of the document is stored consecutively
     and ensure there is a NUL character after the text, then returns a pointer to the first character.
     Applications may then pass this to a function that accepts a character pointer such as a regular
     expression search or a parser. The pointer should <em>not</em> be written to as that may desynchronize
     the internal state of Scintilla.</p>
     <p>Since any action in Scintilla may change its internal state
     this pointer becomes invalid after any call or by allowing user interface activity. The application
     should reacquire the pointer after making any call to Scintilla or performing any user-interface calls such
     as modifying a progress indicator.</p>
     <p>This call takes similar time to inserting a character at the end of the document and this may
     include moving the document contents. Specifically, all the characters after the document gap
     are moved to before the gap. This compacted state should persist over calls and user interface
     actions that do not change the document contents so reacquiring the pointer afterwards is very
     quick. If this call is used to implement a global replace operation, then each replacement will
     move the gap so if <code>SCI_GETCHARACTERPOINTER</code> is called after
     each replacement then the operation will become O(n^2) rather than O(n). Instead, all
     matches should be found and remembered, then all the replacements performed.</p>

     <p><code>SCI_GETRANGEPOINTER</code> provides direct access to just the
     range requested. The gap is not moved unless it is within the requested range so this call
     can be faster than <code>SCI_GETCHARACTERPOINTER</code>. 
     This can be used by application code that is able to act on blocks of text or ranges of lines.</p>

     <p><code>SCI_GETGAPPOSITION</code> returns the current gap position.
     This is a hint that applications can use to avoid calling <code>SCI_GETRANGEPOINTER</code>
     with a range that contains the gap and consequent costs of moving the gap.</p>

    <h2 id="MultipleViews">Multiple views</h2>

    <p>A Scintilla window and the document that it displays are separate entities. When you create
    a new window, you also create a new, empty document. Each document has a reference count that
    is initially set to 1. The document also has a list of the Scintilla windows that are linked to
    it so when any window changes the document, all other windows in which it appears are notified
    to cause them to update. The system is arranged in this way so that you can work with many
    documents in a single Scintilla window and so you can display a single document in multiple
    windows (for use with splitter windows).</p>

    <p>Although these messages use <code>document *pDoc</code>, to ensure compatibility with future
    releases of Scintilla you should treat <code>pDoc</code> as an opaque <code>void*</code>. That
    is, you can use and store the pointer as described in this section but you should not
    dereference it.</p>
    <code><a class="message" href="#SCI_GETDOCPOINTER">SCI_GETDOCPOINTER</a><br />
     <a class="message" href="#SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(&lt;unused&gt;, document
    *pDoc)</a><br />
     <a class="message" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</a><br />
     <a class="message" href="#SCI_ADDREFDOCUMENT">SCI_ADDREFDOCUMENT(&lt;unused&gt;, document
    *pDoc)</a><br />
     <a class="message" href="#SCI_RELEASEDOCUMENT">SCI_RELEASEDOCUMENT(&lt;unused&gt;, document
    *pDoc)</a><br />
    </code>

    <p><b id="SCI_GETDOCPOINTER">SCI_GETDOCPOINTER</b><br />
     This returns a pointer to the document currently in use by the window. It has no other
    effect.</p>

    <p><b id="SCI_SETDOCPOINTER">SCI_SETDOCPOINTER(&lt;unused&gt;, document *pDoc)</b><br />
     This message does the following:<br />
     1. It removes the current window from the list held by the current document.<br />
     2. It reduces the reference count of the current document by 1.<br />
     3. If the reference count reaches 0, the document is deleted.<br />
     4. <code>pDoc</code> is set as the new document for the window.<br />
     5. If <code>pDoc</code> was 0, a new, empty document is created and attached to the
    window.<br />
     6. If <code>pDoc</code> was not 0, its reference count is increased by 1.</p>

    <p><b id="SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</b><br />
     This message creates a new, empty document and returns a pointer to it. This document is not
    selected into the editor and starts with a reference count of 1. This means that you have
    ownership of it and must either reduce its reference count by 1 after using
    <code>SCI_SETDOCPOINTER</code> so that the Scintilla window owns it or you must make sure that
    you reduce the reference count by 1 with <code>SCI_RELEASEDOCUMENT</code> before you close the
    application to avoid memory leaks.</p>

    <p><b id="SCI_ADDREFDOCUMENT">SCI_ADDREFDOCUMENT(&lt;unused&gt;, document *pDoc)</b><br />
     This increases the reference count of a document by 1. If you want to replace the current
    document in the Scintilla window and take ownership of the current document, for example if you
    are editing many documents in one window, do the following:<br />
     1. Use <code>SCI_GETDOCPOINTER</code> to get a pointer to the document,
    <code>pDoc</code>.<br />
     2. Use <code>SCI_ADDREFDOCUMENT(0, pDoc)</code> to increment the reference count.<br />
     3. Use <code>SCI_SETDOCPOINTER(0, pNewDoc)</code> to set a different document or
    <code>SCI_SETDOCPOINTER(0, 0)</code> to set a new, empty document.</p>

    <p><b id="SCI_RELEASEDOCUMENT">SCI_RELEASEDOCUMENT(&lt;unused&gt;, document *pDoc)</b><br />
     This message reduces the reference count of the document identified by <code>pDoc</code>. pDoc
    must be the result of <code>SCI_GETDOCPOINTER</code> or <code>SCI_CREATEDOCUMENT</code> and
    must point at a document that still exists. If you call this on a document with a reference
    count of 1 that is still attached to a Scintilla window, bad things will happen. To keep the
    world spinning in its orbit you must balance each call to <code>SCI_CREATEDOCUMENT</code> or
    <code>SCI_ADDREFDOCUMENT</code> with a call to <code>SCI_RELEASEDOCUMENT</code>.</p>

    <h2 id="BackgroundLoadSave">Background loading and saving</h2>

    <p>To ensure a responsive user interface, applications may decide to load and save documents using a separate thread
    from the user interface.</p>

    <h3 id="BackgroundLoad">Loading in the background</h2>

    <p>An application can load all of a file into a buffer it allocates on a background thread and then add the data in that buffer
    into a Scintilla document on the user interface thread. That technique uses extra memory to store a complete copy of the
    file and also means that the time that Scintilla takes to perform initial line end discovery blocks the user interface.</p>

    <p>To avoid these issues, a loader object may be created and used to load the file. The loader object supports the ILoader interface.</p>

    <p><b id="SCI_CREATELOADER">SCI_CREATELOADER(int bytes)</b><br />
     Create an object that supports the <code>ILoader</code> interface which can be used to load data and then
     be turned into a Scintilla document object for attachment to a view object.
     The <code>bytes</code> argument determines the initial memory allocation for the document as it is more efficient
     to allocate once rather than rely on the buffer growing as data is added.
     If <code>SCI_CREATELOADER</code> fails then 0 is returned.</p>

<h4>ILoader</h4>

<div class="highlighted">
<span class="S5">class</span><span class="S0"> </span>ILoader<span class="S0"> </span><span class="S10">{</span><br />
<span class="S5">public</span><span class="S10">:</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>Release<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">// Returns a status code from SC_STATUS_*</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>AddData<span class="S10">(</span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>data<span class="S10">,</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>length<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span><span class="S0"> </span><span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>ConvertToDocument<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S10">};</span><br />
</div>

    <p>The application should call the <code>AddData</code> method with each block of data read from the file.
    <code>AddData</code> will return SC_STATUS_OK unless a failure, such as memory exhaustion occurs.
    If a failure occurs in <code>AddData</code> or in a file reading call then loading can be abandoned and the loader released with
    the <code>Release</code> call.
    When the whole file has been read, the <code>ConvertToDocument</code> method should be called to produce a Scintilla
    document pointer which can be used in the same way as a document pointer returned from
    <a class="message" href="#SCI_CREATEDOCUMENT">SCI_CREATEDOCUMENT</a>.
    There is no need to call <code>Release</code> after <code>ConvertToDocument</code>.</p>

    <h3 id="BackgroundSave">Saving in the background</h2>

    <p>An application that wants to save in the background should lock the document with <code>SCI_SETREADONLY(1)</code>
    to prevent modifications and retrieve a pointer to the unified document contents with
    <a class="message" href="#SCI_GETCHARACTERPOINTER">SCI_GETCHARACTERPOINTER</a></code>.
    The buffer of a locked document will not move so the pointer is valid until the application calls <code>SCI_SETREADONLY(0)</code>.</p>

    <p>If the user tries to performs a modification while the document is locked then a <code><a class="message"
    href="#SCN_MODIFYATTEMPTRO">SCN_MODIFYATTEMPTRO</a></code> notification is sent to the application.
    The application may then decide to ignore the modification or to terminate the background saving thread and reenable
    modification before returning from the notification.</p>

    <h2 id="Folding">Folding</h2>

    <p>The fundamental operation in folding is making lines invisible or visible. Line visibility
    is a property of the view rather than the document so each view may be displaying a different
    set of lines. From the point of view of the user, lines are hidden and displayed using fold
    points. Generally, the fold points of a document are based on the hierarchical structure of the
    document contents. In Python, the hierarchy is determined by indentation and in C++ by brace
    characters. This hierarchy can be represented within a Scintilla document object by attaching a
    numeric "fold level" to each line. The fold level is most easily set by a lexer, but you can
    also set it with messages.</p>

    <p>It is up to your code to set the connection between user actions and folding and unfolding.
    The best way to see how this is done is to search the SciTE source code for the messages used
    in this section of the documentation and see how they are used. You will also need to use
    markers and a folding margin to complete your folding implementation.
    The <code>"fold"</code> property should be set to <code>"1"</code> with
    <code>SCI_SETPROPERTY("fold", "1")</code> to enable folding. </p>
    <code><a class="message" href="#SCI_VISIBLEFROMDOCLINE">SCI_VISIBLEFROMDOCLINE(int
    docLine)</a><br />
     <a class="message" href="#SCI_DOCLINEFROMVISIBLE">SCI_DOCLINEFROMVISIBLE(int
    displayLine)</a><br />
     <a class="message" href="#SCI_SHOWLINES">SCI_SHOWLINES(int lineStart, int lineEnd)</a><br />
     <a class="message" href="#SCI_HIDELINES">SCI_HIDELINES(int lineStart, int lineEnd)</a><br />
     <a class="message" href="#SCI_GETLINEVISIBLE">SCI_GETLINEVISIBLE(int line)</a><br />
     <a class="message" href="#SCI_GETALLLINESVISIBLE">SCI_GETALLLINESVISIBLE</a><br />
     <a class="message" href="#SCI_SETFOLDLEVEL">SCI_SETFOLDLEVEL(int line, int level)</a><br />
     <a class="message" href="#SCI_GETFOLDLEVEL">SCI_GETFOLDLEVEL(int line)</a><br />
     <a class="message" href="#SCI_SETFOLDFLAGS">SCI_SETFOLDFLAGS(int flags)</a><br />
     <a class="message" href="#SCI_GETLASTCHILD">SCI_GETLASTCHILD(int line, int level)</a><br />
     <a class="message" href="#SCI_GETFOLDPARENT">SCI_GETFOLDPARENT(int line)</a><br />
     <a class="message" href="#SCI_SETFOLDEXPANDED">SCI_SETFOLDEXPANDED(int line, bool
    expanded)</a><br />
     <a class="message" href="#SCI_GETFOLDEXPANDED">SCI_GETFOLDEXPANDED(int line)</a><br />
     <a class="message" href="#SCI_CONTRACTEDFOLDNEXT">SCI_CONTRACTEDFOLDNEXT(int lineStart)</a><br />
     <a class="message" href="#SCI_TOGGLEFOLD">SCI_TOGGLEFOLD(int line)</a><br />
     <a class="message" href="#SCI_ENSUREVISIBLE">SCI_ENSUREVISIBLE(int line)</a><br />
     <a class="message" href="#SCI_ENSUREVISIBLEENFORCEPOLICY">SCI_ENSUREVISIBLEENFORCEPOLICY(int
    line)</a><br />
    </code>

    <p><b id="SCI_VISIBLEFROMDOCLINE">SCI_VISIBLEFROMDOCLINE(int docLine)</b><br />
     When some lines are hidden and/or annotations are displayed, then a particular line in the
     document may be displayed at a
    different position to its document position. If no lines are hidden and there are no annotations,
    this message returns
    <code>docLine</code>. Otherwise, this returns the display line (counting the very first visible
    line as 0). The display line of an invisible line is the same as the previous visible line. The
    display line number of the first line in the document is 0. If lines are hidden and
    <code>docLine</code> is outside the range of lines in the document, the return value is -1.
    Lines can occupy more than one display line if they wrap.</p>

    <p><b id="SCI_DOCLINEFROMVISIBLE">SCI_DOCLINEFROMVISIBLE(int displayLine)</b><br />
     When some lines are hidden and/or annotations are displayed, then a particular line in the
     document may be displayed at a
    different position to its document position. This message returns the document line number that
    corresponds to a display line (counting the display line of the first line in the document as
    0). If <code>displayLine</code> is less than or equal to 0, the result is 0. If
    <code>displayLine</code> is greater than or equal to the number of displayed lines, the result
    is the number of lines in the document.</p>

    <p><b id="SCI_SHOWLINES">SCI_SHOWLINES(int lineStart, int lineEnd)</b><br />
     <b id="SCI_HIDELINES">SCI_HIDELINES(int lineStart, int lineEnd)</b><br />
     <b id="SCI_GETLINEVISIBLE">SCI_GETLINEVISIBLE(int line)</b><br />
     <b id="SCI_GETALLLINESVISIBLE">SCI_GETALLLINESVISIBLE</b><br />
     The first two messages mark a range of lines as visible or invisible and then redraw the
    display.
    <code>SCI_GETLINEVISIBLE</code> reports on the visible state of a line and returns 1 if it is
    visible and 0 if it is not visible.
    <code>SCI_GETALLLINESVISIBLE</code> returns 1 if all lines are visible and 0
    if some lines are hidden.
    These messages have no effect on fold levels or fold
    flags. The first line can not be hidden.</p>

    <p><b id="SCI_SETFOLDLEVEL">SCI_SETFOLDLEVEL(int line, int level)</b><br />
     <b id="SCI_GETFOLDLEVEL">SCI_GETFOLDLEVEL(int line)</b><br />
     These two messages set and get a 32-bit value that contains the fold level of a line and some
    flags associated with folding. The fold level is a number in the range 0 to
    <code>SC_FOLDLEVELNUMBERMASK</code> (4095). However, the initial fold level is set to
    <code>SC_FOLDLEVELBASE</code> (1024) to allow unsigned arithmetic on folding levels. There are
    two addition flag bits. <code>SC_FOLDLEVELWHITEFLAG</code> indicates that the line is blank and
    allows it to be treated slightly different then its level may indicate. For example, blank
    lines should generally not be fold points and will be considered part of the preceding section even though
    they may have a lesser fold level.
    <code>SC_FOLDLEVELHEADERFLAG</code> indicates that
    the line is a header (fold point).</p>

    <p>Use <code>SCI_GETFOLDLEVEL(line) &amp; SC_FOLDLEVELNUMBERMASK</code> to get the fold level
    of a line. Likewise, use <code>SCI_GETFOLDLEVEL(line) &amp; SC_FOLDLEVEL*FLAG</code> to get the
    state of the flags. To set the fold level you must or in the associated flags. For instance, to
    set the level to <code>thisLevel</code> and mark a line as being a fold point use:
    <code>SCI_SETFOLDLEVEL(line, thisLevel | SC_FOLDLEVELHEADERFLAG)</code>.</p>
    If you use a lexer, you should not need to use <code>SCI_SETFOLDLEVEL</code> as this is far
    better handled by the lexer. You will need to use <code>SCI_GETFOLDLEVEL</code> to decide how
    to handle user folding requests. If you do change the fold levels, the folding margin will
    update to match your changes.

    <p><b id="SCI_SETFOLDFLAGS">SCI_SETFOLDFLAGS(int flags)</b><br />
     In addition to showing markers in the folding margin, you can indicate folds to the user by
    drawing lines in the text area. The lines are drawn in the foreground colour set for <a
    class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>. Bits set in
    <code>flags</code> determine where folding lines are drawn:<br />
    </p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Fold flags">
      <tbody>
        <tr>
          <th align="left">Symbol</th>
          <th align="left">Value</th>
          <th align="left">Effect</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"></td>
          <td align="left">1</td>
          <td align="left">Experimental feature that has been removed.</td>
        </tr>

        <tr>
          <td align="left">SC_FOLDFLAG_LINEBEFORE_EXPANDED</td>
          <td align="left">2</td>

          <td align="left">Draw above if expanded</td>
        </tr>

        <tr>
          <td align="left">SC_FOLDFLAG_LINEBEFORE_CONTRACTED</td>
          <td align="left">4</td>

          <td align="left">Draw above if not expanded</td>
        </tr>

        <tr>
          <td align="left">SC_FOLDFLAG_LINEAFTER_EXPANDED</td>
          <td align="left">8</td>

          <td align="left">Draw below if expanded</td>
        </tr>

        <tr>
          <td align="left">SC_FOLDFLAG_LINEAFTER_CONTRACTED</td>
          <td align="left">16</td>

          <td align="left">Draw below if not expanded</td>
        </tr>

        <tr>
          <td align="left">SC_FOLDFLAG_LEVELNUMBERS</td>
          <td align="left">64</td>

          <td align="left">display hexadecimal fold levels in line margin to aid debugging of
          folding. The appearance of this feature may change in the future.</td>
        </tr>
      </tbody>
    </table>

    <p>This message causes the display to redraw.</p>

    <p><b id="SCI_GETLASTCHILD">SCI_GETLASTCHILD(int startLine, int level)</b><br />
     This message searches for the next line after <code>startLine</code>, that has a folding level
    that is less than or equal to <code>level</code> and then returns the previous line number. If
    you set <code>level</code> to -1, <code>level</code> is set to the folding level of line
    <code>startLine</code>. If <code>from</code> is a fold point, <code>SCI_GETLASTCHILD(from,
    -1)</code> returns the last line that would be in made visible or hidden by toggling the fold
    state.</p>

    <p><b id="SCI_GETFOLDPARENT">SCI_GETFOLDPARENT(int startLine)</b><br />
     This message returns the line number of the first line before <code>startLine</code> that is
    marked as a fold point with <code>SC_FOLDLEVELHEADERFLAG</code> and has a fold level less than
    the <code>startLine</code>. If no line is found, or if the header flags and fold levels are
    inconsistent, the return value is -1.</p>

    <p><b id="SCI_TOGGLEFOLD">SCI_TOGGLEFOLD(int line)</b><br />
     Each fold point may be either expanded, displaying all its child lines, or contracted, hiding
    all the child lines. This message toggles the folding state of the given line as long as it has
    the <code>SC_FOLDLEVELHEADERFLAG</code> set. This message takes care of folding or expanding
    all the lines that depend on the line. The display updates after this message.</p>

    <p><b id="SCI_SETFOLDEXPANDED">SCI_SETFOLDEXPANDED(int line, bool expanded)</b><br />
     <b id="SCI_GETFOLDEXPANDED">SCI_GETFOLDEXPANDED(int line)</b><br />
     These messages set and get the expanded state of a single line. The set message has no effect
    on the visible state of the line or any lines that depend on it. It does change the markers in
    the folding margin. If you ask for the expansion state of a line that is outside the document,
    the result is <code>false</code> (0).</p>

    <p>If you just want to toggle the fold state of one line and handle all the lines that are
    dependent on it, it is much easier to use <code>SCI_TOGGLEFOLD</code>. You would use the
    <code>SCI_SETFOLDEXPANDED</code> message to process many folds without updating the display
    until you had finished. See <code>SciTEBase::FoldAll()</code> and
    <code>SciTEBase::Expand()</code> for examples of the use of these messages.</p>

    <p><b id="SCI_CONTRACTEDFOLDNEXT">SCI_CONTRACTEDFOLDNEXT(int lineStart)</b><br />
     Search efficiently for lines that are contracted fold headers.
     This is useful when saving the user's folding when switching documents or saving folding with a file.
     The search starts at line number <code>lineStart</code> and continues forwards to the end of the file.
     <code>lineStart</code> is returned if it is a contracted fold header otherwise the next contracted
     fold header is returned. If there are no more contracted fold headers then -1 is returned.</p>

    <p><b id="SCI_ENSUREVISIBLE">SCI_ENSUREVISIBLE(int line)</b><br />
     <b id="SCI_ENSUREVISIBLEENFORCEPOLICY">SCI_ENSUREVISIBLEENFORCEPOLICY(int line)</b><br />
     A line may be hidden because more than one of its parent lines is contracted. Both these
    message travels up the fold hierarchy, expanding any contracted folds until they reach the top
    level. The line will then be visible. If you use <code>SCI_ENSUREVISIBLEENFORCEPOLICY</code>,
    the vertical caret policy set by <a class="message"
    href="#SCI_SETVISIBLEPOLICY"><code>SCI_SETVISIBLEPOLICY</code></a> is then applied.</p>

    <h2 id="LineWrapping">Line wrapping</h2>

    <code><a class="message" href="#SCI_SETWRAPMODE">SCI_SETWRAPMODE(int wrapMode)</a><br />
     <a class="message" href="#SCI_GETWRAPMODE">SCI_GETWRAPMODE</a><br />
     <a class="message" href="#SCI_SETWRAPVISUALFLAGS">SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)</a><br />
     <a class="message" href="#SCI_GETWRAPVISUALFLAGS">SCI_GETWRAPVISUALFLAGS</a><br />
     <a class="message" href="#SCI_SETWRAPVISUALFLAGSLOCATION">SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)</a><br />
     <a class="message" href="#SCI_GETWRAPVISUALFLAGSLOCATION">SCI_GETWRAPVISUALFLAGSLOCATION</a><br />
     <a class="message" href="#SCI_SETWRAPINDENTMODE">SCI_SETWRAPINDENTMODE(int indentMode)</a><br />
     <a class="message" href="#SCI_GETWRAPINDENTMODE">SCI_GETWRAPINDENTMODE</a><br />
     <a class="message" href="#SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT(int indent)</a><br />
     <a class="message" href="#SCI_GETWRAPSTARTINDENT">SCI_GETWRAPSTARTINDENT</a><br />
     <a class="message" href="#SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</a><br />
     <a class="message" href="#SCI_GETLAYOUTCACHE">SCI_GETLAYOUTCACHE</a><br />
     <a class="message" href="#SCI_SETPOSITIONCACHE">SCI_SETPOSITIONCACHE(int size)</a><br />
     <a class="message" href="#SCI_GETPOSITIONCACHE">SCI_GETPOSITIONCACHE</a><br />
     <a class="message" href="#SCI_LINESSPLIT">SCI_LINESSPLIT(int pixelWidth)</a><br />
     <a class="message" href="#SCI_LINESJOIN">SCI_LINESJOIN</a><br />
     <a class="message" href="#SCI_WRAPCOUNT">SCI_WRAPCOUNT(int docLine)</a><br />
    </code>

    <p>By default, Scintilla does not wrap lines of text. If you enable line wrapping, lines wider
    than the window width are continued on the following lines. Lines are broken after space or tab
    characters or between runs of different styles. If this is not possible because a word in one
    style is wider than the window then the break occurs after the last character that completely
    fits on the line. The horizontal scroll bar does not appear when wrap mode is on.</p>

        <p>For wrapped lines Scintilla can draw visual flags (little arrows) at end of a a subline of a
        wrapped line and at begin of the next subline. These can be enabled individually, but if Scintilla
        draws the visual flag at the beginning of the next subline this subline will be indented by one char.
        Independent from drawing a visual flag at the begin the subline can have an indention.</p>

    <p>Much of the time used by Scintilla is spent on laying out and drawing text. The same text
    layout calculations may be performed many times even when the data used in these calculations
    does not change. To avoid these unnecessary calculations in some circumstances, the line layout
    cache can store the results of the calculations. The cache is invalidated whenever the
    underlying data, such as the contents or styling of the document changes. Caching the layout of
    the whole document has the most effect, making dynamic line wrap as much as 20 times faster but
    this requires 7 times the memory required by the document contents plus around 80 bytes per
    line.</p>

    <p>Wrapping is not performed immediately there is a change but is delayed until the display
    is redrawn. This delay improves peformance by allowing a set of changes to be performed
    and then wrapped and displayed once. Because of this, some operations may not occur as
    expected. If a file is read and the scroll position moved to a particular line in the text,
    such as occurs when a container tries to restore a previous editing session, then
    the scroll position will have been determined before wrapping so an unexpected range
    of text will be displayed. To scroll to the position correctly, delay the scroll until the
    wrapping has been performed by waiting for an initial
    <a class="message" href="#SCN_PAINTED">SCN_PAINTED</a> notification.</p>

    <p><b id="SCI_SETWRAPMODE">SCI_SETWRAPMODE(int wrapMode)</b><br />
     <b id="SCI_GETWRAPMODE">SCI_GETWRAPMODE</b><br />
     Set wrapMode to <code>SC_WRAP_WORD</code> (1) to enable wrapping
     on word boundaries, <code>SC_WRAP_CHAR</code> (2) to enable wrapping
     between any characters, and to <code>SC_WRAP_NONE</code> (0) to disable line
     wrapping. <code>SC_WRAP_CHAR</code> is preferred to
     <code>SC_WRAP_WORD</code> for Asian languages where there is no white space
     between words.</p>


    <p><b id="SCI_SETWRAPVISUALFLAGS">SCI_SETWRAPVISUALFLAGS(int wrapVisualFlags)</b><br />
     <b id="SCI_GETWRAPVISUALFLAGS">SCI_GETWRAPVISUALFLAGS</b><br />
                You can enable the drawing of visual flags to indicate a line is wrapped. Bits set in
                wrapVisualFlags determine which visual flags are drawn.
    </p>
    <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags">
      <tbody>
        <tr>
          <th align="left">Symbol</th>
          <th>Value</th>
          <th align="left">Effect</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAG_NONE</code></td>
          <td align="center">0</td>
          <td>No visual flags</td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAG_END</code></td>
          <td align="center">1</td>
          <td>Visual flag at end of subline of a wrapped line.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAG_START</code></td>
          <td align="center">2</td>
          <td>Visual flag at begin of subline of a wrapped line.<br />
                                             Subline is indented by at least 1 to make room for the flag.<br />
                                </td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAG_MARGIN</code></td>
          <td align="center">4</td>
          <td>Visual flag in line number margin.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETWRAPVISUALFLAGSLOCATION">SCI_SETWRAPVISUALFLAGSLOCATION(int wrapVisualFlagsLocation)</b><br />
     <b id="SCI_GETWRAPVISUALFLAGSLOCATION">SCI_GETWRAPVISUALFLAGSLOCATION</b><br />
                You can set whether the visual flags to indicate a line is wrapped are drawn near the border or near the text.
                Bits set in wrapVisualFlagsLocation set the location to near the text for the corresponding visual flag.
    </p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags locations">
      <tbody>
        <tr>
          <th align="left">Symbol</th>
          <th>Value</th>
          <th align="left">Effect</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAGLOC_DEFAULT</code></td>
          <td align="center">0</td>
          <td>Visual flags drawn near border</td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAGLOC_END_BY_TEXT</code></td>
          <td align="center">1</td>
          <td>Visual flag at end of subline drawn near text</td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPVISUALFLAGLOC_START_BY_TEXT</code></td>
          <td align="center">2</td>
          <td>Visual flag at beginning of subline drawn near text</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETWRAPINDENTMODE">SCI_SETWRAPINDENTMODE(int indentMode)</b><br />
     <b id="SCI_GETWRAPINDENTMODE">SCI_GETWRAPINDENTMODE</b><br />
                Wrapped sublines can be indented to the position of their first subline or one more indent level.
	  The default is <code>SC_WRAPINDENT_FIXED</code>.
                The modes are:
    </p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Wrap visual flags locations">
      <tbody>
        <tr>
          <th align="left">Symbol</th>
          <th>Value</th>
          <th align="left">Effect</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_WRAPINDENT_FIXED</code></td>
          <td align="center">0</td>
          <td>Wrapped sublines aligned to left of window plus amount set by
	  <a class="message" href="#SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT</a></td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPINDENT_SAME</code></td>
          <td align="center">1</td>
          <td>Wrapped sublines are aligned to first subline indent</td>
        </tr>

        <tr>
          <td align="left"><code>SC_WRAPINDENT_INDENT</code></td>
          <td align="center">2</td>
          <td>Wrapped sublines are aligned to first subline indent plus one more level of indentation</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETWRAPSTARTINDENT">SCI_SETWRAPSTARTINDENT(int indent)</b><br />
     <b id="SCI_GETWRAPSTARTINDENT">SCI_GETWRAPSTARTINDENT</b><br />
     <code>SCI_SETWRAPSTARTINDENT</code> sets the size of indentation of sublines for
                 wrapped lines in terms of the average character width in
                <a class="message" href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>.
                There are no limits on indent sizes, but values        less than 0 or large values may have
                undesirable effects.<br />
                The indention of sublines is independent of visual flags, but if
                <code>SC_WRAPVISUALFLAG_START</code> is set an indent of at least 1 is used.
     </p>

    <p><b id="SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</b><br />
     <b id="SCI_GETLAYOUTCACHE">SCI_GETLAYOUTCACHE</b><br />
     You can set <code>cacheMode</code> to one of the symbols in the table:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Line caching styles">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Layout cached for these lines</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_CACHE_NONE</code></td>

          <td align="center">0</td>

          <td>No lines are cached.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_CACHE_CARET</code></td>

          <td align="center">1</td>

          <td>The line containing the text caret. This is the default.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_CACHE_PAGE</code></td>

          <td align="center">2</td>

          <td>Visible lines plus the line containing the caret.</td>
        </tr>

        <tr>
          <td align="left"><code>SC_CACHE_DOCUMENT</code></td>

          <td align="center">3</td>

          <td>All lines in the document.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETPOSITIONCACHE">SCI_SETPOSITIONCACHE(int size)</b><br />
     <b id="SCI_GETPOSITIONCACHE">SCI_GETPOSITIONCACHE</b><br />
     The position cache stores position information for short runs of text
     so that their layout can be determined more quickly if the run recurs.
     The size in entries of this cache can be set with <code>SCI_SETPOSITIONCACHE</code>.</p>

    <p><b id="SCI_LINESSPLIT">SCI_LINESSPLIT(int pixelWidth)</b><br />
     Split a range of lines indicated by the target into lines that are at most pixelWidth wide.
     Splitting occurs on word boundaries wherever possible in a similar manner to line wrapping.
     When <code>pixelWidth</code> is 0 then the width of the window is used.
     </p>

    <p><b id="SCI_LINESJOIN">SCI_LINESJOIN</b><br />
     Join a range of lines indicated by the target into one line by
     removing line end characters.
     Where this would lead to no space between words, an extra space is inserted.
     </p>

    <p><b id="SCI_WRAPCOUNT">SCI_WRAPCOUNT(int docLine)</b><br />
    Document lines can occupy more than one display line if they wrap and this
    returns the number of display lines needed to wrap a document line.</p>

    <h2 id="Zooming">Zooming</h2>

    <p>Scintilla incorporates a "zoom factor" that lets you make all the text in the document
    larger or smaller in steps of one point. The displayed point size never goes below 2, whatever
    zoom factor you set. You can set zoom factors in the range -10 to +20 points.</p>
    <code><a class="message" href="#SCI_ZOOMIN">SCI_ZOOMIN</a><br />
     <a class="message" href="#SCI_ZOOMOUT">SCI_ZOOMOUT</a><br />
     <a class="message" href="#SCI_SETZOOM">SCI_SETZOOM(int zoomInPoints)</a><br />
     <a class="message" href="#SCI_GETZOOM">SCI_GETZOOM</a><br />
    </code>

    <p><b id="SCI_ZOOMIN">SCI_ZOOMIN</b><br />
     <b id="SCI_ZOOMOUT">SCI_ZOOMOUT</b><br />
     <code>SCI_ZOOMIN</code> increases the zoom factor by one point if the current zoom factor is
    less than 20 points. <code>SCI_ZOOMOUT</code> decreases the zoom factor by one point if the
    current zoom factor is greater than -10 points.</p>

    <p><b id="SCI_SETZOOM">SCI_SETZOOM(int zoomInPoints)</b><br />
     <b id="SCI_GETZOOM">SCI_GETZOOM</b><br />
     These messages let you set and get the zoom factor directly. There is no limit set on the
    factors you can set, so limiting yourself to -10 to +20 to match the incremental zoom functions
    is a good idea.</p>

    <h2 id="LongLines">Long lines</h2>

    <p>You can choose to mark lines that exceed a given length by drawing a vertical line or by
    colouring the background of characters that exceed the set length.</p>
    <code><a class="message" href="#SCI_SETEDGEMODE">SCI_SETEDGEMODE(int mode)</a><br />
     <a class="message" href="#SCI_GETEDGEMODE">SCI_GETEDGEMODE</a><br />
     <a class="message" href="#SCI_SETEDGECOLUMN">SCI_SETEDGECOLUMN(int column)</a><br />
     <a class="message" href="#SCI_GETEDGECOLUMN">SCI_GETEDGECOLUMN</a><br />
     <a class="message" href="#SCI_SETEDGECOLOUR">SCI_SETEDGECOLOUR(int colour)</a><br />
     <a class="message" href="#SCI_GETEDGECOLOUR">SCI_GETEDGECOLOUR</a><br />
    </code>

    <p><b id="SCI_SETEDGEMODE">SCI_SETEDGEMODE(int edgeMode)</b><br />
     <b id="SCI_GETEDGEMODE">SCI_GETEDGEMODE</b><br />
     These two messages set and get the mode used to display long lines. You can set one of the
    values in the table:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Long line styles">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Long line display mode</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>EDGE_NONE</code></td>

          <td align="center">0</td>

          <td>Long lines are not marked. This is the default state.</td>
        </tr>

        <tr>
          <td align="left"><code>EDGE_LINE</code></td>

          <td align="center">1</td>

          <td>A vertical line is drawn at the column number set by <code>SCI_SETEDGECOLUMN</code>.
          This works well for monospaced fonts. The line is drawn at a position based on the width
          of a space character in <a class="message"
          href="#StyleDefinition"><code>STYLE_DEFAULT</code></a>, so it may not work very well if
          your styles use proportional fonts or if your style have varied font sizes or you use a
          mixture of bold, italic and normal text.</td>
        </tr>

        <tr>
          <td align="left"><code>EDGE_BACKGROUND</code></td>

          <td align="center">2</td>

          <td>The background colour of characters after the column limit is changed to the colour
          set by <code>SCI_SETEDGECOLOUR</code>. This is recommended for proportional fonts.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCI_SETEDGECOLUMN">SCI_SETEDGECOLUMN(int column)</b><br />
     <b id="SCI_GETEDGECOLUMN">SCI_GETEDGECOLUMN</b><br />
     These messages set and get the column number at which to display the long line marker. When
    drawing lines, the column sets a position in units of the width of a space character in
    <code>STYLE_DEFAULT</code>. When setting the background colour, the column is a character count
    (allowing for tabs) into the line.</p>

    <p><b id="SCI_SETEDGECOLOUR">SCI_SETEDGECOLOUR(int <a class="jump"
    href="#colour">colour</a>)</b><br />
     <b id="SCI_GETEDGECOLOUR">SCI_GETEDGECOLOUR</b><br />
     These messages set and get the colour of the marker used to show that a line has exceeded the
    length set by <code>SCI_SETEDGECOLUMN</code>.</p>

    <h2 id="Lexer">Lexer</h2>

    <p>If you define the symbol <code>SCI_LEXER</code> when building Scintilla, (this is sometimes
    called the SciLexer version of Scintilla), lexing support for a wide range of programming
    languages is included and the messages in this section are supported. If you want to set
    styling and fold points for an unsupported language you can either do this in the container or
    better still, write your own lexer following the pattern of one of the existing ones.</p>

    <p>Scintilla also supports external lexers. These are DLLs (on Windows) or .so modules (on GTK+/Linux) that export three
    functions: <code>GetLexerCount</code>, <code>GetLexerName</code>, and
    <code>GetLexerFactory</code>. See <code>externalLexer.cxx</code> for more.</p>
    <code><a class="message" href="#SCI_SETLEXER">SCI_SETLEXER(int lexer)</a><br />
     <a class="message" href="#SCI_GETLEXER">SCI_GETLEXER</a><br />
     <a class="message" href="#SCI_SETLEXERLANGUAGE">SCI_SETLEXERLANGUAGE(&lt;unused&gt;, const char
    *name)</a><br />
     <a class="message" href="#SCI_GETLEXERLANGUAGE">SCI_GETLEXERLANGUAGE(&lt;unused&gt;, char
    *name)</a><br />
     <a class="message" href="#SCI_LOADLEXERLIBRARY">SCI_LOADLEXERLIBRARY(&lt;unused&gt;, const char
    *path)</a><br />
     <a class="message" href="#SCI_COLOURISE">SCI_COLOURISE(int start, int end)</a><br />
     <a class="message" href="#SCI_CHANGELEXERSTATE">SCI_CHANGELEXERSTATE(int start, int end)</a><br />
     <a class="message" href="#SCI_PROPERTYNAMES">SCI_PROPERTYNAMES(&lt;unused&gt;, char *names)</a><br />
     <a class="message" href="#SCI_PROPERTYTYPE">SCI_PROPERTYTYPE(const char *name)</a><br />
     <a class="message" href="#SCI_DESCRIBEPROPERTY">SCI_DESCRIBEPROPERTY(const char *name, char *description)</a><br />
     <a class="message" href="#SCI_SETPROPERTY">SCI_SETPROPERTY(const char *key, const char *value)</a><br />
     <a class="message" href="#SCI_GETPROPERTY">SCI_GETPROPERTY(const char *key, char *value)</a><br />
     <a class="message" href="#SCI_GETPROPERTYEXPANDED">SCI_GETPROPERTYEXPANDED(const char *key, char *value)</a><br />
     <a class="message" href="#SCI_GETPROPERTYINT">SCI_GETPROPERTYINT(const char *key, int default)</a><br />
     <a class="message" href="#SCI_DESCRIBEKEYWORDSETS">SCI_DESCRIBEKEYWORDSETS(&lt;unused&gt;, char *descriptions)</a><br />
     <a class="message" href="#SCI_SETKEYWORDS">SCI_SETKEYWORDS(int keyWordSet, const char
    *keyWordList)</a><br />
     <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a><br />

<div  class="provisional">
     <a class="message" href="#SCI_GETSUBSTYLEBASES">SCI_GETSUBSTYLEBASES(&lt;unused&gt;, char *styles)</a><br />
     <a class="message" href="#SCI_DISTANCETOSECONDARYSTYLES">SCI_DISTANCETOSECONDARYSTYLES</a><br />
     <a class="message" href="#SCI_ALLOCATESUBSTYLES">SCI_ALLOCATESUBSTYLES(int styleBase, int numberStyles)</a><br />
     <a class="message" href="#SCI_FREESUBSTYLES">SCI_FREESUBSTYLES</a><br />
     <a class="message" href="#SCI_GETSUBSTYLESSTART">SCI_GETSUBSTYLESSTART(int styleBase)</a><br />
     <a class="message" href="#SCI_GETSUBSTYLESLENGTH">SCI_GETSUBSTYLESLENGTH(int styleBase)</a><br />
     <a class="message" href="#SCI_SETIDENTIFIERS">SCI_SETIDENTIFIERS(int style, const char *identifiers)</a><br />
</div>

    </code>

    <p><b id="SCI_SETLEXER">SCI_SETLEXER(int lexer)</b><br />
     <b id="SCI_GETLEXER">SCI_GETLEXER</b><br />
     You can select the lexer to use with an integer code from the <code>SCLEX_*</code> enumeration
    in <code>Scintilla.h</code>. There are two codes in this sequence that do not use lexers:
    <code>SCLEX_NULL</code> to select no lexing action and <code>SCLEX_CONTAINER</code> which sends
    the <code><a class="message" href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a></code> notification to
    the container whenever a range of text needs to be styled. You cannot use the
    <code>SCLEX_AUTOMATIC</code> value; this identifies additional external lexers that Scintilla
    assigns unused lexer numbers to.</p>

    <p><b id="SCI_SETLEXERLANGUAGE">SCI_SETLEXERLANGUAGE(&lt;unused&gt;, const char *name)</b><br />
    <b id="SCI_GETLEXERLANGUAGE">SCI_GETLEXERLANGUAGE(&lt;unused&gt;, char *name)</b><br />
     <code>SCI_SETLEXERLANGUAGE</code> lets you select a lexer by name, and is the only method if you are using an
    external lexer or if you have written a lexer module for a language of your own and do not wish
    to assign it an explicit lexer number. To select an existing lexer, set <code>name</code> to
    match the (case sensitive) name given to the module, for example "ada" or "python", not "Ada"
    or "Python". To locate the name for the built-in lexers, open the relevant
    <code>Lex*.cxx</code> file and search for <code>LexerModule</code>. The third argument in the
    <code>LexerModule</code> constructor is the name to use.</p>

    <p>To test if your lexer assignment worked, use <a class="message"
    href="#SCI_GETLEXER"><code>SCI_GETLEXER</code></a> before and after setting the new lexer to
    see if the lexer number changed.</p>

    <p><code>SCI_GETLEXERLANGUAGE</code> retrieves the name of the lexer.</p>

    <p><b id="SCI_LOADLEXERLIBRARY">SCI_LOADLEXERLIBRARY(&lt;unused&gt;, const char *path)</b><br />
     Load a lexer implemented in a shared library. This is a .so file on GTK+/Linux or a .DLL file on Windows.
     </p>

    <p><b id="SCI_COLOURISE">SCI_COLOURISE(int startPos, int endPos)</b><br />
     This requests the current lexer or the container (if the lexer is set to
    <code>SCLEX_CONTAINER</code>) to style the document between <code>startPos</code> and
    <code>endPos</code>. If <code>endPos</code> is -1, the document is styled from
    <code>startPos</code> to the end. If the <code>"fold"</code> property is set to
    <code>"1"</code> and your lexer or container supports folding, fold levels are also set. This
    message causes a redraw.</p>

    <p><b id="SCI_CHANGELEXERSTATE">SCI_CHANGELEXERSTATE(int startPos, int endPos)</b><br />
    Indicate that the internal state of a lexer has changed over a range and therefore
    there may be a need to redraw.</p>

    <p><b id="SCI_PROPERTYNAMES">SCI_PROPERTYNAMES(&lt;unused&gt;, char *names)</b><br />
    <b id="SCI_PROPERTYTYPE">SCI_PROPERTYTYPE(const char *name)</b><br />
    <b id="SCI_DESCRIBEPROPERTY">SCI_DESCRIBEPROPERTY(const char *name, char *description)</b><br />
    Information may be retrieved about the properties that can be set for the current lexer.
    This information is only available for newer lexers.
    <code>SCI_PROPERTYNAMES</code> returns a string with all of the valid properties separated by "\n".
    If the lexer does not support this call then an empty string is returned.
    Properties may be boolean (<code>SC_TYPE_BOOLEAN</code>), integer (<code>SC_TYPE_INTEGER</code>),
    or string (<code>SC_TYPE_STRING</code>) and this is found with <code>SCI_PROPERTYTYPE</code>.
    A description of a property in English is returned by <code>SCI_DESCRIBEPROPERTY</code>.</p>

    <p><b id="SCI_SETPROPERTY">SCI_SETPROPERTY(const char *key, const char *value)</b><br />
     You can communicate settings to lexers with keyword:value string pairs. There is no limit to
    the number of keyword pairs you can set, other than available memory. <code>key</code> is a
    case sensitive keyword, <code>value</code> is a string that is associated with the keyword. If
    there is already a value string associated with the keyword, it is replaced. If you pass a zero
    length string, the message does nothing. Both <code>key</code> and <code>value</code> are used
    without modification; extra spaces at the beginning or end of <code>key</code> are
    significant.</p>

    <p>The <code>value</code> string can refer to other keywords. For example,
    <code>SCI_SETPROPERTY("foldTimes10", "$(fold)0")</code> stores the string
    <code>"$(fold)0"</code>, but when this is accessed, the <code>$(fold)</code> is replaced by the
    value of the <code>"fold"</code> keyword (or by nothing if this keyword does not exist).</p>

    <p>Currently the "fold" property is defined for most of the lexers to set the fold structure if
    set to "1". <code>SCLEX_PYTHON</code> understands <code>"tab.timmy.whinge.level"</code> as a
    setting that determines how to indicate bad indentation. Most keywords have values that are
    interpreted as integers. Search the lexer sources for <code>GetPropertyInt</code> to see how
    properties are used.</p>

    <p>There is a convention for naming properties used by lexers so that the set of properties can be found by scripts.
    Property names should start with "lexer.&lt;lexer&gt;." or "fold.&lt;lexer&gt;." when they apply to one
    lexer or start with "lexer." or "fold." if they apply to multiple lexers.</p>

    <p>Applications may discover the set of properties used by searching the source code of lexers for lines that contain
    <code>GetProperty</code> and a double quoted string and extract the value of the double quoted string as the property name.
    The <code>scintilla/src/LexGen.py</code> script does this and can be used as an example.
    Documentation for the property may be located above the call as a multi-line comment starting with
    <br/><code>// property &lt;property-name&gt;</code></p>

    <p><b id="SCI_GETPROPERTY">SCI_GETPROPERTY(const char *key, char *value)</b><br />
    Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied
    buffer and return the length (not including the terminating 0).  If not found, copy an empty string
    to the buffer and return 0.</p>

    <p>Note that  "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
    <code>SCI_SETPROPERTY</code></a> will not be performed.</p>

    <p>If the value argument is 0 then the length that should be allocated to store the value is returned;
    again, the terminating 0 is not included.</p>

    <p><b id="SCI_GETPROPERTYEXPANDED">SCI_GETPROPERTYEXPANDED(const char *key, char *value)</b><br />
    Lookup a keyword:value pair using the specified key; if found, copy the value to the user-supplied
    buffer and return the length (not including the terminating 0).  If not found, copy an empty string
    to the buffer and return 0.</p>

    <p>Note that  "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
    <code>SCI_SETPROPERTY</code></a> will be performed.</p>

    <p>If the value argument is 0 then the length that should be allocated to store the value (including any indicated keyword replacement)
    is returned; again, the terminating 0 is not included.</p>

    <p><b id="SCI_GETPROPERTYINT">SCI_GETPROPERTYINT(const char *key, int default)</b><br />
    Lookup a keyword:value pair using the specified key; if found, interpret the value as an integer and return it.
    If not found (or the value is an empty string) then return the supplied default.  If the keyword:value pair is found but is not
    a number, then return 0.</p>

    <p>Note that  "keyword replacement" as described in <a class="message" href="#SCI_SETPROPERTY">
    <code>SCI_SETPROPERTY</code></a> will be performed before any numeric interpretation.</p>

    <p><b id="SCI_SETKEYWORDS">SCI_SETKEYWORDS(int keyWordSet, const char *keyWordList)</b><br />
     You can set up to 9 lists of keywords for use by the current lexer. This was increased from 6
    at revision 1.50. <code>keyWordSet</code> can be 0 to 8 (actually 0 to <code>KEYWORDSET_MAX</code>)
    and selects which keyword list to replace. <code>keyWordList</code> is a list of keywords
    separated by spaces, tabs, <code>"\n"</code> or <code>"\r"</code> or any combination of these.
    It is expected that the keywords will be composed of standard ASCII printing characters,
    but there is nothing to stop you using any non-separator character codes from 1 to 255
    (except common sense).</p>

    <p>How these keywords are used is entirely up to the lexer. Some languages, such as HTML may
    contain embedded languages, VBScript and JavaScript are common for HTML. For HTML, key word set
    0 is for HTML, 1 is for JavaScript and 2 is for VBScript, 3 is for Python, 4 is for PHP and 5
    is for SGML and DTD keywords. Review the lexer code to see examples of keyword list. A fully
    conforming lexer sets the fourth argument of the <code>LexerModule</code> constructor to be a
    list of strings that describe the uses of the keyword lists.</p>

    <p>Alternatively, you might use set 0 for general keywords, set 1 for keywords that cause
    indentation and set 2 for keywords that cause unindentation. Yet again, you might have a simple
    lexer that colours keywords and you could change languages by changing the keywords in set 0.
    There is nothing to stop you building your own keyword lists into the lexer, but this means
    that the lexer must be rebuilt if more keywords are added.</p>

    <p><b id="SCI_DESCRIBEKEYWORDSETS">SCI_DESCRIBEKEYWORDSETS(&lt;unused&gt;, char *descriptions)</b><br />
    A description of all of the keyword sets separated by "\n" is returned by <code>SCI_DESCRIBEKEYWORDSETS</code>.</p>

    <p><b id="SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</b><br />
     Retrieve the number of bits the current lexer needs for styling. This should normally be the argument
     to <a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS</a>.
     </p>

<div  class="provisional">
    <h3 id="Substyles">Substyles</h3>
    <a href="#ProvisionalMessages">These features are provisional</a><br />
    <p>Lexers may support several different sublanguages and each sublanguage may want to style some number of
    sets of identifiers (or similar lexemes such as documentation keywords) uniquely. Preallocating a large number for each
    purpose would exhaust the number of allowed styles quickly.
    This is alleviated by substyles which allow the application to determine how many sets of identifiers to allocate for
    each purpose.
    Lexers have to explicitly support this feature by implementing the methods in <code>ILexerWithSubStyles</code>.</p>

    <p><b id="SCI_GETSUBSTYLEBASES">SCI_GETSUBSTYLEBASES(&lt;unused&gt;, char *styles)</b><br />
     Fill <code>styles</code> with a byte for each style that can be split into substyles.</p>

    <p><b id="SCI_DISTANCETOSECONDARYSTYLES">SCI_DISTANCETOSECONDARYSTYLES</b><br />
     Returns the distance between a primary style and its corresponding secondary style.</p>

    <p><b id="SCI_ALLOCATESUBSTYLES">SCI_ALLOCATESUBSTYLES(int styleBase, int numberStyles)</b><br />
     Allocate some number of substyles for a particular base style returning the first substyle number allocated.
     Substyles are allocated contiguously.</p>

    <p><b id="SCI_FREESUBSTYLES">SCI_FREESUBSTYLES</b><br />
     Free all allocated substyles.</p>

    <p><b id="SCI_GETSUBSTYLESSTART">SCI_GETSUBSTYLESSTART(int styleBase)</b><br />
    <b id="SCI_GETSUBSTYLESLENGTH">SCI_GETSUBSTYLESLENGTH(int styleBase)</b><br />
     Return the start and length of the substyles allocated for a base style.</p>

    <p><b id="SCI_SETIDENTIFIERS">SCI_SETIDENTIFIERS(int style, const char *identifiers)</b><br />
     Similar to <code>SCI_SETKEYWORDS</code> but for substyles.</p>
</div>

    <h2 id="LexerObjects">Lexer Objects</h2>

    <p>Lexers are programmed as objects that implement the ILexer interface and that interact
    with the document they are lexing through the IDocument interface.
    Previously lexers were defined by providing lexing and folding functions but creating an object
    to handle the interaction of a lexer with a document allows the lexer to store state information that
    can be used during lexing. For example a C++ lexer may store a set of preprocessor definitions
    or variable declarations and style these depending on their role.</p>

    <p>A set of helper classes allows older lexers defined by functions to be used in Scintilla.</p>
<h4>ILexer</h4>

<div class="highlighted">
<span class="S5">class</span><span class="S0"> </span>ILexer<span class="S0"> </span><span class="S10">{</span><br />
<span class="S5">public</span><span class="S10">:</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Version<span class="S10">()</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Release<span class="S10">()</span><span class="S0"> </span>
<span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span>
<span class="S5">char</span><span class="S0"> </span>
<span class="S10">*</span><span class="S0"> </span>
SCI_METHOD<span class="S0"> </span>PropertyNames<span class="S10">()</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>PropertyType<span class="S10">(</span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>name<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>DescribeProperty<span class="S10">(</span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>name<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>PropertySet<span class="S10">(</span><span class="S5">const</span>
<span class="S0"> </span><span class="S5">char</span>
<span class="S0"> </span><span class="S10">*</span>key<span class="S10">,</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>
<span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>val<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span>
<span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>DescribeWordListSets<span class="S10">()</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>WordListSet<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>n<span class="S10">,</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>
<span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>wl<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Lex<span class="S10">(</span><span class="S5">unsigned</span>
<span class="S0"> </span><span class="S5">int</span>
<span class="S0"> </span>startPos<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span>
<span class="S0"> </span>lengthDoc<span class="S10">,</span><span class="S0">
</span><span class="S5">int</span><span class="S0"> </span>initStyle<span class="S10">,</span>
<span class="S0"> </span>IDocument<span class="S0">
</span><span class="S10">*</span>pAccess<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Fold<span class="S10">(</span><span class="S5">unsigned</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>startPos<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span>
<span class="S0"> </span>lengthDoc<span class="S10">,</span><span class="S0">
</span><span class="S5">int</span><span class="S0"> </span>initStyle<span class="S10">,</span>
<span class="S0"> </span>IDocument<span class="S0">
</span><span class="S10">*</span>pAccess<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>
<span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0">
</span>PrivateCall<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>operation<span class="S10">,</span><span class="S0">
</span><span class="S5">void</span><span class="S0"> </span>
<span class="S10">*</span>pointer<span class="S10">)</span><span class="S0"> </span>
<span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S10">};</span><br />
</div>

<p>
The return values from PropertySet and WordListSet are used to indicate whether the change requires
performing lexing or folding over any of the document. It is the position at which to restart lexing and folding or -1
if the change does not require any extra work on the document.
A simple approach is to return 0 if there is any possibility that a change requires lexing the document again while an
optimisation could be to remember where a setting first affects the document and return that position.
</p>

<p><code>Release</code> is called to destroy the lexer object.</p>

<p><code>PrivateCall</code> allows for direct communication between the
application and a lexer. An example would be where an application
maintains a single large data structure containing symbolic information
about system headers (like Windows.h) and provides this to the lexer
where it can be applied to each document. This avoids the costs of
constructing the system header information for each document. This is
invoked with the <code>SCI_PRIVATELEXERCALL</code> API.</p>

<p><code>Fold</code> is called with the exact range that needs folding.
Previously, lexers were called with a range that started one line before the range that
needs to be folded as this allowed fixing up the last line from the previous folding.
The new approach allows the lexer to decide whether to backtrack or to handle this
more efficiently.</p>

<h4 class="provisional">ILexerWithSubStyles</h4>

<p class="provisional">
To allow lexers to report which line ends they support, and to support substyles,
<code>Ilexer</code> is extended to <code>ILexerWithSubStyles</code>.
</p>

<div class="highlighted">
<span class="S5">class</span><span class="S0"> </span>ILexerWithSubStyles<span class="S0"> </span><span class="S10">:</span><span class="S0"> </span><span class="S5">public</span><span class="S0"> </span>ILexer<span class="S0"> </span><span class="S10">{</span><br />
<span class="S5">public</span><span class="S10">:</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>LineEndTypesSupported<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>AllocateSubStyles<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">,</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>numberStyles<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SubStylesStart<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SubStylesLength<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>FreeSubStyles<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SetIdentifiers<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>style<span class="S10">,</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>identifiers<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>DistanceToSecondaryStyles<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>GetSubStyleBases<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S10">};</span><br />
</div>

<h4>IDocument</h4>

<div class="highlighted">
<span class="S5">class</span><span class="S0"> </span>IDocument
<span class="S0"> </span><span class="S10">{</span><br />
<span class="S5">public</span><span class="S10">:</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Version<span class="S10">()</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>SetErrorStatus<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>status<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>Length<span class="S10">()</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>GetCharRange<span class="S10">(</span><span class="S5">char</span>
<span class="S0"> </span><span class="S10">*</span>buffer<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>
position<span class="S10">,</span><span class="S0"> </span>
<span class="S5">int</span><span class="S0"> </span>lengthRetrieve<span class="S10">)</span>
<span class="S0"> </span><span class="S5">const</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">char</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>StyleAt<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>position<span class="S10">)</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>LineFromPosition<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>position<span class="S10">)</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span>
<span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>LineStart<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>line<span class="S10">)</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span>
<span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>GetLevel<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>line<span class="S10">)</span>
<span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span>
<span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>SetLevel<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>line<span class="S10">,</span><span class="S0"> </span>
<span class="S5">int</span><span class="S0"> </span>level<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>GetLineState<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>line<span class="S10">)</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span>
<span class="S10">=</span><span class="S0"> </span><span class="S4">0</span>
<span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>SetLineState<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>line<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>state<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>StartStyling<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>position<span class="S10">,</span>
<span class="S0"> </span><span class="S5">char</span><span class="S0"> </span>mask<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">bool</span>
<span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>SetStyleFor<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>length<span class="S10">,</span>
<span class="S0"> </span><span class="S5">char</span><span class="S0"> </span>style<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span>
<span class="S10">;</span><br />
 <span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">bool</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>SetStyles<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>length<span class="S10">,</span><span class="S0"> </span>
<span class="S5">const</span><span class="S0"> </span><span class="S5">char</span>
<span class="S0"> </span><span class="S10">*</span>styles<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span>
<span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>DecorationSetCurrentIndicator<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>indicator<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>DecorationFillRange<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>position<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>value<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>fillLength<span class="S10">)</span>
<span class="S0">
 </span><span class="S10">=</span><span class="S0"> </span>
<span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>ChangeLexerState<span class="S10">(</span><span class="S5">int</span>
<span class="S0"> </span>start<span class="S10">,</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>end<span class="S10">)</span>
<span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span>
<span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>CodePage<span class="S10">()</span><span class="S0">
 </span><span class="S5">const</span><span class="S0"> </span>
<span class="S10">=</span><span class="S0"> </span><span class="S4">0</span>
<span class="S10">;</span><br />
<span class="S0">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">bool</span>
<span class="S0"> </span>SCI_METHOD
<span class="S0"> </span>IsDBCSLeadByte<span class="S10">(</span><span class="S5">char</span>
<span class="S0"> </span>ch<span class="S10">)</span>
<span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">=</span>
<span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S10">};</span><br />
</div>

<p>Scintilla tries to minimize the consequences of modifying text to
only relex and redraw the line of the change where possible. Lexer
objects contain their own private extra state which can affect later
lines. For example, if the C++ lexer is greying out inactive code
segments then changing the statement <code>#define BEOS 0</code> to <code>#define
 BEOS 1</code> may require restyling and redisplaying later parts of the
 document. The lexer can call <code>ChangeLexerState</code> to signal to
 the document that it should relex and display more.</p>

<p><code>SetErrorStatus</code> is used to notify the document of
exceptions. Exceptions should not be thrown over build boundaries as the
 two sides may be built with different compilers or incompatible
exception options.</p>

<h4>IDocumentWithLineEnd</h4>

<p>
To allow lexers to determine the end position of a line and thus more easily support Unicode line ends
<code>IDocument</code> is extended to <code>IDocumentWithLineEnd</code>.
</p>

<div class="highlighted">
<span class="S5">class</span><span class="S0"> </span>IDocumentWithLineEnd<span class="S0"> </span><span class="S10">:</span><span class="S0"> </span><span class="S5">public</span><span class="S0"> </span>IDocument<span class="S0"> </span><span class="S10">{</span><br />
<span class="S5">public</span><span class="S10">:</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>LineEnd<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>line<span class="S10">)</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
<span class="S10">};</span><br />
</div>

<p>The <code>ILexer</code>, <code>ILexerWithSubStyles</code>, <code>IDocument</code>, and 
<code>IDocumentWithLineEnd</code>  interfaces may be
expanded in the future with extended versions (<code>ILexer2</code>...).
 The <code>Version</code> method indicates which interface is
implemented and thus which methods may be called.</p>

    <h2 id="Notifications">Notifications</h2>

    <p>Notifications are sent (fired) from the Scintilla control to its container when an event has
    occurred that may interest the container. Notifications are sent using the
    <code>WM_NOTIFY</code> message on Windows and the "notify" signal on GTK+. The container is
    passed a <code>SCNotification</code> structure containing information about the event.</p>
<pre id="SCNotification">
struct NotifyHeader {   // This matches the Win32 NMHDR structure
    void *hwndFrom;     // environment specific window handle/pointer
    uptr_t idFrom;        // CtrlID of the window issuing the notification
    unsigned int code;  // The SCN_* notification code
};

struct SCNotification {
	struct Sci_NotifyHeader nmhdr;
	int position;
	/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
	/* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */
	/* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */
	/* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
	/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */

	int ch;		/* SCN_CHARADDED, SCN_KEY */
	int modifiers;
	/* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
	/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */

	int modificationType;	/* SCN_MODIFIED */
	const char *text;
	/* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */

	int length;		/* SCN_MODIFIED */
	int linesAdded;	/* SCN_MODIFIED */
	int message;	/* SCN_MACRORECORD */
	uptr_t wParam;	/* SCN_MACRORECORD */
	sptr_t lParam;	/* SCN_MACRORECORD */
	int line;		/* SCN_MODIFIED */
	int foldLevelNow;	/* SCN_MODIFIED */
	int foldLevelPrev;	/* SCN_MODIFIED */
	int margin;		/* SCN_MARGINCLICK */
	int listType;	/* SCN_USERLISTSELECTION */
	int x;			/* SCN_DWELLSTART, SCN_DWELLEND */
	int y;		/* SCN_DWELLSTART, SCN_DWELLEND */
	int token;		/* SCN_MODIFIED with SC_MOD_CONTAINER */
	int annotationLinesAdded;	/* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */
	int updated;	/* SCN_UPDATEUI */
};
</pre>

    <p>The notification messages that your container can choose to handle and the messages
    associated with them are:</p>
    <code><a class="message" href="#SCN_STYLENEEDED">SCN_STYLENEEDED</a><br />
     <a class="message" href="#SCN_CHARADDED">SCN_CHARADDED</a><br />
     <a class="message" href="#SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</a><br />
     <a class="message" href="#SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</a><br />
     <a class="message" href="#SCN_MODIFYATTEMPTRO">SCN_MODIFYATTEMPTRO</a><br />
     <a class="message" href="#SCN_KEY">SCN_KEY</a><br />
     <a class="message" href="#SCN_DOUBLECLICK">SCN_DOUBLECLICK</a><br />
     <a class="message" href="#SCN_UPDATEUI">SCN_UPDATEUI</a><br />
     <a class="message" href="#SCN_MODIFIED">SCN_MODIFIED</a><br />
     <a class="message" href="#SCN_MACRORECORD">SCN_MACRORECORD</a><br />
     <a class="message" href="#SCN_MARGINCLICK">SCN_MARGINCLICK</a><br />
     <a class="message" href="#SCN_NEEDSHOWN">SCN_NEEDSHOWN</a><br />
     <a class="message" href="#SCN_PAINTED">SCN_PAINTED</a><br />
     <a class="message" href="#SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</a><br />
     <a class="message" href="#SCN_URIDROPPED">SCN_URIDROPPED</a><br />
     <a class="message" href="#SCN_DWELLSTART">SCN_DWELLSTART</a><br />
     <a class="message" href="#SCN_DWELLEND">SCN_DWELLEND</a><br />
     <a class="message" href="#SCN_ZOOM">SCN_ZOOM</a><br />
     <a class="message" href="#SCN_HOTSPOTCLICK">SCN_HOTSPOTCLICK</a><br />
     <a class="message" href="#SCN_HOTSPOTDOUBLECLICK">SCN_HOTSPOTDOUBLECLICK</a><br />
     <a class="message" href="#SCN_HOTSPOTRELEASECLICK">SCN_HOTSPOTRELEASECLICK</a><br />
     <a class="message" href="#SCN_INDICATORCLICK">SCN_INDICATORCLICK</a><br />
     <a class="message" href="#SCN_INDICATORRELEASE">SCN_INDICATORRELEASE</a><br />
     <a class="message" href="#SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</a><br />
     <a class="message" href="#SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</a><br />
     <a class="message" href="#SCN_AUTOCCANCELLED">SCN_AUTOCCANCELLED</a><br />
     <a class="message" href="#SCN_AUTOCCHARDELETED">SCN_AUTOCCHARDELETED</a><br />
    </code>

    <p>The following <code>SCI_*</code> messages are associated with these notifications:</p>
    <code><a class="message" href="#SCI_SETMODEVENTMASK">SCI_SETMODEVENTMASK(int eventMask)</a><br />
     <a class="message" href="#SCI_GETMODEVENTMASK">SCI_GETMODEVENTMASK</a><br />
     <a class="message" href="#SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME(int milliseconds)</a><br />
     <a class="message" href="#SCI_GETMOUSEDWELLTIME">SCI_GETMOUSEDWELLTIME</a><br />
     <a class="message" href="#SCI_SETIDENTIFIER">SCI_SETIDENTIFIER(int identifier)</a><br />
     <a class="message" href="#SCI_GETIDENTIFIER">SCI_GETIDENTIFIER</a><br />
    </code>

    <p>The following additional notifications are sent using the <code>WM_COMMAND</code> message on
    Windows and the "Command" signal on GTK+. This emulates the Windows Edit control. Only the lower
    16 bits of the control's ID is passed in these notifications.</p>
    <code><a class="message" href="#SCEN_CHANGE">SCEN_CHANGE</a><br />
     <a class="message" href="#SCEN_SETFOCUS">SCEN_SETFOCUS</a><br />
     <a class="message" href="#SCEN_KILLFOCUS">SCEN_KILLFOCUS</a><br />
    </code>

    <p><b id="SCI_SETIDENTIFIER">SCI_SETIDENTIFIER(int identifier)</b><br />
     <b id="SCI_GETIDENTIFIER">SCI_GETIDENTIFIER</b><br />
     These two messages set and get the identifier of the Scintilla instance which is included in notifications as the 
     <code>idFrom</code> field. 
     When an application creates multiple Scintilla widgets, this allows the source of each notification to be found.
     On Windows, this value is initialised in the <code>CreateWindow</code> call and stored as the 
     <code>GWLP_ID</code> attribute of the window. 
     The value should be small, preferrably less than 16 bits,
     rather than a pointer as some of the functions will only transmit 16 or 32 bits.
    </p>

    <p><b id="SCN_STYLENEEDED">SCN_STYLENEEDED</b><br />
     If you used <code><a class="message"
    href="#SCI_SETLEXER">SCI_SETLEXER</a>(SCLEX_CONTAINER)</code> to make the container act as the
    lexer, you will receive this notification when Scintilla is about to display or print text that
    requires styling. You are required to style the text from the line that contains the position
    returned by <a class="message" href="#SCI_GETENDSTYLED"><code>SCI_GETENDSTYLED</code></a> up to
    the position passed in <code>SCNotification.position</code>. Symbolically, you need code of the
    form:</p>
<pre>
    startPos = <a class="message" href="#SCI_GETENDSTYLED">SCI_GETENDSTYLED</a>()
    lineNumber = <a class="message"
href="#SCI_LINEFROMPOSITION">SCI_LINEFROMPOSITION</a>(startPos);
    startPos = <a class="message"
href="#SCI_POSITIONFROMLINE">SCI_POSITIONFROMLINE</a>(lineNumber);
    MyStyleRoutine(startPos, SCNotification.position);
</pre>

    <p><b id="SCN_CHARADDED">SCN_CHARADDED</b><br />
     This is sent when the user types an ordinary text character (as opposed to a command
    character) that is entered into the text. The container can use this to decide to display a <a
    class="jump" href="#CallTips">call tip</a> or an <a class="jump" href="#Autocompletion">auto
    completion list</a>. The character is in <code>SCNotification.ch</code>.
        This notification is sent before the character has been styled so processing that depends on
        styling should instead be performed in the SCN_UPDATEUI notification.</p>

    <p><b id="SCN_SAVEPOINTREACHED">SCN_SAVEPOINTREACHED</b><br />
     <b id="SCN_SAVEPOINTLEFT">SCN_SAVEPOINTLEFT</b><br />
     Sent to the container when the save point is entered or left, allowing the container to
    display a "document dirty" indicator and change its menus.<br />
     See also: <a class="message" href="#SCI_SETSAVEPOINT"><code>SCI_SETSAVEPOINT</code></a>, <a
    class="message" href="#SCI_GETMODIFY"><code>SCI_GETMODIFY</code></a></p>

    <p><b id="SCN_MODIFYATTEMPTRO">SCN_MODIFYATTEMPTRO</b><br />
     When in read-only mode, this notification is sent to the container if the user tries to change
    the text. This can be used to check the document out of a version control system. You can set
    the read-only state of a document with <code><a class="message"
    href="#SCI_SETREADONLY">SCI_SETREADONLY</a></code>.</p>

    <p><b id="SCN_KEY">SCN_KEY</b><br />
     Reports all keys pressed but not consumed by Scintilla. Used on GTK+ because of
     some problems with keyboard focus and is not sent by the Windows version. <code>SCNotification.ch</code> holds the key code and
    <code>SCNotification.modifiers</code> holds the modifiers. This notification is sent if the
    modifiers include <code>SCMOD_ALT</code> or <code>SCMOD_CTRL</code> and the key code is less
    than 256.</p>

    <p><b id="SCN_DOUBLECLICK">SCN_DOUBLECLICK</b><br />
     The mouse button was double clicked in editor. The <code>position</code> field is set to the text position of the
    double click, the <code>line</code> field is set to the line of the double click, and
    the <code>modifiers</code> field is set to the key modifiers
    held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.</p>

    <p><b id="SCN_UPDATEUI">SCN_UPDATEUI</b><br />
     Either the text or styling of the document has changed or the selection range or scroll position has changed.
     Now would be a good time to update any container UI elements that depend on document or view state.
     The <code>updated</code> field is set to the bit set of things changed since the previous notification.</p>
    <table cellpadding="1" cellspacing="2" border="0" summary="Modify notification type flags">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Meaning</th>

        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_UPDATE_CONTENT</code></td>

          <td align="center">0x01</td>

          <td>Contents, styling or markers have been changed.</td>

        </tr>

        <tr>
          <td align="left"><code>SC_UPDATE_SELECTION</code></td>

          <td align="center">0x02</td>

          <td>Selection has been changed.</td>

        </tr>

        <tr>
          <td align="left"><code>SC_UPDATE_V_SCROLL</code></td>

          <td align="center">0x04</td>

          <td>Scrolled vertically.</td>

        </tr>

        <tr>
          <td align="left"><code>SC_UPDATE_H_SCROLL</code></td>

          <td align="center">0x08</td>

          <td>Scrolled horizontally.</td>

        </tr>
      </tbody>
    </table>

    <p><b id="SCN_MODIFIED">SCN_MODIFIED</b><br />
     This notification is sent when the text or styling of the document changes or is about to
    change. You can set a mask for the notifications that are sent to the container with <a
    class="message" href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>. The
    notification structure contains information about what changed, how the change occurred and
    whether this changed the number of lines in the document. No modifications may be performed
    while in a <code>SCN_MODIFIED</code> event. The <code>SCNotification</code> fields used
    are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Modify notification types">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>modificationType</code></td>

          <td align="left">A set of flags that identify the change(s) made. See the next
          table.</td>
        </tr>

        <tr>
          <td align="left"><code>position</code></td>

          <td align="left">Start position of a text or styling change. Set to 0 if not used.</td>
        </tr>

        <tr>
          <td align="left"><code>length</code></td>

          <td align="left">Length of the change in cells or characters when the text or styling
          changes. Set to 0 if not used.</td>
        </tr>

        <tr>
          <td align="left"><code>linesAdded</code></td>

          <td align="left">Number of added lines. If negative, the number of deleted lines. Set to
          0 if not used or no lines added or deleted.</td>
        </tr>

        <tr>
          <td align="left"><code>text</code></td>

          <td align="left">Valid for text changes, not for style changes. If we are collecting undo
          information this holds a pointer to the text that is handed to the Undo system, otherwise
          it is zero. For user performed SC_MOD_BEFOREDELETE the text field is 0 and
                  for user performed SC_MOD_BEFOREINSERT the text field points to an array of cells,
                   not bytes and the length is the number of cells.</td>
        </tr>

        <tr>
          <td align="left"><code>line</code></td>

          <td align="left">The line number at which a fold level or marker change occurred. This is
          0 if unused and may be -1 if more than one line changed.</td>
        </tr>

        <tr>
          <td align="left"><code>foldLevelNow</code></td>

          <td align="left">The new fold level applied to the line or 0 if this field is
          unused.</td>
        </tr>

        <tr>
          <td align="left"><code>foldLevelPrev</code></td>

          <td align="left">The previous folding level of the line or 0 if this field is
          unused.</td>
        </tr>
      </tbody>
    </table>

    <p>The <code>SCNotification.modificationType</code> field has bits set to tell you what has
    been done. The <code>SC_MOD_*</code> bits correspond to actions. The
    <code>SC_PERFORMED_*</code> bits tell you if the action was done by the user, or the result of
    Undo or Redo of a previous action.</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Modify notification type flags">
      <tbody>
        <tr>
          <th align="left">Symbol</th>

          <th>Value</th>

          <th align="left">Meaning</th>

          <th align="left">SCNotification fields</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>SC_MOD_INSERTTEXT</code></td>

          <td align="center">0x01</td>

          <td>Text has been inserted into the document.</td>

          <td><code>position, length, text, linesAdded</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_DELETETEXT</code></td>

          <td align="center">0x02</td>

          <td>Text has been removed from the document.</td>

          <td><code>position, length, text, linesAdded</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_CHANGESTYLE</code></td>

          <td align="center">0x04</td>

          <td>A style change has occurred.</td>

          <td><code>position, length</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_CHANGEFOLD</code></td>

          <td align="center">0x08</td>

          <td>A folding change has occurred.</td>

          <td><code>line, foldLevelNow, foldLevelPrev</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_PERFORMED_USER</code></td>

          <td align="center">0x10</td>

          <td>Information: the operation was done by the user.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PERFORMED_UNDO</code></td>

          <td align="center">0x20</td>

          <td>Information: this was the result of an Undo.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_PERFORMED_REDO</code></td>

          <td align="center">0x40</td>

          <td>Information: this was the result of a Redo.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_MULTISTEPUNDOREDO</code></td>

          <td align="center">0x80</td>

          <td>This is part of a multi-step Undo or Redo transaction.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_LASTSTEPINUNDOREDO</code></td>

          <td align="center">0x100</td>

          <td>This is the final step in an Undo or Redo transaction.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_CHANGEMARKER</code></td>

          <td align="center">0x200</td>

          <td>One or more markers has changed in a line.</td>

          <td><code>line</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_BEFOREINSERT</code></td>

          <td align="center">0x400</td>

          <td>Text is about to be inserted into the document.</td>

          <td><code>position, if performed by user then text in cells, length in cells</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_BEFOREDELETE</code></td>

          <td align="center">0x800</td>

          <td>Text is about to be deleted from the document.</td>

          <td><code>position, length</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MOD_CHANGEINDICATOR</code></td>

          <td align="center">0x4000</td>

          <td>An indicator has been added or removed from a range of text.</td>

          <td><code>position, length</code></td>
        </tr>

        <tr>
          <td align="left"><code id="SC_MOD_CHANGELINESTATE">SC_MOD_CHANGELINESTATE</code></td>

          <td align="center">0x8000</td>

          <td>A line state has changed because <a class="message" href="#SCI_SETLINESTATE">SCI_SETLINESTATE</a>
          was called.</td>

          <td><code>line</code></td>
        </tr>

        <tr>
          <td align="left"><code id="SC_MOD_LEXERSTATE">SC_MOD_LEXERSTATE</code></td>

          <td align="center">0x80000</td>

          <td>The internal state of a lexer has changed over a range.</td>

          <td><code>position, length</code></td>
        </tr>

        <tr>
          <td align="left"><code id="SC_MOD_CHANGEMARGIN">SC_MOD_CHANGEMARGIN</code></td>

          <td align="center">0x10000</td>

          <td>A text margin has changed.</td>

          <td><code>line</code></td>
        </tr>

        <tr>
          <td align="left"><code id="SC_MOD_CHANGEANNOTATION">SC_MOD_CHANGEANNOTATION</code></td>

          <td align="center">0x20000</td>

          <td>An annotation has changed.</td>

          <td><code>line</code></td>
        </tr>

        <tr>
          <td align="left"><code>SC_MULTILINEUNDOREDO</code></td>

          <td align="center">0x1000</td>

          <td>This is part of an Undo or Redo with multi-line changes.</td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code>SC_STARTACTION</code></td>

          <td align="center">0x2000</td>

          <td>This is set on a SC_PERFORMED_USER action when it is the
          first or only step in an undo transaction. This can be used to integrate the Scintilla
          undo stack with an undo stack in the container application by adding a Scintilla
          action to the container's stack for the currently opened container transaction or
          to open a new container transaction if there is no open container transaction.
          </td>

          <td>None</td>
        </tr>

        <tr>
          <td align="left"><code id="SC_MOD_CONTAINER">SC_MOD_CONTAINER</code></td>

          <td align="center">0x40000</td>

          <td>This is set on for actions that the container stored into the undo stack with
	  <a class="message" href="#SCI_ADDUNDOACTION"><code>SCI_ADDUNDOACTION</code></a>.
          </td>

          <td>token</td>
        </tr>

        <tr>
          <td align="left"><code>SC_MODEVENTMASKALL</code></td>

          <td align="center">0x7FFFF</td>

          <td>This is a mask for all valid flags. This is the default mask state set by <a
          class="message" href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>.</td>

          <td>None</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCEN_CHANGE">SCEN_CHANGE</b><br />
     <code>SCEN_CHANGE</code> (768) is fired when the text (not the style) of the document changes.
    This notification is sent using the <code>WM_COMMAND</code> message on Windows and the
    "Command" signal on GTK+ as this is the behavior of the standard Edit control
    (<code>SCEN_CHANGE</code> has the same value as the Windows Edit control
    <code>EN_CHANGE</code>). No other information is sent. If you need more detailed information
    use <a class="message" href="#SCN_MODIFIED"><code>SCN_MODIFIED</code></a>. You can filter the
    types of changes you are notified about with <a class="message"
    href="#SCI_SETMODEVENTMASK"><code>SCI_SETMODEVENTMASK</code></a>.</p>

    <p><b id="SCI_SETMODEVENTMASK">SCI_SETMODEVENTMASK(int eventMask)</b><br />
     <b id="SCI_GETMODEVENTMASK">SCI_GETMODEVENTMASK</b><br />
     These messages set and get an event mask that determines which document change events are
    notified to the container with <a class="message"
    href="#SCN_MODIFIED"><code>SCN_MODIFIED</code></a> and <a class="message"
    href="#SCEN_CHANGE"><code>SCEN_CHANGE</code></a>. For example, a container may decide to see
    only notifications about changes to text and not styling changes by calling
    <code>SCI_SETMODEVENTMASK(SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)</code>.</p>

    <p>The possible notification types are the same as the <code>modificationType</code> bit flags
    used by <code>SCN_MODIFIED</code>: <code>SC_MOD_INSERTTEXT</code>,
    <code>SC_MOD_DELETETEXT</code>, <code>SC_MOD_CHANGESTYLE</code>,
    <code>SC_MOD_CHANGEFOLD</code>, <code>SC_PERFORMED_USER</code>, <code>SC_PERFORMED_UNDO</code>,
    <code>SC_PERFORMED_REDO</code>, <code>SC_MULTISTEPUNDOREDO</code>,
    <code>SC_LASTSTEPINUNDOREDO</code>, <code>SC_MOD_CHANGEMARKER</code>,
    <code>SC_MOD_BEFOREINSERT</code>, <code>SC_MOD_BEFOREDELETE</code>,
    <code>SC_MULTILINEUNDOREDO</code>, and <code>SC_MODEVENTMASKALL</code>.</p>

    <p><b id="SCEN_SETFOCUS">SCEN_SETFOCUS</b><br />
     <b id="SCEN_KILLFOCUS">SCEN_KILLFOCUS</b><br />
     <code>SCEN_SETFOCUS</code> (512) is fired when Scintilla receives focus and
    <code>SCEN_KILLFOCUS</code> (256) when it loses focus. These notifications are sent using the
    <code>WM_COMMAND</code> message on Windows and the "Command" signal on GTK+ as this is the
    behavior of the standard Edit control. Unfortunately, these codes do not match the Windows Edit
    notification codes <code>EN_SETFOCUS</code> (256) and <code>EN_KILLFOCUS</code> (512). It is
    now too late to change the Scintilla codes as clients depend on the current values.</p>

    <p><b id="SCN_MACRORECORD">SCN_MACRORECORD</b><br />
     The <code><a class="message" href="#SCI_STARTRECORD">SCI_STARTRECORD</a></code> and <a
    class="message" href="#SCI_STOPRECORD"><code>SCI_STOPRECORD</code></a> messages enable and
    disable macro recording. When enabled, each time a recordable change occurs, the
    <code>SCN_MACRORECORD</code> notification is sent to the container. It is up to the container
    to record the action. To see the complete list of <code>SCI_*</code> messages that are
    recordable, search the Scintilla source <code>Editor.cxx</code> for
    <code>Editor::NotifyMacroRecord</code>. The fields of <code>SCNotification</code> set in this
    notification are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Macro record notification data">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>message</code></td>

          <td align="left">The <code>SCI_*</code> message that caused the notification.</td>
        </tr>

        <tr>
          <td align="left"><code>wParam</code></td>

          <td align="left">The value of <code>wParam</code> in the <code>SCI_*</code> message.</td>
        </tr>

        <tr>
          <td align="left"><code>lParam</code></td>

          <td align="left">The value of <code>lParam</code> in the <code>SCI_*</code> message.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCN_MARGINCLICK">SCN_MARGINCLICK</b><br />
     This notification tells the container that the mouse was clicked inside a <a class="jump"
    href="#Margins">margin</a> that was marked as sensitive (see <a class="message"
    href="#SCI_SETMARGINSENSITIVEN"><code>SCI_SETMARGINSENSITIVEN</code></a>). This can be used to
    perform folding or to place breakpoints. The following <code>SCNotification</code> fields are
    used:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Margin click notification">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>modifiers</code></td>

          <td align="left">The appropriate combination of <code>SCI_SHIFT</code>,
          <code>SCI_CTRL</code> and <code>SCI_ALT</code> to indicate the keys that were held down
          at the time of the margin click.</td>
        </tr>

        <tr>
          <td align="left"><code>position</code></td>

          <td align="left">The position of the start of the line in the document that corresponds
          to the margin click.</td>
        </tr>

        <tr>
          <td align="left"><code>margin</code></td>

          <td align="left">The margin number that was clicked.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCN_NEEDSHOWN">SCN_NEEDSHOWN</b><br />
     Scintilla has determined that a range of lines that is currently invisible should be made
    visible. An example of where this may be needed is if the end of line of a contracted fold
    point is deleted. This message is sent to the container in case it wants to make the line
    visible in some unusual way such as making the whole document visible. Most containers will
    just ensure each line in the range is visible by calling <a class="message"
    href="#SCI_ENSUREVISIBLE"><code>SCI_ENSUREVISIBLE</code></a>. The <code>position</code> and
    <code>length</code> fields of <code>SCNotification</code> indicate the range of the document
    that should be made visible. The container code will be similar to the following code
    skeleton:</p>
<pre>
firstLine = SCI_LINEFROMPOSITION(scn.position)
lastLine = SCI_LINEFROMPOSITION(scn.position+scn.length-1)
for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
</pre>

    <p><b id="SCN_PAINTED">SCN_PAINTED</b><br />
     Painting has just been done. Useful when you want to update some other widgets based on a
    change in Scintilla, but want to have the paint occur first to appear more responsive. There is
    no other information in <code>SCNotification</code>.</p>

    <p><b id="SCN_USERLISTSELECTION">SCN_USERLISTSELECTION</b><br />
     The user has selected an item in a <a class="jump" href="#UserLists">user list</a>. The
    <code>SCNotification</code> fields used are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="User list notification">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>listType</code></td>

          <td align="left">This is set to the <code>listType</code> parameter from the <a
          class="message" href="#SCI_USERLISTSHOW"><code>SCI_USERLISTSHOW</code></a> message that
          initiated the list.</td>
        </tr>

        <tr>
          <td align="left"><code>text</code></td>

          <td align="left">The text of the selection.</td>
        </tr>

        <tr>
          <td align="left"><code>position</code></td>

          <td align="left">The position the list was displayed at.</td>
        </tr>
      </tbody>
    </table>
    <br />


    <p><b id="SCN_URIDROPPED">SCN_URIDROPPED</b><br />
     Only on the GTK+ version. Indicates that the user has dragged a URI such as a file name or Web
    address onto Scintilla. The container could interpret this as a request to open the file. The
    <code>text</code> field of <code>SCNotification</code> points at the URI text.</p>

    <p><b id="SCN_DWELLSTART">SCN_DWELLSTART</b><br />
     <b id="SCN_DWELLEND">SCN_DWELLEND</b><br />
     <code>SCN_DWELLSTART</code> is generated when the user keeps the mouse in one position for the
    dwell period (see <code><a class="message"
    href="#SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME</a></code>). <code>SCN_DWELLEND</code> is
    generated after a <code>SCN_DWELLSTART</code> and the mouse is moved or other activity such as
    key press indicates the dwell is over. Both notifications set the same fields in
    <code>SCNotification</code>:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Mouse dwell notification">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>position</code></td>

          <td align="left">This is the nearest position in the document to the position where the
          mouse pointer was lingering.</td>
        </tr>

        <tr>
          <td align="left"><code>x, y</code></td>

          <td align="left">Where the pointer lingered. The <code>position</code> field is set to
          <code><a class="message"
          href="#SCI_POSITIONFROMPOINTCLOSE">SCI_POSITIONFROMPOINTCLOSE</a>(x, y)</code>.</td>
        </tr>
      </tbody>
    </table>
    <br />

    <p><b id="SCI_SETMOUSEDWELLTIME">SCI_SETMOUSEDWELLTIME(int milliseconds)</b><br />
     <b id="SCI_GETMOUSEDWELLTIME">SCI_GETMOUSEDWELLTIME</b><br />
     These two messages set and get the time the mouse must sit still, in milliseconds, to generate
    a <code><a class="message" href="#SCN_DWELLSTART">SCN_DWELLSTART</a></code> notification. If
    set to <code>SC_TIME_FOREVER</code>, the default, no dwell events are generated.</p>

    <p><b id="SCN_ZOOM">SCN_ZOOM</b><br />
     This notification is generated when the user zooms the display using the keyboard or the
    <code><a class="message" href="#SCI_SETZOOM">SCI_SETZOOM</a></code> method is called. This
    notification can be used to recalculate positions, such as the width of the line number margin
    to maintain sizes in terms of characters rather than pixels. <code>SCNotification</code> has no
    additional information.</p>

    <p>
    <b id="SCN_HOTSPOTCLICK">SCN_HOTSPOTCLICK</b><br />
    <b id="SCN_HOTSPOTDOUBLECLICK">SCN_HOTSPOTDOUBLECLICK</b><br />
    <b id="SCN_HOTSPOTRELEASECLICK">SCN_HOTSPOTRELEASECLICK</b><br />
     These notifications are generated when the user clicks or double clicks on
     text that is in a style with the hotspot attribute set.
    This notification can be used to link to variable definitions or web pages.
    The <code>position</code> field is set the text position of the click or
    double click and the <code>modifiers</code> field set to the key modifiers
    held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.
    Only the state of the Ctrl key is reported for <code>SCN_HOTSPOTRELEASECLICK</code>.</p>

    <p>
    <b id="SCN_INDICATORCLICK">SCN_INDICATORCLICK</b><br />
    <b id="SCN_INDICATORRELEASE">SCN_INDICATORRELEASE</b><br />
     These notifications are generated when the user clicks or releases the mouse on
     text that has an indicator.
    The <code>position</code> field is set the text position of the click or
    double click and the <code>modifiers</code> field set to the key modifiers
    held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.</p>

    <p><b id="SCN_CALLTIPCLICK">SCN_CALLTIPCLICK</b><br />
     This notification is generated when the user clicks on a calltip.
    This notification can be used to display the next function prototype when a
    function name is overloaded with different arguments.
    The <code>position</code> field is set to 1 if the click is in an up arrow,
    2 if in a down arrow, and 0 if elsewhere.</p>

    <p><b id="SCN_AUTOCSELECTION">SCN_AUTOCSELECTION</b><br />
     The user has selected an item in an <a class="jump" href="#Autocompletion">autocompletion list</a>. The
     notification is sent before the selection is inserted. Automatic insertion can be cancelled by sending a
     <code><a class="message" href="#SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</a></code> message
     before returning from the notification. The <code>SCNotification</code> fields used are:</p>

    <table cellpadding="1" cellspacing="2" border="0" summary="Autocompletion list notification">
      <tbody>
        <tr>
          <th align="left">Field</th>

          <th align="left">Usage</th>
        </tr>
      </tbody>

      <tbody valign="top">
        <tr>
          <td align="left"><code>position</code></td>

          <td align="left">The start position of the word being completed.</td>
        </tr>
        <tr>
          <td align="left"><code>text</code></td>

          <td align="left">The text of the selection.</td>
        </tr>
      </tbody>
    </table>

    <p><b id="SCN_AUTOCCANCELLED">SCN_AUTOCCANCELLED</b><br />
     The user has cancelled an <a class="jump" href="#Autocompletion">autocompletion list</a>.
     There is no other information in SCNotification.</p>

    <p><b id="SCN_AUTOCCHARDELETED">SCN_AUTOCCHARDELETED</b><br />
     The user deleted a character while autocompletion list was active.
     There is no other information in SCNotification.</p>
     
    <h2 id="Images">Images</h2>
    
    <p>Two formats are supported for images used in margin markers and autocompletion lists, RGBA and XPM.</p>

    <h3 id="RGBA">RGBA</h3>
    
    <p>The RGBA format allows translucency with an <a class="jump" href="#alpha">alpha</a>
    value for each pixel. It is simpler than
    <code>XPM</code> and more capable.</p>
    
    <p>The data is a sequence of 4 byte pixel values starting with the pixels for the top line, with the
    leftmost pixel first, then continuing with the pixels for subsequent lines. There is no gap between
    lines for alignment reasons.</p>

    <p>Each pixel consists of, in order, a red byte, a green byte, a blue byte and an alpha byte.
    The colour bytes are not premultiplied by the alpha value. That is, a fully red pixel that is
    25% opaque will be [FF, 00, 00, 3F]</p>

    <p>Since the RGBA pixel data does not include any size information the 
    width and height must previously been set with the 
    <a class="message" href="#SCI_RGBAIMAGESETWIDTH"><code>SCI_RGBAIMAGESETWIDTH</code></a> and 
    <a class="message" href="#SCI_RGBAIMAGESETHEIGHT"><code>SCI_RGBAIMAGESETHEIGHT</code></a> messages.</p>
    
    <p>GUI platforms often include functions for reading image file formats like PNG into memory
    in the RGBA form or a similar form.
    If there is no suitable platform support, the <a href="http://lodev.org/lodepng/">LodePNG and picoPNG</a> libraries are small libraries
    for loading and decoding PNG files available under a BSD-style license.</p>
    
    <p>RGBA format is supported on Windows, GTK+ and OS X Cocoa.
    It is not supported on OS X Carbon.</p>

    <h3 id="XPM">XPM</h3>
    
    <p>The XPM format is 
    <a class="jump" href="http://en.wikipedia.org/wiki/X_PixMap">described here</a>. 
    Scintilla is only able to handle XPM pixmaps that use one character per pixel with no named colours.
    There may be a completely transparent colour named "None".</p>
    <p>There are two forms of data structure used for XPM images, the first "lines form" format is well suited
    to embedding an image inside C source code and the "text form" is suited to reading from a file.
    In the lines form, an array of strings is used with the first string indicating the dimensions and number of colours
    used. This is followed by a string for each colour and that section is followed by the image with one string per line.
    The text form contains the same data as one null terminated block formatted as C source code starting
    with a "/* XPM */" comment to mark the format.</p>
    <p>Either format may be used with Scintilla APIs with the bytes at the location pointed to examined
    to determine which format: if the bytes start with "/* XPM */" then it is treated as text form,
    otherwise it is treated as lines form.</p>

    <p>XPM format is supported on on all platforms.</p>

    <h2 id="GTK">GTK+</h2>
    <p>On GTK+, the following functions create a Scintilla widget, communicate with it and allow
    resources to be released after all Scintilla widgets have been destroyed.</p>
    <code><a class="message" href="#scintilla_new">GtkWidget *scintilla_new()</a><br />
     <a class="message" href="#scintilla_set_id">void scintilla_set_id(ScintillaObject *sci, uptr_t id)</a><br />
     <a class="message" href="#scintilla_send_message">sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)</a><br />
     <a class="message" href="#scintilla_release_resources">void scintilla_release_resources()</a><br />
     </code>

    <p><b id="scintilla_new">GtkWidget *scintilla_new()</b><br />
    Create a new Scintilla widget. The returned pointer can be added to a container and displayed in the same way as other
    widgets.</p>

    <p><b id="scintilla_set_id">void scintilla_set_id(ScintillaObject *sci, uptr_t id)</b><br />
    Set the control ID which will be used in the idFrom field of the NotifyHeader structure of all
    notifications for this instance.
    This is equivalent to <a class="message" href="#SCI_SETIDENTIFIER">SCI_SETIDENTIFIER</a>.</p>

    <p><b id="scintilla_send_message">sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam)</b><br />
    The main entry point allows sending any of the messages described in this document.</p>

    <p><b id="scintilla_release_resources">void scintilla_release_resources()</b><br />
    Call this to free any remaining resources after all the Scintilla widgets have been destroyed.</p>

    <h2 id="ProvisionalMessages">Provisional messages</h2>

    <p>Complex new features may be added as 'provisional' to allow further changes to the API.
    Provisional features may even be removed if experience shows they are a mistake.</p>

    <p>Provisional features are displayed in this document with <span class="provisional">a distinctive background colour</span>.</p>

    <p>Some developers may want to only use features that are stable and have graduated from
    provisional status. To avoid using provisional messages compile with the symbol
    <code>SCI_DISABLE_PROVISIONAL</code> defined.</p>

    <h2 id="DeprecatedMessages">Deprecated messages and notifications</h2>

    <p>The following messages are currently supported to emulate existing Windows controls, but
    they will be removed in future versions of Scintilla. If you use these messages you should
    replace them with the Scintilla equivalent.</p>
<pre>
WM_GETTEXT(int length, char *text)
WM_SETTEXT(&lt;unused&gt;, const char *text)
EM_GETLINE(int line, char *text)
EM_REPLACESEL(&lt;unused&gt;, const char *text)
EM_SETREADONLY
EM_GETTEXTRANGE(&lt;unused&gt;, TEXTRANGE *tr)
WM_CUT
WM_COPY
WM_PASTE
WM_CLEAR
WM_UNDO
EM_CANUNDO
EM_EMPTYUNDOBUFFER
WM_GETTEXTLENGTH
EM_GETFIRSTVISIBLELINE
EM_GETLINECOUNT
EM_GETMODIFY
EM_SETMODIFY(bool isModified)
EM_GETRECT(RECT *rect)
EM_GETSEL(int *start, int *end)
EM_EXGETSEL(&lt;unused&gt;, CHARRANGE *cr)
EM_SETSEL(int start, int end)
EM_EXSETSEL(&lt;unused&gt;, CHARRANGE *cr)
EM_GETSELTEXT(&lt;unused&gt;, char *text)
EM_LINEFROMCHAR(int position)
EM_EXLINEFROMCHAR(int position)
EM_LINEINDEX(int line)
EM_LINELENGTH(int position)
EM_SCROLL(int line)
EM_LINESCROLL(int column, int line)
EM_SCROLLCARET()
EM_CANPASTE
EM_CHARFROMPOS(&lt;unused&gt;, POINT *location)
EM_POSFROMCHAR(int position, POINT *location)
EM_SELECTIONTYPE
EM_HIDESELECTION(bool hide)
EM_FINDTEXT(int flags, FINDTEXTEX *ft)
EM_FINDTEXTEX(int flags, FINDTEXTEX *ft)
EM_GETMARGINS
EM_SETMARGINS(EC_LEFTMARGIN or EC_RIGHTMARGIN or EC_USEFONTINFO, int val)
EM_FORMATRANGE
</pre>

    <p>The following are features that are only included if you define
    <code>INCLUDE_DEPRECATED_FEATURES</code> in <code>Scintilla.h</code>. To ensure future
    compatibility you should change them as indicated.</p>

    <p><b id="SC_CP_DBCS">SC_CP_DBCS</b> Deprecated<br />
     This was used to set a DBCS (Double Byte Character Set) mode on GTK+.
     An explicit DBCS code page should be used when calling <a class="message" href="#SCI_SETCODEPAGE">SCI_SETCODEPAGE</a></p>

    <p><b id="SCI_SETUSEPALETTE">SCI_SETUSEPALETTE(bool allowPaletteUse)</b> Deprecated<br />
    <b id="SCI_GETUSEPALETTE">SCI_GETUSEPALETTE</b> Deprecated<br />
     Scintilla no longer supports palette mode. The last version to support palettes was 2.29.
     Any calls to these methods should be removed.</p>

    <h2 id="EditMessagesNeverSupportedByScintilla">Edit messages never supported by Scintilla</h2>
<pre>
EM_GETWORDBREAKPROC EM_GETWORDBREAKPROCEX
EM_SETWORDBREAKPROC EM_SETWORDBREAKPROCEX
EM_GETWORDWRAPMODE EM_SETWORDWRAPMODE
EM_LIMITTEXT EM_EXLIMITTEXT
EM_SETRECT EM_SETRECTNP
EM_FMTLINES
EM_GETHANDLE EM_SETHANDLE
EM_GETPASSWORDCHAR EM_SETPASSWORDCHAR
EM_SETTABSTOPS
EM_FINDWORDBREAK
EM_GETCHARFORMAT EM_SETCHARFORMAT
EM_GETOLEINTERFACE EM_SETOLEINTERFACE
EM_SETOLECALLBACK
EM_GETPARAFORMAT EM_SETPARAFORMAT
EM_PASTESPECIAL
EM_REQUESTRESIZE
EM_GETBKGNDCOLOR EM_SETBKGNDCOLOR
EM_STREAMIN EM_STREAMOUT
EM_GETIMECOLOR EM_SETIMECOLOR
EM_GETIMEOPTIONS EM_SETIMEOPTIONS
EM_GETOPTIONS EM_SETOPTIONS
EM_GETPUNCTUATION EM_SETPUNCTUATION
EM_GETTHUMB
EM_GETEVENTMASK
EM_SETEVENTMASK
EM_DISPLAYBAND
EM_SETTARGETDEVICE
</pre>

    <p>Scintilla tries to be a superset of the standard windows Edit and RichEdit controls wherever
    that makes sense. As it is not intended for use in a word processor, some edit messages can not
    be sensibly handled. Unsupported messages have no effect.</p>

    <h2 id="BuildingScintilla">Building Scintilla</h2>

    <p>To build Scintilla or SciTE, see the README file present in both the Scintilla and SciTE
    directories. For Windows, GCC 3.2, Borland C++ or Microsoft Visual Studio .NET can be used
    for building. There is a make file for building Scintilla but not SciTE with Visual C++ 6 at
    scintilla/win32/scintilla_vc6.mak. For GTK+, GCC 3.1 should be used. GTK+ 1.2x and 2.0x are
    supported. The version of GTK+ installed should be detected automatically.
    When both GTK+ 1 and GTK+ 2 are present, building for GTK+ 1.x requires defining GTK1
    on the command line.</p>

    <h3>Static linking</h3>

    <p>On Windows, Scintilla is normally used as a dynamic library as a .DLL file. If you want to
    link Scintilla directly into your application .EXE or .DLL file, then the
    <code>STATIC_BUILD</code> preprocessor symbol should be defined and
    <code>Scintilla_RegisterClasses</code> called. <code>STATIC_BUILD</code> prevents compiling the
    <code>DllMain</code> function which will conflict with any <code>DllMain</code> defined in your
    code. <code>Scintilla_RegisterClasses</code> takes the <code>HINSTANCE</code> of your
    application and ensures that the "Scintilla" window class is registered.</p>

    <h3>Ensuring lexers are linked into Scintilla</h3>

    <p>Depending on the compiler and linker used, the lexers may be stripped out. This is most
    often caused when building a static library. To ensure the lexers are linked in, the
    <code>Scintilla_LinkLexers()</code> function may be called.</p>

    <h3>Changing set of lexers</h3>

    <p>To change the set of lexers in Scintilla, add and remove lexer source files
    (<code>Lex*.cxx</code>) from the <code>scintilla/src directory</code> and run the
    <code>src/LexGen.py</code> script from the <code>src</code> directory to update the make files
    and <code>KeyWords.cxx</code>. <code>LexGen.py</code> requires Python 2.1 or later. If you do
    not have access to Python, you can hand edit <code>KeyWords.cxx</code> in a simple-minded way,
    following the patterns of other lexers. The important thing is to include
    <code>LINK_LEXER(lmMyLexer);</code> to correspond with the <code>LexerModule
    lmMyLexer(...);</code> in your lexer source code.</p>

    <h3>Building with an alternative Regular Expression implementation</h3>

 <p id="AlternativeRegEx">A simple interface provides support for switching the Regular Expressions engine at
 compile time. You must implement <code>RegexSearchBase</code> for your chosen engine,
 look at the built-in implementation <code>BuiltinRegex</code> to see how this is done.
 You then need to implement the factory method <code>CreateRegexSearch</code>
 to create an instance of your class. You must disable the built-in implementation by defining
 <code>SCI_OWNREGEX</code>.</p>

  </body>
</html>

Added doc/ScintillaDownload.html.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Download Scintilla
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Download
          Scintilla</font></a>
        </td>
      </tr>
    </table>
    <table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
      <tr>
        <td>
          <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.zip?download">
	Windows</a>&nbsp;&nbsp;
	<a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.tgz?download">
          GTK+/Linux</a>&nbsp;&nbsp;
	</font>
        </td>
      </tr>
    </table>
    <h2>
       Download.
    </h2>
    <p>
       The <a href="License.txt">license</a> for using Scintilla or SciTE is similar to that of Python
      containing very few restrictions.
    </p>
    <h3>
       Release 3.3.0
    </h3>
    <h4>
       Source Code
    </h4>
       The source code package contains all of the source code for Scintilla but no binary
	executable code and is available in
       <ul>
       <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.zip?download">zip format</a> (1250K) commonly used on Windows</li>
       <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.tgz?download">tgz format</a> (1100K) commonly used on Linux and compatible operating systems</li>
       </ul>
       Instructions for building on both Windows and Linux are included in the readme file.
    <h4>
       Windows Executable Code
    </h4>
       There is no download available containing only the Scintilla DLL.
       However, it is included in the <a href="SciTEDownload.html">SciTE
       executable full download</a> as SciLexer.DLL.
    <p>
       <a href="SciTEDownload.html">SciTE</a> is a good demonstration of Scintilla.
    </p>
    <p>
       Previous versions can be downloaded from the <a href="ScintillaHistory.html">history
      page</a>.
    </p>
  </body>
</html>

Added doc/ScintillaHistory.html.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>
      Scintilla and SciTE
    </title>
    <style type="text/css">
        table {
            border-collapse: collapse;
            font-size: 80%;
        }
        td {
            xborder: 1px solid #1F1F1F;
            padding: 0px 4px;
        }
    </style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       History of Scintilla and SciTE
    </h2>
    <h3>
       Contributors
    </h3>
    <p>
       Thanks to all the people that have contributed patches, bug reports and suggestions.
    </p>
    <p>
       Source code and documentation have been contributed by
    </p>
    <table>
      <tr>
	<td>Atsuo Ishimoto</td>
	<td>Mark Hammond</td>
	<td>Francois Le Coguiec</td>
	<td>Dale Nagata</td>
      </tr><tr>
	<td>Ralf Reinhardt</td>
	<td>Philippe Lhoste</td>
	<td>Andrew McKinlay</td>
	<td>Stephan R. A. Deibel</td>
      </tr><tr>
	<td>Hans Eckardt</td>
	<td>Vassili Bourdo</td>
	<td>Maksim Lin</td>
	<td>Robin Dunn</td>
      </tr><tr>
	<td>John Ehresman</td>
	<td>Steffen Goeldner</td>
	<td>Deepak S.</td>
	<td>Yann Gaillard</td>
      </tr><tr>
	<td>Aubin Paul</td>
	<td>Jason Diamond</td>
	<td>Ahmad Baitalmal</td>
	<td>Paul Winwood</td>
      </tr><tr>
	<td>Maxim Baranov</td>
	<td>Ragnar Højland</td>
	<td>Christian Obrecht</td>
	<td>Andreas Neukoetter</td>
      </tr><tr>
	<td>Adam Gates</td>
	<td>Steve Lhomme</td>
	<td>Ferdinand Prantl</td>
	<td>Jan Dries</td>
      </tr><tr>
	<td>Markus Gritsch</td>
	<td>Tahir Karaca</td>
	<td>Ahmad Zawawi</td>
	<td>Laurent le Tynevez</td>
      </tr><tr>
	<td>Walter Braeu</td>
	<td>Ashley Cambrell</td>
	<td>Garrett Serack</td>
	<td>Holger Schmidt</td>
      </tr><tr>
	<td><a href="http://www.activestate.com">ActiveState</a></td>
	<td>James Larcombe</td>
	<td>Alexey Yutkin</td>
	<td>Jan Hercek</td>
      </tr><tr>
	<td>Richard Pecl</td>
	<td>Edward K. Ream</td>
	<td>Valery Kondakoff</td>
	<td>Smári McCarthy</td>
      </tr><tr>
	<td>Clemens Wyss</td>
	<td>Simon Steele</td>
	<td>Serge A. Baranov</td>
	<td>Xavier Nodet</td>
      </tr><tr>
	<td>Willy Devaux</td>
	<td>David Clain</td>
	<td>Brendon Yenson</td>
	<td>Vamsi Potluru</td>
      </tr><tr>
	<td>Praveen Ambekar</td>
	<td>Alan Knowles</td>
	<td>Kengo Jinno</td>
	<td>Valentin Valchev</td>
      </tr><tr>
	<td>Marcos E. Wurzius</td>
	<td>Martin Alderson</td>
	<td>Robert Gustavsson</td>
	<td>José Fonseca</td>
      </tr><tr>
	<td>Holger Kiemes</td>
	<td>Francis Irving</td>
	<td>Scott Kirkwood</td>
	<td>Brian Quinlan</td>
      </tr><tr>
	<td>Ubi</td>
	<td>Michael R. Duerig</td>
	<td>Deepak T</td>
	<td>Don Paul Beletsky</td>
      </tr><tr>
	<td>Gerhard Kalab</td>
	<td>Olivier Dagenais</td>
	<td>Josh Wingstrom</td>
	<td>Bruce Dodson</td>
      </tr><tr>
	<td>Sergey Koshcheyev</td>
	<td>Chuan-jian Shen</td>
	<td>Shane Caraveo</td>
	<td>Alexander Scripnik</td>
      </tr><tr>
	<td>Ryan Christianson</td>
	<td>Martin Steffensen</td>
	<td>Jakub Vrána</td>
	<td>The Black Horus</td>
      </tr><tr>
	<td>Bernd Kreuss</td>
	<td>Thomas Lauer</td>
	<td>Mike Lansdaal</td>
	<td>Yukihiro Nakai</td>
      </tr><tr>
	<td>Jochen Tucht</td>
	<td>Greg Smith</td>
	<td>Steve Schoettler</td>
	<td>Mauritius Thinnes</td>
      </tr><tr>
	<td>Darren Schroeder</td>
	<td>Pedro Guerreiro</td>
	<td>Dan Petitt</td>
	<td>Biswapesh Chattopadhyay</td>
      </tr><tr>
	<td>Kein-Hong Man</td>
	<td>Patrizio Bekerle</td>
	<td>Nigel Hathaway</td>
	<td>Hrishikesh Desai</td>
      </tr><tr>
	<td>Sergey Puljajev</td>
	<td>Mathias Rauen</td>
	<td>Angelo Mandato</td>
	<td>Denis Sureau</td>
      </tr><tr>
	<td>Kaspar Schiess</td>
	<td>Christoph Hösler</td>
	<td>João Paulo F Farias</td>
	<td>Ron Schofield</td>
      </tr><tr>
	<td>Stefan Wosnik</td>
	<td>Marius Gheorghe</td>
	<td>Naba Kumar</td>
	<td>Sean O'Dell</td>
      </tr><tr>
	<td>Stefanos Togoulidis</td>
	<td>Hans Hagen</td>
	<td>Jim Cape</td>
	<td>Roland Walter</td>
      </tr><tr>
	<td>Brian Mosher</td>
	<td>Nicholas Nemtsev</td>
	<td>Roy Wood</td>
	<td>Peter-Henry Mander</td>
      </tr><tr>
	<td>Robert Boucher</td>
	<td>Christoph Dalitz</td>
	<td>April White</td>
	<td>S. Umar</td>
      </tr><tr>
	<td>Trent Mick</td>
	<td>Filip Yaghob</td>
	<td>Avi Yegudin</td>
	<td>Vivi Orunitia</td>
      </tr><tr>
	<td>Manfred Becker</td>
	<td>Dimitris Keletsekis</td>
	<td>Yuiga</td>
	<td>Davide Scola</td>
      </tr><tr>
	<td>Jason Boggs</td>
	<td>Reinhold Niesner</td>
	<td>Jos van der Zande</td>
	<td>Pescuma</td>
      </tr><tr>
	<td>Pavol Bosik</td>
	<td>Johannes Schmid</td>
	<td>Blair McGlashan</td>
	<td>Mikael Hultgren</td>
      </tr><tr>
	<td>Florian Balmer</td>
	<td>Hadar Raz</td>
	<td>Herr Pfarrer</td>
	<td>Ben Key</td>
      </tr><tr>
	<td>Gene Barry</td>
	<td>Niki Spahiev</td>
	<td>Carsten Sperber</td>
	<td>Phil Reid</td>
      </tr><tr>
	<td>Iago Rubio</td>
	<td>Régis Vaquette</td>
	<td>Massimo Corà</td>
	<td>Elias Pschernig</td>
      </tr><tr>
	<td>Chris Jones</td>
	<td>Josiah Reynolds</td>
	<td>Robert Roessler <a href="http://www.rftp.com">rftp.com</a></td>
	<td>Steve Donovan</td>
      </tr><tr>
	<td>Jan Martin Pettersen</td>
	<td>Sergey Philippov</td>
	<td>Borujoa</td>
	<td>Michael Owens</td>
      </tr><tr>
	<td>Franck Marcia</td>
	<td>Massimo Maria Ghisalberti</td>
	<td>Frank Wunderlich</td>
	<td>Josepmaria Roca</td>
      </tr><tr>
	<td>Tobias Engvall</td>
	<td>Suzumizaki Kimitaka</td>
	<td>Michael Cartmell</td>
	<td>Pascal Hurni</td>
      </tr><tr>
	<td>Andre</td>
	<td>Randy Butler</td>
	<td>Georg Ritter</td>
	<td>Michael Goffioul</td>
      </tr><tr>
	<td>Ben Harper</td>
	<td>Adam Strzelecki</td>
	<td>Kamen Stanev</td>
	<td>Steve Menard</td>
      </tr><tr>
	<td>Oliver Yeoh</td>
	<td>Eric Promislow</td>
	<td>Joseph Galbraith</td>
	<td>Jeffrey Ren</td>
      </tr><tr>
	<td>Armel Asselin</td>
	<td>Jim Pattee</td>
	<td>Friedrich Vedder</td>
	<td>Sebastian Pipping</td>
      </tr><tr>
	<td>Andre Arpin</td>
	<td>Stanislav Maslovski</td>
	<td>Martin Stone</td>
	<td>Fabien Proriol</td>
      </tr><tr>
	<td>mimir</td>
	<td>Nicola Civran</td>
	<td>Snow</td>
	<td>Mitchell Foral</td>
      </tr><tr>
	<td>Pieter Holtzhausen</td>
	<td>Waldemar Augustyn</td>
	<td>Jason Haslam</td>
	<td>Sebastian Steinlechner</td>
      </tr><tr>
	<td>Chris Rickard</td>
	<td>Rob McMullen</td>
	<td>Stefan Schwendeler</td>
	<td>Cristian Adam</td>
      </tr><tr>
	<td>Nicolas Chachereau</td>
	<td>Istvan Szollosi</td>
	<td>Xie Renhui</td>
	<td>Enrico Tröger</td>
      </tr><tr>
	<td>Todd Whiteman</td>
	<td>Yuval Papish</td>
	<td>instanton</td>
	<td>Sergio Lucato</td>
      </tr><tr>
	<td>VladVRO</td>
	<td>Dmitry Maslov</td>
	<td>chupakabra</td>
	<td>Juan Carlos Arevalo Baeza</td>
      </tr><tr>
	<td>Nick Treleaven</td>
	<td>Stephen Stagg</td>
	<td>Jean-Paul Iribarren</td>
	<td>Tim Gerundt</td>
      </tr><tr>
	<td>Sam Harwell</td>
	<td>Boris</td>
	<td>Jason Oster</td>
	<td>Gertjan Kloosterman</td>
      </tr><tr>
	<td>alexbodn</td>
	<td>Sergiu Dotenco</td>
	<td>Anders Karlsson</td>
	<td>ozlooper</td>
      </tr><tr>
	<td>Marko Njezic</td>
	<td>Eugen Bitter</td>
	<td>Christoph Baumann</td>
	<td>Christopher Bean</td>
      </tr><tr>
	<td>Sergey Kishchenko</td>
	<td>Kai Liu</td>
	<td>Andreas Rumpf</td>
	<td>James Moffatt</td>
      </tr><tr>
	<td>Yuzhou Xin</td>
	<td>Nic Jansma</td>
	<td>Evan Jones</td>
	<td>Mike Lischke</td>
      </tr><tr>
	<td>Eric Kidd</td>
	<td>maXmo</td>
	<td>David Severwright</td>
	<td>Jon Strait</td>
      </tr><tr>
	<td>Oliver Kiddle</td>
	<td>Etienne Girondel</td>
	<td>Haimag Ren</td>
	<td>Andrey Moskalyov</td>
      </tr><tr>
	<td>Xavi</td>
	<td>Toby Inkster</td>
	<td>Eric Forgeot</td>
	<td>Colomban Wendling</td>
      </tr><tr>
	<td>Neo</td>
	<td>Jordan Russell</td>
	<td>Farshid Lashkari</td>
	<td>Sam Rawlins</td>
      </tr><tr>
	<td>Michael Mullin</td>
	<td>Carlos SS</td>
	<td>vim</td>
	<td>Martial Demolins</td>
      </tr><tr>
	<td>Tino Weinkauf</td>
	<td>Jérôme Laforge</td>
	<td>Udo Lechner</td>
	<td>Marco Falda</td>
      </tr><tr>
	<td>Dariusz Knociński</td>
	<td>Ben Fisher</td>
	<td>Don Gobin</td>
	<td>John Yeung</td>
      </tr><tr>
	<td>Adobe</td>
	<td>Elizabeth A. Irizarry</td>
	<td>Mike Schroeder</td>
	<td>Morten MacFly</td>
      </tr><tr>
	<td>Jaime Gimeno</td>
	<td>Thomas Linder Puls</td>
	<td>Artyom Zuikov</td>
	<td>Gerrit</td>
      </tr><tr>
	<td>Occam's Razor</td>
	<td>Ben Bluemel</td>
	<td>David Wolfendale</td>
	<td>Chris Angelico</td>
      </tr><tr>
	<td>Marat Dukhan</td>
	<td>Stefan Weil</td>
	<td>Rex Conn</td>
	<td>Ross McKay</td>
      </tr><tr>
	<td>Bruno Barbieri</td>
	<td>Gordon Smith</td>
	<td>dimitar</td>
	<td>Sébastien Granjoux</td>
      </tr><tr>
	<td>zeniko</td>
	<td>James Ribe</td>
	<td>Markus Nißl</td>
	<td>Martin Panter</td>
      </tr><tr>
	<td>Mark Yen</td>
	<td>Philippe Elsass</td>
	<td>Dimitar Zhekov</td>
	<td>Fan Yang</td>
      </tr><tr>
	<td>Denis Shelomovskij</td>
	<td>darmar</td>
	<td>John Vella</td>
	<td>Chinh Nguyen</td>
      </tr><tr>
	<td>Sakshi Verma</td>
	<td>Joel B. Mohler</td>
	<td>Isiledhel</td>
	<td>Vidya Wasi</td>
      </tr><tr>
	<td>G. Hu</td>
	<td>Byron Hawkins</td>
	<td>Alpha</td>
    </tr>
    </table>
    <p>
       Images used in GTK+ version
    </p>
    <ul>
      <li>
        <a href="http://sourceforge.net/projects/icon-collection/">
        Icons</a> Copyright(C) 1998 by Dean S. Jones<br />
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite330.zip?download">Release 3.3.0</a>
    </h3>
    <ul>
	<li>
	Released 30 March 2013.
	</li>
	<li>
	Overlay scrollers and kinetic scrolling implemented on Cocoa.
	</li>
	<li>
	To improve display smoothness, styling and UI Update notifications will, when possible, be performed in
	a high-priority idle task on Cocoa instead of during painting.
	Performing these jobs inside painting can cause paints to be abandoned and a new paint scheduled.
	On GTK+, the high-priority idle task is used in more cases.
	</li>
	<li>
	SCI_SCROLLRANGE added to scroll the view to display a range of text.
	If the whole range can not be displayed, priority is given to one end.
	</li>
	<li>
	C++ lexer no longer recognises raw (R"") strings when the first character after "
	is invalid.
	<a href="http://sourceforge.net/p/scintilla/bugs/1454/">Bug #1454.</a>
	</li>
	<li>
	HTML lexer recognises JavaScript RegEx literals in more contexts.
	<a href="http://sourceforge.net/p/scintilla/bugs/1412/">Bug #1412.</a>
	</li>
	<li>
	Fixed automatic display of folded text when return pressed at end of fold header and
	first folded line was blank.
	<a href="http://sourceforge.net/p/scintilla/bugs/1455/">Bug #1455.</a>
	</li>
	<li>
	SCI_VISIBLEFROMDOCLINE fixed to never return a line beyond the document end.
	</li>
	<li>
	SCI_LINESCROLL fixed for a negative column offset.
	<a href="http://sourceforge.net/p/scintilla/bugs/1450/">Bug #1450.</a>
	</li>
	<li>
	On GTK+, fix tab markers so visible if indent markers are visible.
	<a href="http://sourceforge.net/p/scintilla/bugs/1453/">Bug #1453.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite325.zip?download">Release 3.2.5</a>
    </h3>
    <ul>
	<li>
	Released 26 February 2013.
	</li>
	<li>
	To allow cooperation between different uses of extended (beyond 255) styles they should be allocated
	using SCI_ALLOCATEEXTENDEDSTYLES.
	</li>
	<li>
	For Unicode documents, lexers that use StyleContext will retrieve whole characters
	instead of bytes.
	LexAccessor provides a LineEnd method which can be a more efficient way to
	handle line ends and can enable Unicode line ends.
	</li>
	<li>
	The C++ lexer understands the #undef directive when determining preprocessor definitions.
	<a href="http://sourceforge.net/p/scintilla/feature-requests/978/">Feature #978.</a>
	</li>
	<li>
	The errorlist lexer recognises gcc include path diagnostics that appear before an error.
	</li>
	<li>
	Folding implemented for GetText (PO)  translation language.
	<a href="http://sourceforge.net/p/scintilla/bugs/1437/">Bug #1437.</a>
	</li>
	<li>
	HTML lexer does not interrupt comment style for processing instructions.
	<a href="http://sourceforge.net/p/scintilla/bugs/1447/">Bug #1447.</a>
	</li>
	<li>
	Fix SciTE forgetting caret x-position when switching documents.
	<a href="http://sourceforge.net/p/scintilla/bugs/1442/">Bug #1442.</a>
	</li>
	<li>
	Fixed bug where vertical scrollbar thumb appeared at beginning of document when
	scrollbar shown.
	<a href="http://sourceforge.net/p/scintilla/bugs/1446/">Bug #1446.</a>
	</li>
	<li>
	Fixed brace-highlighting bug on OS X 10.8 where matching brace is on a different line.
	</li>
	<li>
	<a href="ScintillaDoc.html#ProvisionalMessages">Provisional features</a>
	are new features that may change or be removed if they cause problems but should become
	permanent if they work well.
	For this release <a href="ScintillaDoc.html#SCI_GETLINEENDTYPESSUPPORTED">Unicode line ends</a> and
	<a href="ScintillaDoc.html#Substyles">substyles</a>
	are provisional features.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite324.zip?download">Release 3.2.4</a>
    </h3>
    <ul>
	<li>
	Released 17 January 2013.
	</li>
	<li>
	Caret line highlight can optionally remain visible when window does not have focus.
	<a href="http://sourceforge.net/p/scintilla/feature-requests/964/">Feature #964.</a>
	</li>
	<li>
	Delegate mechanism for notifications added on Cocoa.
	</li>
	<li>
	NUL characters in selection are copied to clipboard as spaces to avoid truncating
	at the NUL.
	<a href="http://sourceforge.net/p/scintilla/bugs/1289/">Bug #1289.</a>
	</li>
	<li>
	C++ lexer fixes problem with showing inactive sections when preprocessor lines contain trailing comment.
	<a href="http://sourceforge.net/p/scintilla/bugs/1413/">Bug #1413.</a>
	</li>
	<li>
	C++ lexer fixes problem with JavaScript regular expressions with '/' in character ranges.
	<a href="http://sourceforge.net/p/scintilla/bugs/1415/">Bug #1415.</a>
	</li>
	<li>
	LaTeX folder added.
	<a href="http://sourceforge.net/p/scintilla/feature-requests/970/">Feature #970.</a>
	</li>
	<li>
	LaTeX lexer improves styling of math environments.
	<a href="http://sourceforge.net/p/scintilla/feature-requests/970/">Feature #970.</a>
	</li>
	<li>
	MySQL lexer implements hidden commands.
	</li>
	<li>
	Only produce a single undo step when autocompleting a single word.
	<a href="http://sourceforge.net/p/scintilla/bugs/1421/">Bug #1421.</a>
	</li>
	<li>
	Fixed crash when printing lines longer than 8000 characters.
	<a href="http://sourceforge.net/p/scintilla/bugs/1430/">Bug #1430.</a>
	</li>
	<li>
	Fixed problem in character movement extends selection mode where reversing
	direction collapsed the selection.
	</li>
	<li>
	Memory issues fixed on Cocoa, involving object ownership,
	lifetime of timers, and images held by the info bar.
	<a href="http://sourceforge.net/p/scintilla/bugs/1436/">Bug #1436.</a>
	</li>
	<li>
	Cocoa key binding for Alt+Delete changed to delete previous word to be more compatible with
	platform standards.
	</li>
	<li>
	Fixed crash on Cocoa with scrollbar when there is no scrolling possible.
	<a href="http://sourceforge.net/p/scintilla/bugs/1416/">Bug #1416.</a>
	</li>
	<li>
	On Cocoa with retina display fixed positioning of autocompletion lists.
	</li>
	<li>
	Fixed SciTE on Windows failure to run a batch file with a name containing a space by
	quoting the path in the properties file.
	<a href="http://sourceforge.net/p/scintilla/bugs/1423/">Bug #1423.</a>
	</li>
	<li>
	Fixed scaling bug when printing on GTK+.
	<a href="http://sourceforge.net/p/scintilla/bugs/1427/">Bug #1427.</a>
	</li>
	<li>
	SciTE on GTK toolbar.detachable feature removed.
	</li>
	<li>
	Fixed some background saving bugs in SciTE.
	<a href="http://sourceforge.net/p/scintilla/bugs/1366/">Bug #1366.</a>
	<a href="http://sourceforge.net/p/scintilla/bugs/1339/">Bug #1339.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite323.zip?download">Release 3.2.3</a>
    </h3>
    <ul>
	<li>
	Released 21 October 2012.
	</li>
	<li>
	Improve speed when performing multiple searches.
	</li>
	<li>
	SciTE adds definition of PLAT_UNIX for both PLAT_GTK and PLAT_MAC to allow consolidation of
	settings valid on all Unix variants.
	</li>
	<li>
	Signal autoCompleteCancelled added on Qt.
	</li>
	<li>
	Bash lexer supports nested delimiter pairs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3569352&group_id=2439">Feature #3569352.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1515556&group_id=2439">Bug #1515556.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3008483&group_id=2439">Bug #3008483.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3512208&group_id=2439">Bug #3512208.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3515392&group_id=2439">Bug #3515392.</a>
	</li>
	<li>
	For C/C++, recognise exponent in floating point hexadecimal literals.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3576454&group_id=2439">Bug #3576454.</a>
	</li>
	<li>
	For C #include statements, do not treat // in the path as a comment.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3519260&group_id=2439">Bug #3519260.</a>
	</li>
	<li>
	Lexer for GetText translations (PO) improved with additional styles and single instance limitation fixed.
	</li>
	<li>
	Ruby for loop folding fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3240902&group_id=2439">Bug #3240902.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3567391&group_id=2439">Bug #3567391.</a>
	</li>
	<li>
	Ruby recognition of here-doc after class or instance variable fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3567809&group_id=2439">Bug #3567809.</a>
	</li>
	<li>
	SQL folding of loop and case fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3567905&group_id=2439">Bug #3567905.</a>
	</li>
	<li>
	SQL folding of case with assignment fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3571820&group_id=2439">Bug #3571820.</a>
	</li>
	<li>
	Fix hang when removing all characters from indicator at end of document.
	</li>
	<li>
	Fix failure of \xhh in regular expression search for values greater than 0x79.
	</li>
	<li>
	On Cocoa on OS X 10.8, fix inverted drawing of find indicator.
	</li>
	<li>
	On Cocoa, fix double drawing when horizontal scroll range small and user swipes horizontally.
	</li>
	<li>
	On Cocoa, remove incorrect setting of save point when reading information through 'string' and 'selectedString'.
	</li>
	<li>
	On Cocoa, fix incorrect memory managment of infoBar.
	</li>
	<li>
	On GTK+ 3 Ubuntu, fix crash when drawing margin.
	</li>
	<li>
	On ncurses, fix excessive spacing with italics line end.
	</li>
	<li>
	On Windows, search for D2D1.DLL and DWRITE.DLL in system directory to avoid loading from earlier
	in path where could be planted by malware.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite322.zip?download">Release 3.2.2</a>
    </h3>
    <ul>
	<li>
	Released 31 August 2012.
	</li>
	<li>
	Retina display support for Cocoa. Text size fixed.
	Scale factor for images implemented so they can be displayed in high definition.
	</li>
	<li>
	Implement INDIC_SQUIGGLEPIXMAP as a faster version of INDIC_SQUIGGLE.
	Avoid poor drawing at right of INDIC_SQUIGGLE.
	Align INDIC_DOTBOX to pixel grid for full intensity.
	</li>
	<li>
	Implement SCI_GETSELECTIONEMPTY API.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3543121&group_id=2439">Bug #3543121.</a>
	</li>
	<li>
	Added SCI_VCHOMEDISPLAY and SCI_VCHOMEDISPLAYEXTEND key commands.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3561433&group_id=2439">Feature #3561433.</a>
	</li>
	<li>
	Allow specifying SciTE Find in Files directory with find.in.directory property.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3558594&group_id=2439">Feature #3558594.</a>
	</li>
	<li>
	Override SciTE global strip.trailing.spaces with strip.trailing.spaces by pattern files.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3556320&group_id=2439">Feature #3556320.</a>
	</li>
	<li>
	Fix long XML script tag handling in XML lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3534190&group_id=2439">Bug #3534190.</a>
	</li>
	<li>
	Fix rectangular selection range after backspace.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3543097&group_id=2439">Bug #3543097.</a>
	</li>
	<li>
	Send SCN_UPDATEUI with SC_UPDATE_SELECTION for backspace in virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3543121&group_id=2439">Bug #3543121.</a>
	</li>
	<li>
	Avoid problems when calltip highlight range is negative.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3545938&group_id=2439">Bug #3545938.</a>
	</li>
	<li>
	On Cocoa, fix image drawing code so that image is not accessed after being freed
	and is drawn in the correct location.
	</li>
	<li>
	On Cocoa, limit horizontal touch scrolling to existing established width.
	</li>
	<li>
	On Cocoa, decrease sensitivity of pinch-zoom.
	</li>
	<li>
	Fix Cocoa drawing where style changes were not immediately visible.
	</li>
	<li>
	Fix Cocoa memory leak due to reference cycle.
	</li>
	<li>
	Fix Cocoa bug where notifications were sent after Scintilla was freed.
	</li>
	<li>
	SciTE on OS X user shortcuts treats "Ctrl+D" as equivalent to "Ctrl+d".
	</li>
	<li>
	On Windows, saving SciTE's Lua startup script causes it to run.
	</li>
	<li>
	Limit time allowed to highlight current word in SciTE to 0.25 seconds to remain responsive.
	</li>
	<li>
	Fixed SciTE read-only mode to stick with buffer.
	</li>
	<li>
	For SciTE on Windows, enable Ctrl+Z, Ctrl+X, and Ctrl+C (Undo, Cut, and Copy) in the
	editable fields of find and replace strips
	</li>
	<li>
	Remove limit on logical line length in SciTE .properties files.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3544312&group_id=2439">Bug #3544312.</a>
	</li>
	<li>
	Improve performance of SciTE Save As command.
	</li>
	<li>
	Fix SciTE crash with empty .properties files. Bug #3545938.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3555308&group_id=2439">Bug #3555308.</a>
	</li>
	<li>
	Fix repeated letter in SciTE calltips.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3545938&group_id=2439">Bug #3545938.</a>
	</li>
	<li>
	Refine build time checking for Direct2D and DirectWrite.
	</li>
	<li>
	Avoid potential build problems on Windows with MultiMon.h by explicitly checking for multi-monitor APIs.
	</li>
	<li>
	Automatically disable themed drawing in SciTE when building on Windows 2000.
	Reenable building for Windows NT 4 on NT 4 .
	</li>
	<li>
	Added ncurses platform definitions. Implementation is maintained separately as
	<a href="http://foicica.com/scinterm/">Scinterm</a>.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite321.zip?download">Release 3.2.1</a>
    </h3>
    <ul>
	<li>
	Released 14 July 2012.
	</li>
	<li>
	In Scintilla.iface, specify features as properties instead of functions where possible and fix some enumerations.
	</li>
	<li>
	In SciTE Lua scripts, string properties in Scintilla API can be retrieved as well as set using property notation.
	</li>
	<li>
	Added character class APIs: SCI_SETPUNCTUATIONCHARS, SCI_GETWORDCHARS, SCI_GETWHITESPACECHARS,
	and SCI_GETPUNCTUATIONCHARS.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3529805&group_id=2439">Feature #3529805.</a>
	</li>
	<li>
	Less/Hss support added to CSS lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3532413&group_id=2439">Feature #3532413.</a>
	</li>
	<li>
	C++ lexer style SCE_C_PREPROCESSORCOMMENT added for stream comments in preprocessor.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3487406&group_id=2439">Bug #3487406.</a>
	</li>
	<li>
	Fix incorrect styling of inactive code in C++ lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3533036&group_id=2439">Bug #3533036.</a>
	</li>
	<li>
	Fix incorrect styling by C++ lexer after empty lines in preprocessor style.
	</li>
	<li>
	C++ lexer option "lexer.cpp.allow.dollars" fixed so can be turned off after being on.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3541461&group_id=2439">Bug #3541461.</a>
	</li>
	<li>
	Fortran fixed format lexer fixed to style comments from column 73.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3540486&group_id=2439">Bug #3540486.</a>
	</li>
	<li>
	Fortran folder folds CRITICAL .. END CRITICAL.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3540486&group_id=2439">Bug #3540486.</a>
	</li>
	<li>
	Fortran lexer fixes styling after comment line ending with '&amp;'.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3087226&group_id=2439">Bug #3087226.</a>
	</li>
	<li>
	Fortran lexer styles preprocessor lines so they do not trigger incorrect folding.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2906275&group_id=2439">Bug #2906275.</a>
	</li>
	<li>
	Fortran folder fixes folding of nested ifs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2809176&group_id=2439">Bug #2809176.</a>
	</li>
	<li>
	HTML folder fixes folding of CDATA when fold.html.preprocessor=0.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3540491&group_id=2439">Bug #3540491.</a>
	</li>
	<li>
	On Cocoa, fix autocompletion font lifetime issue and row height computation.
	</li>
	<li>
	In 'choose single' mode, autocompletion will close an existing list if asked to display a single entry list.
	</li>
	<li>
	Fixed SCI_MARKERDELETE to only delete one marker per call.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3535806&group_id=2439">Bug #3535806.</a>
	</li>
	<li>
	Properly position caret after undoing coalesced delete operations.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3523326&group_id=2439">Bug #3523326.</a>
	</li>
	<li>
	Ensure margin is redrawn when SCI_MARGINSETSTYLE called.
	</li>
	<li>
	Fix clicks in first pixel of margins to send SCN_MARGINCLICK.
	</li>
	<li>
	Fix infinite loop when drawing block caret for a zero width space character at document start.
	</li>
	<li>
	Crash fixed for deleting negative range.
	</li>
	<li>
	For characters that overlap the beginning of their space such as italics descenders and bold serifs, allow start
	of text to draw 1 pixel into margin.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=699587&group_id=2439">Bug #699587.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3537799&group_id=2439">Bug #3537799.</a>
	</li>
	<li>
	Fixed problems compiling Scintilla for Qt with GCC 4.7.1 x64.
	</li>
	<li>
	Fixed problem with determining GTK+ sub-platform caused when adding Qt support in 3.2.0.
	</li>
	<li>
	Fix incorrect measurement of untitled file in SciTE on Linux leading to message "File ...' is 2147483647 bytes long".
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3537764&group_id=2439">Bug #3537764.</a>
	</li>
	<li>
	In SciTE, fix open of selected filename with line number to go to that line.
	</li>
	<li>
	Fix problem with last visible buffer closing in SciTE causing invisible buffers to be active.
	</li>
	<li>
	Avoid blinking of SciTE's current word highlight when output pane changes.
	</li>
	<li>
	SciTE properties files can be longer than 60K.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite320.zip?download">Release 3.2.0</a>
    </h3>
    <ul>
	<li>
	Released 1 June 2012.
	</li>
	<li>
	Platform layer added for the Qt open-source cross-platform application and user interface framework
	for development in C++ or in Python with the PySide bindings for Qt.
	</li>
	<li>
	Direct access provided to the document bytes for ranges within Scintilla.
	This is similar to the existing SCI_GETCHARACTERPOINTER API but allows for better performance.
	</li>
	<li>
	Ctrl+Double Click and Ctrl+Triple Click add the word or line to the set of selections.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3520037&group_id=2439">Feature #3520037.</a>
	</li>
	<li>
	A SCI_DELETERANGE API was added for deleting a range of text.
	</li>
	<li>
	Line wrap markers may now be drawn in the line number margin.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3518198&group_id=2439">Feature #3518198.</a>
	</li>
	<li>
	SciTE on OS X adds option to hide hidden files in the open dialog box.
	</li>
	<li>
	Lexer added for OScript language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3523197&group_id=2439">Feature #3523197.</a>
	</li>
	<li>
	Lexer added for Visual Prolog language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3523018&group_id=2439">Feature #3523018.</a>
	</li>
	<li>
	UTF-8 validity is checked more stringently and consistently. All 66 non-characters are now treated as invalid.
	</li>
	<li>
	HTML lexer bug fixed with inconsistant highlighting for PHP when attribute on separate line from tag.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3520027&group_id=2439">Bug #3520027.</a>
	</li>
	<li>
	HTML lexer bug fixed for JavaScript block comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3520032&group_id=2439">Bug #3520032.</a>
	</li>
	<li>
	Annotation drawing bug fixed when box displayed with different colours on different lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3519872&group_id=2439">Bug #3519872.</a>
	</li>
	<li>
	On Windows with Direct2D, fix drawing with 125% and 150% DPI system settings.
	</li>
	<li>
	Virtual space selection bug fixed for rectangular selections.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3519246&group_id=2439">Bug #3519246.</a>
	</li>
	<li>
	Replacing multiple selection with newline changed to only affect main selection.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3522251&group_id=2439">Bug #3522251.</a>
	</li>
	<li>
	Replacing selection with newline changed to group deletion and insertion as a single undo action.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3522250&group_id=2439">Bug #3522250.</a>
	</li>
	<li>
	Auto-completion lists on GTK+ 3 set height correctly instead of showing too few lines.
	</li>
	<li>
	Mouse wheel scrolling changed to avoid GTK+ bug in recent distributions.
	</li>
	<li>
	IME bug on Windows fixed for horizontal jump.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3529728&group_id=2439">Bug #3529728.</a>
	</li>
	<li>
	SciTE case-insensitive autocompletion filters equal identifiers better.
	Calltip arrows work with bare word identifiers.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3517810&group_id=2439">Bug #3517810.</a>
	</li>
	<li>
	SciTE bug fixed where shbang lines not setting file type when switching
	to file loaded in background.
	</li>
	<li>
	SciTE on GTK+ shows open and save dialogs with the directory of the current file displayed.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite310.zip?download">Release 3.1.0</a>
    </h3>
    <ul>
	<li>
	Released 20 April 2012.
	</li>
	<li>
	Animated find indicator added on Cocoa.
	</li>
	<li>
	Buttons can be made default in SciTE user strips.
	</li>
	<li>
	SciTE allows find and replace histories to be saved in session.
	</li>
	<li>
	Option added to allow case-insensitive selection in auto-completion lists.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3516538&group_id=2439">Bug #3516538.</a>
	</li>
	<li>
	Replace \0 by complete found text in regular expressions.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3510979&group_id=2439">Feature #3510979.</a>
	</li>
	<li>
	Fixed single quoted strings in bash lexer. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3512208&group_id=2439">Bug #3512208.</a>
	</li>
	<li>
	Incorrect highlighting fixed in C++ lexer for continued lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3509317&group_id=2439">Bug #3509317.</a>
	</li>
	<li>
	Hang fixed in diff lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3508602&group_id=2439">Bug #3508602.</a>
	</li>
	<li>
	Folding improved for SQL CASE/MERGE statement.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3503277&group_id=2439">Bug #3503277.</a>
	</li>
	<li>
	Fix extra drawing of selection inside word wrap indentation.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3515555&group_id=2439">Bug #3515555.</a>
	</li>
	<li>
	Fix problem with determining the last line that needs styling when drawing.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3514882&group_id=2439">Bug #3514882.</a>
	</li>
	<li>
	Fix problems with drawing in margins.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3514882&group_id=2439">Bug #3514882.</a>
	</li>
	<li>
	Fix printing crash when using Direct2D to display on-screen. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3513946&group_id=2439">Bug #3513946.</a>
	</li>
	<li>
	Fix SciTE bug where background.*.size disabled restoration of bookmarks and positions from session.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3514885&group_id=2439">Bug #3514885.</a>
	</li>
	<li>
	Fixed the Move Selected Lines command when last line does not end with a line end character. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3511023&group_id=2439">Bug #3511023.</a>
	</li>
	<li>
	Fix word wrap indentation printing to use printer settings instead of screen settings. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3512961&group_id=2439">Bug #3512961.</a>
	</li>
	<li>
	Fix SciTE bug where executing an empty command prevented executing further commands 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3512976&group_id=2439">Bug #3512976.</a>
	</li>
	<li>
	Fix SciTE bugs with focus in user strips and made strips more robust with invalid definitions.
	</li>
	<li>
	Suppress SciTE regular expression option when searching with find next selection. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3510985&group_id=2439">Bug #3510985.</a>
	</li>
	<li>
	SciTE Find in Files command matches empty pattern to all files.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3495918&group_id=2439">Feature #3495918.</a>
	</li>
	<li>
	Fix scroll with mouse wheel on GTK+.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3501321&group_id=2439">Bug #3501321.</a>
	</li>
	<li>
	Fix column finding method so that tab is counted correctly. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3483713&group_id=2439">Bug #3483713.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite304.zip?download">Release 3.0.4</a>
    </h3>
    <ul>
	<li>
	Released 8 March 2012.
	</li>
	<li>
	SciTE scripts can create user interfaces as strips.
	</li>
	<li>
	SciTE can save files automatically in the background.
	</li>
	<li>
	Pinch zoom implemented on Cocoa.
	</li>
	<li>
	ECL lexer added.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3488209&group_id=2439">Feature #3488209.</a>
	</li>
	<li>
	CPP lexer fixes styling after document comment keywords. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3495445&group_id=2439">Bug #3495445.</a>
	</li>
	<li>
	Pascal folder improves handling of some constructs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3486385&group_id=2439">Feature #3486385.</a>
	</li>
	<li>
	XML lexer avoids entering a bad mode due to complex preprocessor instructions.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3488060&group_id=2439">Bug #3488060.</a>
	</li>
	<li>
	Duplicate command is always remembered as a distinct command for undo.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3495836&group_id=2439">Bug #3495836.</a>
	</li>
	<li>
	SciTE xml.auto.close.tags no longer closes with PHP code similar to &lt;a $this-&gt; 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3488067&group_id=2439">Bug #3488067.</a>
	</li>
	<li>
	Fix bug where setting an indicator for the whole document would fail.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3487440&group_id=2439">Bug #3487440.</a>
	</li>
	<li>
	Crash fixed for SCI_MOVESELECTEDLINESDOWN with empty vertical selection. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3496403&group_id=2439">Bug #3496403.</a>
	</li>
	<li>
	Differences between buffered and unbuffered mode on Direct2D eliminated. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3495791&group_id=2439">Bug #3495791.</a>
	</li>
	<li>
	Font leading implemented for Direct2D to improve display of character blobs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3494744&group_id=2439">Bug #3494744.</a>
	</li>
	<li>
	Fractional widths used for line numbers, character markers and other situations.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3494492&group_id=2439">Bug #3494492.</a>
	</li>
	<li>
	Translucent rectangles drawn using Direct2D with sharper corners.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3494492&group_id=2439">Bug #3494492.</a>
	</li>
	<li>
	RGBA markers drawn sharper when centred using Direct2D.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3494202&group_id=2439">Bug #3494202.</a>
	</li>
	<li>
	RGBA markers are drawn centred when taller than line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3494184&group_id=2439">Bug #3494184.</a>
	</li>
	<li>
	Image marker drawing problem fixed for markers taller than line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3493503&group_id=2439">Bug #3493503.</a>
	</li>
	<li>
	Markers are drawn horizontally off-centre based on margin type instead of dimensions.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3488696&group_id=2439">Bug #3488696.</a>
	</li>
	<li>
	Fold tail markers drawn vertically centred.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3488289&group_id=2439">Feature #3488289.</a>
	</li>
	<li>
	On Windows, Scintilla is more responsive in wrap mode.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3487397&group_id=2439">Bug #3487397.</a>
	</li>
	<li>
	Unimportant "Gdk-CRITICAL" messages are no longer displayed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3488481&group_id=2439">Bug #3488481.</a>
	</li>
	<li>
	SciTE on Windows Find in Files sets focus to dialog when already created; allows opening dialog when a job is running. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3480635&group_id=2439">Bug #3480635.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3486657&group_id=2439">Bug #3486657.</a>
	</li>
	<li>
	Fixed problems with multiple clicks in margin and with mouse actions combined with virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3484370&group_id=2439">Bug #3484370.</a>
	</li>
	<li>
	Fixed bug with using page up and down and not returning to original line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3485669&group_id=2439">Bug #3485669.</a>
	</li>
	<li>
	Down arrow with wrapped text no longer skips lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1776560&group_id=2439">Bug #1776560.</a>
	</li>
	<li>
	Fix problem with dwell ending immediately due to word wrap.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3484416&group_id=2439">Bug #3484416.</a>
	</li>
	<li>
	Wrapped lines are rewrapped more consistently while resizing window.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3484179&group_id=2439">Bug #3484179.</a>
	</li>
	<li>
	Selected line ends are highlighted more consistently. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3484330&group_id=2439">Bug #3484330.</a>
	</li>
	<li>
	Fix grey background on files that use shbang to choose language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3482777&group_id=2439">Bug #3482777.</a>
	</li>
	<li>
	Fix failure messages from empty commands in SciTE. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3480645&group_id=2439">Bug #3480645.</a>
	</li>
	<li>
	Redrawing reduced for some marker calls.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3493530&group_id=2439">Feature #3493530.</a>
	</li>
	<li>
	Match brace and select brace commands work in SciTE output pane.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3486598&group_id=2439">Feature #3486598.</a>
	</li>
	<li>
	Performing SciTE "Show Calltip" command when a calltip is already visible shows the next calltip.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3487017&group_id=2439">Feature #3487017.</a>
	</li>
	<li>
	SciTE allows saving file even when file unchanged.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3486654&group_id=2439">Feature #3486654.</a>
	</li>
	<li>
	SciTE allows optional use of character escapes in calltips. 
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3495239&group_id=2439">Feature #3495239.</a>
	</li>
	<li>
	SciTE can open file:// URLs with Ctrl+Shift+O.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3495389&group_id=2439">Feature #3495389.</a>
	</li>
	<li>
	Key modifiers updated for GTK+ on OS X to match upstream changes.
	</li>
	<li>
	SciTE hang when marking all occurrences of regular expressions fixed.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite303.zip?download">Release 3.0.3</a>
    </h3>
    <ul>
	<li>
	Released 28 January 2012.
	</li>
	<li>
	Printing works on GTK+ version 2.x as well as 3.x.
	</li>
	<li>
	Lexer added for the AviSynth language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3475611&group_id=2439">Feature #3475611.</a>
	</li>
	<li>
	Lexer added for the Take Command / TCC scripting language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3462462&group_id=2439">Feature #3462462.</a>
	</li>
	<li>
	CSS lexer gains support for SCSS.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3268017&group_id=2439">Feature #3268017.</a>
	</li>
	<li>
	CPP lexer fixes problems in the preprocessor structure caused by continuation lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3458508&group_id=2439">Bug #3458508.</a>
	</li>
	<li>
	Errorlist lexer handles column numbers for GCC format diagnostics.
	In SciTE, Next Message goes to column where this can be decoded from GCC format diagnostics.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3453075&group_id=2439">Feature #3453075.</a>
	</li>
	<li>
	HTML folder fixes spurious folds on some tags.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3459262&group_id=2439">Bug #3459262.</a>
	</li>
	<li>
	Ruby lexer fixes bug where '=' at start of file caused whole file to appear as a comment.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3452488&group_id=2439">Bug #3452488.</a>
	</li>
	<li>
	SQL folder folds blocks of single line comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3467425&group_id=2439">Feature #3467425.</a>
	</li>
	<li>
	On Windows using Direct2D, defer invalidation of render target until completion of painting to avoid failures.
	</li>
	<li>
	Further support of fractional positioning. Spaces, tabs, and single character tokens can take fractional space
	and wrapped lines are positioned taking fractional positions into account.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3471998&group_id=2439">Bug #3471998.</a>
	</li>
	<li>
	On Windows using Direct2D, fix extra carets appearing.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3471998&group_id=2439">Bug #3471998.</a>
	</li>
	<li>
	For autocompletion lists Page Up and Down move by the list height instead of by 5 lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3455493&group_id=2439">Bug #3455493.</a>
	</li>
	<li>
	For SCI_LINESCROLLDOWN/UP don't select into virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3451681&group_id=2439">Bug #3451681.</a>
	</li>
	<li>
	Fix fold highlight not being fully drawn.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3469936&group_id=2439">Bug #3469936.</a>
	</li>
	<li>
	Fix selection margin appearing black when starting in wrap mode.
	</li>
	<li>
	Fix crash when changing end of document after adding an annotation.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3476637&group_id=2439">Bug #3476637.</a>
	</li>
	<li>
	Fix problems with building to make RPMs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3476149&group_id=2439">Bug #3476149.</a>
	</li>
	<li>
	Fix problem with building on GTK+ where recent distributions could not find gmodule.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3469056&group_id=2439">Bug #3469056.</a>
	</li>
	<li>
	Fix problem with installing SciTE on GTK+ due to icon definition in .desktop file including an extension.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3476117&group_id=2439">Bug #3476117.</a>
	</li>
	<li>
	Fix SciTE bug where new buffers inherited some properties from previously opened file.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3457060&group_id=2439">Bug #3457060.</a>
	</li>
	<li>
	Fix focus when closing tab in SciTE with middle click. Focus moves to edit pane instead of staying on tab bar.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3440142&group_id=2439">Bug #3440142.</a>
	</li>
	<li>
	For SciTE on Windows fix bug where Open Selected Filename for URL would append a file extension.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3459185&group_id=2439">Feature #3459185.</a>
	</li>
	<li>
	For SciTE on Windows fix key handling of control characters in Parameters dialog so normal editing (Ctrl+C, ...) works.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3459345&group_id=2439">Bug #3459345.</a>
	</li>
	<li>
	Fix SciTE bug where files became read-only after saving. Drop the "*" dirty marker after save completes.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3467432&group_id=2439">Bug #3467432.</a>
	</li>
	<li>
	For SciTE handling of diffs with "+++" and "---" lines, also handle case where not followed by tab.
	Go to correct line for diff "+++" message.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3467143&group_id=2439">Bug #3467143.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3467178&group_id=2439">Bug #3467178.</a>
	</li>
	<li>
	SciTE on GTK+ now performs threaded actions even on GTK+ versions before 2.12.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite302.zip?download">Release 3.0.2</a>
    </h3>
    <ul>
	<li>
	Released 9 December 2011.
	</li>
	<li>
	SciTE saves files in the background without blocking the user interface.
	</li>
	<li>
	Printing implemented in SciTE on GTK+ 3.x.
	</li>
	<li>
	ILoader interface for background loading finalised and documented.
	</li>
	<li>
	CoffeeScript lexer added.
	</li>
	<li>
	C++ lexer fixes crash with "#if defined( XXX 1".
	</li>
	<li>
	Crash with Direct2D on Windows fixed.
	</li>
	<li>
	Backspace removing protected range fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3445911&group_id=2439">Bug #3445911.</a>
	</li>
	<li>
	Cursor setting failure on Windows when screen saver on fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3438780&group_id=2439">Bug #3438780.</a>
	</li>
	<li>
	SciTE on GTK+ hang fixed with -open:file option.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3441980&group_id=2439">Bug #3441980.</a>
	</li>
	<li>
	Failure to evaluate shbang fixed in SciTE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3441801&group_id=2439">Bug #3441801.</a>
	</li>
	<li>
	SciTE failure to treat files starting with "&lt;?xml" as XML fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3440718&group_id=2439">Bug #3440718.</a>
	</li>
	<li>
	Made untitled tab saveable when created by closing all files.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3440244&group_id=2439">Bug #3440244.</a>
	</li>
	<li>
	SciTE crash fixed when using Scintillua.
	</li>
	<li>
	SciTE revert command fixed so that undo works on individual actions instead of undoing to revert point.
	</li>
	<li>
	Focus loss in SciTE when opening a recent file fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3440142&group_id=2439">Bug #3440142.</a>
	</li>
	<li>
	Fixed SciTE SelLength property to measure characters instead of bytes.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3283519&group_id=2439">Bug #3283519.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite301.zip?download">Release 3.0.1</a>
    </h3>
    <ul>
	<li>
	Released 15 November 2011.
	</li>
	<li>
	SciTE on Windows now runs Lua scripts directly on the main thread instead of starting them on a
	secondary thread and then moving back to the main thread.
	</li>
	<li>
	Highlight "else" as a keyword for TCL in the same way as other languages.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1836954&group_id=2439">Bug #1836954.</a>
	</li>
	<li>
	Fix problems with setting fonts for autocompletion lists on Windows where
	font handles were copied and later deleted causing a system default font to be used.
	</li>
	<li>
	Fix font size used on Windows for Asian language input methods which sometimes led to IME not being visible.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3436753&group_id=2439">Bug #3436753.</a>
	</li>
	<li>
	Fixed polygon drawing on Windows so fold symbols are visible again.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3433558&group_id=2439">Bug #3433558.</a>
	</li>
	<li>
	Changed background drawing on GTK+ to allow for fractional character positioning as occurs on OS X
	as this avoids faint lines at lexeme boundaries.
	</li>
	<li>
	Ensure pixmaps allocated before painting as there was a crash when Scintilla drew without common initialisation calls.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3432354&group_id=2439">Bug #3432354.</a>
	</li>
	<li>
	Fixed SciTE on Windows bug causing wrong caret position after indenting a selection.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3433433&group_id=2439">Bug #3433433.</a>
	</li>
	<li>
	Fixed SciTE session saving to store buffer position matching buffer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3434372&group_id=2439">Bug #3434372.</a>
	</li>
	<li>
	Fixed leak of document objects in SciTE.
	</li>
	<li>
	Recognise URL characters '?' and '%' for Open Selected command in SciTE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3429409&group_id=2439">Bug #3429409.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite300.zip?download">Release 3.0.0</a>
    </h3>
    <ul>
	<li>
	Released 1 November 2011.
	</li>
	<li>
	Carbon platform support removed. OS X applications should switch to Cocoa.
	</li>
	<li>
	On Windows Vista or newer, drawing may be performed with Direct2D and DirectWrite instead of GDI.
	</li>
	<li>
	Cairo is now used for all drawing on GTK+. GDK drawing was removed. 
	</li>
	<li>
	Paletted display support removed.
	</li>
	<li>
	Fractional font sizes can be specified.
	</li>
	<li>
	Different weights of text supported on some platforms instead of just normal and bold.
	</li>
	<li>
	Sub-pixel character positioning supported.
	</li>
	<li>
	SciTE loads files in the background without blocking the user interface.
	</li>
	<li>
	SciTE can display diagnostic messages interleaved with the text of files immediately after the
	line referred to by the diagnostic.
	</li>
	<li>
	New API to see if all lines are visible which can be used to optimize processing fold structure notifications.
	</li>
	<li>
	Scrolling optimized by avoiding invalidation of fold margin when redrawing whole window.
	</li>
	<li>
	Optimized SCI_MARKERNEXT.
	</li>
	<li>
	C++ lexer supports Pike hash quoted strings when turned on with lexer.cpp.hashquoted.strings.
	</li>
	<li>
	Fixed incorrect line height with annotations in wrapped mode when there are multiple views.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3388159&group_id=2439">Bug #3388159.</a>
	</li>
	<li>
	Calltips may be displayed above the text as well as below.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3410830&group_id=2439">Bug #3410830.</a>
	</li>
	<li>
	For huge files SciTE only examines the first megabyte for newline discovery.
	</li>
	<li>
	SciTE on GTK+ removes the fileselector.show.hidden property and check box as this was buggy and GTK+ now
	supports an equivalent feature.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3413630&group_id=2439">Bug #3413630.</a>
	</li>
	<li>
	SciTE on GTK+ supports mnemonics in dynamic menus.
	</li>
	<li>
	SciTE on GTK+ displays the user's home directory as '~' in menus to make them shorter.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite229.zip?download">Release 2.29</a>
    </h3>
    <ul>
	<li>
	Released 16 September 2011.
	</li>
	<li>
	To automatically discover the encoding of a file when opening it, SciTE can run a program set with command.discover.properties.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3324341&group_id=2439">Feature #3324341.</a>
	</li>
	<li>
	Cairo always used for drawing on GTK+.
	</li>
	<li>
	The set of properties files imported by SciTE can be controlled with the properties imports.include and imports.exclude.
	The import statement has been extended to allow "import *". 
	The properties files for some languages are no longer automatically loaded by default. The properties files affected are
	avenue, baan, escript, lot, metapost, and mmixal.
	</li>
	<li>
	C++ lexer fixed a bug with raw strings being recognised too easily.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3388122&group_id=2439">Bug #3388122.</a>
	</li>
	<li>
	LaTeX lexer improved with more states and fixes to most outstanding bugs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1493111&group_id=2439">Bug #1493111.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1856356&group_id=2439">Bug #1856356.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3081692&group_id=2439">Bug #3081692.</a>
	</li>
	<li>
	Lua lexer updates for Lua 5.2 beta with goto labels and "\z" string escape.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3386330&group_id=2439">Feature #3386330.</a>
	</li>
	<li>
	Perl string styling highlights interpolated variables.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3394258&group_id=2439">Feature #3394258.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3076629&group_id=2439">Bug #3076629.</a>
	</li>
	<li>
	Perl lexer updated for Perl 5.14.0 with 0X and 0B numeric literal prefixes, break keyword and "+" supported in subroutine prototypes.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3388802&group_id=2439">Feature #3388802.</a>
	</li>
	<li>
	Perl bug fixed with CRLF line endings.
	</li>
	<li>
	Markdown lexer fixed to not change state with "_" in middle of word.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3398184&group_id=2439">Bug #3398184.</a>
	</li>
	<li>
	Cocoa restores compatibility with OS X 10.5.
	</li>
	<li>
	Mouse pointer changes over selection to an arrow near start when scrolled horizontally.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3389055&group_id=2439">Bug #3389055.</a>
	</li>
	<li>
	Indicators that finish at the end of the document no longer expand when text is appended.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3378718&group_id=2439">Bug #3378718.</a>
	</li>
	<li>
	SparseState merge fixed to check if other range is empty.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3387053&group_id=2439">Bug #3387053.</a>
	</li>
	<li>
	On Windows, autocompletion lists will scroll instead of document when mouse wheel spun.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3403600&group_id=2439">Feature #3403600.</a>
	</li>
	<li>
	SciTE performs more rapid polling for command completion so will return faster and report more accurate times.
	</li>
	<li>
	SciTE resizes panes proportionally when switched between horizontal and vertical layout.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3376784&group_id=2439">Feature #3376784.</a>
	</li>
	<li>
	SciTE on GTK+ opens multiple files into a single instance more reliably.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3363754&group_id=2439">Bug #3363754.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite228.zip?download">Release 2.28</a>
    </h3>
    <ul>
	<li>
	Released 1 August 2011.
	</li>
	<li>
	GTK+ Cairo support works back to GTK+ version 2.8. Requires changing Scintilla source code to enable before GTK+ 2.22.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3322351&group_id=2439">Bug #3322351.</a>
	</li>
	<li>
	Translucent images in RGBA format can be used for margin markers and in autocompletion lists.
	</li>
	<li>
	INDIC_DOTBOX added as a translucent dotted rectangular indicator.
	</li>
	<li>
	Asian text input using IME works for GTK+ 3.x and GTK+ 2.x with Cairo.
	</li>
	<li>
	On GTK+, IME works for Ctrl+Shift+U Unicode input in Scintilla. For SciTE, Ctrl+Shift+U is still Make Selection Uppercase.
	</li>
	<li>
	Key bindings for GTK+ on OS X made compatible with Cocoa port and platform conventions.
	</li>
	<li>
	Cocoa port supports different character encodings, improves scrolling performance and drag image appearance.
	The control ID is included in WM_COMMAND notifications. Text may be deleted by dragging to the trash.
	ScrollToStart and ScrollToEnd key commands added to simplify implementation of standard OS X Home and End
	behaviour.
	</li>
	<li>
	SciTE on GTK+ uses a paned widget to contain the edit and output panes instead of custom code.
	This allows the divider to be moved easily on GTK+ 3 and its appearance follows GTK+ conventions more closely.
	</li>
	<li>
	SciTE builds and installs on BSD.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3324644&group_id=2439">Bug #3324644.</a>
	</li>
	<li>
	Cobol supports fixed format comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3014850&group_id=2439">Bug #3014850.</a>
	</li>
	<li>
	Mako template language block syntax extended and ## comments recognised.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3325178&group_id=2439">Feature #3325178.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3318818&group_id=2439">Bug #3318818.</a>
	</li>
	<li>
	Folding of Mako template language within HTML fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3324563&group_id=2439">Bug #3324563.</a>
	</li>
	<li>
	Python lexer has lexer.python.keywords2.no.sub.identifiers option to avoid highlighting second set of 
	keywords following '.'.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3325333&group_id=2439">Bug #3325333.</a>
	</li>
	<li>
	Python folder fixes bug where fold would not extend to final line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3349157&group_id=2439">Bug #3349157.</a>
	</li>
	<li>
	SciTE treats LPEG lexers the same as script lexers by setting all 8 style bits.
	</li>
	<li>
	For Cocoa, crashes with unsupported font variants and memory leaks for colour objects fixed.
	</li>
	<li>
	Shift-JIS lead byte ranges modified to match Windows.
	</li>
	<li>
	Mouse pointer changes over selection to an arrow more consistently.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3315756&group_id=2439">Bug #3315756.</a>
	</li>
	<li>
	Bug fixed with annotations beyond end of document.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3347268&group_id=2439">Bug #3347268.</a>
	</li>
	<li>
	Incorrect drawing fixed for combination of background colour change and translucent selection.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3377116&group_id=2439">Bug #3377116.</a>
	</li>
	<li>
	Lexers initialized correctly when started at position other than start of line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3377148&group_id=2439">Bug #3377148.</a>
	</li>
	<li>
	Fold highlight drawing fixed for some situations.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3323015&group_id=2439">Bug #3323015.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3323805&group_id=2439">Bug #3323805.</a>
	</li>
	<li>
	Case insensitive search fixed for cases where folded character uses fewer bytes than base character.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3362038&group_id=2439">Bug #3362038.</a>
	</li>
	<li>
	SciTE bookmark.alpha setting fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3373907&group_id=2439">Bug #3373907.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite227.zip?download">Release 2.27</a>
    </h3>
    <ul>
	<li>
	Released 20 June 2011.
	</li>
	<li>
	On recent GTK+ 2.x versions when using Cairo, bug fixed where wrong colours were drawn.
	</li>
	<li>
	SciTE on GTK+ slow performance in menu maintenance fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3315233&group_id=2439">Bug #3315233.</a>
	</li>
	<li>
	Cocoa platform supports 64-bit builds and uses only non-deprecated APIs.
	Asian Input Method Editors are supported.
	Autocompletion lists and calltips implemented.
	Control identifier used in notifications.
	</li>
	<li>
	On Cocoa, rectangular selection now uses Option/Alt key to be compatible with Apple Human
	Interface Guidelines and other applications.
	The Control key is reported with an SCMOD_META modifier bit.
	</li>
	<li>
	API added for setting and retrieving the identifier number used in notifications.
	</li>
	<li>
	SCI_SETEMPTYSELECTION added to set selection without scrolling or redrawing more than needed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3314877&group_id=2439">Feature #3314877.</a>
	</li>
	<li>
	Added new indicators. INDIC_DASH and INDIC_DOTS are variants of underlines.
	INDIC_SQUIGGLELOW indicator added as shorter alternative to INDIC_SQUIGGLE for small fonts.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3314591&group_id=2439">Bug #3314591</a>
	</li>
	<li>
	Margin line selection can be changed to select display lines instead of document lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3312763&group_id=2439">Bug #3312763.</a>
	</li>
	<li>
	On Windows, SciTE can perform reverse searches by pressing Shift+Enter
	in the Find or Replace strips or dialogs.
	</li>
	<li>
	Matlab lexer does not special case '\' in single quoted strings.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=948757&group_id=2439">Bug #948757</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1755950&group_id=2439">Bug #1755950</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1888738&group_id=2439">Bug #1888738</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3316852&group_id=2439">Bug #3316852.</a>
	</li>
	<li>
	Verilog lexer supports SystemVerilog folding and keywords.
	</li>
	<li>
	Font leak fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3306156&group_id=2439">Bug #3306156.</a>
	</li>
	<li>
	Automatic scrolling works for long wrapped lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3312763&group_id=2439">Bug #3312763.</a>
	</li>
	<li>
	Multiple typing works for cases where selections collapse together.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3309906&group_id=2439">Bug #3309906.</a>
	</li>
	<li>
	Fold expanded when needed in word wrap mode.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3291579&group_id=2439">Bug #3291579.</a>
	</li>
	<li>
	Bug fixed with edge drawn in wrong place on wrapped lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3314807&group_id=2439">Bug #3314807.</a>
	</li>
	<li>
	Bug fixed with unnecessary scrolling for SCI_GOTOLINE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3303406&group_id=2439">Bug #3303406.</a>
	</li>
	<li>
	Bug fixed where extra step needed to undo SCI_CLEAR in virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3159691&group_id=2439">Bug #3159691.</a>
	</li>
	<li>
	Regular expression search fixed for \$ on last line of search range.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3313746&group_id=2439">Bug #3313746.</a>
	</li>
	<li>
	SciTE performance improved when switching to a tab with a very large file.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3311421&group_id=2439">Bug #3311421.</a>
	</li>
	<li>
	On Windows, SciTE advanced search remembers the "Search only in this style" setting.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3313344&group_id=2439">Bug #3313344.</a>
	</li>
	<li>
	On GTK+, SciTE opens help using "xdg-open" instead of "netscape" as "netscape" no longer commonly installed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3314377&group_id=2439">Bug #3314377.</a>
	</li>
	<li>
	SciTE script lexers can use 256 styles.
	</li>
	<li>
	SciTE word highlight works for words containing DBCS characters.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3315173&group_id=2439">Bug #3315173.</a>
	</li>
	<li>
	Compilation fixed for wxWidgets.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3306156&group_id=2439">Bug #3306156.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite226.zip?download">Release 2.26</a>
    </h3>
    <ul>
	<li>
	Released 25 May 2011.
	</li>
	<li>
	Folding margin symbols can be highlighted for the current folding block.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3147069&group_id=2439">Feature #3147069.</a>
	</li>
	<li>
	Selected lines can be moved up or down together.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3304850&group_id=2439">Feature #3304850.</a>
	</li>
	<li>
	SciTE can highlight all occurrences of the current word or selected text.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3291636&group_id=2439">Feature #3291636.</a>
	</li>
	<li>
	Experimental GTK+ 3.0 support: build with "make GTK3=1".
	</li>
	<li>
	INDIC_STRAIGHTBOX added. Is similar to INDIC_ROUNDBOX but without rounded corners.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3290435&group_id=2439">Bug #3290435.</a>
	</li>
	<li>
	Can show brace matching and mismatching with indicators instead of text style.
	Translucency of outline can be altered for INDIC_ROUNDBOX and INDIC_STRAIGHTBOX.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3290434&group_id=2439">Feature #3290434.</a>
	</li>
	<li>
	SciTE can automatically indent python by examining previous line for scope-starting ':' with indent.python.colon.
	</li>
	<li>
	Batch file lexer allows braces '(' or ')' inside variable names.
	</li>
	<li>
	The cpp lexer only recognises Vala triple quoted strings when lexer.cpp.triplequoted.strings property is set.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3239234&group_id=2439">Bug #3239234.</a>
	</li>
	<li>
	Make file lexer treats a variable with a nested variable like $(f$(qx)b) as one variable.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3298223&group_id=2439">Bug #3298223.</a>
	</li>
	<li>
	Folding bug fixed for JavaScript with nested PHP.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3193530&group_id=2439">Bug #3193530.</a>
	</li>
	<li>
	HTML lexer styles Django's {# #} comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3013798&group_id=2439">Bug #3013798.</a>
	</li>
	<li>
	HTML lexer styles JavaScript regular expression correctly for /abc/i.test('abc');.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3209108&group_id=2439">Bug #3209108.</a>
	</li>
	<li>
	Inno Setup Script lexer now works properly when it restarts from middle of [CODE] section.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3283880&group_id=2439">Bug #3283880.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3129044&group_id=2439">Bug #3129044.</a>
	</li>
	<li>
	Lua lexer updated for Lua 5.2 with hexadecimal floating-point numbers and '\*' whitespace escaping in strings.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3243811&group_id=2439">Feature #3243811.</a>
	</li>
	<li>
	Perl folding folds "here doc"s and adds options fold.perl.at.else and fold.perl.comment.explicit. Fold structure for Perl fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3112671&group_id=2439">Feature #3112671.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3265401&group_id=2439">Bug #3265401.</a>
	</li>
	<li>
	Python lexer supports cpdef keyword for Cython.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3279728&group_id=2439">Bug #3279728.</a>
	</li>
	<li>
	SQL folding option lexer.sql.fold.at.else renamed to fold.sql.at.else.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3271474&group_id=2439">Bug #3271474.</a>
	</li>
	<li>
	SQL lexer no longer treats ';' as terminating a comment.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3196071&group_id=2439">Bug #3196071.</a>
	</li>
	<li>
	Text drawing and measurement segmented into smaller runs to avoid platform bugs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3277449&group_id=2439">Bug #3277449.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3165743&group_id=2439">Bug #3165743.</a>
	</li>
	<li>
	SciTE on Windows adds temp.files.sync.load property to open dropped temporary files synchronously as they may
	be removed before they can be opened asynchronously.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3072009&group_id=2439">Bug #3072009.</a>
	</li>
	<li>
	Bug fixed with indentation guides ignoring first line in SC_IV_LOOKBOTH mode.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3291317&group_id=2439">Bug #3291317.</a>
	</li>
	<li>
	Bugs fixed in backward regex search.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3292659&group_id=2439">Bug #3292659.</a>
	</li>
	<li>
	Bugs with display of folding structure fixed for wrapped lines and where there is a fold header but no body.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3291579&group_id=2439">Bug #3291579.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3265401&group_id=2439">Bug #3265401.</a>
	</li>
	<li>
	SciTE on Windows cursor changes to an arrow now when over horizontal splitter near top of window.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3286620&group_id=2439">Bug #3286620.</a>
	</li>
	<li>
	Fixed default widget size problem on GTK+.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3267892&group_id=2439">Bug #3267892.</a>
	</li>
	<li>
	Fixed font size when using Cairo on GTK+.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3272662&group_id=2439">Bug #3272662.</a>
	</li>
	<li>
	Fixed primary selection and cursor issues on GTK+ when unrealized then realized.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3256153&group_id=2439">Bug #3256153.</a>
	</li>
	<li>
	Right click now cancels selection on GTK+ like on Windows.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3235190&group_id=2439">Bug #3235190.</a>
	</li>
	<li>
	SciTE on GTK+ implements z-order buffer switching like on Windows.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3228384&group_id=2439">Bug #3228384.</a>
	</li>
	<li>
	Improve selection position after SciTE Insert Abbreviation command when abbreviation expansion includes '|'.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite225.zip?download">Release 2.25</a>
    </h3>
    <ul>
	<li>
	Released 21 March 2011.
	</li>
	<li>
	SparseState class makes it easier to write lexers which have to remember complex state between lines.
	</li>
	<li>
	Visual Studio project (.dsp) files removed. The make files should be used instead as described in the README.
	</li>
	<li>
	Modula 3 lexer added along with SciTE support.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3173374&group_id=2439">Feature #3173374.</a>
	</li>
	<li>
	Asm, Basic, and D lexers add extra folding properties.
	</li>
	<li>
	Raw string literals for C++0x supported in C++ lexer.
	</li>
	<li>
	Triple-quoted strings used in Vala language supported in C++ lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3177601&group_id=2439">Feature #3177601.</a>
	</li>
	<li>
 	The errorlist lexer used in SciTE's output pane colours lines that start with '&lt;' as diff deletions.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3172878&group_id=2439">Feature #3172878.</a>
	</li>
	<li>
 	The Fortran lexer correctly folds type-bound procedures from Fortran 2003.
	</li>
	<li>
	LPeg lexer support‎ improved in SciTE.
	</li>
	<li>
	SciTE on Windows-64 fixes for menu localisation and Lua scripts.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3204502&group_id=2439">Bug #3204502.</a>
	</li>
	<li>
	SciTE on Windows avoids locking folders when using the open or save dialogs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1795484&group_id=2439">Bug #1795484.</a>
	</li>
	<li>
	Diff lexer fixes problem where diffs of diffs producing lines that start with "----".
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3197952&group_id=2439">Bug #3197952.</a>
	</li>
	<li>
	Bug fixed when searching upwards in Chinese code page 936.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3176271&group_id=2439">Bug #3176271.</a>
	</li>
	<li>
	On Cocoa, translucent drawing performed as on other platforms instead of 2.5 times less translucent.
	</li>
	<li>
	Performance issue and potential bug fixed on GTK+ with caret line for long lines.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite224.zip?download">Release 2.24</a>
    </h3>
    <ul>
	<li>
	Released 3 February 2011.
	</li>
	<li>
	Fixed memory leak in GTK+ Cairo code.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3157655&group_id=2439">Feature #3157655.</a>
	</li>
	<li>
	Insert Abbreviation dialog added to SciTE on GTK+.
	</li>
	<li>
	SCN_UPDATEUI notifications received when window scrolled. An 'updated' bit mask indicates which
	types of update have occurred from SC_UPDATE_SELECTION, SC_UPDATE_CONTENT, SC_UPDATE_H_SCROLL
	or SC_UPDATE_V_SCROLL.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3125977&group_id=2439">Feature #3125977.</a>
	</li>
	<li>
	On Windows, to ensure reverse arrow cursor matches platform default, it is now generated by
	reflecting the platform arrow cursor.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3143968&group_id=2439">Feature #3143968.</a>
	</li>
	<li>
	Can choose mouse cursor used in margins.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3161326&group_id=2439">Feature #3161326.</a>
	</li>
	<li>
	On GTK+, SciTE sets a mime type of text/plain in its .desktop file so that it will appear in the shell context menu.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3137126&group_id=2439">Feature #3137126.</a>
	</li>
	<li>
	Bash folder handles here docs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3118223&group_id=2439">Feature #3118223.</a>
	</li>
	<li>
	C++ folder adds fold.cpp.syntax.based, fold.cpp.comment.multiline, fold.cpp.explicit.start, fold.cpp.explicit.end,
	and fold.cpp.explicit.anywhere properties to allow more control over folding and choice of explicit fold markers.
	</li>
	<li>
	C++ lexer fixed to always handle single quote strings continued past a line end.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3150522&group_id=2439">Bug #3150522.</a>
	</li>
	<li>
	Ruby folder handles here docs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3118224&group_id=2439">Feature #3118224.</a>
	</li>
	<li>
	SQL lexer allows '.' to be part of words.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3103129&group_id=2439">Feature #3103129.</a>
	</li>
	<li>
	SQL folder handles case statements in more situations.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3135027&group_id=2439">Feature #3135027.</a>
	</li>
	<li>
	SQL folder adds fold points inside expressions based on bracket structure.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3165488&group_id=2439">Feature #3165488.</a>
	</li>
	<li>
	SQL folder drops fold.sql.exists property as 'exists' is handled automatically.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3164194&group_id=2439">Bug #3164194.</a>
	</li>
	<li>
	SciTE only forwards properties to lexers when they have been explicitly set so the defaults set by lexers are used
	rather than 0.
	</li>
	<li>
	Mouse double click word selection chooses the word around the character under the mouse rather than
	the inter-character position under the mouse. This makes double clicking select what the user is pointing
	at and avoids selecting adjacent non-word characters.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3111174&group_id=2439">Bug #3111174.</a>
	</li>
	<li>
	Fixed mouse double click to always perform word select, not line select.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3143635&group_id=2439">Bug #3143635.</a>
	</li>
	<li>
	Right click cancels autocompletion.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3144531&group_id=2439">Bug #3144531.</a>
	</li>
	<li>
	Fixed multiPaste to work when additionalSelectionTyping off.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3126221&group_id=2439">Bug #3126221.</a>
	</li>
	<li>
	Fixed virtual space problems when text modified at caret.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3154986&group_id=2439">Bug #3154986.</a>
	</li>
	<li>
	Fixed memory leak in lexer object code.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3133672&group_id=2439">Bug #3133672.</a>
	</li>
	<li>
	Fixed SciTE on GTK+ search failure when using regular expression.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3156217&group_id=2439">Bug #3156217.</a>
	</li>
	<li>
	Avoid unnecessary full window redraw for SCI_GOTOPOS.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3146650&group_id=2439">Feature #3146650.</a>
	</li>
	<li>
	Avoid unnecessary redraw when indicator fill range makes no real change.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite223.zip?download">Release 2.23</a>
    </h3>
    <ul>
	<li>
	Released 7 December 2010.
	</li>
	<li>
	On GTK+ version 2.22 and later, drawing is performed with Cairo rather than GDK.
	This is in preparation for GTK+ 3.0 which will no longer support GDK drawing.
	The appearance of some elements will be different with Cairo as it is anti-aliased and uses sub-pixel positioning.
	Cairo may be turned on for GTK+ versions before 2.22 by defining USE_CAIRO although this has not
	been extensively tested.
	</li>
	<li>
	New lexer a68k for Motorola 68000 assembler.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3101598&group_id=2439">Feature #3101598.</a>
	</li>
	<li>
	Borland C++ is no longer supported for building Scintilla or SciTE on Windows.
	</li>
	<li>
	Performance improved when creating large rectangular selections.
	</li>
	<li>
	PHP folder recognises #region and #endregion comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3101624&group_id=2439">Feature #3101624.</a>
	</li>
	<li>
	SQL lexer has a lexer.sql.numbersign.comment option to turn off use of '#' comments
	as these are a non-standard feature only available in some implementations.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3098071&group_id=2439">Feature #3098071.</a>
	</li>
	<li>
	SQL folder recognises case statements and understands the fold.at.else property.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3104091&group_id=2439">Bug #3104091.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3107362&group_id=2439">Bug #3107362.</a>
	</li>
	<li>
	SQL folder fixes bugs with end statements when fold.sql.only.begin=1.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3104091&group_id=2439">Bug #3104091.</a>
	</li>
	<li>
	SciTE on Windows bug fixed with multi-line tab bar not adjusting correctly when maximizing and demaximizing.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3097517&group_id=2439">Bug #3097517.</a>
	</li>
	<li>
	Crash fixed on GTK+ when Scintilla widget destroyed while it still has an outstanding style idle pending.
	</li>
	<li>
	Bug fixed where searching backwards in DBCS text (code page 936 or similar) failed to find occurrences at the start of the line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3103936&group_id=2439">Bug #3103936.</a>
	</li>
	<li>
	SciTE on Windows supports Unicode file names when executing help applications with winhelp and htmlhelp subsystems.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite222.zip?download">Release 2.22</a>
    </h3>
    <ul>
	<li>
	Released 27 October 2010.
	</li>
	<li>
	SciTE includes support for integrating with Scintillua which allows lexers to be implemented in Lua as a
	Parsing Expression Grammar (PEG).
	</li>
	<li>
	Regular expressions allow use of '?' for non-greedy matches or to match 0 or 1 instances of an item.
	</li>
	<li>
	SCI_CONTRACTEDFOLDNEXT added to allow rapid retrieval of folding state.
	</li>
	<li>
	SCN_HOTSPOTRELEASECLICK notification added which is similar to SCN_HOTSPOTCLICK but occurs
	when the mouse is released.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3082409&group_id=2439">Feature #3082409.</a>
	</li>
	<li>
	Command added for centring current line in window.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3064696&group_id=2439">Feature #3064696.</a>
	</li>
	<li>
	SciTE performance improved by not examining document for line ends when switching buffers and not
	storing folds when folding turned off.
	</li>
	<li>
	Bug fixed where scrolling to ensure the caret is visible did not take into account all pixels of the line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3081721&group_id=2439">Bug #3081721.</a>
	</li>
	<li>
	Bug fixed for autocompletion list overlapping text when WS_EX_CLIENTEDGE used.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3079778&group_id=2439">Bug #3079778.</a>
	</li>
	<li>
	After autocompletion, the caret's X is updated.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3079114&group_id=2439">Bug #3079114.</a>
	</li>
	<li>
	On Windows, default to the system caret blink time.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3079784&group_id=2439">Feature #3079784.</a>
	</li>
	<li>
	PgUp/PgDn fixed to allow virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3077452&group_id=2439">Bug #3077452.</a>
	</li>
	<li>
	Crash fixed when AddMark and AddMarkSet called with negative argument.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3075074&group_id=2439">Bug #3075074.</a>
	</li>
	<li>
	Dwell notifications fixed so that they do not occur when the mouse is outside Scintilla.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3073481&group_id=2439">Bug #3073481.</a>
	</li>
	<li>
	Bash lexer bug fixed for here docs starting with &lt;&lt;-.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3063822&group_id=2439">Bug #3063822.</a>
	</li>
	<li>
	C++ lexer bug fixed for // comments that are continued onto a second line by a \.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3066031&group_id=2439">Bug #3066031.</a>
	</li>
	<li>
	C++ lexer fixes wrong highlighting for float literals containing +/-.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3058924&group_id=2439">Bug #3058924.</a>
	</li>
	<li>
	JavaScript lexer recognise regexes following return keyword.‎
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3062287&group_id=2439">Bug #3062287.</a>
	</li>
	<li>
	Ruby lexer handles % quoting better and treats range dots as operators in 1..2 and 1...2.
	Ruby folder handles "if" keyword used as a modifier even when it is separated from the modified statement by an escaped new line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2093767&group_id=2439">Bug #2093767.</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3058496&group_id=2439">Bug #3058496.</a>
	</li>
	<li>
	Bug fixed where upwards search failed with DBCS code pages.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3065912&group_id=2439">Bug #3065912.</a>
	</li>
	<li>
	SciTE has a default Lua startup script name distributed in SciTEGlobal.properties.
	No error message is displayed if this file does not exist.
	</li>
	<li>
	SciTE on Windows tab control height is calculated better.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2635702&group_id=2439">Bug #2635702.</a>
	</li>
	<li>
	SciTE on Windows uses better themed check buttons in find and replace strips.
	</li>
	<li>
	SciTE on Windows fixes bug with Find strip appearing along with Incremental Find strip.
	</li>
	<li>
	SciTE setting find.close.on.find added to allow preventing the Find dialog from closing.
	</li>
	<li>
	SciTE on Windows attempts to rerun commands that fail by prepending them with "cmd.exe /c".
	This allows commands built in to the command processor like "dir" to run.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite221.zip?download">Release 2.21</a>
    </h3>
    <ul>
	<li>
	Released 1 September 2010.
	</li>
	<li>
	Asian Double Byte Character Set (DBCS) support improved.
	Case insensitive search works and other operations are much faster.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2999125&group_id=2439">Bug #2999125,</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2774616&group_id=2439">Bug #2774616,</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2991942&group_id=2439">Bug #2991942,</a>
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3005688&group_id=2439">Bug #3005688.</a>
	</li>
	<li>
	Scintilla on GTK+ uses only non-deprecated APIs (for GTK+ 2.20) except for GdkFont and GdkFont use can be disabled
	with the preprocessor symbol DISABLE_GDK_FONT.
	</li>
	<li>
	IDocument interface used by lexers adds BufferPointer and GetLineIndentation methods.
	</li>
	<li>
	On Windows, clicking sets focus before processing the click or sending notifications.
	</li>
	<li>
	Bug on OS X (macosx platform) fixed where drag/drop overwrote clipboard.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3039732&group_id=2439">Bug #3039732.</a>
	</li>
	<li>
	GTK+ drawing bug when the view was horizontally scrolled more than 32000 pixels fixed.
	</li>
	<li>
	SciTE bug fixed with invoking Complete Symbol from output pane.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3050957&group_id=2439">Bug #3050957.</a>
	</li>
	<li>
	Bug fixed where it was not possible to disable folding.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3040649&group_id=2439">Bug #3040649.</a>
	</li>
	<li>
	Bug fixed with pressing Enter on a folded fold header line not opening the fold.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3043419&group_id=2439">Bug #3043419.</a>
	</li>
	<li>
	SciTE 'Match case' option in find and replace user interfaces changed to 'Case sensitive' to allow use of 'v'
	rather than 'c' as the mnemonic.
	</li>
	<li>
	SciTE displays stack trace for Lua when error occurs..
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3051397&group_id=2439">Bug #3051397.</a>
	</li>
	<li>
	SciTE on Windows fixes bug where double clicking on error message left focus in output pane.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1264835&group_id=2439">Bug #1264835.</a>
	</li>
	<li>
	SciTE on Windows uses SetDllDirectory to avoid a security problem.
	</li>
	<li>
	C++ lexer crash fixed with preprocessor expression that looked like division by 0.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3056825&group_id=2439">Bug #3056825.</a>
	</li>
	<li>
	Haskell lexer improved.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3039490&group_id=2439">Feature #3039490.</a>
	</li>
	<li>
	HTML lexing fixed around Django {% %} tags.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3034853&group_id=2439">Bug #3034853.</a>
	</li>
	<li>
	HTML JavaScript lexing fixed when line end escaped.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3038381&group_id=2439">Bug #3038381.</a>
	</li>
	<li>
	HTML lexer stores line state produced by a line on that line rather than on the next line.
	</li>
	<li>
	Markdown lexer fixes infinite loop.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3045386&group_id=2439">Bug #3045386.</a>
	</li>
	<li>
	MySQL folding bugs with END statements fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3031742&group_id=2439">Bug #3031742.</a>
	</li>
	<li>
	PowerShell lexer allows '_' as a word character.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3042228&group_id=2439">Feature #3042228.</a>
	</li>
	<li>
	SciTE on GTK+ abandons processing of subsequent commands if a command.go.needs command fails.
	</li>
	<li>
	When SciTE is closed, all buffers now receive an OnClose call.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3033857&group_id=2439">Bug #3033857.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite220.zip?download">Release 2.20</a>
    </h3>
    <ul>
	<li>
	Released 30 July 2010.
	</li>
	<li>
	Lexers are implemented as objects so that they may retain extra state.
	The interfaces defined for this are tentative and may change before the next release.
	Compatibility classes allow current lexers compiled into Scintilla to run with few changes.
	The interface to external lexers has changed and existing external lexers will need to have changes
	made and be recompiled.
	A single lexer object is attached to a document whereas previously lexers were attached to views
	which could lead to different lexers being used for split views with confusing results.
	</li>
	<li>
	C++ lexer understands the preprocessor enough to grey-out inactive code due to conditional compilation.
	</li>
	<li>
	SciTE can use strips within the main window for find and replace rather than dialogs.
	On Windows SciTE always uses a strip for incremental search.
	</li>
	<li>
	Lexer added for Txt2Tags language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3018736&group_id=2439">Feature #3018736.</a>
	</li>
	<li>
	Sticky caret feature enhanced with additional SC_CARETSTICKY_WHITESPACE mode .
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3027559&group_id=2439">Feature #3027559.</a>
	</li>
	<li>
	Bash lexer implements basic parsing of compound commands and constructs.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3033135&group_id=2439">Feature #3033135.</a>
	</li>
	<li>
	C++ folder allows disabling explicit fold comments.
	</li>
	<li>
	Perl folder works for array blocks, adjacent package statements, nested PODs, and terminates package folding at __DATA__, ^D and ^Z.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3030887&group_id=2439">Feature #3030887.</a>
	</li>
	<li>
	PowerShell lexer supports multiline &lt;# .. #&gt; comments and adds 2 keyword classes.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3015176&group_id=2439">Feature #3015176.</a>
	</li>
	<li>
	Lexing performed incrementally when needed by wrapping to make user interface more responsive.
	</li>
	<li>
	SciTE setting replaceselection:yes works on GTK+.
	</li>
	<li>
	SciTE Lua scripts calling io.open or io.popen on Windows have arguments treated as UTF-8 and converted to Unicode
	so that non-ASCII file paths will work. Lua files with non-ASCII paths run.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3016951&group_id=2439">Bug #3016951.</a>
	</li>
	<li>
	Crash fixed when searching for empty string.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3017572&group_id=2439">Bug #3017572.</a>
	</li>
	<li>
	Bugs fixed with folding and lexing when Enter pressed at start of line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3032652&group_id=2439">Bug #3032652.</a>
	</li>
	<li>
	Bug fixed with line selection mode not affecting selection range.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3021480&group_id=2439">Bug #3021480.</a>
	</li>
	<li>
	Bug fixed where indicator alpha was limited to 100 rather than 255.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3021473&group_id=2439">Bug #3021473.</a>
	</li>
	<li>
	Bug fixed where changing annotation did not cause automatic redraw.
	</li>
	<li>
	Regular expression bug fixed when a character range included non-ASCII characters.
	</li>
	<li>
	Compilation failure with recent compilers fixed on GTK+.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3022027&group_id=2439">Bug #3022027.</a>
	</li>
	<li>
	Bug fixed on Windows with multiple monitors where autocomplete pop up would appear off-screen
	or straddling monitors.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3017512&group_id=2439">Bug #3017512.</a>
	</li>
	<li>
	SciTE on Windows bug fixed where changing directory to a Unicode path failed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3011987&group_id=2439">Bug #3011987.</a>
	</li>
	<li>
	SciTE on Windows bug fixed where combo boxes were not allowing Unicode characters.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3012986&group_id=2439">Bug #3012986.</a>
	</li>
	<li>
	SciTE on GTK+ bug fixed when dragging files into SciTE on KDE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3026555&group_id=2439">Bug #3026555.</a>
	</li>
	<li>
	SciTE bug fixed where closing untitled file could lose data if attempt to name file same as another buffer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3011680&group_id=2439">Bug #3011680.</a>
	</li>
	<li>
	COBOL number masks now correctly highlighted.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3012164&group_id=2439">Bug #3012164.</a>
	</li>
	<li>
	PHP comments can include &lt;?PHP without triggering state change.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2854183&group_id=2439">Bug #2854183.</a>
	</li>
	<li>
	VHDL lexer styles unclosed string correctly.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3029627&group_id=2439">Bug #3029627.</a>
	</li>
	<li>
	Memory leak fixed in list boxes on GTK+.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3007669&group_id=2439">Bug #3007669.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite212.zip?download">Release 2.12</a>
    </h3>
    <ul>
	<li>
	Released 1 June 2010.
	</li>
	<li>
	Drawing optimizations improve speed and fix some visible flashing when scrolling.
	</li>
	<li>
	Copy Path command added to File menu in SciTE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2986745&group_id=2439">Feature #2986745.</a>
	</li>
	<li>
	Optional warning displayed by SciTE when saving a file which has been modified by another process.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2975041&group_id=2439">Feature #2975041.</a>
	</li>
	<li>
	Flagship lexer for xBase languages updated to follow the language much more closely.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2992689&group_id=2439">Feature #2992689.</a>
	</li>
	<li>
	HTML lexer highlights Django templates in more regions.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3002874&group_id=2439">Feature #3002874.</a>
	</li>
	<li>
	Dropping files on SciTE on Windows, releases the drag object earlier and opens the files asynchronously,
	leading to smoother user experience.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2986724&group_id=2439">Feature #2986724.</a>
	</li>
	<li>
	SciTE HTML exports take the Use Monospaced Font setting into account.
	</li>
	<li>
	SciTE window title "[n of m]" localised.
	</li>
	<li>
	When new line inserted at start of line, markers are moved down.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2986727&group_id=2439">Bug #2986727.</a>
	</li>
	<li>
	On Windows, dropped text has its line ends converted, similar to pasting.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3005328&group_id=2439">Bug #3005328.</a>
	</li>
	<li>
	Fixed bug with middle-click paste in block select mode where text was pasted next to selection rather than at cursor.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2984460&group_id=2439">Bug #2984460.</a>
	</li>
	<li>
	Fixed SciTE crash where a style had a size parameter without a value.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3003834&group_id=2439">Bug #3003834.</a>
	</li>
	<li>
	Debug assertions in multiple lexers fixed.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3000566&group_id=2439">Bug #3000566.</a>
	</li>
	<li>
	CSS lexer fixed bug where @font-face displayed incorrectly
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2994224&group_id=2439">Bug #2994224.</a>
	</li>
	<li>
	CSS lexer fixed bug where open comment caused highlighting error.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1683672&group_id=2439">Bug #1683672.</a>
	</li>
	<li>
	Shell file lexer fixed highlight glitch with here docs where the first line is a comment.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830239&group_id=2439">Bug #2830239.</a>
	</li>
	<li>
	Bug fixed in SciTE openpath property that caused Open Selected File to fail to open the selected file.
	</li>
	<li>
	Bug fixed in SciTE FileExt property when file name with no extension evaluated to whole path.
	</li>
	<li>
	Fixed SciTE on Windows printing bug where the $(CurrentTime), $(CurrentPage) variables were not expanded.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2994612&group_id=2439">Bug #2994612.</a>
	</li>
	<li>
	SciTE compiles for 64-bit Windows and runs without crashing.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2986312&group_id=2439">Bug #2986312.</a>
	</li>
	<li>
	Full Screen mode in Windows Vista/7 improved to hide Start button and size borders a little better.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3002813&group_id=2439">Bug #3002813.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite211.zip?download">Release 2.11</a>
    </h3>
    <ul>
	<li>
	Released 9 April 2010.
	</li>
	<li>
	Fixes compatibility of Scintilla.h with the C language.
	</li>
	<li>
	With a rectangular selection SCI_GETSELECTIONSTART and SCI_GETSELECTIONEND return limits of the
	rectangular selection rather than the limits of the main selection.
	</li>
	<li>
	When SciTE on Windows is minimized to tray, only takes a single click to restore rather than a double click.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=981917&group_id=2439">Feature #981917.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite210.zip?download">Release 2.10</a>
    </h3>
    <ul>
	<li>
	Released 4 April 2010.
	</li>
	<li>
	Version 1.x of GTK+ is no longer supported.
	</li>
	<li>
	SciTE is no longer supported on Windows 95, 98 or ME.
	</li>
	<li>
	Case-insensitive search works for non-ASCII characters in UTF-8 and 8-bit encodings.
	Non-regex search in DBCS encodings is always case-sensitive.
	</li>
	<li>
	Non-ASCII characters may be changed to upper and lower case.
	</li>
	<li>
	SciTE on Windows can access all files including those with names outside the user's preferred character encoding.
	</li>
	<li>
	SciTE may be extended with lexers written in Lua.
	</li>
	<li>
	When there are multiple selections, the paste command can go either to the main selection or to each
	selection. This is controlled with SCI_SETMULTIPASTE.
	</li>
	<li>
	More forms of bad UTF-8 are detected including overlong sequences, surrogates, and characters outside
	the valid range. Bad UTF-8 bytes are now displayed as 2 hex digits preceded by 'x'.
	</li>
	<li>
	SCI_GETTAG retrieves the value of captured expressions within regular expression searches.
	</li>
	<li>
	Django template highlighting added to the HTML lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2974889&group_id=2439">Feature #2974889.</a>
	</li>
	<li>
	Verilog line comments can be folded.
	</li>
	<li>
	SciTE on Windows allows specifying a filter for the Save As dialog.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2943445&group_id=2439">Feature #2943445.</a>
	</li>
	<li>
	Bug fixed when multiple selection disabled where rectangular selections could be expanded into multiple selections.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2948260&group_id=2439">Bug #2948260.</a>
	</li>
	<li>
	Bug fixed when document horizontally scrolled and up/down-arrow did not return to the same
	column after horizontal scroll occurred.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2950799&group_id=2439">Bug #2950799.</a>
	</li>
	<li>
	Bug fixed to remove hotspot highlight when mouse is moved out of the document. Windows only fix.
	<a href="https://sourceforge.net/tracker/?func=detail&aid=2951353&group_id=2439&atid=102439">Bug #2951353.</a>
	</li>
	<li>
	R lexer now performs case-sensitive check for keywords.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2956543&group_id=2439">Bug #2956543.</a>
	</li>
	<li>
	Bug fixed on GTK+ where text disappeared when a wrap occurred.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2958043&group_id=2439">Bug #2958043.</a>
	</li>
	<li>
	Bug fixed where regular expression replace cannot escape the '\' character by using '\\'.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2959876&group_id=2439">Bug #2959876.</a>
	</li>
	<li>
	Bug fixed on GTK+ when virtual space disabled, middle-click could still paste text beyond end of line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2971618&group_id=2439">Bug #2971618.</a>
	</li>
	<li>
	SciTE crash fixed when double clicking on a malformed error message in the output pane.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2976551&group_id=2439">Bug #2976551.</a>
	</li>
	<li>
	Improved performance on GTK+ when changing parameters associated with scroll bars to the same value.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2964357&group_id=2439">Bug #2964357.</a>
	</li>
	<li>
	Fixed bug with pressing Shift+Tab with a rectangular selection so that it performs an un-indent
	similar to how Tab performs an indent.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite203.zip?download">Release 2.03</a>
    </h3>
    <ul>
	<li>
	Released 14 February 2010.
	</li>
	<li>
	Added SCI_SETFIRSTVISIBLELINE to match SCI_GETFIRSTVISIBLELINE.
	</li>
	<li>
	Erlang lexer extended set of numeric bases recognised; separate style for module:function_name; detects
	built-in functions, known module attributes, and known preprocessor instructions; recognises EDoc and EDoc macros;
	separates types of comments.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2942448&group_id=2439">Bug #2942448.</a>
	</li>
	<li>
	Python lexer extended with lexer.python.strings.over.newline option that allows non-triple-quoted strings to extend
	past line ends. This allows use of the Ren'Py language.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2945550&group_id=2439">Feature #2945550.</a>
	</li>
	<li>
	Fixed bugs with cursor movement after deleting a rectangular selection.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2942131&group_id=2439">Bug #2942131.</a>
	</li>
	<li>
	Fixed bug where calling SCI_SETSEL when there is a rectangular selection left
	the additional selections selected.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2947064&group_id=2439">Bug #2947064.</a>
	</li>
	<li>
	Fixed macro recording bug where not all bytes in multi-byte character insertions were reported through
	SCI_REPLACESEL.
	</li>
	<li>
	Fixed SciTE bug where using Ctrl+Enter followed by Ctrl+Space produced an autocompletion list
	with only a single line containing all the identifiers.
	</li>
	<li>
	Fixed SciTE on GTK+ bug where running a tool made the user interface completely unresponsive.
	</li>
	<li>
	Fixed SciTE on Windows Copy to RTF bug.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2108574&group_id=2439">Bug #2108574.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite202.zip?download">Release 2.02</a>
    </h3>
    <ul>
	<li>
	Released on 25 January 2010.
	</li>
	<li>
	Markdown lexer added.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2844081&group_id=2439">Feature #2844081.</a>
	</li>
	<li>
	On GTK+, include code that understands the ranges of lead bytes for code pages 932, 936, and 950
	so that most Chinese and Japanese text can be used on systems that are not set to the corresponding locale.
	</li>
	<li>
	Allow changing the size of dots in visible whitespace using SCI_SETWHITESPACESIZE.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2839427&group_id=2439">Feature #2839427.</a>
	</li>
	<li>
	Additional carets can be hidden with SCI_SETADDITIONALCARETSVISIBLE.
	</li>
	<li>
	Can choose anti-aliased, non-anti-aliased or lcd-optimized text using SCI_SETFONTQUALITY.
	</li>
	<li>
	Retrieve the current selected text in the autocompletion list with SCI_AUTOCGETCURRENTTEXT.
	</li>
	<li>
	Retrieve the name of the current lexer with SCI_GETLEXERLANGUAGE.
	</li>
	<li>
	Progress 4GL lexer improves handling of comments in preprocessor declaration.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2902206&group_id=2439">Feature #2902206.</a>
	</li>
	<li>
	HTML lexer extended to handle Mako template language.
	</li>
	<li>
	SQL folder extended for SQL Anywhere "EXISTS" and "ENDIF" keywords.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2887524&group_id=2439">Feature #2887524.</a>
	</li>
	<li>
	SciTE adds APIPath and AbbrevPath variables.
	</li>
	<li>
	SciTE on GTK+ uses pipes instead of temporary files for running tools. This should be more secure.
	</li>
	<li>
	Fixed crash when calling SCI_STYLEGETFONT for a style which does not have a font set.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2857425&group_id=2439">Bug #2857425.</a>
	</li>
	<li>
	Fixed crash caused by not having sufficient styles allocated after choosing a lexer.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2881279&group_id=2439">Bug #2881279.</a>
	</li>
	<li>
	Fixed crash in SciTE using autocomplete word when word characters includes space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2840141&group_id=2439">Bug #2840141.</a>
	</li>
	<li>
	Fixed bug with handling upper-case file extensions SciTE on GTK+.
	</li>
	<li>
	Fixed SciTE loading files from sessions with folded folds where it would not
	be scrolled to the correct location.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2882775&group_id=2439">Bug #2882775.</a>
	</li>
	<li>
	Fixed SciTE loading files from sessions when file no longer exists.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2883437&group_id=2439">Bug #2883437.</a>
	</li>
	<li>
	Fixed SciTE export to HTML using the wrong background colour.
	</li>
	<li>
	Fixed crash when adding an annotation and then adding a new line after the annotation.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2929708&group_id=2439">Bug #2929708.</a>
	</li>
	<li>
	Fixed crash in SciTE setting a property to nil from Lua.
	</li>
	<li>
	SCI_GETSELTEXT fixed to return correct length.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2929441&group_id=2439">Bug #2929441.</a>
	</li>
	<li>
	Fixed text positioning problems with selection in some circumstances.
	</li>
	<li>
	Fixed text positioning problems with ligatures on GTK+.
	</li>
	<li>
	Fixed problem pasting into rectangular selection with caret at bottom caused text to go from the caret down
	rather than replacing the selection.
	</li>
	<li>
	Fixed problem replacing in a rectangular selection where only the final line was changed.
	</li>
	<li>
	Fixed inability to select a rectangular area using Alt+Shift+Click at both corners.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2899746&group_id=2439">Bug #2899746.</a>
	</li>
	<li>
	Fixed problem moving to start/end of a rectangular selection with left/right key.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2871358&group_id=2439">Bug #2871358.</a>
	</li>
	<li>
	Fixed problem with Select All when there's a rectangular selection.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2930488&group_id=2439">Bug #2930488.</a>
	</li>
	<li>
	Fixed SCI_LINEDUPLICATE on a rectangular selection to not produce multiple discontinuous selections.
	</li>
	<li>
	Virtual space removed when performing delete word left or delete line left.
	Virtual space converted to real space for delete word right.
	Preserve virtual space when pressing Delete key.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2882566&group_id=2439">Bug #2882566.</a>
	</li>
	<li>
	Fixed problem where Shift+Alt+Down did not move through wrapped lines.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2871749&group_id=2439">Bug #2871749.</a>
	</li>
	<li>
	Fixed incorrect background colour when using coloured lines with virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2914691&group_id=2439">Bug #2914691.</a>
	</li>
	<li>
	Fixed failure to display wrap symbol for SC_WRAPVISUALFLAGLOC_END_BY_TEXT.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2936108&group_id=2439">Bug #2936108.</a>
	</li>
	<li>
	Fixed blank background colour with EOLFilled style on last line.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2890105&group_id=2439">Bug #2890105.</a>
	</li>
	<li>
	Fixed problem in VB lexer with keyword at end of file.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2901239&group_id=2439">Bug #2901239.</a>
	</li>
	<li>
	Fixed SciTE bug where double clicking on a tab closed the file.
	</li>
	<li>
	Fixed SciTE brace matching commands to only work when the caret is next to the brace, not when
	it is in virtual space.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2885560&group_id=2439">Bug #2885560.</a>
	</li>
	<li>
	Fixed SciTE on Windows Vista to access files in the Program Files directory rather than allow Windows
	to virtualize access.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2916685&group_id=2439">Bug #2916685.</a>
	</li>
	<li>
	Fixed NSIS folder to handle keywords that start with '!'.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2872157&group_id=2439">Bug #2872157.</a>
	</li>
	<li>
	Changed linkage of Scintilla_LinkLexers to "C" so that it can be used by clients written in C.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2844718&group_id=2439">Bug #2844718.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite201.zip?download">Release 2.01</a>
    </h3>
    <ul>
	<li>
	Released on 19 August 2009.
	</li>
	<li>
	Fix to positioning rectangular paste when viewing line ends.
	</li>
	<li>
	Don't insert new lines and indentation for line ends at end of rectangular paste.
	</li>
	<li>
	When not in additional selection typing mode, cutting a rectangular selection removes all of the selected text.
	</li>
	<li>
	Rectangular selections are copied to the clipboard in document order, not in the order of selection.
	</li>
	<li>
	SCI_SETCURRENTPOS and SCI_SETANCHOR work in rectangular mode.
	</li>
	<li>
	On GTK+, drag and drop to a later position in the document now drops at the position.
	</li>
	<li>
	Fix bug where missing property did not use default value.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite200.zip?download">Release 2.0</a>
    </h3>
    <ul>
	<li>
	Released on 11 August 2009.
	</li>
	<li>
	Multiple pieces of text can be selected simultaneously by holding control while dragging the mouse.
	Typing, backspace and delete may affect all selections together.
	</li>
	<li>
	Virtual space allows selecting beyond the last character on a line.
	</li>
	<li>
	SciTE on GTK+ path bar is now optional and defaults to off.
	</li>
	<li>
	MagikSF lexer recognises numbers correctly.
	</li>
	<li>
	Folding of Python comments and blank lines improved. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=210240&group_id=2439">Bug #210240.</a>
	</li>
	<li>
	Bug fixed where background colour of last character in document leaked past that character.
	</li>
	<li>
	Crash fixed when adding marker beyond last line in document. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830307&group_id=2439">Bug #2830307.</a>
	</li>
	<li>
	Resource leak fixed in SciTE for Windows when printing fails. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2816524&group_id=2439">Bug #2816524.</a>
	</li>
	<li>
	Bug fixed on Windows where the system caret was destroyed during destruction when another window
	was using the system caret. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2830223&group_id=2439">Bug #2830223.</a>
	</li>
	<li>
	Bug fixed where indentation guides were drawn over text when the indentation used a style with a different
	space width to the default style.
	</li>
	<li>
	SciTE bug fixed where box comment added a bare line feed rather than the chosen line end. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2818104&group_id=2439">Bug #2818104.</a>
	</li>
	<li>
	Reverted fix that led to wrapping whole document when displaying the first line of the document.
	</li>
	<li>
	Export to LaTeX in SciTE fixed to work in more cases and not use as much space. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=1286548&group_id=2439">Bug #1286548.</a>
	</li>
	<li>
	Bug fixed where EN_CHANGE notification was sent when performing a paste operation in a
	read-only document. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2825485&group_id=2439">Bug #2825485.</a>
	</li>
	<li>
	Refactored code so that Scintilla exposes less of its internal implementation and uses the C++ standard
	library for some basic collections. Projects that linked to Scintilla's SString or PropSet classes
	should copy this code from a previous version of Scintilla or from SciTE.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite179.zip?download">Release 1.79</a>
    </h3>
    <ul>
	<li>
	Released on 1 July 2009.
	</li>
	<li>
	Memory exhaustion and other exceptions handled by placing an error value into the
	status property rather than crashing.
	Scintilla now builds with exception handling enabled and requires exception handling to be enabled. <br />
	This is a major change and application developers should consider how they will deal with Scintilla exhausting
	memory since Scintilla may not be in a stable state.
	</li>
	<li>
	Deprecated APIs removed. The symbols removed are:
	<ul>
 <li>SCI_SETCARETPOLICY</li>
<li> CARET_CENTER</li>
<li> CARET_XEVEN</li>
<li> CARET_XJUMPS</li>
<li> SC_FOLDFLAG_BOX</li>
<li> SC_FOLDLEVELBOXHEADERFLAG</li>
<li> SC_FOLDLEVELBOXFOOTERFLAG</li>
<li> SC_FOLDLEVELCONTRACTED</li>
<li> SC_FOLDLEVELUNINDENT</li>
<li> SCN_POSCHANGED</li>
<li> SCN_CHECKBRACE</li>
<li> SCLEX_ASP</li>
<li> SCLEX_PHP</li>
</ul>
	</li>
	<li>
	Cocoa platform added.
	</li>
	<li>
	Names of struct types in Scintilla.h now start with "Sci_" to avoid possible clashes with platform
	definitions. Currently, the old names still work but these will be phased out.
	</li>
	<li>
	When lines are wrapped, subsequent lines may be indented to match the indent of the initial line,
	or one more indentation level. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2796119&group_id=2439">Feature #2796119.</a>
	</li>
	<li>
	APIs added for finding the character at a point rather than an inter-character position. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2646738&group_id=2439">Feature #2646738.</a>
	</li>
	<li>
	A new marker SC_MARK_BACKGROUND_UNDERLINE is drawn in the text area as an underline
	the full width of the window.
	</li>
	<li>
	Batch file lexer understands variables surrounded by '!'.
	</li>
	<li>
	CAML lexer also supports SML.
	</li>
	<li>
	D lexer handles string and numeric literals more accurately. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2793782&group_id=2439">Feature #2793782.</a>
	</li>
	<li>
	Forth lexer is now case-insensitive and better supports numbers like $hex and %binary. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2804894&group_id=2439">Feature #2804894.</a>
	</li>
	<li>
	Lisp lexer treats '[', ']', '{', and '}' as balanced delimiters which is common usage. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2794989&group_id=2439">Feature #2794989.</a>
	<br />
	It treats keyword argument names as being equivalent to symbols. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2794901&group_id=2439">Feature #2794901.</a>
	</li>
	<li>
	Pascal lexer bug fixed to prevent hang when 'interface' near beginning of file. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2802863&group_id=2439">Bug #2802863.</a>
	</li>
	<li>
	Perl lexer bug fixed where previous lexical states persisted causing "/" special case styling and
	subroutine prototype styling to not be correct. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2809168&group_id=2439">Bug #2809168.</a>
	</li>
	<li>
	XML lexer fixes bug where Unicode entities like '&amp;—' were broken into fragments. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2804760&group_id=2439">Bug #2804760.</a>
	</li>
	<li>
	SciTE on GTK+ enables scrolling the tab bar on recent versions of GTK+. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2061821&group_id=2439">Feature #2061821.</a>
	</li>
	<li>
	SciTE on Windows allows tab bar tabs to be reordered by drag and drop.
	</li>
	<li>
	Unit test script for Scintilla on Windows included with source code.
	</li>
	<li>
	User defined menu items are now localised when there is a matching translation.
	</li>
	<li>
	Width of icon column of autocompletion lists on GTK+ made more consistent.
	</li>
	<li>
	Bug with slicing UTF-8 text into character fragments when there is a sequence of 100 or more 3 byte characters. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2780566&group_id=2439">Bug #2780566.</a>
	</li>
	<li>
	Folding bugs introduced in 1.78 fixed. Some of the fix was generic and there was also a specific fix for C++.
	</li>
	<li>
	Bug fixed where a rectangular paste was not padding the line with sufficient spaces to align the pasted text.
	</li>
	<li>
	Bug fixed with showing all text on each line of multi-line annotations when styling the whole annotation using SCI_ANNOTATIONSETSTYLE. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2789430&group_id=2439">Bug #2789430.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite178.zip?download">Release 1.78</a>
    </h3>
    <ul>
	<li>
	Released on 28 April 2009.
	</li>
	<li>
	Annotation lines may be added to each line.
	</li>
	<li>
	A text margin may be defined with different text on each line.
	</li>
	<li>
	Application actions may be added to the undo history.
	</li>
	<li>
	Can query the symbol defined for a marker.
	An available symbol added for applications to indicate that plugins may allocate a marker.
	</li>
	<li>
	Can increase the amount of font ascent and descent.
	</li>
	<li>
	COBOL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
	</li>
	<li>
	Nimrod lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2642620&group_id=2439">Feature #2642620.</a>
	</li>
	<li>
	PowerPro lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2195308&group_id=2439">Feature #2195308.</a>
	</li>
	<li>
	SML lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2710950&group_id=2439">Feature #2710950.</a>
	</li>
	<li>
	SORCUS Installation file lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2343375&group_id=2439">Feature #2343375.</a>
	</li>
	<li>
	TACL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
	</li>
	<li>
	TAL lexer added. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2127406&group_id=2439">Feature #2127406.</a>
	</li>
	<li>
	Rewritten Pascal lexer with improved folding and other fixes. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2190650&group_id=2439">Feature #2190650.</a>
	</li>
	<li>
	INDIC_ROUNDBOX translucency level can be modified. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2586290&group_id=2439">Feature #2586290.</a>
	</li>
	<li>
	C++ lexer treats angle brackets in #include directives as quotes when styling.within.preprocessor. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2551033&group_id=2439">Bug #2551033.</a>
	</li>
	<li>
	Inno Setup lexer is sensitive to whether within the [Code] section and handles comments better. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2552973&group_id=2439">Bug #2552973.</a>
	</li>
	<li>
	HTML lexer does not go into script mode when script tag is self-closing.
	</li>
	<li>
	HTML folder fixed where confused by comments when fold.html.preprocessor off. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2532774&group_id=2439">Bug #2532774.</a>
	</li>
	<li>
	Perl lexer fixes problem with string matching caused by line endings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2648342&group_id=2439">Bug #2648342.</a>
	</li>
	<li>
	Progress lexer fixes problem with "last-event:function" phrase. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2483619&group_id=2439">Bug #2483619.</a>
	</li>
	<li>
	Properties file lexer extended to handle RFC2822 text when lexer.props.allow.initial.spaces on.
	</li>
	<li>
	Python lexer adds options for Python 3 and Cython.
	</li>
	<li>
	Shell lexer fixes heredoc problem caused by line endings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2635257&group_id=2439">Bug #2635257.</a>
	</li>
	<li>
	TeX lexer handles comment at end of line correctly. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2698766&group_id=2439">Bug #2698766.</a>
	</li>
	<li>
	SciTE retains selection range when performing a replace selection command. <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=2339160&group_id=2439">Feature #2339160.</a>
	</li>
	<li>
	SciTE definition of word characters fixed to match documentaiton. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2464531&group_id=2439">Bug #2464531.</a>
	</li>
	<li>
	SciTE on GTK+ performing Search or Replace when dialog already shown now brings dialog to foreground.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2634224&group_id=2439">Bug #2634224.</a>
	</li>
	<li>
	Fixed encoding bug with calltips on GTK+.
	</li>
	<li>
	Block caret drawn in correct place on wrapped lines. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2126144&group_id=2439">Bug #2126144.</a>
	</li>
	<li>
	Compilation for 64 bit Windows works using MinGW. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2515578&group_id=2439">Bug #2515578.</a>
	</li>
	<li>
	Incorrect memory freeing fixed on OS X.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2354098&group_id=2439">Bug #2354098</a>,
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2671749&group_id=2439">Bug #2671749.</a>
	</li>
	<li>
	SciTE on GTK+ crash fixed on startup when child process exits before initialisation complete.
	<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2716987&group_id=2439">Bug #2716987.</a>
	</li>
	<li>
	Crash fixed when AutoCompleteGetCurrent called with no active autocompletion.
	</li>
	<li>
	Flickering diminished when pressing Tab. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2723006&group_id=2439">Bug #2723006.</a>
	</li>
	<li>
	Namespace compilation issues with GTK+ on OS X fixed.
	</li>
	<li>
	Increased maximum length of SciTE's Language menu on GTK+ to 100 items. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2528241&group_id=2439">Bug #2528241.</a>
	</li>
	<li>
	Fixed incorrect Python lexing for multi-line continued strings. <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2450963&group_id=2439">Bug #2450963.</a>
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite177.zip?download">Release 1.77</a>
    </h3>
    <ul>
	<li>
	Released on 18 October 2008.
	</li>
	<li>
	Direct temporary access to Scintilla's text buffer to allow simple efficient interfacing
	to libraries like regular expression libraries.
	</li>
	<li>
	Scintilla on Windows can interpret keys as Unicode even when a narrow character
	window with SCI_SETKEYSUNICODE.
	</li>
	<li>
	Notification sent when autocompletion cancelled.
	</li>
	<li>
	MySQL lexer added.
	</li>
	<li>
	Lexer for gettext .po files added.
	</li>
	<li>
	Abaqus lexer handles program structure more correctly.
	</li>
	<li>
	Assembler lexer works with non-ASCII text.
	</li>
	<li>
	C++ lexer allows mixed case doc comment tags.
	</li>
	<li>
	CSS lexer updated and works with non-ASCII.
	</li>
	<li>
	Diff lexer adds style for changed lines, handles subversion diffs better and
	fixes styling and folding for lines containing chunk dividers ("---").
	</li>
	<li>
	FORTRAN lexer accepts more styles of compiler directive.
	</li>
	<li>
	Haskell lexer allows hexadecimal literals.
	</li>
	<li>
	HTML lexer improves PHP and JavaScript folding.
	PHP heredocs, nowdocs, strings and comments processed more accurately.
	Internet Explorer's non-standard &gt;comment&lt; tag supported.
	Script recognition in XML can be controlled with lexer.xml.allow.scripts property.
	</li>
	<li>
	Lua lexer styles last character correctly.
	</li>
	<li>
	Perl lexer update.
	</li>
	<li>
	Comment folding implemented for Ruby.
	</li>
	<li>
	Better TeX folding.
	</li>
	<li>
	Verilog lexer updated.
	</li>
	<li>
	Windows Batch file lexer handles %~ and %*.
	</li>
	<li>
	YAML lexer allows non-ASCII text.
	</li>
	<li>
	SciTE on GTK+ implements "Replace in Buffers" in advanced mode.
	</li>
	<li>
	The extender OnBeforeSave method can override the default file saving behaviour by retuning true.
	</li>
	<li>
	Window position and recent files list may be saved into the session file.
	</li>
	<li>
	Right button press outside the selection moves the caret.
	</li>
	<li>
	SciTE load.on.activate works when closing a document reveals a changed document.
	</li>
	<li>
	SciTE bug fixed where eol.mode not used for initial buffer.
	</li>
	<li>
	SciTE bug fixed where a file could be saved as the same name as another
	buffer leading to confusing behaviour.
	</li>
	<li>
	Fixed display bug for long lines in same style on Windows.
	</li>
	<li>
	Fixed SciTE crash when finding matching preprocessor command used on some files.
	</li>
	<li>
	Drawing performance improved for files with many blank lines.
	</li>
	<li>
	Folding bugs fixed where changing program text produced a decrease in fold level on a fold header line.
	</li>
	<li>
	Clearing document style now clears all indicators.
	</li>
	<li>
	SciTE's embedded Lua updated to 5.1.4.
	</li>
	<li>
	SciTE will compile with versions of GTK+ before 2.8 again.
	</li>
	<li>
	SciTE on GTK+ bug fixed where multiple files not opened.
	</li>
	<li>
	Bug fixed with SCI_VCHOMEWRAP and SCI_VCHOMEWRAPEXTEND on white last line.
	</li>
	<li>
	Regular expression bug fixed where "^[^(]+$" matched empty lines.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite176.zip?download">Release 1.76</a>
    </h3>
    <ul>
	<li>
	Released on 16 March 2008.
	</li>
	<li>
	Support for PowerShell.
	</li>
	<li>
	Lexer added for Magik.
	</li>
	<li>
	Director extension working on GTK+.
	</li>
	<li>
	Director extension may set focus to SciTE through "focus:" message on GTK+.
	</li>
	<li>
	C++ folder handles final line better in some cases.
	</li>
	<li>
	SCI_COPYALLOWLINE added which is similar to SCI_COPY except that if the selection is empty then
	the line holding the caret is copied. On Windows an extra clipboard format allows pasting this as a whole
	line before the current selection. This behaviour is compatible with Visual Studio.
	</li>
	<li>
	On Windows, the horizontal scroll bar can handle wider files.
	</li>
	<li>
	On Windows, a system palette leak was fixed. Should not affect many as palette mode is rarely used.
	</li>
	<li>
	Install command on GTK+ no longer tries to set explicit owner.
	</li>
	<li>
	Perl lexer handles defined-or operator "//".
	</li>
	<li>
	Octave lexer fixes "!=" operator.
	</li>
	<li>
	Optimized selection change drawing to not redraw as much when not needed.
	</li>
	<li>
	SciTE on GTK+ no longer echoes Lua commands so is same as on Windows.
	</li>
	<li>
	Automatic vertical scrolling limited to one line at a time so is not too fast.
	</li>
	<li>
	Crash fixed when line states set beyond end of line states. This occurred when lexers did not
	set a line state for each line.
	</li>
	<li>
	Crash in SciTE on Windows fixed when search for 513 character string fails.
	</li>
	<li>
	SciTE disables translucent features on Windows 9x due to crashes reported when using translucency.
	</li>
	<li>
	Bug fixed where whitespace background was not seen on wrapped lines.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite175.zip?download">Release 1.75</a>
    </h3>
    <ul>
	<li>
	Released on 22 November 2007.
	</li>
	<li>
	Some WordList and PropSet functionality moved from Scintilla to SciTE.
	Projects that link to Scintilla's code for these classes may need to copy
	code from SciTE.
	</li>
	<li>
	Borland C++ can no longer build Scintilla.
	</li>
	<li>
	Invalid bytes in UTF-8 mode are displayed as hex blobs. This also prevents crashes due to
	passing invalid UTF-8 to platform calls.
	</li>
	<li>
	Indentation guides enhanced to be visible on completely empty lines when possible.
	</li>
	<li>
	The horizontal scroll bar may grow to match the widest line displayed.
	</li>
	<li>
	Allow autocomplete pop ups to appear outside client rectangle in some cases.
	</li>
	<li>
	When line state changed, SC_MOD_CHANGELINESTATE modification notification sent and
	margin redrawn.
	</li>
	<li>
	SciTE scripts can access the menu command values IDM_*.
	</li>
	<li>
	SciTE's statement.end property has been implemented again.
	</li>
	<li>
	SciTE shows paths and matches in different styles for Find In Files.
	</li>
	<li>
	Incremental search in SciTE for Windows is modeless to make it easier to exit.
	</li>
	<li>
	Folding performance improved.
	</li>
	<li>
	SciTE for GTK+ now includes a Browse button in the Find In Files dialog.
	</li>
	<li>
	On Windows versions that support Unicode well, Scintilla is a wide character window
	which allows input for some less common languages like Armenian, Devanagari,
	Tamil, and Georgian. To fully benefit, applications should use wide character calls.
	</li>
	<li>
	Lua function names are exported from SciTE to allow some extension libraries to work.
	</li>
	<li>
	Lexers added for Abaqus, Ansys APDL, Asymptote, and R.
	</li>
	<li>
	SCI_DELWORDRIGHTEND added for closer compatibility with GTK+ entry widget.
	</li>
	<li>
	The styling buffer may now use all 8 bits in each byte for lexical states with 0 bits for indicators.
	</li>
	<li>
	Multiple characters may be set for SciTE's calltip.&lt;lexer&gt;.parameters.start property.
	</li>
	<li>
	Bash lexer handles octal literals.
	</li>
	<li>
	C++/JavaScript lexer recognises regex literals in more situations.
	</li>
	<li>
	Haskell lexer fixed for quoted strings.
	</li>
	<li>
	HTML/XML lexer does not notice XML indicator if there is
	non-whitespace between the "&lt;?" and "XML".
	ASP problem fixed where &lt;/ is used inside a comment.
	</li>
	<li>
	Error messages from Lua 5.1 are recognised.
	</li>
	<li>
	Folding implemented for Metapost.
	</li>
	<li>
	Perl lexer enhanced for handling minus-prefixed barewords,
	underscores in numeric literals and vector/version strings,
	^D and ^Z similar to __END__,
	subroutine prototypes as a new lexical class,
	formats and format blocks as new lexical classes, and
	'/' suffixed keywords and barewords.
	</li>
	<li>
	Python lexer styles all of a decorator in the decorator style rather than just the name.
	</li>
	<li>
	YAML lexer styles colons as operators.
	</li>
	<li>
	Fixed SciTE bug where undo would group together multiple separate modifications.
	</li>
	<li>
	Bug fixed where setting background colour of calltip failed.
	</li>
	<li>
	SciTE allows wildcard suffixes for file pattern based properties.
	</li>
	<li>
	SciTE on GTK+ bug fixed where user not prompted to save untitled buffer.
	</li>
	<li>
	SciTE bug fixed where property values from one file were not seen by lower priority files.
	</li>
	<li>
	Bug fixed when showing selection with a foreground colour change which highlighted
	an incorrect range in some positions.
	</li>
	<li>
	Cut now invokes SCN_MODIFYATTEMPTRO notification.
	</li>
	<li>
	Bug fixed where caret not shown at beginning of wrapped lines.
	Caret made visible in some cases after wrapping and scroll bar updated after wrapping.
	</li>
	<li>
	Modern indicators now work on wrapped lines.
	</li>
	<li>
	Some crashes fixed for 64-bit GTK+.
	</li>
	<li>
	On GTK+ clipboard features improved for VMWare tools copy and paste.
	SciTE exports the clipboard more consistently on shut down.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite174.zip?download">Release 1.74</a>
    </h3>
    <ul>
	<li>
	Released on 18 June 2007.
	</li>
	<li>
	OS X support.
	</li>
	<li>
	Indicators changed to be a separate data structure allowing more indicators. Storing indicators in high bits
	of styling bytes is deprecated and will be removed in the next version.
	</li>
	<li>
	Unicode support extended to all Unicode characters not just the Basic Multilingual Plane.
	</li>
	<li>
	Performance improved on wide lines by breaking long runs in a single style into shorter segments.
	</li>
	<li>
	Performance improved by caching layout of short text segments.
	</li>
	<li>
	SciTE includes Lua 5.1.
	</li>
	<li>
	Caret may be displayed as a block.
	</li>
	<li>
	Lexer added for GAP.
	</li>
	<li>
	Lexer added for PL/M.
	</li>
	<li>
	Lexer added for Progress.
	</li>
	<li>
	SciTE session files have changed format to be like other SciTE .properties files
	and now use the extension .session.
	Bookmarks and folds may optionally be saved in session files.
	Session files created with previous versions of SciTE will not load into this version.
	</li>
	<li>
	SciTE's extension and scripting interfaces add OnKey, OnDwellStart, and OnClose methods.
	</li>
	<li>
	On GTK+, copying to the clipboard does not include the text/urilist type since this caused problems when
	pasting into Open Office.
	</li>
	<li>
	On GTK+, Scintilla defaults caret blink rate to platform preference.
	</li>
	<li>
	Dragging does not start until the mouse has been dragged a certain amount.
	This stops spurious drags when just clicking inside the selection.
	</li>
	<li>
	Bug fixed where brace highlight not shown when caret line background set.
	</li>
	<li>
	Bug fixed in Ruby lexer where out of bounds access could occur.
	</li>
	<li>
	Bug fixed in XML folding where tags were not being folded because they are singletons in HTML.
	</li>
	<li>
	Bug fixed when many font names used.
	</li>
	<li>
	Layout bug fixed on GTK+ where fonts have ligatures available.
	</li>
	<li>
	Bug fixed with SCI_LINETRANSPOSE on a blank line.
	</li>
	<li>
	SciTE hang fixed when using UNC path with directory properties feature.
	</li>
	<li>
	Bug on Windows fixed by examining dropped text for Unicode even in non-Unicode mode so it
	can work when source only provides Unicode or when using an encoding different from the
	system default.
	</li>
	<li>
	SciTE bug on GTK+ fixed where Stop Executing did not work when more than a single process started.
	</li>
	<li>
	SciTE bug on GTK+ fixed where mouse wheel was not switching between buffers.
	</li>
	<li>
	Minor line end fix to PostScript lexer.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite173.zip?download">Release 1.73</a>
    </h3>
    <ul>
	<li>
	Released on 31 March 2007.
	</li>
	<li>
	SciTE adds a Directory properties file to configure behaviour for files in a directory and its subdirectories.
	</li>
	<li>
	Style changes may be made during text modification events.
	</li>
	<li>
	Regular expressions recognise \d, \D, \s, \S, \w, \W, and \xHH.
	</li>
	<li>
	Support for cmake language added.
	</li>
	<li>
	More Scintilla properties can be queried.
	</li>
	<li>
	Edge line drawn under text.
	</li>
	<li>
	A savesession command added to SciTE director interface.
	</li>
	<li>
	SciTE File | Encoding menu item names changed to be less confusing.
	</li>
	<li>
	SciTE on GTK+ dialog buttons reordered to follow guidelines.
	</li>
	<li>
	SciTE on GTK+ removed GTK+ 1.x compatible file dialog code.
	</li>
	<li>
	SciTE on GTK+ recognises key names KeypadMultiply and KeypadDivide.
	</li>
	<li>
	Background colour of line wrapping visual flag changed to STYLE_DEFAULT.
	</li>
	<li>
	Makefile lexing enhanced for ':=' operator and when lines start with tab.
	</li>
	<li>
	TADS3 lexer and folder improved.
	</li>
	<li>
	SCN_DOUBLECLICK notification may set SCI_SHIFT, SCI_CTRL, and SCI_ALT flags on modifiers field.
	</li>
	<li>
	Slow folding of large constructs in Python fixed.
	</li>
	<li>
	MSSQL folding fixed to be case-insensitive and fold at more keywords.
	</li>
	<li>
	SciTE's brace matching works better for HTML.
	</li>
	<li>
	Determining API list items checks for specified parameters start character before default '('.
	</li>
	<li>
	Hang fixed in HTML lexer.
	</li>
	<li>
	Bug fixed in with LineTranspose command where markers could move to different line.
	</li>
	<li>
	Memory released when buffer completely emptied.
	</li>
	<li>
	If translucency not available on Windows, draw rectangular outline instead.
	</li>
	<li>
	Bash lexer handles "-x" in "--x-includes..." better.
	</li>
	<li>
	AutoIt3 lexer fixes string followed by '+'.
	</li>
	<li>
	LinesJoin fixed where it stopped early due to not adjusting for inserted spaces..
	</li>
	<li>
	StutteredPageDown fixed when lines wrapped.
	</li>
	<li>
	FormatRange fixed to not double count line number width which could lead to a large space.
	</li>
	<li>
	SciTE Export As PDF and Latex commands fixed to format floating point numbers with '.' even in locales
	that use ','.
	</li>
	<li>
	SciTE bug fixed where File | New could produce buffer with contents of previous file when using read-only mode.
	</li>
	<li>
	SciTE retains current scroll position when switching buffers and fold.on.open set.
	</li>
	<li>
	SciTE crash fixed where '*' used to invoke parameters dialog.
	</li>
	<li>
	SciTE bugs when writing large UCS-2 files fixed.
	</li>
	<li>
	Bug fixed when scrolling inside a SCN_PAINTED event by invalidating window
	rather than trying to perform synchronous painting.
	</li>
	<li>
	SciTE for GTK+ View | Full Screen works on recent versions of GTK+.
	</li>
	<li>
	SciTE for Windows enables and disables toolbar commands correctly.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite172.zip?download">Release 1.72</a>
    </h3>
    <ul>
	<li>
	Released on 15 January 2007.
	</li>
	<li>
	Performance of per-line data improved.
	</li>
	<li>
	SC_STARTACTION flag set on the first modification notification in an undo
	transaction to help synchronize the container's undo stack with Scintilla's.
	</li>
	<li>
	On GTK+ drag and drop defaults to move rather than copy.
	</li>
	<li>
	Scintilla supports extending appearance of selection to right hand margin.
	</li>
	<li>
	Incremental search available on GTK+.
	</li>
	<li>
	SciTE Indentation Settings dialog available on GTK+ and adds a "Convert" button.
	</li>
	<li>
	Find in Files can optionally ignore binary files or directories that start with ".".
	</li>
	<li>
	Lexer added for "D" language.
	</li>
	<li>
	Export as HTML shows folding with underline lines and +/- symbols.
	</li>
	<li>
	Ruby lexer interprets interpolated strings as expressions.
	</li>
	<li>
	Lua lexer fixes some cases of numeric literals.
	</li>
	<li>
	C++ folder fixes bug with "@" in doc comments.
	</li>
	<li>
	NSIS folder handles !if and related commands.
	</li>
	<li>
	Inno setup lexer adds styling for single and double quoted strings.
	</li>
	<li>
	Matlab lexer handles backslashes in string literals correctly.
	</li>
	<li>
	HTML lexer fixed to allow "?&gt;" in comments in Basic script.
	</li>
	<li>
	Added key codes for Windows key and Menu key.
	</li>
	<li>
	Lua script method scite.MenuCommand(x) performs a menu command.
	</li>
	<li>
	SciTE bug fixed with box comment command near start of file setting selection to end of file.
	</li>
	<li>
	SciTE on GTK+, fixed loop that occurred with automatic loading for an unreadable file.
	</li>
	<li>
	SciTE asks whether to save files when Windows shuts down.
	</li>
	<li>
	Save Session on Windows now defaults the extension to "ses".
	</li>
	<li>
	Bug fixed with single character keywords.
	</li>
	<li>
	Fixed infinite loop for SCI_GETCOLUMN for position beyond end of document.
	</li>
	<li>
	Fixed failure to accept typing on Solaris/GTK+ when using default ISO-8859-1 encoding.
	</li>
	<li>
	Fixed warning from Lua in SciTE when creating a new buffer when already have
	maximum number of buffers open.
	</li>
	<li>
	Crash fixed with "%%" at end of batch file.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite171.zip?download">Release 1.71</a>
    </h3>
    <ul>
	<li>
	Released on 21 August 2006.
	</li>
	<!--li>
	On GTK+ drag and drop defaults to move rather than copy.
	</li-->
	<li>
	Double click notification includes line and position.
	</li>
	<li>
	VB lexer bugs fixed for preprocessor directive below a comment or some other states and
	to use string not closed style back to the starting quote when there are internal doubled quotes.
	</li>
	<li>
	C++ lexer allows identifiers to contain '$' and non-ASCII characters such as UTF-8.
	The '$' character can be disallowed with lexer.cpp.allow.dollars=0.
	</li>
	<li>
	Perl lexer allows UTF-8 identifiers and has some other small improvements.
	</li>
	<li>
	SciTE's $(CurrentWord) uses word.characters.&lt;filepattern&gt; to define the word
	rather than a hardcoded list of word characters.
	</li>
	<li>
	SciTE Export as HTML adds encoding information for UTF-8 file and fixes DOCTYPE.
	</li>
	<li>
	SciTE session and .recent files default to the user properties directory rather than global
	properties directory.
	</li>
	<li>
	Left and right scroll events handled correctly on GTK+ and horizontal scroll bar has more sensible
	distances for page and arrow clicks.
	</li>
	<li>
	SciTE on GTK+ tab bar fixed to work on recent versions of GTK+.
	</li>
	<li>
	On GTK+, if the approximate character set conversion is unavailable, a second attempt is made
	without approximations. This may allow keyboard input and paste to work on older systems.
	</li>
	<li>
	SciTE on GTK+ can redefine the Insert key.
	</li>
	<li>
	SciTE scripting interface bug fixed where some string properties could not be changed.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite170.zip?download">Release 1.70</a>
    </h3>
    <ul>
	<li>
	Released on 20 June 2006.
	</li>
	<li>
	On GTK+, character set conversion is performed using an option that allows approximate conversions rather
	than failures when a character can not be converted. This may lead to similar characters being inserted or
	when no similar character is available a '?' may be inserted.
	</li>
	<li>
	On GTK+, the internationalised IM (Input Method) feature is used for all typed input for all character sets.
	</li>
	<li>
	Scintilla has new margin types SC_MARGIN_BACK and SC_MARGIN_FORE that use the default
	style's background and foreground colours (normally white and black) as the background to the margin.
	</li>
	<li>
	Scintilla/GTK+ allows file drops on Windows when drop is of type DROPFILES_DND
	as well as text/uri-list.
	</li>
	<li>
	Code page can only be set to one of the listed valid values.
	</li>
	<li>
	Text wrapping fixed for cases where insertion was not wide enough to trigger
	wrapping before being styled but was after styling.
	</li>
	<li>
	SciTE find marks are removed before printing or exporting to avoid producing incorrect styles.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite169.zip?download">Release 1.69</a>
    </h3>
    <ul>
	<li>
	Released on 29 May 2006.
	</li>
	<li>
	SciTE supports z-order based buffer switching on Ctrl+Tab.
	</li>
	<li>
	Translucent support for selection and whole line markers.
	</li>
	<li>
	SciTE may have per-language abbreviations files.
	</li>
	<li>
	Support for Spice language.
	</li>
	<li>
	On GTK+ autocompletion lists are optimised and use correct selection colours.
	</li>
	<li>
	On GTK+ the URI data type is preferred in drag and drop so that applications
	will see files dragged from the shell rather than dragging the text of the file name
	into the document.
	</li>
	<li>
	Increased number of margins to 5.
	</li>
	<li>
	Basic lexer allows include directive $include: "file name".
	</li>
	<li>
	SQL lexer no longer bases folding on indentation.
	</li>
	<li>
	Line ends are transformed when copied to clipboard on
	Windows/GTK+2 as well as Windows/GTK+ 1.
	</li>
	<li>
	Lexing code masks off the indicator bits on the start style before calling the lexer
	to avoid confusing the lexer when an application has used an indicator.
	</li>
	<li>
	SciTE savebefore:yes only saves the file when it has been changed.
	</li>
	<li>
	SciTE adds output.initial.hide setting to allow setting the size of the output pane
	without it showing initially.
	</li>
	<li>
	SciTE on Windows Go To dialog allows line number with more digits.
	</li>
	<li>
	Bug in HTML lexer fixed where a segment of PHP could switch scripting language
	based on earlier text on that line.
	</li>
	<li>
	Memory bug fixed when freeing regions on GTK+.
	Other minor bugs fixed on GTK+.
	</li>
	<li>
	Deprecated GTK+ calls in Scintilla replaced with current calls.
	</li>
	<li>
	Fixed a SciTE bug where closing the final buffer, if read-only, left the text present in an
	untitled buffer.
	</li>
	<li>
	Bug fixed in bash lexer that prevented folding.
	</li>
	<li>
	Crash fixed in bash lexer when backslash at end of file.
	</li>
	<li>
	Crash on recent releases of GTK+ 2.x avoided by changing default font from X
	core font to Pango font "!Sans".
	</li>
	<li>
	Fix for SciTE properties files where multiline properties continued over completely blank lines.
	</li>
	<li>
	Bug fixed in SciTE/GTK+ director interface where more data available than
	buffer size.
	</li>
	<li>
	Minor visual fixes to SciTE splitter on GTK+.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite168.zip?download">Release 1.68</a>
    </h3>
    <ul>
	<li>
	Released on 9 March 2006.
	</li>
	<li>
	Translucent drawing implemented for caret line and box indicators.
	</li>
	<li>
	Lexer specifically for TCL is much more accurate than reusing C++ lexer.
	</li>
	<li>
	Support for Inno Setup scripts.
	</li>
	<li>
	Support for Opal language.
	</li>
	<li>
	Calltips may use a new style, STYLE_CALLTIP which allows choosing a
	different font for calltips.
	</li>
	<li>
	Python lexer styles comments on decorators.
	</li>
	<li>
	HTML lexer refined handling of "?>" and "%>" within server
	side scripts.
	</li>
	<li>
	Batch file lexer improved.
	</li>
	<li>
	Eiffel lexer doesn't treat '.' as a name character.
	</li>
	<li>
	Lua lexer handles length operator, #, and hex literals.
	</li>
	<li>
	Properties file lexer has separate style for keys.
	</li>
	<li>
	PL/SQL folding improved.
	</li>
	<li>
	SciTE Replace dialog always searches in forwards direction.
	</li>
	<li>
	SciTE can detect language of file from initial #! line.
	</li>
	<li>
	SciTE on GTK+ supports output.scroll=2 setting.
	</li>
	<li>
	SciTE can perform an import a properties file from the command line.
	</li>
	<li>
	Set of word characters used for regular expression \&lt; and \&gt;.
	</li>
	<li>
	Bug fixed with SCI_COPYTEXT stopping too early.
	</li>
	<li>
	Bug fixed with splitting lines so that all lines are split.
	</li>
	<li>
	SciTE calls OnSwitchFile when closing one buffer causes a switch to another.
	</li>
	<li>
	SciTE bug fixed where properties were being reevaluated without good reason
	after running a macro.
	</li>
	<li>
	Crash fixed when clearing document with some lines contracted in word wrap mode.
	</li>
	<li>
	Palette expands as more entries are needed.
	</li>
	<li>
	SCI_POSITIONFROMPOINT returns more reasonable value when close to
	last text on a line.
	</li>
	<li>
	On Windows, long pieces of text may be drawn in segments if they fail to draw
	as a whole.
	</li>
	<li>
	Bug fixed with bad drawing when some visual changes made inside SCN_UPDATEUI
	notification.
	</li>
	<li>
	SciTE bug fixed with groupundo setting.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite167.zip?download">Release 1.67</a>
    </h3>
    <ul>
	<li>
	Released on 17 December 2005.
	</li>
	<li>
	Scintilla checks the paint region more accurately when seeing if an area is being
	repainted. Platform layer implementations may need to change for this to take
	effect. This fixes some drawing and styling bugs. Also optimized some parts of
	marker code to only redraw the line of the marker rather than whole of the margin.
	</li>
	<li>
	Quoted identifier style for SQL. SQL folding performed more simply.
	</li>
	<li>
	Ruby lexer improved to better handle here documents and non-ASCII
	characters.
	</li>
	<li>
	Lua lexer supports long string and block comment syntax from Lua 5.1.
	</li>
	<li>
	Bash lexer handles here documents better.
	</li>
	<li>
	JavaScript lexing recognises regular expressions more accurately and includes flag
	characters in the regular expression style. This is both in JavaScript files and when
	JavaScript is embedded in HTML.
	</li>
	<li>
	Scintilla API provided to reveal how many style bits are needed for the
	current lexer.
	</li>
	<li>
	Selection duplicate added.
	</li>
	<li>
	Scintilla API for adding a set of markers to a line.
	</li>
	<li>
	DBCS encodings work on Windows 9x.
	</li>
	<li>
	Convention defined for property names to be used by lexers and folders
	so they can be automatically discovered and forwarded from containers.
	</li>
	<li>
	Default bookmark in SciTE changed to a blue sphere image.
	</li>
	<li>
	SciTE stores the time of last asking for a save separately for each buffer
	which fixes bugs with automatic reloading.
	</li>
	<li>
	On Windows, pasted text has line ends converted to current preference.
	GTK+ already did this.
	</li>
	<li>
	Kid template language better handled by HTML lexer by finishing ASP Python
	mode when a ?> is found.
	</li>
	<li>
	SciTE counts number of characters in a rectangular selection correctly.
	</li>
	<li>
	64-bit compatibility improved. One change that may affect user code is that
	the notification message header changed to include a pointer-sized id field
	to match the current Windows definition.
	</li>
	<li>
	Empty ranges can no longer be dragged.
	</li>
	<li>
	Crash fixed when calls made that use layout inside the painted notification.
	</li>
	<li>
	Bug fixed where Scintilla created pixmap buffers that were too large leading
	to failures when many instances used.
	</li>
	<li>
	SciTE sets the directory of a new file to the directory of the currently
	active file.
	</li>
	<li>
	SciTE allows choosing a code page for the output pane.
	</li>
	<li>
	SciTE HTML exporter no longer honours monospaced font setting.
	</li>
	<li>
	Line layout cache in page mode caches the line of the caret. An assertion is
	now used to ensure that the layout reentrancy problem that caused this
	is easier to find.
	</li>
	<li>
	Speed optimized for long lines and lines containing many control characters.
	</li>
	<li>
	Bug fixed in brace matching in DBCS files where byte inside character
	is same as brace.
	</li>
	<li>
	Indent command does not indent empty lines.
	</li>
	<li>
	SciTE bug fixed for commands that operate on files with empty extensions.
	</li>
	<li>
	SciTE bug fixed where monospaced option was copied for subsequently opened files.
	</li>
	<li>
	SciTE on Windows bug fixed in the display of a non-ASCII search string
	which can not be found.
	</li>
	<li>
	Bugs fixed with nested calls displaying a new calltip while one is already
	displayed.
	</li>
	<li>
	Bug fixed when styling PHP strings.
	</li>
	<li>
	Bug fixed when styling C++ continued preprocessor lines.
	</li>
	<li>
	SciTE bug fixed where opening file from recently used list reset choice of
	language.
	</li>
	<li>
	SciTE bug fixed when compiled with NO_EXTENSIONS and
	closing one file closes the application.
	</li>
	<li>
	SciTE crash fixed for error messages that look like Lua messages but aren't
	in the same order.
	</li>
	<li>
	Remaining fold box support deprecated. The symbols SC_FOLDLEVELBOXHEADERFLAG,
   SC_FOLDLEVELBOXFOOTERFLAG, SC_FOLDLEVELCONTRACTED,
   SC_FOLDLEVELUNINDENT, and SC_FOLDFLAG_BOX are deprecated.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite166.zip?download">Release 1.66</a>
    </h3>
    <ul>
	<li>
	Released on 26 August 2005.
	</li>
	<li>
	New, more ambitious Ruby lexer.
	</li>
	<li>
	SciTE Find in Files dialog has options for matching case and whole words which are
	enabled when the internal find command is used.
	</li>
	<li>
	SciTE output pane can display automatic completion after "$(" typed.
	An initial ">" on a line is ignored when Enter pressed.
	</li>
	<li>
	C++ lexer recognises keywords within line doc comments. It continues styles over line
	end characters more consistently so that eolfilled style can be used for preprocessor lines
	and line comments.
	</li>
	<li>
	VB lexer improves handling of file numbers and date literals.
	</li>
	<li>
	Lua folder handles repeat until, nested comments and nested strings.
	</li>
	<li>
	POV lexer improves handling of comment lines.
	</li>
	<li>
	AU3 lexer and folder updated. COMOBJ style added.
	</li>
	<li>
	Bug fixed with text display on GTK+ with Pango 1.8.
	</li>
	<li>
	Caret painting avoided when not focused.
	</li>
	<li>
	SciTE on GTK+ handles file names used to reference properties as case-sensitive.
	</li>
	<li>
	SciTE on GTK+ Save As and Export commands set the file name field.
	On GTK+ the Export commands modify the file name in the same way as on Windows.
	</li>
	<li>
	Fixed SciTE problem where confirmation was not displaying when closing a file where all
	contents had been deleted.
	</li>
	<li>
	Middle click on SciTE tab now closes correct buffer on Windows when tool bar is visible.
	</li>
	<li>
	SciTE bugs fixed where files contained in directory that includes '.' character.
	</li>
	<li>
	SciTE bug fixed where import in user options was reading file from directory of
	global options.
	</li>
	<li>
	SciTE calltip bug fixed where single line calltips had arrow displayed incorrectly.
	</li>
	<li>
	SciTE folding bug fixed where empty lines were shown for no reason.
	</li>
	<li>
	Bug fixed where 2 byte per pixel XPM images caused crash although they are still not
	displayed.
	</li>
	<li>
	Autocompletion list size tweaked.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite165.zip?download">Release 1.65</a>
    </h3>
    <ul>
	<li>
	Released on 1 August 2005.
	</li>
	<li>
	FreeBasic support.
	</li>
	<li>
	SciTE on Windows handles command line arguments
	"-" (read standard input into buffer),
	"--" (read standard input into output pane) and
	"-@" (read file names from standard input and open each).
	</li>
	<li>
	SciTE includes a simple implementation of Find in Files which is used if no find.command is set.
	</li>
	<li>
	SciTE can close tabs with a mouse middle click.
	</li>
	<li>
	SciTE includes a save.all.for.build setting.
	</li>
	<li>
	Folder for MSSQL.
	</li>
	<li>
	Batch file lexer understands more of the syntax and the behaviour of built in commands.
	</li>
	<li>
	Perl lexer handles here docs better; disambiguates barewords, quote-like delimiters, and repetition operators;
	handles Pods after __END__; recognises numbers better; and handles some typeglob special variables.
	</li>
	<li>
	Lisp adds more lexical states.
	</li>
	<li>
	PHP allows spaces after &lt;&lt;&lt;.
	</li>
	<li>
	TADS3 has a simpler set of states and recognises identifiers.
	</li>
	<li>
	Avenue elseif folds better.
	</li>
	<li>
	Errorlist lexer treats lines starting with '+++' and '---' as separate
	styles from '+' and '-' as they indicate file names in diffs.
	</li>
	<li>
	SciTE error recogniser handles file paths in extra explanatory lines from MSVC
	and in '+++' and '---' lines from diff.
	</li>
	<li>
	Bugs fixed in SciTE and Scintilla folding behaviour when text pasted before
	folded text caused unnecessary
	unfolding and cutting text could lead to text being irretrievably hidden.
	</li>
	<li>
	SciTE on Windows uses correct font for dialogs and better font for tab bar
	allowing better localisation
	</li>
	<li>
	When Windows is used with a secondary monitor before the primary
	monitor, autocompletion lists are not forced onto the primary monitor.
	</li>
	<li>
	Scintilla calltip bug fixed where down arrow setting wrong value in notification
	if not in first line. SciTE bug fixed where second arrow only shown on multiple line
	calltip and was therefore misinterpreting the notification value.
	</li>
	<li>
	Lexers will no longer be re-entered recursively during, for example, fold level setting.
	</li>
	<li>
	Undo of typing in overwrite mode undoes one character at a time rather than requiring a removal
	and addition step for each character.
	</li>
	<li>
	EM_EXSETSEL(0,-1) fixed.
	</li>
	<li>
	Bug fixed where part of a rectangular selection was not shown as selected.
	</li>
	<li>
	Autocomplete window size fixed.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite164.zip?download">Release 1.64</a>
    </h3>
    <ul>
	<li>
	Released on 6 June 2005.
	</li>
	<li>
	TADS3 support
	</li>
	<li>
	Smalltalk support.
	</li>
	<li>
	Rebol support.
	</li>
	<li>
	Flagship (Clipper / XBase) support.
	</li>
	<li>
	CSound support.
	</li>
	<li>
	SQL enhanced to support SQL*Plus.
	</li>
	<li>
	SC_MARK_FULLRECT margin marker fills the whole marker margin for marked
	lines with a colour.
	</li>
	<li>
	Performance improved for some large undo and redo operations and modification flags
	added in notifications.
	</li>
	<li>
	SciTE adds command equivalents for fold margin mouse actions.
	</li>
	<li>
	SciTE adds OnUpdateUI to set of events that can be handled by a Lua script.
	</li>
	<li>
	Properties set in Scintilla can be read.
	</li>
	<li>
	GTK+ SciTE exit confirmation adds Cancel button.
	</li>
	<li>
	More accurate lexing of numbers in PHP and Caml.
	</li>
	<li>
	Perl can fold POD and package sections. POD verbatim section style.
	Globbing syntax recognised better.
	</li>
	<li>
	Context menu moved slightly on GTK+ so that it will be under the mouse and will
	stay open if just clicked rather than held.
	</li>
	<li>
	Rectangular selection paste works the same whichever direction the selection was dragged in.
	</li>
	<li>
	EncodedFromUTF8 handles -1 length argument as documented.
	</li>
	<li>
	Undo and redo can cause SCN_MODIFYATTEMPTRO notifications.
	</li>
	<li>
	Indicators display correctly when they start at the second character on a line.
	</li>
	<li>
	SciTE Export As HTML uses standards compliant CSS.
	</li>
	<li>
	SciTE automatic indentation handles keywords for indentation better.
	</li>
	<li>
	SciTE fold.comment.python property removed as does not work.
	</li>
	<li>
	Fixed problem with character set conversion when pasting on GTK+.
	</li>
	<li>
	SciTE default character set changed from ANSI_CHARSET to DEFAULT_CHARSET.
	</li>
	<li>
	Fixed crash when creating empty autocompletion list.
	</li>
	<li>
	Autocomplete window size made larger under some conditions to make truncation less common.
	</li>
	<li>
	Bug fixed where changing case of a selection did not affect initial character of lines
	in multi-byte encodings.
	</li>
	<li>
	Bug fixed where rectangular selection not displayed after Alt+Shift+Click.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite163.zip?download">Release 1.63</a>
    </h3>
    <ul>
	<li>
	Released on 4 April 2005.
	</li>
	<li>
	Autocompletion on Windows changed to use pop up window, be faster,
	allow choice of maximum width and height, and to highlight only the text of the
	selected item rather than both the text and icon if any.
	</li>
	<li>
	Extra items can be added to the context menu in SciTE.
	</li>
	<li>
	Character wrap mode in Scintilla helps East Asian languages.
	</li>
	<li>
	Lexer added for Haskell.
	</li>
	<li>
	Objective Caml support.
	</li>
	<li>
	BlitzBasic and PureBasic support.
	</li>
	<li>
	CSS support updated to handle CSS2.
	</li>
	<li>
	C++ lexer is more selective about document comment keywords.
	</li>
	<li>
	AutoIt 3 lexer improved.
	</li>
	<li>
	Lua lexer styles end of line characters on comment and preprocessor
	lines so that the eolfilled style can be applied to them.
	</li>
	<li>
	NSIS support updated for line continuations, box comments, SectionGroup and
	PageEx, and with more up-to-date properties.
	</li>
	<li>
	Clarion lexer updated to perform folding and have more styles.
	</li>
	<li>
	SQL lexer gains second set of keywords.
	</li>
	<li>
	Errorlist lexer recognises Borland Delphi error messages.
	</li>
	<li>
	Method added for determining number of visual lines occupied by a document
	line due to wrapping.
	</li>
	<li>
	Sticky caret mode does not modify the preferred caret x position when typing
	and may be useful for typing columns of text.
	</li>
	<li>
	Dwell end notification sent when scroll occurs.
	</li>
	<li>
	On GTK+, Scintilla requisition height is screen height rather than large fixed value.
	</li>
	<li>
	Case insensitive autocompletion prefers exact case match.
	</li>
	<li>
	SCI_PARADOWN and SCI_PARAUP treat lines containing only white
	space as empty and handle text hidden by folding.
	</li>
	<li>
	Scintilla on Windows supports WM_PRINTCLIENT although there are some
	limitations.
	</li>
	<li>
	SCN_AUTOCSELECTION notification sent when user selects from autoselection list.
	</li>
	<li>
	SciTE's standard properties file sets buffers to 10, uses Pango fonts on GTK+ and
	has dropped several languages to make the menu fit on screen.
	</li>
	<li>
	SciTE's encoding cookie detection loosened so that common XML files will load
	in UTF-8 if that is their declared encoding.
	</li>
	<li>
	SciTE on GTK+ changes menus and toolbars to not be detachable unless turned
	on with a property. Menus no longer tear off. The toolbar may be set to use the
	default theme icons rather than SciTE's set. Changed key for View | End of Line
	because of a conflict. Language menu can contain more items.
	</li>
	<li>
	SciTE on GTK+ 2.x allows the height and width of the file open file chooser to
	be set, for the show hidden files check box to be set from an option and for it
	to be opened in the directory of the current file explicitly. Enter key works in
	save chooser.
	</li>
	<li>
	Scintilla lexers should no longer see bits in style bytes that are outside the set
	they modify so should be able to correctly lex documents where the container
	has used indicators.
	</li>
	<li>
	SciTE no longer asks to save before performing a revert.
	</li>
	<li>
	SciTE director interface adds a reloadproperties command to reload properties
	from files.
	</li>
	<li>
	Allow build on CYGWIN platform.
	</li>
	<li>
	Allow use from LccWin compiler.
	</li>
	<li>
	SCI_COLOURISE for SCLEX_CONTAINER causes a
	SCN_STYLENEEDED notification.
	</li>
	<li>
	Bugs fixed in lexing of HTML/ASP/JScript.
	</li>
	<li>
	Fix for folding becoming confused.
	</li>
	<li>
	On Windows, fixes for Japanese Input Method Editor and for 8 bit Katakana
	characters.
	</li>
	<li>
	Fixed buffer size bug avoided when typing long words by making buffer bigger.
	</li>
	<li>
	Undo after automatic indentation more sensible.
	</li>
	<li>
	SciTE menus on GTK+ uses Shift and Ctrl rather than old style abbreviations.
	</li>
	<li>
	SciTE full screen mode on Windows calculates size more correctly.
	</li>
	<li>
	SciTE on Windows menus work better with skinning applications.
	</li>
	<li>
	Searching bugs fixed.
	</li>
	<li>
	Colours reallocated when changing image using SCI_REGISTERIMAGE.
	</li>
	<li>
	Caret stays visible when Enter held down.
	</li>
	<li>
	Undo of automatic indentation more reasonable.
	</li>
	<li>
	High processor usage fixed in background wrapping under some
	circumstances.
	</li>
	<li>
	Crashing bug fixed on AMD64.
	</li>
	<li>
	SciTE crashing bug fixed when position.height or position.width not set.
	</li>
	<li>
	Crashing bug on GTK+ fixed when setting cursor and window is NULL.
	</li>
	<li>
	Crashing bug on GTK+ preedit window fixed.
	</li>
	<li>
	SciTE crashing bug fixed in incremental search on Windows ME.
	</li>
	<li>
	SciTE on Windows has a optional find and replace dialogs that can search through
	all buffers and search within a particular style number.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite162.zip?download">Release 1.62</a>
    </h3>
    <ul>
	<li>
	Released on 31 October 2004.
	</li>
	<li>
	Lexer added for ASN.1.
	</li>
	<li>
	Lexer added for VHDL.
	</li>
	<li>
	On Windows, an invisible system caret is used to allow screen readers to determine
	where the caret is. The visible caret is still drawn by the painting code.
	</li>
	<li>
	On GTK+, Scintilla has methods to read the target as UTF-8 and to convert
	a string from UTF-8 to the document encoding. This eases integration with
	containers that use the UTF-8 encoding which is the API encoding for GTK+ 2.
	</li>
	<li>
	SciTE on GTK+2 and Windows NT/2000/XP allows search and replace of Unicode text.
	</li>
	<li>
	SciTE calltips allow setting the characters used to start and end parameter lists and
	to separate parameters.
	</li>
	<li>
	FindColumn method converts a line and column into a position, taking into account
	tabs and multi-byte characters.
	</li>
	<li>
	On Windows, when Scintilla copies text to the clipboard as Unicode, it avoids
	adding an ANSI copy as the system will automatically convert as required in
	a context-sensitive manner.
	</li>
	<li>
	SciTE indent.auto setting automatically determines indent.size and use.tabs from
	document contents.
	</li>
	<li>
	SciTE defines a CurrentMessage property that holds the most recently selected
	output pane message.
	</li>
	<li>
	SciTE Lua scripting enhanced with
	<ul>
	<li>A Lua table called 'buffer' is associated with each buffer and can be used to
	maintain buffer-specific state.</li>
	<li>A 'scite' object allows interaction with the application such as opening
	files from script.</li>
	<li>Dynamic properties can be reset by assigning nil to a given key in
	the props table.</li>
	<li>An 'OnClear' event fires whenever properties and extension scripts are
	about to be reloaded.</li>
	<li>On Windows, loadlib is enabled and can be used to access Lua
	binary modules / DLLs.</li></ul>
	</li>
	<li>
	SciTE Find in Files on Windows can be used in a modeless way and gains a '..'
	button to move up to the parent directory. It is also wider so that longer paths
	can be seen.
	</li>
	<li>
	Close buttons added to dialogs in SciTE on Windows.
	</li>
	<li>
	SciTE on GTK+ 2 has a "hidden files" check box in file open dialog.
	</li>
	<li>
	SciTE use.monospaced setting removed. More information in the
	<a href="SciTEFAQ.html">FAQ</a>.
	</li>
	<li>
	APDL lexer updated with more lexical classes
	</li>
	<li>
	AutoIt3 lexer updated.
	</li>
	<li>
	Ada lexer fixed to support non-ASCII text.
	</li>
	<li>
	Cpp lexer now only matches exactly three slashes as starting a doc-comment so that
	lines of slashes are seen as a normal comment.
	Line ending characters are appear in default style on preprocessor and single line
	comment lines.
	</li>
	<li>
	CSS lexer updated to support CSS2 including second set of keywords.
	</li>
	<li>
	Errorlist lexer now understands Java stack trace lines.
	</li>
	<li>
	SciTE's handling of HTML Tidy messages jumps to column as well as line indicated.
	</li>
	<li>
	Lisp lexer allows multiline strings.
	</li>
	<li>
	Lua lexer treats .. as an operator when between identifiers.
	</li>
	<li>
	PHP lexer handles 'e' in numerical literals.
	</li>
	<li>
	PowerBasic lexer updated for macros and optimised.
	</li>
	<li>
	Properties file folder changed to leave lines before a header at the base level
	and thus avoid a vertical line when using connected folding symbols.
	</li>
	<li>
	GTK+ on Windows version uses Alt for rectangular selection to be compatible with
	platform convention.
	</li>
	<li>
	SciTE abbreviations file moved from system directory to user directory
	so each user can have separate abbreviations.
	</li>
	<li>
	SciTE on GTK+ has improved .desktop file and make install support that may
	lead to better integration with system shell.
	</li>
	<li>
	Disabling of themed background drawing on GTK+ extended to all cases.
	</li>
	<li>
	SciTE date formatting on Windows performed with the user setting rather than the
	system setting.
	</li>
	<li>
	GTK+ 2 redraw while scrolling fixed.
	</li>
	<li>
	Recursive property definitions are safer, avoiding expansion when detected.
	</li>
	<li>
	SciTE thread synchronization for scripts no longer uses HWND_MESSAGE
	so is compatible with older versions of Windows.
	Other Lua scripting bugs fixed.
	</li>
	<li>
	SciTE on Windows localisation of menu accelerators changed to be compatible
	with alternative UI themes.
	</li>
	<li>
	SciTE on Windows full screen mode now fits better when menu different height
	to title bar height.
	</li>
	<li>
	SC_MARK_EMPTY marker is now invisible and does not change the background
	colour.
	</li>
	<li>
	Bug fixed in HTML lexer to allow use of &lt;?xml in strings in scripts without
	triggering xml mode.
	</li>
	<li>
	Bug fixed in SciTE abbreviation expansion that could break indentation or crash.
	</li>
	<li>
	Bug fixed when searching for a whole word string that ends one character before
	end of document.
	</li>
	<li>
	Drawing bug fixed when indicators drawn on wrapped lines.
	</li>
	<li>
	Bug fixed when double clicking a hotspot.
	</li>
	<li>
	Bug fixed where autocompletion would remove typed text if no match found.
	</li>
	<li>
	Bug fixed where display does not scroll when inserting in long wrapped line.
	</li>
	<li>
	Bug fixed where SCI_MARKERDELETEALL would only remove one of the markers
	on a line that contained multiple markers with the same number.
	</li>
	<li>
	Bug fixed where markers would move when converting line endings.
	</li>
	<li>
	Bug fixed where SCI_LINEENDWRAP would move too far when line ends are visible.
	</li>
	<li>
	Bugs fixed where calltips with unicode or other non-ASCII text would display
	incorrectly.
	</li>
	<li>
	Bug fixed in determining if at save point after undoing from save point and then
	performing changes.
	</li>
	<li>
	Bug fixed on GTK+ using unsupported code pages where extraneous text could
	be drawn.
	</li>
	<li>
	Bug fixed in drag and drop code on Windows where dragging from SciTE to
	Firefox could hang both applications.
	</li>
	<li>
	Crashing bug fixed on GTK+ when no font allocation succeeds.
	</li>
	<li>
	Crashing bug fixed when autocompleting word longer than 1000 characters.
	</li>
	<li>
	SciTE crashing bug fixed when both Find and Replace dialogs shown by disallowing
	this situation.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite161.zip?download">Release 1.61</a>
    </h3>
    <ul>
	<li>
	Released on 29 May 2004.
	</li>
	<li>
	Improvements to selection handling on GTK+.
	</li>
	<li>
	SciTE on GTK+ 2.4 uses the improved file chooser which allows
	file extension filters, multiple selection, and remembers favourite
	directories.
	</li>
	<li>
	SciTE Load Session and Save Session commands available on GTK+.
	</li>
	<li>
	SciTE lists Lua Startup Script in Options menu when loaded.
	</li>
	<li>
	In SciTE, OnUserListSelection can be implemented in Lua.
	</li>
	<li>
	SciTE on Windows has a context menu on the file tabs.
	</li>
	<li>
	SQL lexer allows '#' comments and optionally '\' quoting inside strings.
	</li>
	<li>
	Mssql lexer improved.
	</li>
	<li>
	AutoIt3 lexer updated.
	</li>
	<li>
	Perl lexer recognises regular expression use better.
	</li>
	<li>
	Errorlist lexer understands Lua tracebacks and copes with findstr
	output for file names that end with digits.
	</li>
	<li>
	Drawing of lines on GTK+ improved and made more like Windows
	without final point.
	</li>
	<li>
	SciTE on GTK+ uses a high resolution window icon.
	</li>
	<li>
	SciTE can be set to warn before loading files larger than a particular size.
	</li>
	<li>
	SciTE Lua scripting bugs fixed included a crashing bug when using
	an undefined function name that would go before first actual name.
	</li>
	<li>
	SciTE bug fixed where a modified buffer was not saved if it was
	the last buffer and was not current when the New command used.
	</li>
	<li>
	SciTE monofont mode no longer affects line numbers.
	</li>
	<li>
	Crashing bug in SciTE avoided by not allowing both the Find and Replace
	dialogs to be visible at one time.
	</li>
	<li>
	Crashing bug in SciTE fixed when Lua scripts were being run
	concurrently.
	</li>
	<li>
	Bug fixed that caused incorrect line number width in SciTE.
	</li>
	<li>
	PHP folding bug fixed.
	</li>
	<li>
	Regression fixed when setting word characters to not include
	some of the standard word characters.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite160.zip?download">Release 1.60</a>
    </h3>
    <ul>
	<li>
	Released on 1 May 2004.
	</li>
	<li>
	SciTE can be scripted using the Lua programming language.
	</li>
	<li>
	command.mode is a better way to specify tool command options in SciTE.
	</li>
	<li>
	Continuation markers can be displayed so that you can see which lines are wrapped.
	</li>
	<li>
	Lexer for Gui4Cli language.
	</li>
	<li>
	Lexer for Kix language.
	</li>
	<li>
	Lexer for Specman E language.
	</li>
	<li>
	Lexer for AutoIt3 language.
	</li>
	<li>
	Lexer for APDL language.
	</li>
	<li>
	Lexer for Bash language. Also reasonable for other Unix shells.
	</li>
	<li>
	SciTE can load lexers implemented in external shared libraries.
	</li>
	<li>
	Perl treats "." not as part of an identifier and interprets '/' and '->'
	correctly in more circumstances.
	</li>
	<li>
	PHP recognises variables within strings.
	</li>
	<li>
	NSIS has properties "nsis.uservars" and "nsis.ignorecase".
	</li>
	<li>
	MSSQL lexer adds keyword list for operators and stored procedures,
	defines '(', ')', and ',' as operators and changes some other details.
	</li>
	<li>
	Input method preedit window on GTK+ 2 may support some Asian languages.
	</li>
	<li>
	Platform interface adds an extra platform-specific flag to Font::Create.
	Used on wxWidgets to choose antialiased text display but may be used for
	any task that a platform needs.
	</li>
	<li>
	OnBeforeSave method added to Extension interface.
	</li>
	<li>
	Scintilla methods that return strings can be called with a NULL pointer
	to find out how long the string should be.
	</li>
	<li>
	Visual Studio .NET project file now in VS .NET 2003 format so can not be used
	directly in VS .NET 2002.
	</li>
	<li>
	Scintilla can be built with GTK+ 2 on Windows.
	</li>
	<li>
	Updated RPM spec for SciTE on GTK+.
	</li>
	<li>
	GTK+ makefile for SciTE allows selection of destination directory, creates destination
	directories and sets file modes and owners better.
	</li>
	<li>
	Tab indents now go to next tab multiple rather than add tab size.
	</li>
	<li>
	SciTE abbreviations now use the longest possible match rather than the shortest.
	</li>
	<li>
	Autocompletion does not remove prefix when actioned with no choice selected.
	</li>
	<li>
	Autocompletion cancels when moving beyond the start position, not at the start position.
	</li>
	<li>
	SciTE now shows only calltips for functions that match exactly, not
	those that match as a prefix.
	</li>
	<li>
	SciTE can repair box comment sections where some lines were added without
	the box comment middle line prefix.
	</li>
	<li>
	Alt+ works in user.shortcuts on Windows.
	</li>
	<li>
	SciTE on GTK+ enables replace in selection for rectangular selections.
	</li>
	<li>
	Key bindings for command.shortcut implemented in a way that doesn't break
	when the menus are localised.
	</li>
	<li>
	Drawing of background on GTK+ faster as theme drawing disabled.
	</li>
	<li>
	On GTK+, calltips are moved back onto the screen if they extend beyond the screen bounds.
	</li>
	<li>
	On Windows, the Scintilla object is destroyed on WM_NCDESTROY rather than
	WM_DESTROY which arrives earlier. This fixes some problems when Scintilla was subclassed.
	</li>
	<li>
	The zorder switching feature removed due to number of crashing bugs.
	</li>
	<li>
	Code for XPM images made more robust.
	</li>
	<li>
	Bug fixed with primary selection on GTK+.
	</li>
	<li>
	On GTK+ 2, copied or cut text can still be pasted after the Scintilla widget is destroyed.
	</li>
	<li>
	Styling change not visible problem fixed when line was cached.
	</li>
	<li>
	Bug in SciTE on Windows fixed where clipboard commands stopped working.
	</li>
	<li>
	Crashing bugs in display fixed in line layout cache.
	</li>
	<li>
	Crashing bug may be fixed on AMD64 processor on GTK+.
	</li>
	<li>
	Rare hanging crash fixed in Python lexer.
	</li>
	<li>
	Display bugs fixed with DBCS characters on GTK+.
	</li>
	<li>
	Autocompletion lists on GTK+ 2 are not sorted by the ListModel as the
	contents are sorted correctly by Scintilla.
	</li>
	<li>
	SciTE fixed to not open extra untitled buffers with check.if.already.open.
	</li>
	<li>
	Sizing bug fixed on GTK+ when window resized while unmapped.
	</li>
	<li>
	Text drawing crashing bug fixed on GTK+ with non-Pango fonts and long strings.
	</li>
	<li>
	Fixed some issues if characters are unsigned.
	</li>
	<li>
	Fixes in NSIS support.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite159.zip?download">Release 1.59</a>
    </h3>
    <ul>
	<li>
	Released on 19 February 2004.
	</li>
	<li>
	SciTE Options and Language menus reduced in length by commenting
	out some languages. Languages can be enabled by editing the global
	properties file.
	</li>
	<li>
	Verilog language supported.
	</li>
	<li>
	Lexer for Microsoft dialect of SQL. SciTE properties file available from extras page.
	</li>
	<li>
	Perl lexer disambiguates '/' better.
	</li>
	<li>
	NSIS lexer improved with a lexical class for numbers, option for ignoring case
	of keywords, and folds only occurring when folding keyword first on line.
	</li>
	<li>
	PowerBasic lexer improved with styles for constants and assembler and
	folding improvements.
	</li>
	<li>
	On GTK+, input method support only invoked for Asian languages and not
	European languages as the old European keyboard code works better.
	</li>
	<li>
	Scintilla can be requested to allocate a certain amount and so avoid repeated
	reallocations and memory inefficiencies. SciTE uses this and so should require
	less memory.
	</li>
	<li>
	SciTE's "toggle current fold" works when invoked on child line as well as
	fold header.
	</li>
	<li>
	SciTE output pane scrolling can be set to not scroll back to start after
	completion of command.
	</li>
	<li>
	SciTE has a $(SessionPath) property.
	</li>
	<li>
	SciTE on Windows can use VK_* codes for keys in user.shortcuts.
	</li>
	<li>
	Stack overwrite bug fixed in SciTE's command to move to the end of a
	preprocessor conditional.
	</li>
	<li>
	Bug fixed where vertical selection appeared to select a different set of characters
	then would be used by, for example, a copy.
	</li>
	<li>
	SciTE memory leak fixed in fold state remembering.
	</li>
	<li>
	Bug fixed where changing the style of some text outside the
	standard StyleNeeded notification would not be visible.
	</li>
	<li>
	On GTK+ 2 g_iconv is used in preference to iconv, as it is provided by GTK+
	so should avoid problems finding the iconv library.
	</li>
	<li>
	On GTK+ fixed a style reference count bug.
	</li>
	<li>
	Memory corruption bug fixed with GetSelText.
	</li>
	<li>
	On Windows Scintilla deletes memory on WM_NCDESTROY rather than
	the earlier WM_DESTROY to avoid problems when the window is subclassed.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite158.zip?download">Release 1.58</a>
    </h3>
    <ul>
	<li>
	Released on 11 January 2004.
	</li>
	<li>
	Method to discover the currently highlighted element in an autocompletion list.
	</li>
	<li>
	On GTK+, the lexers are now included in the scintilla.a library file. This
	will require changes to the make files of dependent projects.
	</li>
	<li>
	Octave support added alongside related Matlab language and Matlab support improved.
	</li>
	<li>
	VB lexer gains an unterminated string state and 4 sets of keywords.
	</li>
	<li>
	Ruby lexer handles $' correctly.
	</li>
	<li>
	Error line handling improved for FORTRAN compilers from Absoft and Intel.
	</li>
	<li>
	International input enabled on GTK+ 2 although there is no way to choose an
	input method.
	</li>
	<li>
	MultiplexExtension in SciTE allows multiple extensions to be used at once.
	</li>
	<li>
	Regular expression replace interprets backslash expressions \a, \b, \f, \n, \r, \t,
	and \v in the replacement value.
	</li>
	<li>
	SciTE Replace dialog displays number of replacements made when Replace All or
	Replace in Selection performed.
	</li>
	<li>
	Localisation files may contain a translation.encoding setting which is used
	on GTK+ 2 to automatically reencode the translation to UTF-8 so it will be
	the localised text will be displayed correctly.
	</li>
	<li>
	SciTE on GTK+ implements check.if.already.open.
	</li>
	<li>
	Make files for Mac OS X made more robust.
	</li>
	<li>
	Performance improved in SciTE when switching buffers when there
	is a rectangular selection.
	</li>
	<li>
	Fixed failure to display some text when wrapped.
	</li>
	<li>
	SciTE crashes from Ctrl+Tab buffer cycling fixed.
	May still be some rare bugs here.
	</li>
	<li>
	Crash fixed when decoding an error message that appears similar to a
	Borland error message.
	</li>
	<li>
	Fix to auto-scrolling allows containers to implement enhanced double click selection.
	</li>
	<li>
	Hang fixed in idle word wrap.
	</li>
	<li>
	Crash fixed in hotspot display code..
	</li>
	<li>
	SciTE on Windows Incremental Search no longer moves caret back.
	</li>
	<li>
	SciTE hang fixed when performing a replace with a find string that
	matched zero length strings such as ".*".
	</li>
	<li>
	SciTE no longer styles the whole file when saving buffer fold state
	as that was slow.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite157.zip?download">Release 1.57</a>
    </h3>
    <ul>
	<li>
	Released on 27 November 2003.
	</li>
	<li>
	SciTE remembers folding of each buffer.
	</li>
	<li>
	Lexer for Erlang language.
	</li>
	<li>
	Scintilla allows setting the set of white space characters.
	</li>
	<li>
	Scintilla has 'stuttered' page movement commands to first move
	to top or bottom within current visible lines before scrolling.
	</li>
	<li>
	Scintilla commands for moving to end of words.
	</li>
	<li>
	Incremental line wrap enabled on Windows.
	</li>
	<li>
	SciTE PDF exporter produces output that is more compliant with reader
	applications, is smaller and allows more configuration.
	HTML exporter optimizes size of output files.
	</li>
	<li>
	SciTE defines properties PLAT_WINNT and PLAT_WIN95 on the
	corresponding platforms.
	</li>
	<li>
	SciTE can adjust the line margin width to fit the largest line number.
	The line.numbers property is split between line.margin.visible and
	line.margin.width.
	</li>
	<li>
	SciTE on GTK+ allows user defined menu accelerators.
	Alt can be included in user.shortcuts.
	</li>
	<li>
	SciTE Language menu can have items commented out.
	</li>
	<li>
	SciTE on Windows Go to dialog allows choosing a column number as
	well as a line number.
	</li>
	<li>
	SciTE on GTK+ make file uses prefix setting more consistently.
	</li>
	<li>
	Bug fixed that caused word wrapping to fail to display all text.
	</li>
	<li>
	Crashing bug fixed in GTK+ version of Scintilla when using GDK fonts
	and opening autocompletion.
	</li>
	<li>
	Bug fixed in Scintilla SCI_GETSELTEXT where an extra NUL
	was included at end of returned string
	</li>
	<li>
	Crashing bug fixed in SciTE z-order switching implementation.
	</li>
	<li>
	Hanging bug fixed in Perl lexer.
	</li>
	<li>
	SciTE crashing bug fixed for using 'case' without argument in style definition.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite156.zip?download">Release 1.56</a>
    </h3>
    <ul>
	<li>
	Released on 25 October 2003.
	</li>
	<li>
	Rectangular selection can be performed using the keyboard.
	Greater programmatic control over rectangular selection.
	This has caused several changes to key bindings.
	</li>
	<li>
	SciTE Replace In Selection works on rectangular selections.
	</li>
	<li>
	Improved lexer for TeX, new lexer for Metapost and other support for these
	languages.
	</li>
	<li>
	Lexer for PowerBasic.
	</li>
	<li>
	Lexer for Forth.
	</li>
	<li>
	YAML lexer improved to include error styling.
	</li>
	<li>
	Perl lexer improved to correctly handle more cases.
	</li>
	<li>
	Assembler lexer updated to support single-quote strings and fix some
	problems.
	</li>
	<li>
	SciTE on Windows can switch between buffers in order of use (z-order) rather
	than static order.
	</li>
	<li>
	SciTE supports adding an extension for "Open Selected Filename".
	The openpath setting works on GTK+.
	</li>
	<li>
	SciTE can Export as XML.
	</li>
	<li>
	SciTE $(SelHeight) variable gives a more natural result for empty and whole line
	selections.
	</li>
	<li>
	Fixes to wrapping problems, such as only first display line being visible in some
	cases.
	</li>
	<li>
	Fixes to hotspot to only highlight when over the hotspot, only use background
	colour when set and option to limit hotspots to a single line.
	</li>
	<li>
	Small fixes to FORTRAN lexing and folding.
	</li>
	<li>
	SQL lexer treats single quote strings as a separate class to double quote strings..
	</li>
	<li>
	Scintilla made compatible with expectations of container widget in GTK+ 2.3.
	</li>
	<li>
	Fix to strip out pixmap ID when automatically choosing from an autocompletion
	list with only one element.
	</li>
	<li>
	SciTE bug fixed where UTF-8 files longer than 128K were gaining more than one
	BOM.
	</li>
	<li>
	Crashing bug fixed in SciTE on GTK+ where using "Stop Executing" twice leads
	to all applications exiting.
	</li>
	<li>
	Bug fixed in autocompletion scrolling on GTK+ 2 with a case sensitive list.
	The ListBox::Sort method is no longer needed or available so platform
	maintainers should remove it.
	</li>
	<li>
	SciTE check.if.already.open setting removed from GTK+ version as unmaintained.
	</li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite155.zip?download">Release 1.55</a>
    </h3>
    <ul>
      <li>
	Released on 25 September 2003.
      </li>
      <li>
	Fix a crashing bug in indicator display in Scintilla.
      </li>
      <li>
	GTK+ version now defaults to building for GTK+ 2 rather than 1.
      </li>
      <li>
	Mingw make file detects compiler version and avoids options
	that are cause problems for some versions.
      </li>
      <li>
	Large performance improvement on GTK+ 2 for long lines.
      </li>
      <li>
	Incremental line wrap on GTK+.
      </li>
      <li>
	International text entry works much better on GTK+ with particular
	improvements for Baltic languages and languages that use 'dead' accents.
	NUL key events such as those generated by some function keys, ignored.
      </li>
      <li>
	Unicode clipboard support on GTK+.
      </li>
      <li>
	Indicator type INDIC_BOX draws a rectangle around the text.
      </li>
      <li>
	Clarion language support.
      </li>
      <li>
	YAML language support.
      </li>
      <li>
	MPT LOG language support.
      </li>
      <li>
	On Windows, SciTE can switch buffers based on activation order rather
	than buffer number.
      </li>
      <li>
	SciTE save.on.deactivate saves all buffers rather than just the current buffer.
      </li>
      <li>
	Lua lexer handles non-ASCII characters correctly.
      </li>
      <li>
	Error lexer understands Borland errors with pathnames that contain space.
      </li>
      <li>
	On GTK+ 2, autocompletion uses TreeView rather than deprecated CList.
      </li>
      <li>
	SciTE autocompletion removed when expand abbreviation command used.
      </li>
      <li>
	SciTE calltips support overloaded functions.
      </li>
      <li>
	When Save fails in SciTE, choice offered to Save As.
      </li>
      <li>
	SciTE message boxes on Windows may be moved to front when needed.
      </li>
      <li>
	Indicators drawn correctly on wrapped lines.
      </li>
      <li>
	Regular expression search no longer matches characters with high bit
	set to characters without high bit set.
      </li>
      <li>
	Hang fixed in backwards search in multi byte character documents.
      </li>
      <li>
	Hang fixed in SciTE Mark All command when wrap around turned off.
      </li>
      <li>
	SciTE Incremental Search no longer uses hot keys on Windows.
      </li>
      <li>
	Calltips draw non-ASCII characters correctly rather than as arrows.
      </li>
      <li>
	SciTE crash fixed when going to an error message with empty file name.
      </li>
      <li>
	Bugs fixed in XPM image handling code.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite154.zip?download">Release 1.54</a>
    </h3>
    <ul>
      <li>
	Released on 12 August 2003.
      </li>
      <li>
	SciTE on GTK+ 2.x can display a tab bar.
      </li>
      <li>
	SciTE on Windows provides incremental search.
      </li>
      <li>
	Lexer for PostScript.
      </li>
      <li>
	Lexer for the NSIS scripting language.
      </li>
      <li>
	New lexer for POV-Ray Scene Description Language
	replaces previous implementation.
      </li>
      <li>
	Lexer for the MMIX Assembler language.
      </li>
      <li>
	Lexer for the Scriptol language.
      </li>
      <li>
	Incompatibility: SQL keywords are specified in lower case rather than upper case.
	SQL lexer allows double quoted strings.
      </li>
      <li>
	Pascal lexer: character constants that start with '#' understood,
	'@' only allowed within assembler blocks,
	'$' can be the start of a number,
	initial '.' in 0..constant not treated as part of a number,
	and assembler blocks made more distinctive.
      </li>
      <li>
	Lua lexer allows '.' in keywords.
	Multi-line strings and comments can be folded.
      </li>
      <li>
	CSS lexer handles multiple psuedoclasses.
      </li>
      <li>
	Properties file folder works for INI file format.
      </li>
      <li>
	Hidden indicator style allows the container to mark text within Scintilla
	without there being any visual effect.
      </li>
      <li>
	SciTE does not prompt to save changes when the buffer is empty and untitled.
      </li>
      <li>
	Modification notifications caused by SCI_INSERTSTYLEDSTRING
	now include the contents of the insertion.
      </li>
      <li>
	SCI_MARKERDELETEALL deletes all the markers on a line
	rather than just the first match.
      </li>
      <li>
	Better handling of 'dead' accents on GTK+ 2 for languages
	that use accented characters.
      </li>
      <li>
	SciTE now uses value of output.vertical.size property.
      </li>
      <li>
	Crash fixed in SciTE autocompletion on long lines.
      </li>
      <li>
	Crash fixed in SciTE comment command on long lines.
      </li>
      <li>
	Bug fixed with backwards regular expression search skipping
	every second match.
      </li>
      <li>
	Hang fixed with regular expression replace where both target and replacement were empty.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite153.zip?download">Release 1.53</a>
    </h3>
    <ul>
      <li>
	Released on 16 May 2003.
      </li>
      <li>
	On GTK+ 2, encodings other than ASCII, Latin1, and Unicode are
	supported for both display and input using iconv.
      </li>
      <li>
	External lexers supported on GTK+/Linux.
	External lexers must now be explicitly loaded with SCI_LOADLEXERLIBRARY
	rather than relying upon a naming convention and automatic loading.
      </li>
      <li>
	Support of Lout typesetting language.
      </li>
      <li>
	Support of E-Scripts language used in the POL Ultima Online Emulator.
      </li>
      <li>
	Scrolling and drawing performance on GTK+ enhanced, particularly for GTK+ 2.x
	with an extra window for the text area avoiding conflicts with the scroll bars.
      </li>
      <li>
	CopyText and CopyRange methods in Scintilla allow container to
	easily copy to the system clipboard.
      </li>
      <li>
	Line Copy command implemented and bound to Ctrl+Shift+T.
      </li>
      <li>
	Scintilla APIs PositionBefore and PositionAfter can be used to iterate through
	a document taking into account the encoding and multi-byte characters.
      </li>
      <li>
	C++ folder can fold on the "} else {" line of an if statement by setting
	fold.at.else property to 1.
      </li>
      <li>
	C++ lexer allows an extra set of keywords.
      </li>
      <li>
	Property names and thus abbreviations may be non-ASCII.
      </li>
      <li>
	Removed attempt to load a file when setting properties that was
	part of an old scripting experiment.
      </li>
      <li>
	SciTE no longer warns about a file not existing when opening
	properties files from the Options menu as there is a good chance
	the user wants to create one.
      </li>
      <li>
	Bug fixed with brace recognition in multi-byte encoded files where a partial
	character matched a brace byte.
      </li>
      <li>
	More protection against infinite loops or recursion with recursive property definitions.
      </li>
      <li>
	On Windows, cursor will no longer disappear over margins in custom builds when
	cursor resource not present. The Windows default cursor is displayed instead.
      </li>
      <li>
	load.on.activate fixed in SciTE as was broken in 1.52.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite152.zip?download">Release 1.52</a>
    </h3>
    <ul>
      <li>
	Released on 17 April 2003.
      </li>
      <li>
	Pango font support on GTK+ 2.
	Unicode input improved on GTK+ 2.
      </li>
      <li>
	Hotspot style implemented in Scintilla.
      </li>
      <li>
	Small up and down arrows can be displayed in calltips and the container
	is notified when the mouse is clicked on a calltip.
	Normal and selected calltip text colours can be set.
      </li>
      <li>
	POSIX compatibility flag in Scintilla regular expression search
	interprets bare ( and ) as tagged sections.
      </li>
      <li>
	Error message lexer tightened to yield fewer false matches.
	Recognition of Lahey and Intel FORTRAN error formats.
      </li>
      <li>
	Scintilla keyboard commands for moving to start and end of
	screen lines rather than document lines, unless already there
	where these keys move to the start or end of the document line.
      </li>
      <li>
	Line joining command.
      </li>
      <li>
	Lexer for POV-Ray.
      </li>
      <li>
	Calltips on Windows are no longer clipped by the parent window.
      </li>
      <li>
	Autocompletion lists are cancelled when focus leaves their parent window.
      </li>
      <li>
	Move to next/previous empty line delimited paragraph key commands.
      </li>
      <li>
	SciTE hang fixed with recursive property definitions by placing limit
	on number of substitutions performed.
      </li>
      <li>
	SciTE Export as PDF reenabled and works.
      </li>
      <li>
	Added loadsession: command line command to SciTE.
      </li>
      <li>
	SciTE option to quit application when last document closed.
      </li>
      <li>
	SciTE option to ask user if it is OK to reload a file that has been
	modified outside SciTE.
      </li>
      <li>
	SciTE option to automatically save before running particular command tools
	or to ask user or to not save.
      </li>
      <li>
	SciTE on Windows 9x will write a Ctrl+Z to the process input pipe before
	closing the pipe when running tool commands that take input.
      </li>
      <li>
	Added a manifest resource to SciTE on Windows to enable Windows XP
	themed UI.
      </li>
      <li>
	SciTE calltips handle nested calls and other situations better.
      </li>
      <li>
	CSS lexer improved.
      </li>
      <li>
	Interface to platform layer changed - Surface initialisation now requires
	a WindowID parameter.
      </li>
      <li>
	Bug fixed with drawing or measuring long pieces of text on Windows 9x
	by truncating the pieces.
      </li>
      <li>
	Bug fixed with SciTE on GTK+ where a user shortcut for a visible character
	inserted the character as well as executing the command.
      </li>
      <li>
	Bug fixed where primary selection on GTK+ was reset by
	Scintilla during creation.
      </li>
      <li>
	Bug fixed where SciTE would close immediately on startup
	when using save.session.
      </li>
      <li>
	Crash fixed when entering '\' in LaTeX file.
      </li>
      <li>
	Hang fixed when '#' last character in VB file.
      </li>
      <li>
	Crash fixed in error message lexer.
      </li>
      <li>
	Crash fixed when searching for long regular expressions.
      </li>
      <li>
	Pressing return when nothing selected in user list sends notification with
	empty text rather than random text.
      </li>
      <li>
	Mouse debouncing disabled on Windows as it interfered with some
	mouse utilities.
      </li>
      <li>
	Bug fixed where overstrike mode inserted before rather than replaced last
	character in document.
      </li>
      <li>
	Bug fixed with syntax highlighting of Japanese text.
      </li>
      <li>
	Bug fixed in split lines function.
      </li>
      <li>
	Cosmetic fix to SciTE tab bar on Windows when window resized.
	Focus sticks to either pane more consistently.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite151.zip?download">Release 1.51</a>
    </h3>
    <ul>
      <li>
	Released on 16 February 2003.
      </li>
      <li>
	Two phase drawing avoids cutting off text that overlaps runs by drawing
	all the backgrounds of a line then drawing all the text transparently.
	Single phase drawing is an option.
      </li>
      <li>
	Scintilla method to split lines at a particular width by adding new line
	characters.
      </li>
      <li>
	The character used in autocompletion lists to separate the text from the image
	number can be changed.
      </li>
      <li>
	The scrollbar range will automatically expand when the caret is moved
	beyond the current range.
	The scroll bar is updated when SCI_SETXOFFSET is called.
      </li>
      <li>
	Mouse cursors on GTK+ improved to be consistent with other applications
	and the Windows version.
      </li>
      <li>
	Horizontal scrollbar on GTK+ now disappears in wrapped mode.
      </li>
      <li>
	Scintilla on GTK+ 2: mouse wheel scrolling, cursor over scrollbars, focus,
	and syntax highlighting now work.
	gtk_selection_notify avoided for compatibility with GTK+ 2.2.
      </li>
      <li>
	Fold margin colours can now be set.
      </li>
      <li>
	SciTE can be built for GTK+ 2.
      </li>
      <li>
	SciTE can optionally preserve the undo history over an automatic file reload.
      </li>
      <li>
	Tags can optionally be case insensitive in XML and HTML.
      </li>
      <li>
	SciTE on Windows handles input to tool commands in a way that should avoid
	deadlock. Output from tools can be used to replace the selection.
      </li>
      <li>
	SciTE on GTK+ automatically substitutes '|' for '/' in menu items as '/'
	is used to define the menu hierarchy.
      </li>
      <li>
	Optional buffer number in SciTE title bar.
      </li>
      <li>
	Crash fixed in SciTE brace matching.
      </li>
      <li>
	Bug fixed where automatic scrolling past end of document
	flipped back to the beginning.
      </li>
      <li>
	Bug fixed where wrapping caused text to disappear.
      </li>
      <li>
	Bug fixed on Windows where images in autocompletion lists were
	shown on the wrong item.
      </li>
      <li>
	Crash fixed due to memory bug in autocompletion lists on Windows.
      </li>
      <li>
	Crash fixed when double clicking some error messages.
      </li>
      <li>
	Bug fixed in word part movement where sometimes no movement would occur.
      </li>
      <li>
	Bug fixed on Windows NT where long text runs were truncated by
	treating NT differently to 9x where there is a limitation.
      </li>
      <li>
	Text in not-changeable style works better but there remain some cases where
	it is still possible to delete text protected this way.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite150.zip?download">Release 1.50</a>
    </h3>
    <ul>
      <li>
	Released on 24 January 2003.
      </li>
      <li>
	Autocompletion lists may have a per-item pixmap.
      </li>
      <li>
	Autocompletion lists allow Unicode text on Windows.
      </li>
      <li>
	Scintilla documentation rewritten.
      </li>
      <li>
	Additional DBCS encoding support in Scintilla on GTK+ primarily aimed at
	Japanese EUC encoding.
      </li>
      <li>
	CSS (Cascading Style Sheets) lexer added.
      </li>
      <li>
	diff lexer understands some more formats.
      </li>
      <li>
	Fold box feature is an alternative way to show the structure of code.
      </li>
      <li>
	Avenue lexer supports multiple keyword lists.
      </li>
      <li>
	The caret may now be made invisible by setting the caret width to 0.
      </li>
      <li>
	Python folder attaches comments before blocks to the next block rather
	than the previous block.
      </li>
      <li>
	SciTE openpath property on Windows searches a path for files that are
	the subject of the Open Selected Filename command.
      </li>
      <li>
        The localisation file name can be changed with the locale.properties property.
      </li>
      <li>
	On Windows, SciTE can pipe the result of a string expression into a command line tool.
      </li>
      <li>
	On Windows, SciTE's Find dialog has a Mark All button.
      </li>
      <li>
	On Windows, there is an Insert Abbreviation command that allows a choice from
	the defined abbreviations and inserts the selection into the abbreviation at the
	position of a '|'.
      </li>
      <li>
	Minor fixes to Fortran lexer.
      </li>
      <li>
	fold.html.preprocessor decides whether to fold &lt;? and ?&gt;.
	Minor improvements to PHP folding.
      </li>
      <li>
	Maximum number of keyword lists allowed increased from 6 to 9.
      </li>
      <li>
	Duplicate line command added with default assignment to Ctrl+D.
      </li>
      <li>
	SciTE sets $(Replacements) to the number of replacements made by the
	Replace All command. $(CurrentWord) is set to the word before the caret if the caret
	is at the end of a word.
      </li>
      <li>
	Opening a SciTE session now loads files in remembered order, sets the current file
	as remembered, and moves the caret to the remembered line.
      </li>
      <li>
	Bugs fixed with printing on Windows where line wrapping was causing some text
	to not print.
      </li>
      <li>
	Bug fixed with Korean Input Method Editor on Windows.
      </li>
      <li>
	Bugs fixed with line wrap which would sometimes choose different break positions
	after switching focus away and back.
      </li>
      <li>
	Bug fixed where wheel scrolling had no effect on GTK+ after opening a fold.
      </li>
      <li>
	Bug fixed with file paths containing non-ASCII characters on Windows.
      </li>
      <li>
	Crash fixed with printing on Windows after defining pixmap marker.
      </li>
      <li>
	Crash fixed in makefile lexer when first character on line was '='.
      </li>
      <li>
	Bug fixed where local properties were not always being applied.
      </li>
      <li>
	Ctrl+Keypad* fold command works on GTK+.
      </li>
      <li>
	Hangs fixed in SciTE's Replace All command when replacing regular expressions '^'
	or '$'.
      </li>
      <li>
	SciTE monospace setting behaves more sensibly.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite149.zip?download">Release 1.49</a>
    </h3>
    <ul>
      <li>
	Released on 1 November 2002.
      </li>
      <li>
	Unicode supported on GTK+. To perform well, this added a font cache to GTK+
	and to make that safe, a mutex is used. The mutex requires the application to link in
	the threading library by evaluating `glib-config --libs gthread`. A Unicode locale
	should also be set up by a call like setlocale(LC_CTYPE, "en_US.UTF-8").
	scintilla_release_resources function added to release mutex.
      </li>
      <li>
	FORTRAN and assembler lexers added along with other support for these
	languages in SciTE.
      </li>
      <li>
	Ada lexer improved handling of based numbers, identifier validity and attributes
	distinguished from character literals.
      </li>
      <li>
	Lua lexer handles block comments and a deep level of nesting for literal strings
	and block comments.
      </li>
      <li>
	Errorlist lexer recognises PHP error messages.
      </li>
      <li>
	Variant of the C++ lexer with case insensitive keywords
	called cppnocase. Whitespace in preprocessor text handled more correctly.
      </li>
      <li>
	Folder added for Perl.
      </li>
      <li>
	Compilation with GCC 3.2 supported.
      </li>
      <li>
	Markers can be pixmaps.
      </li>
      <li>
	Lines are wrapped when printing.
	Bug fixed which printed line numbers in different styles.
      </li>
      <li>
	Text can be appended to end with AppendText method.
      </li>
      <li>
	ChooseCaretX method added.
      </li>
      <li>
	Vertical scroll bar can be turned off with SetVScrollBar method.
      </li>
      <li>
	SciTE Save All command saves all buffers.
      </li>
      <li>
	SciTE localisation compares keys case insensitively to make translations more flexible.
      </li>
      <li>
	SciTE detects a utf-8 coding cookie "coding: utf-8" in first two
	lines and goes into Unicode mode.
      </li>
      <li>
	SciTE key bindings are definable.
      </li>
      <li>
	SciTE Find in Files dialog can display directory browser to
	choose directory to search.
      </li>
      <li>
	SciTE enabling of undo and redo toolbar buttons improved.
      </li>
      <li>
	SciTE on Windows file type filters in open dialog sorted.
      </li>
      <li>
	Fixed crashing bug when using automatic tag closing in XML or HTML.
      </li>
      <li>
	Fixed bug on Windows causing very long (&gt;64K) lines to not display.
      </li>
      <li>
	Fixed bug in backwards regular expression searching.
      </li>
      <li>
	Fixed bug in calltips where wrong argument was highlighted.
      </li>
      <li>
	Fixed bug in tab timmy feature when file has line feed line endings.
      </li>
      <li>
	Fixed bug in compiling without INCLUDE_DEPRECATED_FEATURES
	defined.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite148.zip?download">Release 1.48</a>
    </h3>
    <ul>
      <li>
	Released on 9 September 2002.
      </li>
      <li>
	Improved Pascal lexer with context sensitive keywords
	and separate folder which handles  //{ and //} folding comments and
	{$region} and {$end} folding directives.
	The "case" statement now folds correctly.
      </li>
      <li>
	C++ lexer correctly handles comments on preprocessor lines.
      </li>
      <li>
	New commands for moving to beginning and end of display lines when in line
	wrap mode. Key bindings added for these commands.
      </li>
      <li>
	New marker symbols that look like ">>>" and "..." which can be used for
	interactive shell prompts for Python.
      </li>
      <li>
	The foreground and background colours of visible whitespace can be chosen
	independent of the colours chosen for the lexical class of that whitespace.
      </li>
      <li>
	Per line data optimised by using an exponential allocation scheme.
      </li>
      <li>
	SciTE API file loading optimised.
      </li>
      <li>
	SciTE for GTK+ subsystem 2 documented. The exit status of commands
	is decoded into more understandable fields.
      </li>
      <li>
	SciTE find dialog remembers previous find string when there is no selection.
	Find in Selection button disabled when selection is rectangular as command
	did not work.
      </li>
      <li>
	Shift+Enter made equivalent to Enter to avoid users having to let go of
	the shift key when typing. Avoids the possibility of entering single carriage
	returns in a file that contains CR+LF line ends.
      </li>
      <li>
	Autocompletion does not immediately disappear when the length parameter
	to SCI_AUTOCSHOW is 0.
      </li>
      <li>
	SciTE focuses on the editor pane when File | New executed and when the
	output pane is closed with F8. Double clicking on a non-highlighted output
	pane line selects the word under the cursor rather than seeking the next
	highlighted line.
      </li>
      <li>
	SciTE director interface implements an "askproperty" command.
      </li>
      <li>
	SciTE's Export as LaTeX output improved.
      </li>
      <li>
	Better choice of autocompletion displaying above the caret rather then
	below when that is more sensible.
      </li>
      <li>
	Bug fixed where context menu would not be completely visible if invoked
	when cursor near bottom or left of screen.
      </li>
      <li>
	Crashing bug fixed when displaying long strings on GTK+ caused failure of X server
	by displaying long text in segments.
      </li>
      <li>
	Crashing bug fixed on GTK+ when a Scintilla window was removed from its parent
	but was still the selection owner.
      </li>
      <li>
	Bug fixed on Windows in Unicode mode where not all characters on a line
	were displayed when that line contained some characters not in ASCII.
      </li>
      <li>
	Crashing bug fixed in SciTE on Windows with clearing output while running command.
      </li>
      <li>
	Bug fixed in SciTE for GTK+ with command completion not detected when
	no output was produced by the command.
      </li>
      <li>
	Bug fixed in SciTE for Windows where menus were not shown translated.
      </li>
      <li>
	Bug fixed where words failed to display in line wrapping mode with visible
	line ends.
      </li>
      <li>
	Bug fixed in SciTE where files opened from a session file were not closed.
      </li>
      <li>
	Cosmetic flicker fixed when using Ctrl+Up and Ctrl+Down with some caret policies.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite147.zip?download">Release 1.47</a>
    </h3>
    <ul>
      <li>
	Released on 1 August 2002.
      </li>
      <li>
	Support for GTK+ 2 in Scintilla. International input methods not supported
	on GTK+2.
      </li>
      <li>
	Line wrapping performance improved greatly.
      </li>
      <li>
	New caret policy implementation that treats horizontal and vertical
	positioning equivalently and independently. Old caret policy methods
	deprecated and not all options work correctly with old methods.
      </li>
      <li>
	Extra fold points for C, C++, Java, ... for fold comments //{ .. //} and
	#if / #ifdef .. #endif and the #region .. #endregion feature of C#.
      </li>
      <li>
	Scintilla method to find the height in pixels of a line. Currently returns the
	same result for every line as all lines are same height.
      </li>
      <li>
	Separate make file, scintilla_vc6.mak, for Scintilla to use Visual C++
	version 6 since main makefile now assumes VS .NET.
	VS .NET project files available for combined Scintilla and
	SciTE in scite/boundscheck.
      </li>
      <li>
	SciTE automatically recognises Unicode files based
	on their Byte Order Marks and switches to Unicode mode.
	On Windows, where SciTE supports Unicode display, this
	allows display of non European characters.
	The file is saved back into the same character encoding unless
	the user decides to switch using the File | Encoding menu.
      </li>
      <li>
	Handling of character input changed so that a fillup character, typically '('
	displays a calltip when an autocompletion list was being displayed.
      </li>
      <li>
	Multiline strings lexed better for C++ and Lua.
      </li>
      <li>
	Regular expressions in JavaScript within hypertext files are lexed better.
      </li>
      <li>
	On Windows, Scintilla exports a function called Scintilla_DirectFunction
	that can be used the same as the function returned by GetDirectFunction.
      </li>
      <li>
	Scintilla converts line endings of text obtained from the clipboard to
	the current default line endings.
      </li>
      <li>
	New SciTE property ensure.final.line.end can ensure that saved files
	always end with a new line as this is required by some tools.
	The ensure.consistent.line.ends property ensures all line ends are the
	current default when saving files.
	The strip.trailing.spaces property now works on the buffer so the
	buffer in memory and the file on disk are the same after a save is performed.
      </li>
      <li>
	The SciTE expand abbreviation command again allows '|' characters
	in expansions to be quoted by using '||'.
      </li>
      <li>
	SciTE on Windows can send data to the find tool through standard
	input rather than using a command line argument to avoid problems
	with quoting command line arguments.
      </li>
      <li>
	The Stop Executing command in SciTE on Windows improved to send
	a Ctrl+Z character to the tool. Better messages when stopping a tool.
      </li>
      <li>
	Autocompletion can automatically "fill up" when one of a set of characters is
	type with the autocomplete.&lt;lexer&gt;.fillups property.
      </li>
      <li>
	New predefined properties in SciTE, SelectionStartColumn, SelectionStartLine,
	SelectionEndColumn, SelectionEndLine can be used to integrate with other
	applications.
      </li>
      <li>
	Environment variables are available as properties in SciTE.
      </li>
      <li>
	SciTE on Windows keeps status line more current.
      </li>
      <li>
	Abbreviations work in SciTE on Linux when first opened.
      </li>
      <li>
	File saving fixed in SciTE to ensure files are not closed when they can not be
	saved because of file permissions. Also fixed a problem with buffers that
	caused files to not be saved.
      </li>
      <li>
	SciTE bug fixed where monospace mode not remembered when saving files.
	Some searching options now remembered when switching files.
      </li>
      <li>
	SciTE on Linux now waits on child termination when it shuts a child down
	to avoid zombies.
      </li>
      <li>
	SciTE on Linux has a Print menu command that defaults to invoking a2ps.
      </li>
      <li>
	Fixed incorrect highlighting of indentation guides in SciTE for Python.
      </li>
      <li>
	Crash fixed in Scintilla when calling GetText for 0 characters.
      </li>
      <li>
	Exporting as LaTeX improved when processing backslashes and tabs
	and setting up font.
      </li>
      <li>
	Crash fixed in SciTE when exporting or copying as RTF.
      </li>
      <li>
	SciTE session loading fixed to handle more than 10 files in session.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite146.zip?download">Release 1.46</a>
    </h3>
    <ul>
      <li>
	Released on 10 May 2002.
      </li>
      <li>
	Set of lexers compiled into Scintilla can now be changed by adding and
	removing lexer source files from scintilla/src and running LexGen.py.
      </li>
      <li>
	SCN_ZOOM notification provided by Scintilla when user changes zoom level.
	Method to determine width of strings in pixels so that elements can be sized
	relative to text size.
	SciTE changed to keep line number column displaying a given
	number of characters.
      </li>
      <li>
	The logical width of the document used to determine scroll bar range can be set.
      </li>
      <li>
	Setting to allow vertical scrolling to display last line at top rather than
	bottom of window.
      </li>
      <li>
	Read-only mode improved to avoid changing the selection in most cases
	when a modification is attempted. Drag and drop cursors display correctly
	for read-only in some cases.
      </li>
      <li>
	Visual C++ options in make files changed to suit Visual Studio .NET.
      </li>
      <li>
	Scintilla.iface includes feature types for enumerations and lexers.
      </li>
      <li>
	Lua lexer improves handling of literal strings and copes with nested literal strings.
      </li>
      <li>
	Diff lexer changed to treat lines starting with "***" similarly to "---".
	Symbolic names defined for lexical classes.
      </li>
      <li>
	nncrontab lexer improved.
      </li>
      <li>
	Turkish fonts (iso8859-9) supported on GTK+.
      </li>
      <li>
	Automatic close tag feature for XML and HTML in SciTE.
      </li>
      <li>
	Automatic indentation in SciTE improved.
      </li>
      <li>
	Maximum number of buffers available in SciTE increased. May be up to 100
	although other restrictions on menu length limit the real maximum.
      </li>
      <li>
	Save a Copy command added to SciTE.
      </li>
      <li>
	Export as TeX command added to SciTE.
      </li>
      <li>
	Export as HTML command in SciTE respects Use Monospaced Font and
	background colour settings.
      </li>
      <li>
	Compilation problem on Solaris fixed.
      </li>
      <li>
	Order of files displayed for SciTE's previous and next menu and key commands
	are now consistent.
      </li>
      <li>
	Saving of MRU in recent file changed so files open when SciTE quit
	are remembered.
      </li>
      <li>
	More variants of ctags tags handled by Open Selected Filename in SciTE.
      </li>
      <li>
	JavaScript embedded in XML highlighted again.
      </li>
      <li>
	SciTE status bar updated after changing parameters in case they are being
	displayed in status bar.
      </li>
      <li>
	Crash fixed when handling some multi-byte languages.
      </li>
      <li>
	Crash fixed when replacing end of line characters.
      </li>
      <li>
	Bug in SciTE fixed in multiple buffer mode where automatic loading
	turned on could lead to losing file contents.
      </li>
      <li>
	Bug in SciTE on GTK+ fixed where dismissing dialogs with close box led to
	those dialogs never being shown again.
      </li>
      <li>
	Bug in SciTE on Windows fixed where position.tile with default positions
	led to SciTE being positioned off-screen.
      </li>
      <li>
	Bug fixed in read-only mode, clearing all deletes contraction state data
	leading to it not being synchronized with text.
      </li>
      <li>
	Crash fixed in SciTE on Windows when tab bar displayed.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite145.zip?download">Release 1.45</a>
    </h3>
    <ul>
      <li>
	Released on 15 March 2002.
      </li>
      <li>
	Line layout cache implemented to improve performance by maintaining
	the positioning of characters on lines. Can be set to cache nothing,
	the line with the caret, the visible page or the whole document.
      </li>
      <li>
	Support, including a new lexer, added for Matlab programs.
      </li>
      <li>
	Lua folder supports folding {} ranges and compact mode.
	Lua lexer styles floating point numbers in number style instead of
	setting the '.' in operator style.
	Up to 6 sets of keywords.
	Better support for [[ although only works well
	when all on one line.
      </li>
      <li>
	Python lexer improved to handle floating point numbers that contain negative
	exponents and that start with '.'.
      </li>
      <li>
	When performing a rectangular paste, the caret now remains at the
	insertion point.
      </li>
      <li>
	On Windows with a wheel mouse, page-at-a-time mode is recognised.
      </li>
      <li>
	Read-only mode added to SciTE with a property to initialise it and another property,
	$(ReadOnly) available to show this mode in the status bar.
      </li>
      <li>
	SciTE status bar can show the number of lines in the selection
	with the $(SelHeight) property.
      </li>
      <li>
	SciTE's "Export as HTML" command uses the current character set to produce
	correct output for non-Western-European character sets, such as Russian.
      </li>
      <li>
	SciTE's "Export as RTF" fixed to produce correct output when file contains '\'.
      </li>
      <li>
	SciTE goto command accepts a column as well as a line.
	If given a column, it selects the word at that column.
      </li>
      <li>
	SciTE's Build, Compile and Go commands are now disabled if no
	action has been assigned to them.
      </li>
      <li>
	The Refresh button in the status bar has been removed from SciTE on Windows.
      </li>
      <li>
	Bug fixed in line wrap mode where cursor up or down command did not work.
      </li>
      <li>
	Some styling bugs fixed that were due to a compilation problem with
	gcc and inline functions with same name but different code.
      </li>
      <li>
	The way that lexers loop over text was changed to avoid accessing beyond the
	end or setting beyond the end. May fix some bugs and make the code safer but
	may also cause new bugs.
      </li>
      <li>
	Bug fixed in HTML lexer's handling of SGML.
      </li>
      <li>
	Bug fixed on GTK+/X where lines wider than 32767 pixels did not display.
      </li>
      <li>
	SciTE bug fixed with file name generation for standard property files.
      </li>
      <li>
	SciTE bug fixed with Open Selected Filename command when used with
	file name and line number combination.
      </li>
      <li>
	In SciTE, indentation and tab settings stored with buffers so maintained correctly
	as buffers selected.
	The properties used to initialise these settings can now be set separately for different
	file patterns.
      </li>
      <li>
	Thread safety improved on Windows with a critical section protecting the font
	cache and initialisation of globals performed within Scintilla_RegisterClasses.
	New Scintilla_ReleaseResources call provided to allow explicit freeing of resources
	when statically bound into another application. Resources automatically freed
	in DLL version. The window classes are now unregistered as part of resource
	freeing which fixes bugs that occurred in some containers such as Internet Explorer.
      </li>
      <li>
	'make install' fixed on Solaris.
      </li>
      <li>
	Bug fixed that could lead to a file being opened twice in SciTE.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite144.zip?download">Release 1.44</a>
    </h3>
    <ul>
      <li>
	Released on 4 February 2002.
      </li>
      <li>
	Crashing bug fixed in Editor::Paint.
      </li>
      <li>
	Lua lexer no longer treats '.' as a word character and
	handles 6 keyword sets.
      </li>
      <li>
	WordStartPosition and WordEndPosition take an onlyWordCharacters
	argument.
      </li>
      <li>
	SciTE option for simplified automatic indentation which repeats
	the indentation of the previous line.
      </li>
      <li>
	Compilation fix on Alpha because of 64 bit.
      </li>
      <li>
	Compilation fix for static linking.
      </li>
      <li>
	Limited maximum line length handled to 8000 characters as previous
	value of 16000 was causing stack exhaustion crashes for some.
      </li>
      <li>
	When whole document line selected, only the last display line gets
	the extra selected rectangle at the right hand side rather than
	every display line.
      </li>
      <li>
	Caret disappearing bug fixed for the case that the caret was not on the
	first display line of a document line.
      </li>
      <li>
	SciTE bug fixed where untitled buffer containing text was sometimes
	deleted without chance to save.
      </li>
      <li>
	SciTE bug fixed where use.monospaced not working with
	multiple buffers.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite143.zip?download">Release 1.43</a>
    </h3>
    <ul>
      <li>
	Released on 19 January 2002.
      </li>
      <li>
	Line wrapping robustness and performance improved in Scintilla.
      </li>
      <li>
	Line wrapping option added to SciTE for both edit and output panes.
      </li>
      <li>
	Static linking on Windows handles cursor resource better.
	Documentation of static linking improved.
      </li>
      <li>
	Autocompletion has an option to delete any word characters after the caret
	upon selecting an item.
      </li>
      <li>
	FOX version identified by PLAT_FOX in Platform.h.
      </li>
      <li>
	Calltips in SciTE use the calltip.&lt;lexer&gt;.word.characters setting to
	correctly find calltips for functions that include characters like '$' which
	is not normally considered a word character.
      </li>
      <li>
	SciTE has a command to show help on itself which gets hooked up to displaying
	SciTEDoc.html.
      </li>
      <li>
	SciTE option calltip.&lt;lexer&gt;.end.definition to display help text on a
	second line of calltip.
      </li>
      <li>
	Fixed the handling of the Buffers menu on GTK+ to ensure current buffer
	indicated and no warnings occur.
	Changed some menu items on GTK+ version to be same as Windows version.
      </li>
      <li>
	use.monospaced property for SciTE determines initial state of Use Monospaced Font
	setting.
      </li>
      <li>
	The SciTE Complete Symbol command now works when there are no word
	characters before the caret, even though it is slow to display the whole set of
	symbols.
      </li>
      <li>
	Function names removed from SciTE's list of PHP keywords. The full list of
	predefined functions is available from another web site mentioned on the
	Extras page.
      </li>
      <li>
	Crashing bug at startup on GTK+ for some configurations fixed.
      </li>
      <li>
	Crashing bug on GTK+ on 64 bit platforms fixed.
      </li>
      <li>
	Compilation problem with some compilers fixed in GTK+.
      </li>
      <li>
	Japanese text entry improved on Windows 9x.
      </li>
      <li>
        SciTE recent files directory problem on Windows when HOME and SciTE_HOME
	environment variables not set is now the directory of the executable.
      </li>
      <li>
	Session files no longer include untitled buffers.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite142.zip?download">Release 1.42</a>
    </h3>
    <ul>
      <li>
	Released on 24 December 2001.
      </li>
      <li>
	Better localisation support including context menus and most messages.
	Translations of the SciTE user interface available for Bulgarian,
	French, German, Italian, Russian, and Turkish.
      </li>
      <li>
	Can specify a character to use to indicate control characters
	rather than having them displayed as mnemonics.
      </li>
      <li>
	Scintilla key command for backspace that will not delete line
	end characters.
      </li>
      <li>
	Scintilla method to find start and end of words.
      </li>
      <li>
	SciTE on GTK+ now supports the load.on.activate and save.on.deactivate
	properties in an equivalent way to the Windows version.
      </li>
      <li>
	The output pane of SciTE on Windows is now interactive so command line
	utilities that prompt for input or confirmation can be used.
      </li>
      <li>
	SciTE on Windows can choose directory for a "Find in Files"
	command like the GTK+ version could.
      </li>
      <li>
	SciTE can now load a set of API files rather than just one file.
      </li>
      <li>
	ElapsedTime class added to Platform for accurate measurement of durations.
	Used for debugging and for showing the user how long commands take in SciTE.
      </li>
      <li>
	Baan lexer added.
      </li>
      <li>
	In C++ lexer, document comment keywords no longer have to be at the start
	of the line.
      </li>
      <li>
	PHP lexer changed to match keywords case insensitively.
      </li>
      <li>
	More shell keywords added.
      </li>
      <li>
	SciTE support for VoiceXML added to xml.properties.
      </li>
       <li>
	In SciTE the selection is not copied to the find field of the Search and Replace
	dialogs if it contains end of line characters.
      </li>
      <li>
	SciTE on Windows has a menu item to decide whether to respond to other
	instances which are performing their check.if.already.open check.
      </li>
      <li>
	SciTE accelerator key for Box Comment command changed to avoid problems
	in non-English locales.
      </li>
      <li>
	SciTE context menu includes Close command for the editor pane and
	Hide command for the output pane.
      </li>
      <li>
	output: command added to SciTE director interface to add text to the
	output pane. The director interface can execute commands (such as tool
	commands with subsystem set to 3) by sending a macro:run message.
      </li>
      <li>
	SciTE on GTK+ will defer to the Window Manager for position if position.left or
	position.top not set and for size if position.width or position.height not set.
      </li>
      <li>
	SciTE on Windows has a position.tile property to place a second instance
	to the right of the first.
      </li>
      <li>
	 Scintilla on Windows again supports EM_GETSEL and EM_SETSEL.
      </li>
      <li>
	Problem fixed in Scintilla on Windows where control ID is no longer cached
	as it could be changed by external code.
      </li>
      <li>
	Problems fixed in SciTE on Windows when finding any other open instances at
	start up when check.if.already.open is true.
      </li>
      <li>
	Bugs fixed in SciTE where command strings were not always having
	variables evaluated.
      </li>
      <li>
	Bugs fixed with displaying partial double-byte and Unicode characters
	in rectangular selections and at the edge when edge mode is EDGE_BACKGROUND.
	Column numbers reported by GetColumn treat multiple byte characters as one column
	rather than counting bytes.
      </li>
      <li>
	Bug fixed with caret movement over folded lines.
      </li>
      <li>
        Another bug fixed with tracking selection in secondary views when performing
	modifications.
      </li>
      <li>
	Horizontal scrolling and display of long lines optimised.
      </li>
      <li>
	Cursor setting in Scintilla on GTK+ optimised.
      </li>
      <li>
	Experimental changeable style attribute.
	Set to false to make text read-only.
	Currently only stops caret from being within not-changeable
	text and does not yet stop deleting a range that contains
	not-changeable text.
	Can be used from SciTE by adding notchangeable to style entries.
      </li>
      <li>
	Experimental line wrapping.
	Currently has performance and appearence problems.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite141.zip?download">Release 1.41</a>
    </h3>
    <ul>
      <li>
	Released on 6 November 2001.
      </li>
      <li>
        Changed Platform.h to not include platform	headers. This lessens likelihood and impact of
	name clashes from system headers and also speeds up compilation.
	Renamed DrawText to DrawTextNoClip to avoid name clash.
      </li>
      <li>
        Changed way word functions work to treat a sequence of punctuation as
	a word. This is more sensible and also more compatible with other editors.
      </li>
      <li>
        Cursor changes over the margins and selection on GTK+ platform.
      </li>
      <li>
        SC_MARK_BACKGROUND is a marker that only changes the line's background colour.
      </li>
      <li>
	Enhanced Visual Basic lexer handles character date and octal literals,
	and bracketed keywords for VB.NET. There are two VB lexers, vb and vbscript
	with type indication characters like ! and $ allowed at the end of identifiers
	in vb but not vbscript. Lexer states now separate from those used for C++ and
	names start with SCE_B.
      </li>
      <li>
         Lexer added for Bullant language.
      </li>
      <li>
         The horizontal scroll position, xOffset, is now exposed through the API.
      </li>
      <li>
         The SCN_POSCHANGED notification is deprecated as it was causing confusion.
	 Use SCN_UPDATEUI  instead.
      </li>
      <li>
         Compilation problems fixed for some versions of gcc.
      </li>
      <li>
        Support for WM_GETTEXT restored on Windows.
      </li>
      <li>
        Double clicking on an autocompletion list entry works on GTK+.
      </li>
      <li>
        Bug fixed with case insensitive sorts for autocompletion lists.
      </li>
      <li>
        Bug fixed with tracking selection in secondary views when performing modifications.
      </li>
      <li>
        SciTE's abbreviation expansion feature will now indent expansions to the current
	indentation level if indent.automatic is on.
      </li>
      <li>
        SciTE allows setting up of parameters to commands from a dialog and can also
       show this dialog automatically to prompt for arguments when running a command.
      </li>
      <li>
        SciTE's Language menu (formerly Options | Use Lexer) is now defined by the
	menu.language property rather than being hardcoded.
      </li>
      <li>
        The user interface of SciTE can be localised to a particular language by editing
	a locale.properties file.
      </li>
      <li>
        On Windows, SciTE will try to move to the front when opening a new file from
	the shell and using check.if.already.open.
      </li>
      <li>
        SciTE can display the file name and directory in the title bar in the form
	"file @ directory" when title.full.path=2.
      </li>
      <li>
        The SciTE time.commands property reports the time taken by a command as well
	as its status when completed.
      </li>
      <li>
        The SciTE find.files property is now a list separated by '|' characters and this list is
	added into the Files pull down of the Find in Files dialog.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite140.zip?download">Release 1.40</a>
    </h3>
    <ul>
      <li>
	Released on 23 September 2001.
      </li>
      <li>
	Removal of emulation of Win32 RichEdit control in core of Scintilla.
	<em>This change may be incompatible with existing client code.</em>
	Some emulation still done in Windows platform layer.
      </li>
      <li>
	SGML support in the HTML/XML lexer.
      </li>
      <li>
	SciTE's "Stop Executing" command will terminate GUI programs on
	Windows NT and Windows 2000.
      </li>
      <li>
	StyleContext class helps construct lexers that are simple and accurate.
	Used in the C++, Eiffel, and Python lexers.
      </li>
      <li>
	Clipboard operations in GTK+ version convert between platform '\n' line endings and
	currently chosen line endings.
      </li>
      <li>
	Any character in range 0..255 can be used as a marker.
	This can be used to support numbered bookmarks, for example.
      </li>
      <li>
	The default scripting language for ASP can be set.
      </li>
      <li>
	New lexer and other support for crontab files used with the nncron scheduler.
      </li>
      <li>
	Folding of Python improved.
      </li>
      <li>
	The ` character is treated as a Python operator.
      </li>
      <li>
	Line continuations ("\" at end of line) handled inside Python strings.
      </li>
      <li>
	More consistent handling of line continuation ('\' at end of line) in
	C++ lexer.
	This fixes macro definitions that span more than one line.
      </li>
      <li>
	C++ lexer can understand Doxygen keywords in doc comments.
      </li>
      <li>
	SciTE on Windows allows choosing to open the "open" dialog on the directory
	of the current file rather than in the default directory.
      </li>
      <li>
	SciTE on Windows handles command line arguments in "check.if.already.open"
	correctly when the current directory of the new instance is different to the
	already open instance of SciTE.
      </li>
      <li>
	"cwd" command (change working directory) defined for SciTE director interface.
      </li>
      <li>
	SciTE "Export As HTML" produces better, more compliant, and shorter files.
      </li>
      <li>
	SciTE on Windows allows several options for determining default file name
	for exported files.
      </li>
      <li>
	Automatic indentation of Python in SciTE fixed.
      </li>
      <li>
	Exported HTML can support folding.
      </li>
      <li>
	Bug fixed in SCI_GETTEXT macro command of director interface.
      </li>
      <li>
	Cursor leak fixed on GTK+.
      </li>
      <li>
	During SciTE shutdown, "identity" messages are no longer sent over the director interface.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite139.zip?download">Release 1.39</a>
    </h3>
    <ul>
      <li>
	Released on 22 August 2001.
      </li>
      <li>
	Windows version requires msvcrt.dll to be available so will not work
	on original Windows 95 version 1. The msvcrt.dll file is installed
	by almost everything including Internet Explorer so should be available.
      </li>
      <li>
	Flattened tree control style folding margin. The SciTE fold.plus option is
	now fold.symbols and has more values for the new styles.
      </li>
      <li>
	Mouse dwell events are generated when the user holds the mouse steady
	over Scintilla.
      </li>
      <li>
      PositionFromPointClose is like PositionFromPoint but returns
      INVALID_POSITION when point outside window or after end of line.
      </li>
      <li>
      Input of Hungarian and Russian characters in GTK+ version works by
      truncating input to 8 bits if in the range of normal characters.
      </li>
      <li>
      Better choices for font descriptors on GTK+ for most character sets.
      </li>
      <li>
      GTK+ Scintilla is destroyed upon receiving destroy signal rather than
      destroy_event signal.
      </li>
      <li>
      Style setting that force upper or lower case text.
      </li>
      <li>
      Case-insensitive autocompletion lists work correctly.
      </li>
      <li>
      Keywords can be prefix based so ^GTK_ will treat all words that start
      with GTK_ as keywords.
      </li>
      <li>
      Horizontal scrolling can be jumpy rather than gradual.
      </li>
      <li>
      GetSelText places a '\0' in the buffer if the selection is empty..
      </li>
      <li>
      EnsureVisible split into two methods EnsureVisible which will not scroll to show
      the line and EnsureVisibleEnforcePolicy which may scroll.
      </li>
      <li>
      Python folder has options to fold multi-line comments and triple quoted strings.
      </li>
      <li>
      C++ lexer handles keywords before '.' like "this.x" in Java as keywords.
      Compact folding mode option chooses whether blank lines after a structure are
      folded with that structure. Second set of keywords with separate style supported.
      </li>
      <li>
      Ruby lexer handles multi-line comments.
      </li>
      <li>
      VB has folder.
      </li>
      <li>
      PHP lexer has an operator style, handles "&lt;?" and "?&gt;" inside strings
      and some comments.
      </li>
      <li>
      TCL lexer which is just an alias for the C++ lexer so does not really
      understand TCL syntax.
      </li>
      <li>
      Error lines lexer has styles for Lua error messages and .NET stack traces.
      </li>
      <li>
      Makefile lexer has a target style.
      </li>
      <li>
      Lua lexer handles some [[]] string literals.
      </li>
      <li>
      HTML and XML lexer have a SCE_H_SGML state for tags that
      start with "&lt;!".
      </li>
      <li>
      Fixed Scintilla bugs with folding. When modifications were performed near
      folded regions sometimes no unfolding occurred when it should have. Deleting a
      fold causing character sometimes failed to update fold information correctly.
      </li>
      <li>
      Better support for Scintilla on GTK+ for Win32 including separate
      PLAT_GTK_WIN32 definition and correct handling of rectangular selection
      with clipboard operations.
      </li>
      <li>
      SciTE has a Tools | Switch Pane (Ctrl+F6) command to switch focus between
      edit and output panes.
      </li>
      <li>
      SciTE option output.scroll allows automatic scrolling of output pane to
      be turned off.
      </li>
      <li>
      Commands can be typed into the SciTE output pane similar to a shell window.
      </li>
      <li>
      SciTE properties magnification and output magnification set initial zoom levels.
      </li>
      <li>
      Option for SciTE comment block command to place comments at start of line.
      </li>
      <li>
       SciTE for Win32 has an option to minimize to the tray rather than the task bar.
      </li>
      <li>
      Close button on SciTE tool bar for Win32.
      </li>
      <li>
      SciTE compiles with GCC 3.0.
      </li>
      <li>
      SciTE's automatic indentation of C++ handles braces without preceding keyword
      correctly.
      </li>
      <li>
      Bug fixed with GetLine method writing past the end of where it should.
      </li>
      <li>
      Bug fixed with mouse drag automatic scrolling when some lines were folded.
      </li>
      <li>
      Bug fixed because caret XEven setting was inverted.
      </li>
      <li>
      Bug fixed where caret was initially visible even though window was not focussed.
      </li>
      <li>
      Bug fixed where some file names could end with "\\" which caused slow
      downs on Windows 9x.
      </li>
      <li>
      On Win32, SciTE Replace dialog starts with focus on replacement text.
      </li>
      <li>
      SciTE Go to dialog displays correct current line.
      </li>
      <li>
      Fixed bug with SciTE opening multiple files at once.
      </li>
      <li>
      Fixed bug with Unicode key values reported to container truncated.
      </li>
      <li>
      Fixed bug with unnecessary save point notifications.
      </li>
      <li>
      Fixed bugs with indenting and unindenting at start of line.
      </li>
      <li>
      Monospace Font setting behaves more consistently.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite138.zip?download">Release 1.38</a>
    </h3>
    <ul>
      <li>
	Released on 23 May 2001.
      </li>
      <li>
	Loadable lexer plugins on Windows.
      </li>
      <li>
	Ruby lexer and support.
      </li>
      <li>
	Lisp lexer and support.
      </li>
      <li>
	Eiffel lexer and support.
      </li>
      <li>
	Modes for better handling of Tab and BackSpace keys within
	indentation. Mode to avoid autocompletion list cancelling when
	there are no viable matches.
      </li>
      <li>
	ReplaceTarget replaced with two calls ReplaceTarget
	(which is incompatible with previous ReplaceTarget) and
	ReplaceTargetRE. Both of these calls have a count first
	parameter which allows using strings containing nulls.
	SearchInTarget and SetSearchFlags functions allow
	specifying a search in several simple steps which helps
	some clients which can not create structs or pointers easily.
      </li>
      <li>
	Asian language input through an Input Method Editor works
	on Windows 2000.
      </li>
      <li>
	On Windows, control characters can be entered through use of
	the numeric keypad in conjunction with the Alt key.
      </li>
      <li>
	Document memory allocation changed to grow exponentially
	which reduced time to load a 30 Megabyte file from
	1000 seconds to 25. Change means more memory may be used.
      </li>
      <li>
	Word part movement keys now handled in Scintilla rather than
	SciTE.
      </li>
      <li>
	Regular expression '^' and '$' work more often allowing insertion
	of text at start or end of line with a replace command.
	Backslash quoted control characters \a, \b, \f, \t, and \v
	recognised within sets.
      </li>
      <li>
	Session files for SciTE.
      </li>
      <li>
	Export as PDF command hidden in SciTE as it often failed.
	Code still present so can be turned on by those willing to cope.
      </li>
      <li>
	Bug fixed in HTML lexer handling % before &gt; as end ASP
	even when no start ASP encountered.
        Bug fixed when scripts ended with a quoted string and
        end tag was not seen.
      </li>
      <li>
	Bug fixed on Windows where context menu key caused menu to
	appear in corner of screen rather than within window.
      </li>
      <li>
	Bug fixed in SciTE's Replace All command not processing
	whole file when replace string longer than search string.
      </li>
      <li>
	Bug fixed in SciTE's MRU list repeating entries if Ctrl+Tab
	used when all entries filled.
      </li>
      <li>
	ConvertEOLs call documentation fixed.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite137.zip?download">Release 1.37</a>
    </h3>
    <ul>
      <li>
	Released on 17 April 2001.
      </li>
      <li>
	Bug fixed with scroll bars being invisible on GTK+ 1.2.9.
      </li>
      <li>
	Scintilla and SciTE support find and replace using simple regular
	expressions with tagged expressions. SciTE supports C '\' escapes
	in the Find and Replace dialogs.
	Replace in Selection available in SciTE.
      </li>
      <li>
	Scintilla has a 'target' feature for replacing code rapidly without
	causing display updates.
      </li>
      <li>
	Scintilla and SciTE on GTK+ support file dropping from file managers
	such as Nautilus and gmc. Files or other URIs dropped on Scintilla
	result in a URIDropped notification.
      </li>
      <li>
	Lexers may have separate Lex and Fold functions.
      </li>
      <li>
	Lexer infrastructure improved to allow for plug in lexers and for referring
	to lexers by name rather than by ID.
      </li>
      <li>
	Ada lexer and support added.
      </li>
      <li>
	Option in both Scintilla and SciTE to treat both left and right margin
	as equally important when repositioning visible area in response to
	caret movement. Default is to prefer visible area positioning which
	minimises the horizontal scroll position thus favouring the left margin.
      </li>
      <li>
	Caret line highlighting.
      </li>
      <li>
	Commands to delete from the caret to the end of line and
	from the caret to the beginning of line.
      </li>
      <li>
	SciTE has commands for inserting and removing block comments and
	for inserting stream comments.
      </li>
      <li>
	SciTE Director interface uses C++ '\' escapes to send control characters.
      </li>
      <li>
	SciTE Director interface adds more commands including support for macros.
      </li>
      <li>
	SciTE has menu options for recording and playing macros which are visible
	when used with a companion program that supports these features.
      </li>
      <li>
	SciTE has an Expand Abbreviation command.
	Abbreviations are stored in a global abbrev.properties file.
      </li>
      <li>
	SciTE has a Full Screen command to switch between a normal window
	size and using the full screen. On Windows, the menu bar can be turned
	off when in full screen mode.
      </li>
      <li>
	SciTE has a Use monospaced font command to switch between the normal
	set of fonts and one size of a particular fixed width font.
      </li>
      <li>
	SciTE's use of tabs can be controlled for particular file names
	as well as globally.
      </li>
      <li>
	The contents of SciTE's status bar can be defined by a property and
	include variables. On Windows, several status bar definitions can be active
	with a click on the status bar cycling through them.
      </li>
      <li>
	Copy as RTF command in SciTE on Windows to allow pasting
	styled text into word processors.
      </li>
      <li>
	SciTE can allow the use of non-alphabetic characters in
	Complete Symbol lists and can automatically display this autocompletion
	list when a trigger character such as '.' is typed.
	Complete word can be set to pop up when the user is typing a word and
	there is only one matching word in the document.
      </li>
      <li>
	SciTE lists the imported properties files on a menu to allow rapid
	access to them.
      </li>
      <li>
	SciTE on GTK+ improvements to handling accelerator keys and focus
	in dialogs. Message boxes respond to key presses without the Alt key as
	they have no text entries to accept normal keystrokes.
      </li>
      <li>
	SciTE on GTK+ sets the application icon.
      </li>
      <li>
	SciTE allows setting the colours used to indicate the current
	error line.
      </li>
      <li>
	Variables within PHP strings have own style. Keyword list updated.
      </li>
      <li>
	Keyword list for Lua updated for Lua 4.0.
      </li>
      <li>
	Bug fixed in rectangular selection where rectangle still appeared
	selected after using cursor keys to move caret.
      </li>
      <li>
	Bug fixed in C++ lexer when deleting a '{' controlling a folded range
	led to that range becoming permanently invisible.
      </li>
      <li>
	Bug fixed in Batch lexer where comments were not recognised.
      </li>
      <li>
	Bug fixed with undo actions coalescing into steps incorrectly.
      </li>
      <li>
	Bug fixed with Scintilla on GTK+ positioning scroll bars 1 pixel
	over the Scintilla window leading to their sides being chopped off.
      </li>
      <li>
	Bugs fixed in SciTE when doing some actions led to the start
	or end of the file being displayed rather than the current location.
      </li>
      <li>
	Appearance of calltips fixed to look like document text including
	any zoom factor. Positioned to be outside current line even when
	multiple fonts and sizes used.
      </li>
      <li>
	Bug fixed in Scintilla macro support where typing Enter caused both a newline
	command and newline character insertion to be recorded.
      </li>
      <li>
	Bug fixed in SciTE on GTK+ where focus was moving
	between widgets incorrectly.
      </li>
      <li>
	Bug fixed with fold symbols sometimes not updating when
	the text changed.
      </li>
      <li>
	Bugs fixed in SciTE's handling of folding commands.
      </li>
      <li>
	Deprecated undo collection enumeration removed from API.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite136.zip?download">Release 1.36</a>
    </h3>
    <ul>
      <li>
	Released on 1 March 2001.
      </li>
      <li>
	Scintilla supports GTK+ on Win32.
      </li>
      <li>
	Some untested work on making Scintilla and SciTE 64 bit compatible.
	For users on GTK+ this requires including Scintilla.h before
	ScintillaWidget.h.
      </li>
      <li>
	HTML lexer allows folding HTML.
      </li>
      <li>
	New lexer for Avenue files which are used in the ESRI ArcView GIS.
      </li>
      <li>
	DOS Batch file lexer has states for '@', external commands, variables and
	operators.
      </li>
      <li>
	C++ lexer can fold comments of /* .. */ form.
      </li>
      <li>
	Better disabling of pop up menu items in Scintilla when in read-only mode.
      </li>
      <li>
	Starting to move to Doxygen compatible commenting.
      </li>
      <li>
	Director interface on Windows enables another application to control SciTE.
      </li>
      <li>
	Opening SciTE on Windows 9x sped up greatly for some cases.
      </li>
      <li>
	The command.build.directory property allows SciTE to run the build
	command in a different directory to the source files.
      </li>
      <li>
	SciTE on Windows allows setting foreground and background colours
	for printed headers and footers.
      </li>
      <li>
	Bug fixed in finding calltips in SciTE which led to no calltips for some identifiers.
      </li>
      <li>
	Documentation added for lexers and for the extension and director interfaces.
      </li>
      <li>
	SciTE menus rearranged with new View menu taking over some of the items that
	were under the Options menu. Clear All Bookmarks command added.
      </li>
      <li>
	Clear Output command in SciTE.
      </li>
      <li>
	SciTE on Windows gains an Always On Top command.
      </li>
      <li>
	Bug fixed in SciTE with attempts to define properties recursively.
      </li>
      <li>
	Bug fixed in SciTE properties where only one level of substitution was done.
      </li>
      <li>
	Bug fixed in SciTE properties where extensions were not being
	matched in a case insensitive manner.
      </li>
      <li>
	Bug fixed in SciTE on Windows where the Go to dialog displays the correct
	line number.
      </li>
      <li>
	In SciTE, if fold.on.open set then switching buffers also performs fold.
      </li>
      <li>
	Bug fixed in Scintilla where ensuring a line was visible in the presence of folding
	operated on the document line instead of the visible line.
      </li>
      <li>
	SciTE command line processing modified to operate on arguments in order and in
	two phases. First any arguments before the first file name are processed, then the
	UI is opened, then the remaining arguments are processed. Actions defined for the
	Director interface (currently only "open") may also be used on the command line.
	For example, "SciTE -open:x.txt" will start SciTE and open x.txt.
      </li>
      <li>
	Numbered menu items SciTE's Buffers menu and the Most Recently Used portion
	of the File menu go from 1..0 rather than 0..9.
      </li>
      <li>
	The tab bar in SciTE for Windows has numbers.
	The tab.hide.one option hides the tab bar until there is more than one buffer open.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite135.zip?download">Release 1.35</a>
    </h3>
    <ul>
      <li>
        Released on 29 January 2001.
      </li>
      <li>
        Rewritten and simplified widget code for the GTK+ version to enhance
        solidity and make more fully compliant with platform norms. This includes more
        normal handling of keystrokes so they are forwarded to containers correctly.
      </li>
      <li>
        User defined lists can be shown.
      </li>
      <li>
        Many fixes to the Perl lexer.
      </li>
      <li>
        Pascal lexer handles comments more correctly.
      </li>
      <li>
        C/C++/Java/JavaScipt lexer has a state for line doc comments.
      </li>
      <li>
        Error output lexer understands Sun CC messages.
      </li>
      <li>
        Make file lexer has variable, preprocessor, and operator states.
      </li>
      <li>
        Wider area given to an italics character that is at the end of a line to prevent it
	being cut off.
      </li>
      <li>
        Call to move the caret inside the currently visible area.
      </li>
      <li>
        Paste Rectangular will space fill on the left hand side of the pasted text as
	needed to ensure it is kept rectangular.
      </li>
      <li>
        Cut and Paste Rectangular does nothing in read-only mode.
      </li>
      <li>
        Undo batching changed so that a paste followed by typing creates two undo actions..
      </li>
      <li>
        A "visibility policy" setting for Scintilla determines which range of lines are displayed
	when a particular line is moved to. Also exposed as a property in SciTE.
      </li>
      <li>
        SciTE command line allows property settings.
      </li>
      <li>
        SciTE has a View Output command to hide or show the output pane.
      </li>
      <li>
        SciTE's Edit menu has been split in two with searching commands moved to a
	new Search menu. Find Previous and Previous Bookmark are in the Search menu.
      </li>
      <li>
        SciTE on Windows has options for setting print margins, headers and footers.
      </li>
      <li>
        SciTE on Windows has tooltips for toolbar.
      </li>
      <li>
        SciTE on GTK+ has properties for setting size of file selector.
      </li>
      <li>
        Visual and audio cues in SciTE on Windows enhanced.
      </li>
      <li>
        Fixed performance problem in SciTE for GTK+ by dropping the extra 3D
        effect on the content windows.
      </li>
      <li>
        Fixed problem in SciTE where choosing a specific lexer then meant
        that no lexer was chosen when files opened.
      </li>
      <li>
        Default selection colour changed to be visible on low colour displays.
      </li>
      <li>
        Fixed problems with automatically reloading changed documents in SciTE on
        Windows.
      </li>
      <li>
        Fixed problem with uppercase file extensions in SciTE.
      </li>
      <li>
        Fixed some problems when using characters >= 128, some of which were being
        incorrectly treated as spaces.
      </li>
      <li>
        Fixed handling multiple line tags, non-inline scripts, and XML end tags /&gt; in HTML/XML lexer.
      </li>
      <li>
        Bookmarks in SciTE no longer disappear when switching between buffers.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite134.zip?download">Release 1.34</a>
    </h3>
    <ul>
      <li>
        Released on 28 November 2000.
      </li>
      <li>
        Pascal lexer.
      </li>
      <li>
        Export as PDF in SciTE.
      </li>
      <li>
        Support for the OpenVMS operating system in SciTE.
      </li>
      <li>
        SciTE for GTK+ can check for another instance of SciTE
	editing a file and switch to it rather than open a second instance
	on one file.
      </li>
      <li>
        Fixes to quoting and here documents in the Perl lexer.
      </li>
      <li>
        SciTE on Windows can give extra visual and audio cues when a
	warning is shown or find restarts from beginning of file.
      </li>
      <li>
        Open Selected Filename command in SciTE. Also understands some
	warning message formats.
      </li>
      <li>
        Wider area for line numbers when printing.
      </li>
      <li>
        Better scrolling performance on GTK+.
      </li>
      <li>
        Fixed problem where rectangles with negative coordinates were
	invalidated leading to trouble with platforms that use
	unsigned coordinates.
      </li>
      <li>
        GTK+ Scintilla uses more compliant signalling code so that keyboard
	events should propagate to containers.
      </li>
      <li>
        Bug fixed with opening full or partial paths.
      </li>
      <li>
        Improved handling of paths in error messages in SciTE.
      </li>
      <li>
        Better handling of F6 in SciTE.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite133.zip?download">Release 1.33</a>
    </h3>
    <ul>
      <li>
        Released on 6 November 2000.
      </li>
      <li>
        XIM support for the GTK+ version of Scintilla ensures that more non-English
        characters can be typed.
      </li>
      <li>
        Caret may be 1, 2, or 3 pixels wide.
      </li>
      <li>
        Cursor may be switched to wait image during lengthy processing.
      </li>
      <li>
        Scintilla's internal focus flag is exposed for clients where focus is handled in
        complex ways.
      </li>
      <li>
        Error status defined for Scintilla to hold indication that an operation failed and the reason
        for that failure. No detection yet implemented but clients may start using the interface
        so as to be ready for when it does.
      </li>
      <li>
        Context sensitive help in SciTE.
      </li>
      <li>
        CurrentWord property available in SciTE holding the value of the word the
        caret is within or near.
      </li>
      <li>
        Apache CONF file lexer.
      </li>
      <li>
        Changes to Python lexer to allow 'as' as a context sensitive keyword and the
        string forms starting with u, r, and ur to be recognised.
      </li>
      <li>
        SCN_POSCHANGED notification now working and SCN_PAINTED notification added.
      </li>
      <li>
        Word part movement commands for cursoring between the parts of reallyLongCamelIdentifiers and
        other_ways_of_making_words.
      </li>
      <li>
        When text on only one line is selected, Shift+Tab moves to the previous tab stop.
      </li>
      <li>
        Tab control available for Windows version of SciTE listing all the buffers
        and making it easy to switch between them.
      </li>
      <li>
        SciTE can be set to automatically determine the line ending type from the contents of a
        file when it is opened.
      </li>
      <li>
        Dialogs in GTK+ version of SciTE made more modal and have accelerator keys.
      </li>
      <li>
        Find in Files command in GTK+ version of SciTE allows choice of directory.
      </li>
      <li>
        On Windows, multiple files can be opened at once.
      </li>
      <li>
        SciTE source broken up into more files.
      </li>
      <li>
        Scintilla headers made safe for C language, not just C++.
      </li>
      <li>
        New printing modes - force background to white and force default background to white.
      </li>
      <li>
        Automatic unfolding not occurring when Enter pressed at end of line bug fixed.
      </li>
      <li>
        Bugs fixed in line selection.
      </li>
      <li>
        Bug fixed with escapes in PHP strings in the HTML lexer.
      </li>
      <li>
        Bug fixed in SciTE for GTK+ opening files when given full paths.
      </li>
      <li>
        Bug fixed in autocompletion where user backspaces into existing text.
      </li>
      <li>
        Bugs fixed in opening files and ensuring they are saved before running.
        A case bug also fixed here.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite132.zip?download">Release 1.32</a>
    </h3>
    <ul>
      <li>
        Released on 8 September 2000.
      </li>
      <li>
        Fixes bugs in complete word and related code. Protection against a bug when
	receiving a bad argument.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite131.zip?download">Release 1.31</a>
    </h3>
    <ul>
      <li>
        Released on 6 September 2000.
      </li>
      <li>
        Scintilla is available as a COM control from the scintillactrl module in CVS.
      </li>
      <li>
        Style setting to underline text. Exposed in SciTE as "underlined".
      </li>
      <li>
        Style setting to make text invisible.
      </li>
      <li>
        SciTE has an extensibility interface that can be used to implement features such as
        a scripting language or remote control. An example use of this is the extlua module
        available from CVS which allows SciTE to be scripted in Lua.
      </li>
      <li>
        Many minor fixes to all of the lexers.
      </li>
      <li>
        New lexer for diff and patch files.
      </li>
      <li>
        Error message lexer understands Perl error messages.
      </li>
      <li>
        C/C++/Java lexer now supports C#, specifically verbatim strings and
	@ quoting of identifiers that are the same as keywords. SciTE has
	a set of keywords for C# and a build command set up for C#.
      </li>
      <li>
        Scintilla property to see whether in overtype or insert state.
      </li>
      <li>
         PosChanged notification fired when caret moved.
      </li>
      <li>
        Comboboxes in dialogs in SciTE on Windows can be horizontally scrolled.
      </li>
      <li>
        Autocompletion and calltips can treat the document as case sensitive or
        case insensitive.
      </li>
      <li>
        Autocompletion can be set to automatically choose the only
	element in a single element list.
      </li>
      <li>
        Set of characters that automatically complete an autocompletion list
	can be set.
      </li>
      <li>
        SciTE command to display calltip - useful when dropped because of
	editing.
      </li>
      <li>
        SciTE has a Revert command to go back to the last saved version.
      </li>
      <li>
        SciTE has an Export as RTF command. Save as HTML is renamed
	to Export as HTML and is located on the Export sub menu.
      </li>
      <li>
        SciTE command "Complete Word" searches document for any
	words starting with characters before caret.
      </li>
      <li>
        SciTE options for changing aspects of the formatting of files exported
	as HTML or RTF.
      </li>
      <li>
        SciTE "character.set" option for choosing the character
	set for all fonts.
      </li>
      <li>
        SciTE has a "Toggle all folds" command.
      </li>
      <li>
        The makefiles have changed. The makefile_vc and
	makefile_bor files in scintilla/win32 and scite/win32 have been
	merged into scintilla/win32/scintilla.mak and scite/win32/scite.mak.
	DEBUG may be defined for all make files and this will turn on
	assertions and for some make files will choose other debugging
	options.
      </li>
      <li>
         To make debugging easier and allow good use of BoundsChecker
	 there is a Visual C++ project file in scite/boundscheck that builds
	 all of Scintilla and SciTE into one executable.
      </li>
      <li>
         The size of the SciTE output window can be set with the
	 output.horizontal.size and output.vertical.size settings.
      </li>
      <li>
         SciTE status bar indicator for insert or overwrite mode.
      </li>
      <li>
        Performance improvements to autocompletion and calltips.
      </li>
      <li>
        A caret redraw problem when undoing is fixed.
      </li>
      <li>
        Crash with long lines fixed.
      </li>
      <li>
        Bug fixed with merging markers when lines merged.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite130.zip?download">Release 1.30</a>
    </h3>
    <ul>
      <li>
        Released on 26 July 2000.
      </li>
      <li>
        Much better support for PHP which is now an integral part of the HTML support.
      </li>
      <li>
        Start replacement of Windows-specific APIs with cross platform APIs.
        In 1.30, the new APIs are introduced but the old APIs are still available.
        For the GTK+ version, may have to include "WinDefs.h" explicitly to
        use the old APIs.
      </li>
      <li>
        "if" and "import" statements in SciTE properties files allows modularisation into
        language-specific properties files and choices based upon platform.
        This means that SciTE is delivered with 9 language-specific properties files
        as well as the standard SciTEGlobal.properties file.
      </li>
      <li>
        Much lower resource usage on Windows 9x.
      </li>
      <li>
        "/p" option in SciTE on Windows for printing a file and then exiting.
      </li>
      <li>
        Options for printing with inverted brightness (when the screen is set to use
        a dark background) and to force black on white printing.
      </li>
      <li>
        Option for printing magnified or miniaturised from screen settings.
      </li>
      <li>
        In SciTE, Ctrl+F3 and Ctrl+Shift+F3 find the selection in the forwards and backwards
        directions respectively.
      </li>
      <li>
        Auto-completion lists may be set to cancel when the cursor goes before
        its start position or before the start of string being completed.
      </li>
      <li>
        Auto-completion lists automatically size more sensibly.
      </li>
      <li>
        SCI_CLEARDOCUMENTSTYLE zeroes all style bytes, ensures all
        lines are shown and deletes all folding information.
      </li>
      <li>
        On Windows, auto-completion lists are visually outdented rather than indented.
      </li>
      <li>
        Close all command in SciTE.
      </li>
      <li>
        On Windows multiple files can be dragged into SciTE.
      </li>
      <li>
        When saving a file, the SciTE option save.deletes.first deletes it before doing the save.
        This allows saving with a different capitalisation on Windows.
      </li>
      <li>
        When use tabs option is off pressing the tab key inserts spaces.
      </li>
      <li>
        Bug in indicators leading to extra line drawn fixed.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite128.zip?download">Release 1.28</a>
    </h3>
    <ul>
      <li>
        Released on 27 June 2000.
      </li>
      <li>
         Fixes crash in indentation guides when indent size set to 0.
      </li>
      <li>
         Fixes to installation on GTK+/Linux. User properties file on GTK+ has a dot at front of name:
         .SciTEUser.properties. Global properties file location configurable at compile time
         defaulting to $prefix/share/scite. $prefix determined from Gnome if present else its
         /usr/local and can be overridden by installer. Gnome menu integration performed in
         make install if Gnome present.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite127.zip?download">Release 1.27</a>
    </h3>
    <ul>
      <li>
        Released on 23 June 2000.
      </li>
      <li>
         Indentation guides. View whitespace mode may be set to not display whitespace
	 in indentation.
      </li>
      <li>
        Set methods have corresponding gets for UndoCollection, BufferedDraw,
	CodePage, UsePalette, ReadOnly, CaretFore, and ModEventMask.
      </li>
      <li>
        Caret is continuously on rather than blinking while typing or holding down
	delete or backspace. And is now always shown if non blinking when focused on GTK+.
      </li>
      <li>
        Bug fixed in SciTE with file extension comparison now done in case insensitive way.
      </li>
      <li>
        Bugs fixed in SciTE's file path handling on Windows.
      </li>
      <li>
        Bug fixed with preprocessor '#' last visible character causing hang.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite126.zip?download">Release 1.26</a>
    </h3>
    <ul>
      <li>
        Released on 13 June 2000.
      </li>
      <li>
         Support for the Lua language in both Scintilla and SciTE.
      </li>
      <li>
        Multiple buffers may be open in SciTE.
      </li>
      <li>
        Each style may have a character set configured. This may determine
	the characters that are displayed by the style.
      </li>
      <li>
         In the C++ lexer, lexing of preprocessor source may either treat it all as being in
	 the preprocessor class or only the initial # and preprocessor command word as
	 being in the preprocessor class.
      </li>
      <li>
        Scintilla provides SCI_CREATEDOCUMENT, SCI_ADDREFDOCUMENT, and
	SCI_RELEASEDOCUMENT to make it easier for a container to deal with multiple
	documents.
      </li>
      <li>
        GTK+ specific definitions in Scintilla.h were removed to ScintillaWidget.h. All GTK+ clients will need to
	#include "ScintillaWidget.h".
      </li>
      <li>
        For GTK+, tools can be executed in the background by setting subsystem to 2.
      </li>
      <li>
        Keys in the properties files are now case sensitive. This leads to a performance increase.
      </li>
      <li>
        Menu to choose which lexer to use on a file.
      </li>
      <li>
        Tab size dialog on Windows.
      </li>
      <li>
        File dialogs enlarged on GTK+.
      </li>
      <li>
         Match Brace command bound to Ctrl+E on both platforms with Ctrl+] a synonym on Windows.
         Ctrl+Shift+E is select to matching brace. Brace matching tries to match to either the inside or the
         outside, depending on whether the cursor is inside or outside the braces initially.
	View End of Line bound to Ctrl+Shift+O.
      </li>
      <li>
        The Home key may be bound to move the caret to either the start of the line or the start of the
        text on the line.
      </li>
      <li>
        Visual C++ project file for SciTE.
      </li>
      <li>
        Bug fixed with current x location after Tab key.
      </li>
      <li>
        Bug fixed with hiding fold margin by setting fold.margin.width to 0.
      </li>
      <li>
        Bugs fixed with file name confusion on Windows when long and short names used, or different capitalisations,
	or relative paths.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite125.zip?download">Release 1.25</a>
    </h3>
    <ul>
      <li>
        Released on 9 May 2000.
      </li>
      <li>
        Some Unicode support on Windows. Treats buffer and API as UTF-8 and displays
	through UCS-2 of Windows.
      </li>
      <li>
        Automatic indentation. Indentation size can be different to tab size.
      </li>
      <li>
        Tool bar.
      </li>
      <li>
        Status bar now on Windows as well as GTK+.
      </li>
      <li>
        Input fields in Find and Replace dialogs now have history on both Windows and
	GTK+.
      </li>
      <li>
        Auto completion list items may be separated by a chosen character to allow spaces
	in items. The selected item may be changed through the API.
      </li>
      <li>
        Horizontal scrollbar can be turned off.
      </li>
      <li>
        Property to remove trailing spaces when saving file.
      </li>
      <li>
        On Windows, changed font size calculation to be more compatible with
	other applications.
      </li>
      <li>
        On GTK+, SciTE's global properties files are looked for in the directory specified in the
	SCITE_HOME environment variable if it is set. This allows hiding in a dot directory.
      </li>
      <li>
        Keyword lists in SciTE updated for JavaScript to include those destined to be used in
	the future. IDL includes XPIDL keywords as well as MSIDL keywords.
      </li>
      <li>
        Zoom level can be set and queried through API.
      </li>
      <li>
        New notification sent before insertions and deletions.
      </li>
      <li>
        LaTeX lexer.
      </li>
      <li>
        Fixes to folding including when deletions and additions are performed.
      </li>
      <li>
        Fix for crash with very long lines.
      </li>
      <li>
        Fix to affect all of rectangular selections with deletion and case changing.
      </li>
      <li>
        Removed non-working messages that had been included only for Richedit compatibility.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/scite124.zip">Release 1.24</a>
    </h3>
    <ul>
      <li>
        Released on 29 March 2000.
      </li>
      <li>
        Added lexing of IDL based on C++ lexer with extra UUID lexical class.
      </li>
      <li>
        Functions and associated keys for Line Delete, Line Cut, Line Transpose,
	Selection Lower Case and Selection Upper Case.
      </li>
      <li>
        Property setting for SciTE, eol.mode, chooses initial state of line end characters.
      </li>
      <li>
        Fixed bugs in undo history with small almost-contiguous changes being incorrectly coalesced.
      </li>
      <li>
        Fixed bugs with incorrect expansion of ContractionState data structures causing crash.
      </li>
      <li>
        Fixed bugs relating to null fonts.
      </li>
      <li>
        Fixed bugs where recolourisation was not done sometimes when required.
      </li>
      <li>
        Fixed compilation problems with SVector.h.
      </li>
      <li>
        Fixed bad setting of fold points in Python.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/scite123.zip?download">Release 1.23</a>
    </h3>
    <ul>
      <li>
        Released on 21 March 2000.
      </li>
      <li>
        Directory structure to separate on basis of product (Scintilla, SciTE, DMApp)
	and environment (Cross-platform, Win32, GTK+).
      </li>
      <li>
        Download packaging to allow download of the source or platform dependent executables.
      </li>
      <li>
        Source code now available from CVS at SourceForge.
      </li>
      <li>
        Very simple Windows-only demonstration application DMApp is available from cvs as dmapp.
      </li>
      <li>
        Lexing functionality may optionally be included in Scintilla rather than be provided by
        the container.
      </li>
      <li>
        Set of lexers included is determined at link time by defining which of the Lex* object files
	are linked in.
      </li>
      <li>
        On Windows, the SciLexer.DLL extends Scintilla.DLL with the standard lexers.
      </li>
      <li>
        Enhanced HTML lexer styles embedded VBScript and Python.
	ASP segments are styled and ASP scripts in JavaScript, VBScript and Python are styled.
      </li>
      <li>
        PLSQL and PHP supported.
      </li>
      <li>
        Maximum number of lexical states extended to 128.
      </li>
      <li>
        Lexers may store per line parse state for multiple line features such as ASP script language choice.
      </li>
      <li>
        Lexing API simplified.
      </li>
      <li>
        Project file for Visual C++.
      </li>
      <li>
        Can now cycle through all recent files with Ctrl+Tab in SciTE.
      </li>
      <li>
        Bookmarks in SciTE.
      </li>
      <li>
        Drag and drop copy works when dragging to the edge of the selection.
      </li>
      <li>
        Fixed bug with value sizes in properties file.
      </li>
      <li>
        Fixed bug with last line in properties file not being used.
      </li>
      <li>
        Bug with multiple views of one document fixed.
      </li>
      <li>
        Keypad now works on GTK+.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/SciTE122.zip?download">Release 1.22</a>
    </h3>
    <ul>
      <li>
        Released on 27 February 2000.
      </li>
      <li>
        wxWindows platform defined.
	Implementation for wxWindows will be available separately
	from main Scintilla distribution.
      </li>
      <li>
        Line folding in Scintilla.
      </li>
      <li>
        SciTE performs syntax directed folding for C/C++/Java/JavaScript and for Python.
      </li>
      <li>
        Optional macro recording support.
      </li>
      <li>
        User properties file (SciTEUser.properties) allows for customisation by the user
	that is not overwritten with each installation of SciTE.
      </li>
      <li>
        Python lexer detects and highlights inconsistent indentation.
      </li>
      <li>
        Margin API made more orthogonal. SCI_SETMARGINWIDTH and SCI_SETLINENUMBERWIDTH
        are deprecated in favour of this new API.
      </li>
      <li>
        Margins may be made sensitive to forward mouse click events to container.
      </li>
      <li>
        SQL lexer and styles included.
      </li>
      <li>
        Perl lexer handles regular expressions better.
      </li>
      <li>
        Caret policy determines how closely caret is tracked by visible area.
      </li>
      <li>
        New marker shapes: arrow pointing down, plus and minus.
      </li>
      <li>
        Optionally display full path in title rather than just file name.
      </li>
      <li>
        Container is notified when Scintilla gains or loses focus.
      </li>
      <li>
        SciTE handles focus in a more standard way and applies the main
	edit commands to the focused pane.
      </li>
      <li>
        Container is notified when Scintilla determines that a line needs to be made visible.
      </li>
      <li>
        Document watchers receive notification when document about to be deleted.
      </li>
      <li>
        Document interface allows access to list of watchers.
      </li>
      <li>
        Line end determined correctly for lines ending with only a '\n'.
      </li>
      <li>
        Search variant that searches form current selection and sets selection.
      </li>
      <li>
        SciTE understands format of diagnostic messages from WScript.
      </li>
      <li>
        SciTE remembers top line of window for each file in MRU list so switching to a recent file
	is more likely to show the same text as when the file was previously visible.
      </li>
      <li>
        Document reference count now initialised correctly.
      </li>
      <li>
        Setting a null document pointer creates an empty document.
      </li>
      <li>
        WM_GETTEXT can no longer overrun buffer.
      </li>
      <li>
        Polygon drawing bug fixed on GTK+.
      </li>
      <li>
        Java and JavaScript lexers merged into C++ lexer.
      </li>
      <li>
        C++ lexer indicates unterminated strings by colouring the end of the line
	rather than changing the rest of the file to string style. This is less
	obtrusive and helps the folding.
      </li>
    </ul>
    <h3>
       <a href="http://prdownloads.sourceforge.net/scintilla/SciTE121.zip?download">Release 1.21</a>
    </h3>
    <ul>
      <li>
        Released on 2 February 2000.
      </li>
      <li>
        Blank margins on left and right side of text.
      </li>
      <li>
        SCN_CHECKBRACE renamed SCN_UPDATEUI and made more efficient.
      </li>
      <li>
        SciTE source code refactored into platform independent and platform specific classes.
      </li>
      <li>
        XML and Perl subset lexers in SciTE.
      </li>
      <li>
        Large improvement to lexing speed.
      </li>
      <li>
        A new subsystem, 2, allows use of ShellExec on Windows.
      </li>
      <li>
        Borland compatible makefile.
      </li>
      <li>
        Status bar showing caret position in GTK+ version of SciTE.
      </li>
      <li>
        Bug fixes to selection drawing when part of selection outside window, mouse release over
        scroll bars, and scroll positioning after deletion.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE120.zip">Release 1.2</a>
    </h3>
    <ul>
      <li>
        Released on 21 January 2000.
      </li>
      <li>
        Multiple views of one document.
      </li>
      <li>
        Rectangular selection, cut, copy, paste, drag and drop.
      </li>
      <li>
        Long line indication.
      </li>
      <li>
        Reverse searching
      </li>
      <li>
        Line end conversion.
      </li>
      <li>
        Generic autocompletion and calltips in SciTE.
      </li>
      <li>
        Call tip background colour can be set.
      </li>
      <li>
        SCI_MARKERPREV for moving to a previous marker.
      </li>
      <li>
        Caret kept more within window where possible.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE115.zip">Release 1.15</a>
    </h3>
    <ul>
      <li>
        Released on 15 December 1999.
      </li>
      <li>
        Brace highlighting and badlighting (for mismatched braces).
      </li>
      <li>
        Visible line ends.
      </li>
      <li>
        Multiple line call tips.
      </li>
      <li>
        Printing now works from SciTE on Windows.
      </li>
      <li>
        SciTE has a global "*" lexer style that is used as the basis for all the lexers' styles.
      </li>
      <li>
        Fixes some warnings on GTK+ 1.2.6.
      </li>
      <li>
        Better handling of modal dialogs on GTK+.
      </li>
      <li>
        Resize handle drawn on pane splitter in SciTE on GTK+ so it looks more like a regular GTK+
        *paned widget.
      </li>
      <li>
        SciTE does not place window origin offscreen if no properties file found on GTK+.
      </li>
      <li>
        File open filter remembered in SciTE on Windows.
      </li>
      <li>
        New mechanism using style numbers 32 to 36 standardises the setting of styles for brace
        highlighting, brace badlighting, line numbers, control characters and the default style.
      </li>
      <li>
        Old messages SCI_SETFORE .. SCI_SETFONT have been replaced by the default style 32. The old
        messages are deprecated and will disappear in a future version.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE114.zip">Release 1.14</a>
    </h3>
    <ul>
      <li>
        Released on 20 November 1999.
      </li>
      <li>
        Fixes a scrolling bug reported on GTK+.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE113.zip">Release 1.13</a>
    </h3>
    <ul>
      <li>
        Released on 18 November 1999.
      </li>
      <li>
        Fixes compilation problems with the mingw32 GCC 2.95.2 on Windows.
      </li>
      <li>
        Control characters are now visible.
      </li>
      <li>
        Performance has improved, particularly for scrolling.
      </li>
      <li>
        Windows RichEdit emulation is more accurate. This may break client code that uses these
        messages: EM_GETLINE, EM_GETLINECOUNT, EM_EXGETSEL, EM_EXSETSEL, EM_EXLINEFROMCHAR,
        EM_LINELENGTH, EM_LINEINDEX, EM_CHARFROMPOS, EM_POSFROMCHAR, and EM_GETTEXTRANGE.
      </li>
      <li>
        Menus rearranged and accelerator keys set for all static items.
      </li>
      <li>
        Placement of space indicators in view whitespace mode is more accurate with some fonts.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE112.zip">Release 1.12</a>
    </h3>
    <ul>
      <li>
        Released on 9 November 1999.
      </li>
      <li>
        Packaging error in 1.11 meant that the compilation error was not fixed in that release.
        Linux/GTK+ should compile with GCC 2.95 this time.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE111.zip">Release 1.11</a>
    </h3>
    <ul>
      <li>
        Released on 7 November 1999.
      </li>
      <li>
        Fixed a compilation bug in ScintillaGTK.cxx.
      </li>
      <li>
        Added a README file to explain how to build.
      </li>
      <li>
        GTK+/Linux downloads now include documentation.
      </li>
      <li>
        Binary only Sc1.EXE one file download for Windows.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE110.zip">Release 1.1</a>
    </h3>
    <ul>
      <li>
        Released on 6 November 1999.
      </li>
      <li>
        Major restructuring for better modularity and platform independence.
      </li>
      <li>
        Inter-application drag and drop.
      </li>
      <li>
        Printing support in Scintilla on Windows.
      </li>
      <li>
        Styles can select colouring to end of line. This can be used when a file contains more than
        one language to differentiate between the areas in each language. An example is the HTML +
        JavaScript styling in SciTE.
      </li>
      <li>
        Actions can be grouped in the undo stack, so they will be undone together. This grouping is
        hierarchical so higher level actions such as replace all can be undone in one go. Call to
        discover whether there are any actions to redo.
      </li>
      <li>
        The set of characters that define words can be changed.
      </li>
      <li>
        Markers now have identifiers and can be found and deleted by their identifier. The empty
        marker type can be used to make a marker that is invisible and which is only used to trace
        where a particular line moves to.
      </li>
      <li>
        Double click notification.
      </li>
      <li>
        HTML styling in SciTE also styles embedded JavaScript.
      </li>
      <li>
        Additional tool commands can be added to SciTE.
      </li>
      <li>
        SciTE option to allow reloading if changed upon application activation and saving on
        application deactivation. Not yet working on GTK+ version.
      </li>
      <li>
        Entry fields in search dialogs remember last 10 user entries. Not working in all cases in
        Windows version.
      </li>
      <li>
        SciTE can save a styled copy of the current file in HTML format. As SciTE does not yet
        support printing, this can be used to print a file by then using a browser to print the
        HTML file.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE102.zip">Release 1.02</a>
    </h3>
    <ul>
      <li>
        Released on 1 October 1999.
      </li>
      <li>
        GTK+ version compiles with GCC 2.95.
      </li>
      <li>
        Properly deleting objects when window destroyed under GTK+.
      </li>
      <li>
        If the selection is not empty backspace deletes the selection.
      </li>
      <li>
        Some X style middle mouse button handling for copying the primary selection to and from
        Scintilla. Does not work in all cases.
      </li>
      <li>
        HTML styling in SciTE.
      </li>
      <li>
        Stopped dirty flag being set in SciTE when results pane modified.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE101.zip">Release 1.01</a>
    </h3>
    <ul>
      <li>
        Released on 28 September 1999.
      </li>
      <li>
        Better DBCS support on Windows including IME.
      </li>
      <li>
        Wheel mouse support for scrolling and zooming on Windows. Zooming with Ctrl+KeypadPlus and
        Ctrl+KeypadMinus.
      </li>
      <li>
        Performance improvements especially on GTK+.
      </li>
      <li>
        Caret blinking and settable colour on both GTK+ and Windows.
      </li>
      <li>
        Drag and drop within a Scintilla window. On Windows, files can be dragged into SciTE.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/SciTE100.zip">Release 1.0</a>
    </h3>
    <ul>
      <li>
        Released on 17 May 1999.
      </li>
      <li>
        Changed name of "Tide" to "SciTE" to avoid clash with a TCL based IDE. "SciTE" is a
        SCIntilla based Text Editor and is Latin meaning something like "understanding in a neat
        way" and is also an Old English version of the word "shit".
      </li>
      <li>
        There is a SCI_AUTOCSTOPS message for defining a string of characters that will stop
        autocompletion mode. Autocompletion mode is cancelled when any cursor movement occurs apart
        from backspace.
      </li>
      <li>
        GTK+ version now splits horizontally as well as vertically and all dialogs cancel when the
        escape key is pressed.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide92.zip">Beta release 0.93</a>
    </h3>
    <ul>
      <li>
        Released on 12 May 1999.
      </li>
      <li>
        A bit more robust than 0.92 and supports SCI_MARKERNEXT message.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide92.zip">Beta release 0.92</a>
    </h3>
    <ul>
      <li>
        Released on 11 May 1999.
      </li>
      <li>
        GTK+ version now contains all features of Windows version with some very small differences.
        Executing programs works much better now.
      </li>
      <li>
        New palette code to allow more colours to be displayed in 256 colour screen modes. A line
        number column can be displayed to the left of the selection margin.
      </li>
      <li>
        The code that maps from line numbers to text positions and back has been completely
        rewritten to be faster, and to allow markers to move with the text.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide91.zip">Beta release 0.91</a>
    </h3>
    <ul>
      <li>
        Released on 30 April 1999, containing fixes to text measuring to make Scintilla work better
        with bitmap fonts. Also some small fixes to make compiling work with Visual C++.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide90.zip">Beta release 0.90</a>
    </h3>
    <ul>
      <li>
        Released on 29 April 1999, containing working GTK+/Linux version.
      </li>
      <li>
        The Java, C++ and Python lexers recognise operators as distinct from default allowing them
        to be highlighted.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide82.zip">Beta release 0.82</a>
    </h3>
    <ul>
      <li>
        Released on 1 April 1999, to fix a problem with handling the Enter key in PythonWin. Also
        fixes some problems with cmd key mapping.
      </li>
    </ul>
    <h3>
       <a href="http://www.scintilla.org/Tide81.zip">Beta release 0.81</a>
    </h3>
    <ul>
      <li>
        Released on 30th March 1999, containing bug fixes and a few more features.
      </li>
      <li>
        Static linking supported and Tidy.EXE, a statically linked version of Tide.EXE. Changes to
        compiler flags in the makefiles to optimise for size.
      </li>
      <li>
        Scintilla supports a 'savepoint' in the undo stack which can be set by the container when
        the document is saved. Notifications are sent to the container when the savepoint is
        entered or left, allowing the container to to display a dirty indicator and change its
        menus.
      </li>
      <li>
        When Scintilla is set to read-only mode, a notification is sent to the container should the
        user try to edit the document. This can be used to check the document out of a version
        control system.
      </li>
      <li>
        There is an API for setting the appearance of indicators.
      </li>
      <li>
        The keyboard mapping can be redefined or removed so it can be implemented completely by the
        container. All of the keyboard commands are now commands which can be sent by the
        container.
      </li>
      <li>
        A home command like Visual C++ with one hit going to the start of the text on the line and
        the next going to the left margin is available. I do not personally like this but my
        fingers have become trained to it by much repetition.
      </li>
      <li>
        SCI_MARKERDELETEALL has an argument in wParam which is the number of the type marker to
        delete with -1 performing the old action of removing all marker types.
      </li>
      <li>
        Tide now understands both the file name and line numbers in error messages in most cases.
      </li>
      <li>
        Tide remembers the current lines of files in the recently used list.
      </li>
      <li>
        Tide has a Find in Files command.
      </li>
    </ul>
    <h3>
       Beta release 0.80
    </h3>
    <ul>
      <li>
        This was the first public release on 14th March 1999, containing a mostly working Win32
        Scintilla DLL and Tide EXE.
      </li>
    </ul>
    <h3>
       Beta releases of SciTE were called Tide
    </h3>
  </body>
</html>

Added doc/ScintillaRelated.html.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla and SciTE Related Sites
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Related Sites
    </h2>
    <h3>
       Ports and Bindings of Scintilla
    </h3>
    <p>
	<a href="http://foicica.com/scinterm/">Scinterm</a>
	is an implementation of Scintilla for the ncurses platform.
    </p>
    <p>
	<a href="http://www.morphos-team.net/releasenotes/3.0">Scintilla.mcc</a>
	is a port to MorphOS.
    </p>
    <p>
	<a href="https://metacpan.org/module/Wx::Scintilla">Wx::Scintilla</a>
	is a Perl Binding for Scintilla on wxWidgets.
    </p>
    <p>
	<a href="http://codebrainz.github.com/GtkScintilla/">GtkScintilla</a>
	is a GTK+ widget which enables easily adding a powerful
	source code editor to your applications. Harnessing the abilities
	of the Scintilla editing component, GtkScintilla adds a familiar
	GTK+/GObject API, making the widget comfortable to use in
	these programs, using all the typical GObject conventions.
    </p>
    <p>
	<a href="http://mewsoft.com/cgi-bin/forum/forum.cgi?action=ViewTopic&Topic=1494&Forum=1&Page=1&Period=0a&Lang=English">Editawy</a>
	is an ActiveX Control wrapper that support all Scintilla functions and additional high level functions.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/jintilla/">Jintilla</a>
	is a JNI wrapper that allows Scintilla to be used in Java with
	both SWT and AWT.
    </p>
    <p>
	<a href="http://delphisci.sourceforge.net/">Delphi Scintilla Interface Components</a>
	is a FREE collection of components that makes it easy to use the
         Scintilla source code editing control from within Delphi and C++ Builder.
    </p>
    <p>
	<a href="http://wxcode.sourceforge.net/showcomp.php?name=wxStEdit">wxStEdit</a>
	is a library and sample program that provides extra features over wxStyledTextControl.
    </p>
    <p>
	<a href="http://www.naughter.com/scintilla.html">CScintillaCtrl, CScintillaView &amp; CScintillaDoc</a>
	are freeware MFC classes to encapsulate Scintilla.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/scide/">ScintillaNet
	</a> is an encapsulation of Scintilla for use within the .NET framework.
    </p>
    <p>
	<a href="http://www.riverbankcomputing.co.uk/software/qscintilla/intro">QScintilla
	</a> is a port of Scintilla to the Qt platform. It has a similar license to Qt: GPL for use in
	free software and commercial for use in close-source applications.
    </p>
    <p>
	<a href="http://www.adapower.com/gwindows/">
	GWindows</a> is a Win32 RAD GUI Framework for Ada 95 that
	includes a binding of Scintilla.
    </p>
    <p>
	<a href="http://scintilla.cvs.sourceforge.net/viewvc/scintilla/ScintillaVB/">ScintillaVB</a>
	is an ActiveX control written in VB that encapsulates Scintilla.
    </p>
    <p>
	<a href="http://savannah.nongnu.org/projects/fxscintilla/">FXScintilla
	</a> is a port of Scintilla to the FOX platform. FXRuby includes Ruby
	bindings for FXScintilla.
    </p>
    <p>
	<a href="http://www.pnotepad.org/scintilla/">Delphi wrapper</a> for
	Scintilla which is also usable from Borland C++ Builder.
    </p>
    <p>
       The wxStyledTextCtrl editor component  in the
       <a href="http://www.wxwidgets.org/">wxWidgets</a> cross platform toolkit is based on Scintilla.<br />
       A Python binding for wxStyledTextCtrl is part of <a href="http://wxpython.org/">wxPython</a>.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/moleskine/">gtkscintilla</a>
	is an alternative GTK class implementation for scintilla.
	This implementation acts more like a Gtk+ object, with many methods rather
	than just scintilla_send_message() and is available as a shared library.
	This implementation works with GTK 1.x.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/moleskine/">gtkscintilla2</a>
	is an alternative GTK class implementation for scintilla
	similar to the above, but for GTK 2.x.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/moleskine/">pygtkscintilla</a>
	is a Python binding for gtk1.x scintilla that uses
	gtkscintilla instead of the default GTK class.
    </p>
    <p>
	<a href="http://scintilla.cvs.sourceforge.net/viewvc/scintilla/scintillactrl/">ScintillaCtrl</a>
	is an unmaintained ActiveX control wrapper for Scintilla.
    </p>
    <h3>
       Projects using Scintilla
    </h3>
    <p>
	<a href="http://www.qgis.org/">Quantum GIS</a>
	is a user friendly Open Source Geographic Information System (GIS).
    </p>
    <p>
	<a href="https://gitorious.org/qgrinui">QGrinUI</a>
	searches for a regex within all relevant files in a directory and shows matches using
	SciTE through the director interface.
    </p>
    <p>
	<a href="http://foicica.com/textadept/">Textadept</a>
	is a ridiculously extensible cross-platform text editor for programmers written (mostly) in
	Lua using LPeg to handle the lexers.
    </p>
    <p>
	<a href="http://www.morphos-team.net/releasenotes/3.0">Scribble</a>
	is a text editor included in MorphOS.
    </p>
    <p>
	<a href="http://mysqlworkbench.org/">MySQL Workbench</a>
	is a cross-platform, visual database design, sql coding and administration tool.
    </p>
    <p>
	<a href="http://liveditor.com/index.html">LIVEditor</a>
	is for web front end coders editing html/css/js code.
    </p>
    <p>
	<a href="http://padre.perlide.org/">Padre</a>
	is a wxWidgets-based Perl IDE.
    </p>
    <p>
	<a href="http://manoscoder.gr/CoderStudio/CoderStudio.asp">CoderStudio</a>
	is an IDE for Assembly programming similar to Visual Studio 6.0.
    </p>
    <p>
	<a href="http://www.sparxsystems.com/products/ea/index.html">Enterprise Architect</a>
	is a UML 2.1 analysis and design tool.
    </p>
    <p>
	<a href="https://launchpad.net/codeassistor">The CodeAssistor Editor</a>
	is a small and simple MacOSX source code editor.
    </p>
    <p>
	<a href="http://www.topwizprogramming.com/freecode_pbeditor.html">PBEditor</a>
	is a text editor for PowerBuilder.
    </p>
    <p>
	<a href="http://www.cryptool.org/">CrypTool</a>
	is an application for applying and analyzing cryptographic algorithms.
    </p>
    <p>
	<a href="http://code.google.com/p/fxite/">FXiTe</a>
	is an advanced cross-platform text editor built with the Fox GUI toolkit
	and the FXScintilla text widget.
    </p>
    <p>
	<a href="http://www.jabaco.org/">Jabaco</a>
	is a simple programming language with a Visual Basic like syntax.
    </p>
    <p>
	<a href="http://www.daansystems.com/lispide">LispIDE</a>
	is a basic Lisp editor for Windows 2000, XP and Vista.
    </p>
    <p>
	<a href="http://www.flexsoft.cc/download.htm">FlexEdit</a>
	is Free Text/Hex Editor for Windows.
    </p>
    <p>
	<a href="http://www.assembla.com/wiki/show/FileWorkbench">File Workbench:</a>
	a file manager / text editor environment with Squirrel scripting.
    </p>
    <p>
	<a href="http://kephra.sf.net">Kephra</a>
	is a free, easy and comfortable cross-platform editor written in Perl.
    </p>
    <p>
	<a href="http://top.gresham-computing.com">TOP</a>
	is an interface to HP's NonStop servers which run a proprietary OS.
    </p>
    <p>
	<a href="http://universalindent.sourceforge.net/">UniversalIndentGUI</a>
	is a cross platform GUI for several code formatters, beautifiers and indenters
	like GreatCode, AStyle (Artistic Styler), GNU Indent, BCPP and so on.
    </p>
    <p>
	<a href="http://scitools.com/products/trackback/product.php">TrackBack</a>
	watches and backs up every change made in your source code.
    </p>
    <p>
	<a href="http://elementaryreports.com/">Elementary Reports</a>
	is designed to reduce the time to compose detailed and professional primary school reports.
    </p>
    <p>
	<a href="http://stepaheadsoftware.com/products/vcw/vcw.htm">Visual Classworks</a>
	Visual class modeling and coding in C++ via 'live'
	UML style class diagrams.
    </p>
    <p>
	<a href="http://stepaheadsoftware.com/products/javelin/javelin.htm">Javelin</a>
	Visual Class modeling and coding in Java via 'live' UML style
	class diagrams.
    </p>
    <p>
	The <a href="http://www.adobe.com/devnet/bridge/">ExtendScript Toolkit</a>
	is a development and debugging tool for JavaScript
	scripts included with Adobe CS3 Suites.
    </p>
    <p>
	<a href="http://tortoisesvn.net/">TortoiseSVN</a>
	is a Windows GUI client for the Subversion source control software.
    </p>
    <p>
	<a href="http://www.geany.org/">Geany</a>
	is a small and fast GTK2 based IDE, which has only a few dependencies from other packages.
    </p>
    <p>
	<a href="http://www.elliecomputing.com/products/merge_overview.asp">ECMerge</a>
	is a commercial graphical and batch diff / merge tool for Windows, Linux and Solaris
	(aiming to target all major platforms).
    </p>
    <p>
	<a href="http://pype.sourceforge.net/">PyPE</a>
	is an editor written in Python with the wxPython GUI toolkit.
    </p>
    <p>
	<a href="http://home.mweb.co.za/sd/sdonovan/sciboo.html">Sciboo</a>
	is an editor based on ScintillaNET.
    </p>
    <p>
	<a href="https://sourceforge.net/projects/tsct/">The Scite Config Tool</a>
	is a graphical user interface for changing SciTE properties files.
    </p>
    <p>
	<a href="http://www.totalcmd.net/plugring/SciLister.html">Scintilla Lister</a>
	is a plugin for Total Commander allowing viewing all documents with syntax highlighting
	inside Total Commander.
    </p>
    <p>
	<a href="http://chscite.sourceforge.net">ChSciTE</a>
	is a free IDE for C/C++ interpreter Ch. It runs cross platform.
	Ch is for cross-platform scripting, shell
	programming, 2D/3D plotting, numerical computing, and embedded
	scripting.
    </p>
    <p>
       <a href="http://codeblocks.org/">
       Code::Blocks</a> is an open source, cross platform free C++ IDE.
    </p>
    <p>
       <a href="http://notepad-plus.sourceforge.net/uk/site.htm">
       Notepad++</a> is a free source code editor under Windows.
    </p>
    <p>
       <a href="http://gubed.mccabe.nu/">
       Gubed</a> is a cross platform program to debug PHP scripts.
    </p>
    <p>
       <a href="http://www.lesser-software.com/lswdnl.htm">
       LSW DotNet-Lab</a> is a development environment for the .NET platform.
    </p>
    <p>
       <a href="http://glintercept.nutty.org/">
       GLIntercept</a> is an OpenGL function call interceptor that uses SciTE as a
       run-time shader editor.
    </p>
    <p>
       <a href="http://wxguide.sourceforge.net/indexedit.html">
       wyoEditor</a> is "A nice editor with a well designed and consistent look and feel".
    </p>
    <p>
       <a href="http://www.flos-freeware.ch/notepad2.html">
       Notepad2</a> is "Yet another Notepad replacement".
    </p>
    <p>
       <a href="http://pycrash.sourceforge.net/index.php?type=3">
       PyCrash Viewer</a> can examine crash dumps of Python programs.
    </p>
    <p>
       <a href="http://www.cabletest.com/mpt-wa-software-discovery.shtml">
       MPT series Wire Analyzers</a> use Scintilla and SciTE.
    </p>
    <p>
       <a href="http://www.mygenerationsoftware.com">MyGeneration</a>
	is a .NET based code generator.
    </p>
    <p>
       <a href="http://cssed.sourceforge.net">CSSED</a>
	is a tiny GTK2 CSS editor.
    </p>
    <p>
       <a href="http://wxghostscript.sourceforge.net/">
        IdePS</a>
	is a free Integrated Development Environment for PostScript
    </p>
    <p>
       <a href="http://cute.sourceforge.net/">
        CUTE</a>
	is a user-friendly source code editor easily extended using Python.
    </p>
    <p>
       <a href="http://www.spaceblue.com/venis/">
        Venis IX</a>,
	the Visual Environment for NSIS (Nullsoft Scriptable Install System).
    </p>
    <p>
       <a href="http://www.die-offenbachs.de/detlev/eric.html">Eric3</a>
       is a Python IDE written using PyQt and QScintilla.
    </p>
    <p>
       <a href="http://www.bomberstudios.com/sciteflash/">SciTE|Flash</a>
       is a free Scintilla-based ActionScript editor for Windows.
    </p>
    <p>
       <a href="http://www.computersciencelab.com/CppIde.htm">CPPIDE</a>
       is part of some commercial high-school oriented programming course software.
    </p>
    <p>
       <a href="http://www.blazingtools.com/is.html">Instant Source</a>
       is a commercial tool for looking at the HTML on web sites.
    </p>
    <p>
       <a href="http://www.codejoin.com/radon/">RAD.On++</a>
       is a free C++ Rapid Application Developer for Win32.
    </p>
    <p>
       <a href="http://wxbasic.sourceforge.net/">wxBasic</a> is an open source
       Basic interpreter that uses the wxWidgets toolkit. A small IDE is under construction.
    </p>
    <p>
       <a href="http://freeride.rubyforge.org/wiki/wiki.pl">FreeRIDE</a> will be a
       cross-platform IDE for the Ruby programming language.
    </p>
    <p>
       <a href="http://visual-mingw.sourceforge.net/">Visual MinGW</a> is an
       IDE for the MinGW compiler system.This runs on Windows with gcc.
    </p>
    <p>
       The <a href="http://archaeopteryx.com/wingide">Wing IDE</a> is a
       complete integrated development environment for the Python programming
       language.
       Available on Intel based Linux and Windows and on MacOS X through XDarwin.
    </p>
    <p>
	<a href="http://www.gorlice.net.pl/~rybak/luaide/">LuaIDE</a>
	is an IDE for Lua on Windows.
    </p>
    <p>
	<a href="http://www.aegisknight.org/sphere/">Sphere</a>
	is 2D RPG engine with a development environment.
    </p>
    <p>
	<a href="http://gaiacrtn.free.fr/practical-ruby/index.html">Practical Ruby</a>
	is an IDE for Ruby on Windows.
    </p>
    <p>
	<a href="http://www.gnuenterprise.org/">GNUe</a>
	is a suite of tools and applications for solving the needs of the enterprise.
    </p>
    <p>
	<a href="http://silvercity.sourceforge.net/">SilverCity</a>
	is a lexing package that can provide lexical analysis for over 20 programming
	and markup languages.
    </p>
    <p>
	<a href="http://hapdebugger.sourceforge.net/">HAP Python Remote Debugger</a>
	is a Python debugger that can run on one Windows machine debugging a Python program running
	on either the same or another machine.
    </p>
    <p>
	<a href="http://www.rexx.com/~dkuhlman/">pyeditor and wxEditor</a>
	are scriptable editors implemented in Python. pyeditor is based on GTK+ and
	the pyscintilla wrapper. wxEditor is based on wxWidgets, wxPython and
	wxStyledTextControl.
    </p>
    <p>
	<a href="http://sourceforge.net/projects/pycrust/">PyCrust</a> is an interactive
	Python shell based on wxPython.
    </p>
    <p>
	<a href="http://www.thekompany.com/products/blackadder/">Black Adder</a> is a
	Qt based development environment for Python and Ruby.
    </p>
    <p>
	<a href="http://www.activestate.com/Products/Komodo/">Komodo</a>
	is a cross-platform multi-language development environment built
	as an application of Mozilla.
    </p>
    <p>
	<a href="http://llt.chez-alice.fr/">Filerx</a>
	is a project manager for SciTE on Windows.
	Open source and includes an implementation of SciTE's Director interface so
	will be of interest to others wanting to control SciTE.
    </p>
    <p>
	<a href="http://anjuta.sourceforge.net/">Anjuta</a>
	is an open source C/C++ IDE for Linux/GNOME.
    </p>
    <p>
       A <a href="http://www.burgaud.com">version of SciTE for Win32</a> enhanced
       with a tab control to allow easy movement between buffers.
       Go to the "Goodies" area on this site.
    </p>
    <p>
       <a href="http://www.suneido.com">
       Suneido</a> is an integrated application platform currently available for Win32 that includes an
       object-oriented language, client-server database, and user interface and reporting frameworks.
    </p>
    <p>
       <a href="http://www.allitis.com/agast/home.html">
       Agast</a> is an authoring system for adventure games which includes
       a customised version of SciTE.
    </p>
    <p>
       <a href="http://boa-constructor.sourceforge.net/">Boa Constructor</a> is a RAD GUI
       Building IDE for the wxWidgets cross platform platform. Written using wxPython with the
       wxStyledTextCtrl used as its editor.
    </p>
    <p>
       <a href="http://www.python.org/download/windows/">PythonWin</a>, a Win32 IDE for Python, uses
      Scintilla for both its editing and interactive windows.
    </p>
    <h3>
       Editing Components
    </h3>
    <p>
       <a href="http://www.soft-gems.net/index.php/controls/unicodeeditor-formerly-unicode-syntax-editor">UniCodeEditor</a>
       is a Unicode aware syntax editor control for Delphi and C++ Builder.
    </p>
    <p>
       <a href="http://projects.gnome.org/gtksourceview/">GtkSourceView</a>
	is a text widget that extends the standard GTK+ 2.x text widget and improves it
	by implementing syntax highlighting and other features typical of a source editor.
    </p>
    <p>
       <a href="http://aeditor.rubyforge.org/">AEditor</a>
       is a free source code editing component implemented in Ruby.
    </p>
    <p>
       <a href="http://www.actiprosoftware.com/Products/DotNet/SyntaxEditor/Default.aspx">SyntaxEditor</a>
       is a commercial native .Net source code editing component.
    </p>
    <p>
       <a href="http://jedit.sourceforge.net/">jEdit</a> is a good Open Source syntax colouring
      editor written in and for Java.
    </p>
    <p>
       <a href="http://www.gtk.org/">GTK+</a>, the GIMP Toolkit, contains a rich text editing
      widget.<br />
       <a href="http://gedit.sourceforge.net/">Gedit</a> is an editor for GTK+/GNOME.<br />
    <!--
       <a href="http://www.daimi.au.dk/~mailund/gtk.html">GtkEditor</a> is a source code editing
      widget based on the GTK+ text widget.<br />
       <a href="http://gide.gdev.net/">gIDE</a> is an IDE based on GTK+.<br />
       <a href="http://www.bahnhof.se/~mikeh/linux_software.html">GtkExText</a> is a source code
      oriented text widget for GTK+.
    -->
    </p>
    <p>
       <a href="http://www.codeguru.com/">CodeGuru</a> has source code for several Win32 MFC based
      editors.
    </p>
    <a href="http://synedit.sourceforge.net/">SynEdit</a> is a Win32 edit control written
    in Delphi.
    <p>
       <a href="http://www.tetradyne.com/srcvwax.htm">SourceView</a> is a commercial editing
      component for Win32.
    </p>
    <p>
       <a href="http://www.winmain.com/">CodeMax</a> is another commercial component for Win32.
    </p>
    <h3>
       Documents
    </h3>
    <p>
       <a href="http://www.finseth.com/craft/">The Craft of Text Editing</a>
       describes how EMACS works, <i>Craig A. Finseth</i>
    </p>
    <p>
       <a href="http://www.cs.cmu.edu/~wjh/papers/byte.html">Data Structures in a Bit-Mapped Text
      Editor</a>, <i>Wilfred J. Hanson</i>, Byte January 1987
    </p>
    <p>
       Text Editors: Algorithms and Architectures, <i>Ray Vald&eacute;s</i>, Dr. Dobbs Journal
      April 1993
    </p>
    <p>
       Macintosh User Interface Guidelines and TextEdit chapters of Inside Macintosh
    </p>
    <h3>
       Development Tools
    </h3>
    <p>
       Scintilla and SciTE were developed using the
       <a href="http://www.mingw.org/">Mingw version of GCC</a>.
    </p>
    <p>
       <a href="http://astyle.sourceforge.net/">AStyle</a> is a source code formatter for C++ and
      Java code. SciTE has an Indent command defined for .cxx files that uses AStyle.
    </p>
    <p>
       <a href="http://winmerge.org/">WinMerge</a> is an interactive diff / merge
       for Windows. I prefer code submissions in the form of source files rather than diffs and then run
       WinMerge over the files to work out how to merge.
    </p>
    <p>
       <a href="http://www.python.org">Python</a> is my favourite programming language. Scintilla
      was started after I tried to improve the editor built into <a
      href="http://www.python.org/download/windows/">PythonWin</a>, but was frustrated by the limitations of
      the Windows Richedit control which PythonWin used.
    </p>
    <p>
       <a href="http://www.cse.yorku.ca/~oz/">regex</a> is a public domain
       implementation of regular expression pattern matching used in Scintilla.
    </p>
    <p>
       Inspirational coding soundscapes by <a href="http://www.davidbridie.com.au">David Bridie</a>.
    </p>
  </body>
</html>

Added doc/ScintillaToDo.html.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla and SciTE To Do
    </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          and SciTE</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Bugs and To Do List
    </h2>
    <h3>
       Feedback
    </h3>
    <p>
	Issues can be reported on the <a href="http://sourceforge.net/p/scintilla/bugs/">Bug Tracker</a>
	and features requested on	the <a href="http://sourceforge.net/p/scintilla/feature-requests/">Feature Request Tracker</a>.
    </p>
    <h3>
       Scintilla Bugs
    </h3>
    <p>
      Automatic scrolling when text dragged near edge of window.
    </p>
    <h3>
       Scintilla To Do
    </h3>
    <p>
       Folding for languages that don't have it yet and good folding for languages
       that inherited poor folding from another languages folding code.
    </p>
    <p>
       Simple pattern based styling.
    </p>
    <p>
       Different height lines based upon tallest text on the line rather than on the tallest style
      possible.
    </p>
    <p>
       Composition of lexing for mixed languages (such as ASP+ over COBOL) by
       combining lexers.
    </p>
    <p>
	Stream folding which could be used to fold up the contents of HTML elements.
    </p>
    <p>
	Printing of highlight lines and folding margin.
    </p>
    <p>
	Flow diagrams inside editor similar to
	GRASP.
    </p>
    <p>
	More lexers for other languages.
    </p>
    <h3>
	SciTE To Do
    </h3>
    <p>
	Good regular expression support through a plugin.
    </p>
    <p>
	Allow file name based selection on all properties rather than just a chosen few.
    </p>
    <p>
	Opening from and saving to FTP servers.
    </p>
    <p>
	Setting to fold away comments upon opening.
    </p>
    <p>
	User defined fold ranges.
    </p>
    <p>
	Silent mode that does not display any message boxes.
    </p>
    <h3>
	Features I am unlikely to do
    </h3>
    <p>
	These are features I don't like or don't think are important enough to work on.
	Implementations are welcome from others though.
    </p>
    <p>
	Mouse wheel panning (press the mouse wheel and then move the mouse) on
	Windows.
    </p>
    <p>
	Adding options to the save dialog to save in a particular encoding or with a
	chosen line ending.
    </p>
    <h3>
       Directions
    </h3>
    <p>
       The main point of this development is Scintilla, and this is where most effort will
       go. SciTE will get new features, but only when they make my life easier - I am
       not intending to make it grow up to be a huge full-function IDE like Visual
       Cafe. The lines I've currently decided not to step over in SciTE are any sort of
       project facility and any configuration dialogs. SciTE for Windows now has a
       Director interface for communicating with a separate project manager
       application.
    </p>
    <p>
       If you are interested in contributing code, do not feel any need to make it cross
       platform.
      Just code it for your platform and I'll either reimplement for the other platform or
      ensure that there is no effect on the other platform.
    </p>
  </body>
</html>

Added doc/ScintillaUsage.html.















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>
      Scintilla Usage Notes
    </title>
<style type="text/css">
SPAN {
    font-family: Verdana, Arial, Helvetica;
    font-size: 9pt;
}
.S0 {
    color: #808080;
    font-family: Verdana, Arial, Helvetica;
}
.S1 {
    font-family: Comic Sans MS, Times New Roman, Times;
    color: #007F00;
    font-size: 8pt;
}
.S2 {
    font-family: Comic Sans MS, Times New Roman, Times;
    color: #007F00;
    font-size: 8pt;
}
.S3 {
    font-family: Verdana, Arial, Helvetica;
    color: #7F7F7F;
}
.S4 {
    font-family: Verdana, Arial, Helvetica;
    color: #007F7F;
}
.S5 {
    color: #00007F;
    font-weight: bold;
    font-family: Verdana, Arial, Helvetica;
}
.S6 {
    color: #7F007F;
    font-family: Courier New, Courier;
}
.S7 {
    color: #7F007F;
    font-family: Courier New, Courier;
}
.S8 {
    color: #007F7F;
}
.S9 {
    color: #7F7F00;
}
.S10 {
    font-weight: bold;
}
</style>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">Scintilla
          Usage Notes</font></a>
        </td>
      </tr>
    </table>
    <h2>
       Implementing Auto-Indent
    </h2>
    <p>
       The key idea is to use the SCN_CHARADDED notification to add indentation after a newline.
    </p>
    <p>
       The lParam on the notification is a pointer to a SCNotification structure whose ch member
      specifies the character added. If a newline was added, the previous line can be retrieved and
      the same indentation can be added to the new line.
    </p>
    <p>
       Here is the relevant portion of code from SciTE: (SciTE.cxx SciTEWindow::CharAdded)
    </p>
    <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
    class='S11'>ch</span><span class='S0'>&nbsp;</span> <span class='S10'>==</span><span
    class='S0'>&nbsp;</span> <span class='S7'>'\r'</span><span class='S0'>&nbsp;</span> <span
    class='S10'>||</span><span class='S0'>&nbsp;</span> <span class='S11'>ch</span><span
    class='S0'>&nbsp;</span> <span class='S10'>==</span><span class='S0'>&nbsp;</span> <span
    class='S7'>'\n'</span><span class='S10'>)</span><span class='S0'>&nbsp;</span> <span
    class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>char</span><span class='S0'>&nbsp;</span>
    <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
    class='S10'>];</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
    <span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>GetCurrentLineNumber</span><span
    class='S10'>();</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
    <span class='S11'>lineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
    =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
    class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span class='S10'>);</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S2'>
    //Platform::DebugPrintf("[CR]&nbsp;%d&nbsp;len&nbsp;=&nbsp;%d\n",&nbsp;curLine,&nbsp;lineLength);</span><span
     class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
    class='S10'>(</span><span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span
    class='S10'>&gt;</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S0'>&nbsp;</span> <span class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span>
    <span class='S11'>lineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
    &lt;=</span><span class='S0'>&nbsp;</span> <span class='S4'>2</span><span
    class='S10'>)</span><span class='S0'>&nbsp;</span> <span class='S10'>{</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>int</span><span class='S0'>&nbsp;</span>
    <span class='S11'>prevLineLength</span><span class='S0'>&nbsp;</span> <span class='S10'>
    =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
    class='S10'>(</span><span class='S11'>SCI_LINELENGTH</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span class='S0'>&nbsp;</span> <span
    class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
    class='S10'>);</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
    class='S10'>(</span><span class='S11'>prevLineLength</span><span class='S0'>&nbsp;</span> <span
    class='S10'>&lt;</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
    class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>))</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>WORD</span><span
    class='S0'>&nbsp;</span> <span class='S11'>buflen</span><span class='S0'>&nbsp;</span> <span
    class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
    class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>);</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>memcpy</span><span
    class='S10'>(</span><span class='S11'>linebuf</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S10'>&amp;</span><span class='S11'>buflen</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S5'>sizeof</span><span
    class='S10'>(</span><span class='S11'>buflen</span><span class='S10'>));</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
    SendEditor</span><span class='S10'>(</span><span class='S11'>EM_GETLINE</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>curLine</span><span
    class='S0'>&nbsp;</span> <span class='S10'>-</span><span class='S0'>&nbsp;</span> <span
    class='S4'>1</span><span class='S10'>,</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S5'>reinterpret_cast</span><span class='S10'>&lt;</span><span
    class='S11'>LPARAM</span><span class='S10'>&gt;(</span><span class='S5'>static_cast</span><span
    class='S10'>&lt;</span><span class='S5'>char</span><span class='S0'>&nbsp;</span> <span
    class='S10'>*&gt;(</span><span class='S11'>linebuf</span><span class='S10'>)));</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>linebuf</span><span
    class='S10'>[</span><span class='S11'>prevLineLength</span><span class='S10'>]</span><span
    class='S0'>&nbsp;</span> <span class='S10'>=</span><span class='S0'>&nbsp;</span> <span
    class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>for</span><span
    class='S0'>&nbsp;</span> <span class='S10'>(</span><span class='S5'>int</span><span
    class='S0'>&nbsp;</span> <span class='S11'>pos</span><span class='S0'>&nbsp;</span> <span
    class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S10'>;</span><span class='S0'>&nbsp;</span> <span class='S11'>linebuf</span><span
    class='S10'>[</span><span class='S11'>pos</span><span class='S10'>];</span><span
    class='S0'>&nbsp;</span> <span class='S11'>pos</span><span class='S10'>++)</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span
    class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
    class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
    class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>!=</span><span
    class='S0'>&nbsp;</span> <span class='S7'>'&nbsp;'</span><span class='S0'>&nbsp;</span> <span
    class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span> <span class='S11'>
    linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
    class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>!=</span><span
    class='S0'>&nbsp;</span> <span class='S7'>'\t'</span><span class='S10'>)</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S11'>linebuf</span><span class='S10'>[</span><span class='S11'>pos</span><span
    class='S10'>]</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S7'>'\0'</span><span class='S10'>;</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S10'>}</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
    SendEditor</span><span class='S10'>(</span><span class='S11'>EM_REPLACESEL</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S5'>
    reinterpret_cast</span><span class='S10'>&lt;</span><span class='S11'>LPARAM</span><span
    class='S10'>&gt;(</span><span class='S5'>static_cast</span><span class='S10'>&lt;</span><span
    class='S5'>char</span><span class='S0'>&nbsp;</span> <span class='S10'>*&gt;(</span><span
    class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S10'>}</span><span class='S0'><br />
    </span> <span class='S10'>}</span><br />
     
    <p style="margin-bottom: 0in">
       Of course, fancier handling could be implemented. For example, if the previous line was the
      start of a control construct, the next line could be automatically indented one tab further.
      (Assuming that is your indenting style.)
    </p>
    <h2>
       Implementing Syntax Styling
    </h2>
    <p>
       Syntax styling is handled by the SCN_STYLENEEDED notification. Scintilla keeps track of the
      end of the styled text - this is retrieved with SCI_GETENDSTYLED. In response to the
      SCN_STYLENEEDED notification, you should apply styles to the text from ENDSTYLED to the
      position specified by the notification.
    </p>
    <p>
       Here is the relevant portion of code from SciTE: (SciTE.cxx)
    </p>
    <span class='S5'>void</span><span class='S0'>&nbsp;</span> <span class='S11'>
    SciTEWindow</span><span class='S10'>::</span><span class='S11'>Notify</span><span
    class='S10'>(</span><span class='S11'>SCNotification</span><span class='S0'>&nbsp;</span> <span
    class='S10'>*</span><span class='S11'>notification</span><span class='S10'>)</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>switch</span><span class='S0'>&nbsp;</span>
    <span class='S10'>(</span><span class='S11'>notification</span><span
    class='S10'>-&gt;</span><span class='S11'>nmhdr.code</span><span class='S10'>)</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>case</span><span class='S0'>&nbsp;</span>
    <span class='S11'>SCN_STYLENEEDED</span><span class='S10'>:</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span
    class='S5'>if</span><span class='S0'>&nbsp;</span> <span class='S10'>(</span><span
    class='S11'>notification</span><span class='S10'>-&gt;</span><span
    class='S11'>nmhdr.idFrom</span><span class='S0'>&nbsp;</span> <span class='S10'>==</span><span
    class='S0'>&nbsp;</span> <span class='S11'>IDM_SRCWIN</span><span class='S10'>)</span><span
    class='S0'>&nbsp;</span> <span class='S10'>{</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S5'>int</span><span class='S0'>&nbsp;</span> <span class='S11'>
    endStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
    class='S11'>SCI_GETENDSTYLED</span><span class='S10'>);</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S5'>int</span><span class='S0'>&nbsp;</span> <span class='S11'>
    lineEndStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
    class='S11'>EM_LINEFROMCHAR</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
    <span class='S11'>endStyled</span><span class='S10'>);</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S11'>endStyled</span><span class='S0'>&nbsp;</span> <span class='S10'>
    =</span><span class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span
    class='S10'>(</span><span class='S11'>EM_LINEINDEX</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>lineEndStyled</span><span class='S10'>);</span><span
    class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <span class='S11'>Colourise</span><span class='S10'>(</span><span
    class='S11'>endStyled</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>notification</span><span class='S10'>-&gt;</span><span
    class='S11'>position</span><span class='S10'>);</span><br />
     
    <p>
       Colourize(start, end) retrieves the specified range of text and then calls ColourizeDoc in
      keywords.cxx. It starts the process by calling:
    </p>
    &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessage</span><span class='S10'>(</span><span
    class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>SCI_STARTSTYLING</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
    <span class='S11'>startPos</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S4'>31</span><span class='S10'>);</span><br />
     
    <p>
       and then for each token of the text, calling:
    </p>
    &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessage</span><span class='S10'>(</span><span
    class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>SCI_SETSTYLING</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>length</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>style</span><span class='S10'>);</span><br />
     
    <p>
       where style is a number from 0 to 31 whose appearance has been defined using the
      SCI_STYLESET... messages.
    </p>
    <h2>
       Implementing Calltips
    </h2>
    <p>
       Again, the SCN_CHARADDED notification is used to catch when an opening parenthesis is added.
      The preceding word can then be retrieved from the current line:
    </p>
    &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>char</span><span class='S0'>&nbsp;</span> <span
    class='S11'>linebuf</span><span class='S10'>[</span><span class='S4'>1000</span><span
    class='S10'>];</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
    class='S11'>current</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
    class='S11'>SCI_GETCURLINE</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S5'>sizeof</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
    class='S10'>),</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S5'>
    reinterpret_cast</span><span class='S10'>&lt;</span><span class='S11'>LPARAM</span><span
    class='S10'>&gt;(</span><span class='S5'>static_cast</span><span class='S10'>&lt;</span><span
    class='S5'>char</span><span class='S0'>&nbsp;</span> <span class='S10'>*&gt;(</span><span
    class='S11'>linebuf</span><span class='S10'>)));</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
    class='S11'>pos</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SendEditor</span><span class='S10'>(</span><span
    class='S11'>SCI_GETCURRENTPOS</span><span class='S10'>);</span><span class='S0'><br />
    <br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>int</span><span class='S0'>&nbsp;</span> <span
    class='S11'>startword</span><span class='S0'>&nbsp;</span> <span class='S10'>=</span><span
    class='S0'>&nbsp;</span> <span class='S11'>current</span><span class='S0'>&nbsp;</span> <span
    class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
    class='S10'>;</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>while</span><span class='S0'>&nbsp;</span>
    <span class='S10'>(</span><span class='S11'>startword</span><span class='S0'>&nbsp;</span>
    <span class='S10'>&gt;</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S0'>&nbsp;</span> <span class='S10'>&amp;&amp;</span><span class='S0'>&nbsp;</span>
    <span class='S11'>isalpha</span><span class='S10'>(</span><span class='S11'>linebuf</span><span
    class='S10'>[</span><span class='S11'>startword</span><span class='S0'>&nbsp;</span> <span
    class='S10'>-</span><span class='S0'>&nbsp;</span> <span class='S4'>1</span><span
    class='S10'>]))</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
    startword</span><span class='S10'>--;</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>linebuf</span><span class='S10'>[</span><span
    class='S11'>current</span><span class='S0'>&nbsp;</span> <span class='S10'>-</span><span
    class='S0'>&nbsp;</span> <span class='S4'>1</span><span class='S10'>]</span><span
    class='S0'>&nbsp;</span> <span class='S10'>=</span><span class='S0'>&nbsp;</span> <span
    class='S7'>'\0'</span><span class='S10'>;</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>char</span><span class='S10'>*</span><span
    class='S0'>&nbsp;</span> <span class='S11'>word</span><span class='S0'>&nbsp;</span> <span
    class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S11'>linebuf</span><span
    class='S0'>&nbsp;</span> <span class='S10'>+</span><span class='S0'>&nbsp;</span> <span
    class='S11'>startword</span><span class='S10'>;</span><br />
     
    <p>
       Then if a calltip is available it can be displayed. The calltip appears immediately below
      the position specified. The calltip can be multiple lines separated by newlines (\n).
    </p>
    &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>pos</span><span class='S0'>&nbsp;</span> <span
    class='S10'>=</span><span class='S0'>&nbsp;</span> <span class='S11'>SendMessage</span><span
    class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SCI_GETCURRENTPOS</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>0</span><span
    class='S10'>);</span><span class='S0'><br />
    </span> &nbsp;&nbsp;&nbsp;&nbsp;<span class='S11'>SendMessageText</span><span
    class='S10'>(</span><span class='S11'>hwnd</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>SCI_CALLTIPSHOW</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>pos</span><span
    class='S0'>&nbsp;</span> <span class='S10'>-</span><span class='S0'>&nbsp;</span> <span
    class='S11'>wordLen</span><span class='S0'>&nbsp;</span> <span class='S10'>-</span><span
    class='S0'>&nbsp;</span> <span class='S4'>1</span><span class='S10'>,</span><span
    class='S0'>&nbsp;</span> <span class='S11'>calltip</span><span class='S10'>);</span><br />
     
    <p>
       The calltip can be removed when a closing parenthesis is entered:
    </p>
    &nbsp;&nbsp;&nbsp;&nbsp;<span class='S5'>if</span><span class='S0'>&nbsp;</span> <span
    class='S10'>(</span><span class='S11'>SendMessage</span><span class='S10'>(</span><span
    class='S11'>hwnd</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S11'>SCI_CALLTIPACTIVE</span><span class='S10'>,</span><span class='S0'>&nbsp;</span>
    <span class='S4'>0</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S4'>0</span><span class='S10'>))</span><span class='S0'><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span class='S11'>
    SendMessage</span><span class='S10'>(</span><span class='S11'>hwnd</span><span
    class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S11'>
    SCI_CALLTIPCANCEL</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span
    class='S4'>0</span><span class='S10'>,</span><span class='S0'>&nbsp;</span> <span class='S4'>
    0</span><span class='S10'>);</span><br />
     
    <p>
       Obviously, it is up the application to look after supplying the appropriate calltip text.
    </p>
    <p>
       SciTE goes one step further, counting the commas between arguments and highlighting the
      corresponding part of the calltip. This code is in ContinueCallTip.
    </p>
    <p>
       <i>Page contributed by Andrew McKinlay.</i>
    </p>
  </body>
</html>

Added doc/ScriptLexer.html.







































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SciTE Script Lexer</title>
<meta name="Generator" content="SciTE - www.Scintilla.org" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
.S0 {
	color: #FF0000;
}
.S2 {
	font-family: 'Comic Sans MS';
	color: #007F00;
	font-size: 9pt;
}
.S4 {
	color: #007F7F;
}
.S5 {
	color: #00007F;
	font-weight: bold;
}
.S6 {
	color: #7F007F;
}
.S10 {
	color: #000000;
}
.S14 {
	color: #00007F;
	background: #F5F5FF;
	text-decoration: inherit;
}
.Z0 {
	color: #7f007f;
	font-weight: bold;
}
.Z1 {
	color: #000000;
}
.Z2 {
	color: #000080;
	font-weight: bold;
}
.Z3 {
	color: #008000;
	font-family: 'Georgia';
	font-size: 9pt;
	font-style:italic;
}
span {
	font-family: 'Verdana';
	color: #000000;
	font-size: 10pt;
}
.example {
    color: #008000;
    font-weight: bold;
}
DIV.example {
	background: #F7FCF7;
	border: 1px solid #C0D7C0;
	margin: 0.3em 3em;
	padding: 0.3em 0.6em;
	font-size: 80%;
}
DIV.highlighted {
	background: #F7FCF7;
	border: 1px solid #C0D7C0;
	margin: 0.3em 3em;
	padding: 0.3em 0.6em;
	font-size: 80%;
}
table {
	border: 1px solid #1F1F1F;
	border-collapse: collapse;
}
td {
	border: 1px solid #1F1F1F;
	padding: 1px 5px 1px 5px;
}
th {
	border: 1px solid #1F1F1F;
	padding: 1px 5px 1px 5px;
}
</style>
</head>
<body bgcolor="#FFFFFF">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td>
          <img src="SciTEIco.png" border="3" height="64" width="64" alt="Scintilla icon" />
        </td>
        <td>
          <a href="index.html" style="color:white;text-decoration:none"><font size="5">
	  SciTE Script Lexer</font></a>
        </td>
      </tr>
    </table>
    <h3>
       Warning
    </h3>
	<p>This feature is being developed and is not stable. The API may change in the future.</p>
    <h3>
       Writing lexers in Lua
    </h3>
	<p>A lexer may be written as a script in the Lua language instead of in C++.
	This is a little simpler and allows lexers to be developed without using a C++ compiler.</p>
	<p>A script lexer is attached by setting the file lexer to be a name that starts with "script_".
	Styles and other properties can then be assigned using this name. For example,</p>
	<div class="example">
	lexer.*.zog=script_zog<br/>
style.script_zog.0=fore:#7f007f,bold<br/>
style.script_zog.1=fore:#000000<br/>
style.script_zog.2=fore:#000080,bold<br/>
style.script_zog.3=fore:#008000,font:Georgia,italics,size:9
	</div>
	<p>Then the lexer is implemented in Lua similar to this:</p>
<div class="highlighted">
<span><span class="S2">-- -*- coding: utf-8 -*-</span><br />
<br />
<span class="S5">function</span><span class="S0"> </span>OnStyle<span class="S10">(</span>styler<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>S_DEFAULT<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>S_IDENTIFIER<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">1</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>S_KEYWORD<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">2</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>S_UNICODECOMMENT<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">3</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>identifierCharacters<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S6">"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"</span><br />
<br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>StartStyling<span class="S10">(</span>styler.startPos<span class="S10">,</span><span class="S0"> </span>styler.lengthDoc<span class="S10">,</span><span class="S0"> </span>styler.initStyle<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">while</span><span class="S0"> </span>styler<span class="S10">:</span>More<span class="S10">()</span><span class="S0"> </span><span class="S5">do</span><br />
<br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">-- Exit state if needed</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>styler<span class="S10">:</span>State<span class="S10">()</span><span class="S0"> </span><span class="S10">==</span><span class="S0"> </span>S_IDENTIFIER<span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span><span class="S5">not</span><span class="S0"> </span>identifierCharacters<span class="S10">:</span>find<span class="S10">(</span>styler<span class="S10">:</span>Current<span class="S10">(),</span><span class="S0"> </span><span class="S4">1</span><span class="S10">,</span><span class="S0"> </span><span class="S5">true</span><span class="S10">)</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>identifier<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>styler<span class="S10">:</span>Token<span class="S10">()</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>identifier<span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">"if"</span><span class="S0"> </span><span class="S5">or</span><span class="S0"> </span>identifier<span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">"end"</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>ChangeState<span class="S10">(</span>S_KEYWORD<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>SetState<span class="S10">(</span>S_DEFAULT<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">elseif</span><span class="S0"> </span>styler<span class="S10">:</span>State<span class="S10">()</span><span class="S0"> </span><span class="S10">==</span><span class="S0"> </span>S_UNICODECOMMENT<span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>styler<span class="S10">:</span>Match<span class="S10">(</span><span class="S6">"»"</span><span class="S10">)</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>ForwardSetState<span class="S10">(</span>S_DEFAULT<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">-- Enter state if needed</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>styler<span class="S10">:</span>State<span class="S10">()</span><span class="S0"> </span><span class="S10">==</span><span class="S0"> </span>S_DEFAULT<span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>styler<span class="S10">:</span>Match<span class="S10">(</span><span class="S6">"«"</span><span class="S10">)</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>SetState<span class="S10">(</span>S_UNICODECOMMENT<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">elseif</span><span class="S0"> </span>identifierCharacters<span class="S10">:</span>find<span class="S10">(</span>styler<span class="S10">:</span>Current<span class="S10">(),</span><span class="S0"> </span><span class="S4">1</span><span class="S10">,</span><span class="S0"> </span><span class="S5">true</span><span class="S10">)</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>SetState<span class="S10">(</span>S_IDENTIFIER<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>Forward<span class="S10">()</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>styler<span class="S10">:</span>EndStyling<span class="S10">()</span><br />
<span class="S5">end</span><br />
<span class="S0"></span></span>
</div>

<p>
The result looks like
</p>

<div class="highlighted">
<span><span class="Z1">proc</span><span class="Z0"> </span><span class="Z1">clip</span><span class="Z0">(</span><span class="Z1">int</span><span class="Z0"> </span><span class="Z1">a</span><span class="Z0">)</span><br />
<span class="Z3">« Clip into the positive zone »</span><br />
<span class="Z2">if</span><span class="Z0"> (</span><span class="Z1">a</span><span class="Z0"> &gt; 0) </span><span class="Z1">a</span><br />
<span class="Z0">0</span><br />
<span class="Z2">end</span></span>
</div>
<br />
<h3>Code Structure</h3>
<h4>Document Loop</h4>
<p>The lexer loops through the part of the document indicated assigning a style to each character.</p>
<div class="highlighted">
<span>styler:StartStyling<span class="S10">(</span>styler.startPos<span class="S10">,</span><span class="S0"> </span>styler.lengthDoc<span class="S10">,</span><span class="S0"> </span>styler.initStyle<span class="S10"><span class="S10">)</span><br />
<span class="S5">while</span><span class="S0"> </span>styler:More<span class="S10">()</span><span class="S0"> </span><span class="S5">do</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S2">-- Code that examines the text and sets lexical states</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>styler:Forward<span class="S10">()</span><br />
<span class="S5">end</span><br />
styler:EndStyling<span class="S10">()</span><br />
</span></div>
<p>There are many different ways to structure the code that examines the text and sets lexical states.
A structure that has proven useful in C++ lexers is to write two blocks of code as shown in the example.
The first block checks if the current state should end and if so sets the state to the default 0.
The second block is responsible for detecting whether a new state should be entered from the default state.
This structure means everything is dealt with as switching from or to the default state and avoids having to consider many
combinations of states.</p>
<h4>Encodings</h4>
<p>The styler iterates over whole characters rather than bytes. Thus if the document is encoded in UTF-8, styler:Current() may be a multibyte string. If the script is also encoded in UTF-8,
then it is easy to check against Unicode characters with code like</p>
<div class="highlighted">
<span><span class="S5">if</span><span class="S0"> </span>styler:Current<span class="S10">()</span><span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">"«"</span><span class="S5"> then</span><br />
</span></div>
<p>If using an encoding like Latin-1 and the script is also encoded in the same encoding then literals can be used as above.</p>
<p>If the language can be encoded in different ways then more complex code may be needed along with encoding-specific code.</p>
<h4>Checking Before</h4>
<p>Sometimes a lexer needs to see some information earlier in the file, perhaps a declaration changes the syntax or the particular form of quote
at the start of a string must be matched at its end. Since the standard loop only goes forward from the starting position, different calls must be used like CharAt and StyleAt.
These use byte positions and do not treat multi-byte characters as single entities.</p>
<h4>Performance</h4>
<p>The lexer above can lex approximately 90K per second on a 2.4 GHz Athlon 64. For most situations, this will
feel completely fluid.</p>
<p>More complex lexers will be slower. If a lexer is so slow that the application becomes unresponsive then
the lexer can choose to split up each request. It can do so by deciding upon a range of whole lines and using this range as the
arguments to StartStyling. This allows the user's keystrokes and mouse moves to be processed.
The lexer will automatically be called again to lex more of the document.</p>
<br />
<h3>API</h3>
<p>The API of the styler object passed to OnStyle:</p>
<table cellpadding="0" cellspacing="0" border="1"  summary="Command line escape sequences">
<thead>
	<tr><th>Name</th><th>Explanation</th></tr>
</thead>
	<tr><td>StartStyling(startPos, length, initStyle)</td>
	<td>Start setting styles from startPos for length with initial style initStyle</td></tr>
	<tr><td>EndStyling()</td>
	<td>Styling has been completed so tidy up</td></tr>
	<tr><td>More() → boolean</td>
	<td>Are there any more characters to process</td></tr>
	<tr><td>Forward()</td>
	<td>Move forward one character</td></tr>
	<tr><td>Position() → integer</td>
	<td>What is the position in the document of the current character</td></tr>
	<tr><td>AtLineStart() → boolean</td>
	<td>Is the current character the first on a line</td></tr>
	<tr><td>AtLineEnd() → boolean</td>
	<td>Is the current character the last on a line</td></tr>
	<tr><td>State() → integer</td>
	<td>The current lexical state value</td></tr>
	<tr><td>SetState(state)</td>
	<td>Set the style of the current token to the current state and then change the state to the argument</td></tr>
	<tr><td>ForwardSetState(state)</td>
	<td>Combination of moving forward and setting the state. Useful when the current character is a token terminator like " for a string.</td></tr>
	<tr><td>ChangeState(state)</td>
	<td>Change the current state so that the state of the current token will be set to the argument</td></tr>
	<tr><td>Current() → string</td>
	<td>The current character</td></tr>
	<tr><td>Next() → string</td>
	<td>The next character</td></tr>
	<tr><td>Previous() → string</td>
	<td>The previous character</td></tr>
	<tr><td>Token() → string</td>
	<td>The current token</td></tr>
	<tr><td>Match(string) → boolean</td>
	<td>Is the text from the current position the same as the argument?</td></tr>

	<tr><td>Line(position) → integer</td>
	<td>Convert a byte position into a line number</td></tr>
	<tr><td>CharAt(position) → integer</td>
	<td>Unsigned byte value at argument</td></tr>
	<tr><td>StyleAt(position) → integer</td>
	<td>Style value at argument</td></tr>
	<tr><td>LevelAt(line) → integer</td>
	<td>Fold level for a line</td></tr>
	<tr><td>SetLevelAt(line, level)</td>
	<td>Set the fold level for a line</td></tr>
	<tr><td>LineState(line) → integer</td>
	<td>State value for a line</td></tr>
	<tr><td>SetLineState(line, state)</td>
	<td>Set state value for a line. This can be used to store extra information from lexing,
	such as a current language mode, so that there is no need to look back in the document.</td></tr>

	<tr><td>startPos : integer</td>
	<td>Start of the range to be lexed</td></tr>
	<tr><td>lengthDoc : integer</td>
	<td>Length of the range to be lexed</td></tr>
	<tr><td>initStyle : integer</td>
	<td>Starting style</td></tr>
	<tr><td>language : string</td>
	<td>Name of the language. Allows implementation of multiple languages with one OnStyle function.</td></tr>
</table>
<br />
    <h3>
       A line-oriented example.
    </h3>
    <p>This example is for a line-oriented language as is sometimes used for configuration files.
    It uses low level direct calls instead of the StartStyling/More/Forward/EndStyling calls.</p>
<div class="highlighted">
<span><span class="S2">-- A line oriented lexer - style the line according to the first character</span><br />
<span class="S5">function</span><span class="S0"> </span>OnStyle<span class="S10">(</span>styler<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>lineStart<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>editor<span class="S10">:</span>LineFromPosition<span class="S10">(</span>styler.startPos<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>lineEnd<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>editor<span class="S10">:</span>LineFromPosition<span class="S10">(</span>styler.startPos<span class="S0"> </span><span class="S10">+</span><span class="S0"> </span>styler.lengthDoc<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span>editor<span class="S10">:</span>StartStyling<span class="S10">(</span>styler.startPos<span class="S10">,</span><span class="S0"> </span><span class="S4">31</span><span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">for</span><span class="S0"> </span>line<span class="S10">=</span>lineStart<span class="S10">,</span>lineEnd<span class="S10">,</span><span class="S4">1</span><span class="S0"> </span><span class="S5">do</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>lengthLine<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>editor<span class="S10">:</span>PositionFromLine<span class="S10">(</span>line<span class="S10">+</span><span class="S4">1</span><span class="S10">)</span><span class="S0"> </span><span class="S10">-</span><span class="S0"> </span>editor<span class="S10">:</span>PositionFromLine<span class="S10">(</span>line<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>lineText<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span>editor<span class="S10">:</span>GetLine<span class="S10">(</span>line<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>first<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S14">string.sub</span><span class="S10">(</span>lineText<span class="S10">,</span><span class="S4">1</span><span class="S10">,</span><span class="S4">1</span><span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>style<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">if</span><span class="S0"> </span>first<span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">"+"</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>style<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">1</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">elseif</span><span class="S0"> </span>first<span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">" "</span><span class="S0"> </span><span class="S5">or</span><span class="S0"> </span>first<span class="S0"> </span><span class="S10">==</span><span class="S0"> </span><span class="S6">"\t"</span><span class="S0"> </span><span class="S5">then</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>style<span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">2</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>editor<span class="S10">:</span>SetStyling<span class="S10">(</span>lengthLine<span class="S10">,</span><span class="S0"> </span>style<span class="S10">)</span><br />
<span class="S0">&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="S5">end</span><br />
<span class="S5">end</span><br />
<span class="S0"></span></span>
</div>

</body>
</html>

Added doc/Steps.html.





























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"><title>How to use the Scintilla Edit Control in windows?</title></head><body bgcolor="#ffffff">
	<p><h2>How to use the Scintilla Edit Control in windows?</h2>
		<p>
			This should be a little step by step explanation how to use Scintilla in the windows environment.
		</p>
	</p>
	<p><h2>How to create Scintilla Edit Control?</h2>
		<p>
			First of all, load the Scintilla DLL with something like:
		</p>
		<pre>

	hmod = LoadLibrary(&quot;SciLexer.DLL&quot;);
		if (hmod==NULL)
		{
			MessageBox(hwndParent,
			&quot;The Scintilla DLL could not be loaded.&quot;,
			&quot;Error loading Scintilla&quot;,
			MB_OK | MB_ICONERROR);
		}
		</pre>
		<p>
			If the DLL was loaded successfully, then the DLL has registered (yes, by itself) a new
			window class. The new class called &quot;Scintilla&quot; is the new scintilla edit control.
		</p>
		<p>
			Now you can use this new control just like any other windows control.
		</p>
		<pre>

	hwndScintilla = CreateWindowEx(0,
		&quot;Scintilla&quot;,&quot;&quot;, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPCHILDREN,
		10,10,500,400,hwndParent,(HMENU)GuiID, hInstance,NULL);
		</pre>
		<p>
			Note the new window class name: &quot;Scintilla&quot;. By reaching this point you actually included
			a Scintilla Edit Control to your windows program.
		</p>
	</p>
	<p><h2>How to control the Scintilla Edit Control?</h2>
		<p>
			You can control Scintilla by sending commands to the Edit Control.
			There a 2 ways of doing this. A simple and fast way.
		</p>
		<p><h3>The simple way to control Scintilla</h3>
			<p>
				The simple way is just like with any other windows control. You can send messages to the
				Scintilla Edit Control and receive notifications from the control. (Note that the notifications
				are sent to the parent window of the Scintilla Edit Control.)
			</p>
			<p>
				The Scintilla Edit Control knows a special message for each command.
				To send commands to the Scintilla Edit Control you can use the SendMessage function.
			</p>
			<pre>

	SendMessage(hwndScintilla,sci_command,wparam,lparam);
			</pre>
			<p>
				like:
			</p>
			<pre>

	SendMessage(hwndScintilla,SCI_CREATEDOCUMENT, 0, 0);
			</pre>
			<p>
				Some of the commands will return a value and unused parameters should be set to NULL.
			</p>
		</p>
		<p><h3>The fast way to control Scintilla</h3>
			<p>
				The fast way of controlling the Scintilla Edit Control  is to call message handling function by yourself.
				You can retrieve a pointer to the message handling function of the Scintilla Edit Control and
				call it directly to execute a command. This way is much more faster than the SendMessage() way.
			</p>
			<p>
				1st you have to use the SCI_GETDIRECTFUNCTION and SCI_GETDIRECTPOINTER commands to
				retrieve the pointer to the function and a pointer which must be the first parameter when calling the retrieved
				function pointer.
				You have to do this with the SendMessage way :)
			</p>
			<p>
				The whole thing has to look like this:
			</p>
			<pre>

	int (*fn)(void*,int,int,int);
	void * ptr;
	int canundo;

	fn = (int (__cdecl *)(void *,int,int,int))SendMessage(
		hwndScintilla,SCI_GETDIRECTFUNCTION,0,0);
	ptr = (void *)SendMessage(hwndScintilla,SCI_GETDIRECTPOINTER,0,0);

	canundo = fn(ptr,SCI_CANUNDO,0,0);
			</pre>
			<p>
				with &quot;fn&quot; as the function pointer to the message handling function of the Scintilla Control
				and &quot;ptr&quot; as the pointer that must be used as 1st parameter.
				The next parameters are the Scintilla Command with its two (optional) parameters.
			</p>

		</p>
		<p><h3>How will I receive notifications?</h3>
			<p>
				Whenever an event occurs where Scintilla wants to inform you about something, the Scintilla Edit Control
				will send notification to the parent window. This is done by a WM_NOTITY message.
				When receiving that message, you have to look in the xxx struct for the actual message.
			</p>
			<p>
				So in Scintillas parent window message handling function you have to include some code like this:
			</p>
			<pre>
	NMHDR *lpnmhdr;

	[...]

	case WM_NOTIFY:
		lpnmhdr = (LPNMHDR) lParam;

		if(lpnmhdr-&gt;hwndFrom==hwndScintilla)
		{
			switch(lpnmhdr-&gt;code)
			{
				case SCN_CHARADDED:
					/* Hey, Scintilla just told me that a new */
					/* character was added to the Edit Control.*/
					/* Now i do something cool with that char. */
				break;
			}
		}
	break;
			</pre>
		</p>
	</p>

    <p>
       <i>Page contributed by Holger Schmidt.</i>
    </p>
</body></html>

Added doc/annotations.png.

cannot compute difference between binary files

Added doc/demo.png.

cannot compute difference between binary files

Added doc/index.html.















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />
    <meta name="generator" content="SciTE" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
    <meta name="Description"
    content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
    <meta name="Date.Modified" content="20130330" />
    <style type="text/css">
        #versionlist {
            margin: 0;
            padding: .5em;
            list-style-type: none;
            color: #FFCC99;
            background: #000000;
        }
        #versionlist li {
            margin-bottom: .5em;
        }
        #menu {
            margin: 0;
            padding: .5em 0;
            list-style-type: none;
            font-size: larger;
            background: #CCCCCC;
        }
        #menu li {
            margin: 0;
            padding: 0 .5em;
            display: inline;
        }
    </style>
    <script type="text/javascript">
   	function IsRemote() {
		var loc = '' + window.location;
		return loc.indexOf('http:') != -1;
   	}
    </script>
     <title>
       Scintilla and SciTE
     </title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td width="256">
          <img src="SciWord.jpg" height="78" width="256" alt="Scintilla" />
        </td>
        <td width="40%" align="left">
          <font color="#FFCC99" size="4"> A free source code editing component for Win32 and
          GTK+</font>
        </td>
        <td width="40%" align="right">
          <font color="#FFCC99" size="3"> Release version 3.3.0<br />
           Site last modified March 30 2013</font>
        </td>
        <td width="20%">
          &nbsp;
        </td>
      </tr>
    </table>
    <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
      <tr>
        <td width="100%" style="background: url(http://www.scintilla.org/SciBreak.jpg) no-repeat;height:150px;">
          &nbsp;
        </td>
      </tr>
    </table>
    <ul id="versionlist">
      <li>Version 3.3.0 implements overlay scrollers and kinetic scrolling on Cocoa.
      Performance improved on GTK+ and Cocoa by performing more work in 
      high-priority idle tasks.</li>
      <li>Version 3.2.5 SCI_ALLOCATEEXTENDEDSTYLES introduced so that different uses
      of extended styles can cooperate.
	Unicode line ends and substyles are added as provisional features which means
	they may change before becoming permanent.</li>
    </ul>
    <ul id="menu">
      <li id="remote1"><a href="http://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
      <li id="remote2"><a href="http://www.scintilla.org/ScintillaDownload.html">Download</a></li>
      <li><a href="http://www.scintilla.org/ScintillaDoc.html">Documentation</a></li>
      <li><a href="http://www.scintilla.org/ScintillaToDo.html">Bugs</a></li>
      <li id="remote3"><a href="http://www.scintilla.org/SciTE.html">SciTE</a></li>
      <li><a href="http://www.scintilla.org/ScintillaHistory.html">History</a></li>
      <li><a href="http://www.scintilla.org/ScintillaRelated.html">Related</a></li>
    </ul>
<script type="text/javascript" language="JavaScript"><!--
if (!IsRemote()) { //if NOT remote...
    document.getElementById('remote1').style.display='none';
    document.getElementById('remote2').style.display='none';
    document.getElementById('remote3').style.display='none';
}
//--></script>
    <p>
       <a href="http://www.scintilla.org/ScintillaDoc.html">Scintilla</a> is a free source code editing component.
       It comes with complete source code and a <a href="http://www.scintilla.org/License.txt">license</a> that
       permits use in any free project or commercial product.
    </p>
    <p>
       As well as features found in standard text editing components, Scintilla includes features
       especially useful when editing and debugging source code.
       These include support for syntax styling, error indicators, code completion and call tips.
       The selection margin can contain markers like those used in debuggers to indicate
       breakpoints and the current line. Styling choices are more open than with many editors,
       allowing the use of proportional fonts, bold and italics, multiple foreground and background
       colours and multiple fonts.
    </p>
    <p>
       <a href="http://www.scintilla.org/SciTE.html">SciTE</a> is a SCIntilla based Text Editor. Originally built to
      demonstrate Scintilla, it has grown to be a generally useful editor with facilities for
      building and running programs. It is best used for jobs with simple configurations - I use it
      for building test and demonstration programs as well as SciTE and Scintilla, themselves.
    </p>
    <p>
       Development of Scintilla started as an effort to improve the text editor in PythonWin. After
      being frustrated by problems in the Richedit control used by PythonWin, it looked like the
      best way forward was to write a new edit control. The biggest problem with Richedit and other
      similar controls is that they treat styling changes as important persistent changes to the
      document so they are saved into the undo stack and set the document's dirty flag. For source
      code, styling should not be persisted as it can be mechanically recreated.
    </p>
    <p>
       Scintilla and SciTE are currently available for Intel Win32 and Linux compatible operating
      systems with GTK+. They have been run on Windows XP, Windows 7, and on Ubuntu 10.10
      with GTK+ 2.20. <a href="http://www.scintilla.org/SciTEImage.html">Here is a screenshot of
      SciTE.</a><br />
    </p>
    <p>
       You can <a href="http://www.scintilla.org/ScintillaDownload.html">download Scintilla.</a>
    </p>
    <p>
       The source code can be downloaded via Mercurial at the Source Forge
	<a href="https://sourceforge.net/project/?group_id=2439">Scintilla project page</a>.
    </p>
    <p>
       <a href="http://www.scintilla.org/ScintillaRelated.html">Related sites.</a>
    </p>
    <p>
       <a href="http://www.scintilla.org/ScintillaToDo.html">Bugs and To Do list.</a>
    </p>
    <p>
       <a href="http://www.scintilla.org/ScintillaHistory.html">History and contribution credits.</a>
    </p>
    <p>
       <a href="http://www.scintilla.org/Icons.html">Icons that can be used with Scintilla.</a>
    </p>
    <p>
      Questions and comments about Scintilla should be directed to the
      <a href="http://groups.google.com/group/scintilla-interest">scintilla-interest</a>
      mailing list,
      which is for discussion of Scintilla and related projects, their bugs and future features.
      This is a low traffic list, averaging less than 50 messages per week.
      To avoid spam, only list members can write to the list.
      New versions of Scintilla are announced on scintilla-interest and may also be received by SourceForge
      members by clicking on the Monitor column icon for "scintilla" on
      <a href="https://sourceforge.net/project/showfiles.php?group_id=2439">the downloads page</a>.
      Messages sent to my personal email address that could have been sent to the list
      may receive no response.
      <br />
    </p>
There is a <a href="https://sourceforge.net/project/?group_id=2439">Scintilla project page</a>
hosted on
<script type="text/javascript" language="JavaScript">
<!--
if (IsRemote()) {
    document.write('<a href="http://sourceforge.net/projects/scintilla">');
    document.write('<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a> ');
} else {
    document.write('<a href="http://sourceforge.net/projects/scintilla">SourceForge<\/a>');
}
//-->
</script>
<noscript>
<a href="http://sourceforge.net/projects/scintilla">
<img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2439&amp;type=8" width="80" height="15" alt="Get Scintilla at SourceForge.net. Fast, secure and Free Open Source software downloads" /></a>
</noscript>
  </body>
</html>

Added doc/scite.1.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
.TH SCITE 1 "2001 February 26"
.SH NAME
SciTE \- a programmers text editor
.SH SYNOPSIS
.br
.B SciTE
[file ..]
.SH DESCRIPTION
.B SciTE
is a graphical GTK+ based editor. It has support
for indenting, highlighting, and shortcuts in a myriad
of languages and can be extended by editing object-oriented
configuration files.
.PP
Support is included for Java, C, C++, C#, Shell, Apache.
.SH ON-LINE HELP
Type Alt-H or Click the Help Pulldown menu.
.SH AUTHOR
Most of
.B SciTE
was made by Neil Hodgson, with a lot of help from others.
See Help
.br
.SH BUGS
Probably.

Added doc/styledmargin.png.

cannot compute difference between binary files

Added gtk/Converter.h.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
// Converter.h - Encapsulation of iconv
// Copyright 2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

typedef GIConv ConverterHandle;
const ConverterHandle iconvhBad = (ConverterHandle)(-1);
// Since various versions of iconv can not agree on whether the src argument
// is char ** or const char ** provide a templatised adaptor.
template<typename T>
size_t iconv_adaptor(size_t(*f_iconv)(ConverterHandle, T, size_t *, char **, size_t *),
		ConverterHandle cd, char** src, size_t *srcleft,
		char **dst, size_t *dstleft) {
	return f_iconv(cd, (T)src, srcleft, dst, dstleft);
}
/**
 * Encapsulate iconv safely and avoid iconv_adaptor complexity in client code.
 */
class Converter {
	ConverterHandle iconvh;
	void OpenHandle(const char *fullDestination, const char *charSetSource) {
		iconvh = g_iconv_open(fullDestination, charSetSource);
	}
	bool Succeeded() const {
		return iconvh != iconvhBad;
	}
public:
	Converter() {
		iconvh = iconvhBad;
	}
	Converter(const char *charSetDestination, const char *charSetSource, bool transliterations) {
		iconvh = iconvhBad;
	    	Open(charSetDestination, charSetSource, transliterations);
	}
	~Converter() {
		Close();
	}
	operator bool() const {
		return Succeeded();
	}
	void Open(const char *charSetDestination, const char *charSetSource, bool transliterations=true) {
		Close();
		if (*charSetSource) {
			// Try allowing approximate transliterations
			if (transliterations) {
				char fullDest[200];
				strcpy(fullDest, charSetDestination);
				strcat(fullDest, "//TRANSLIT");
				OpenHandle(fullDest, charSetSource);
			}
			if (!Succeeded()) {
				// Transliterations failed so try basic name
				OpenHandle(charSetDestination, charSetSource);
			}
		}
	}
	void Close() {
		if (Succeeded()) {
			g_iconv_close(iconvh);
			iconvh = iconvhBad;
		}
	}
	size_t Convert(char** src, size_t *srcleft, char **dst, size_t *dstleft) const {
		if (!Succeeded()) {
			return (size_t)(-1);
		} else {
			return iconv_adaptor(g_iconv, iconvh, src, srcleft, dst, dstleft);
		}
	}
};

Added gtk/PlatGTK.cxx.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
// Scintilla source code edit control
// PlatGTK.cxx - implementation of platform facilities on GTK+/Linux
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>

#include <vector>
#include <map>

#include <glib.h>
#include <gmodule.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "Platform.h"

#include "Scintilla.h"
#include "ScintillaWidget.h"
#include "UniConversion.h"
#include "XPM.h"

#if defined(__clang__)
// Clang 3.0 incorrectly displays  sentinel warnings. Fixed by clang 3.1.
#pragma GCC diagnostic ignored "-Wsentinel"
#endif

/* GLIB must be compiled with thread support, otherwise we
   will bail on trying to use locks, and that could lead to
   problems for someone.  `glib-config --libs gthread` needs
   to be used to get the glib libraries for linking, otherwise
   g_thread_init will fail */
#define USE_LOCK defined(G_THREADS_ENABLED) && !defined(G_THREADS_IMPL_NONE)

#include "Converter.h"

#if GTK_CHECK_VERSION(2,20,0)
#define IS_WIDGET_FOCUSSED(w) (gtk_widget_has_focus(GTK_WIDGET(w)))
#else
#define IS_WIDGET_FOCUSSED(w) (GTK_WIDGET_HAS_FOCUS(w))
#endif

// The Pango version guard for pango_units_from_double and pango_units_to_double 
// is more complex than simply implementing these here.

static int pangoUnitsFromDouble(double d) {
	return static_cast<int>(d * PANGO_SCALE + 0.5);
}

static double doubleFromPangoUnits(int pu) {
	return static_cast<double>(pu) / PANGO_SCALE;
}

static cairo_surface_t *CreateSimilarSurface(GdkWindow *window, cairo_content_t content, int width, int height) {
#if GTK_CHECK_VERSION(2,22,0)
	return gdk_window_create_similar_surface(window, content, width, height);
#else
	cairo_surface_t *window_surface, *surface;

	g_return_val_if_fail(GDK_IS_WINDOW(window), NULL);

	window_surface = GDK_DRAWABLE_GET_CLASS(window)->ref_cairo_surface(window);

	surface = cairo_surface_create_similar(window_surface, content, width, height);

	cairo_surface_destroy(window_surface);

	return surface;
#endif
}

static GdkWindow *WindowFromWidget(GtkWidget *w) {
#if GTK_CHECK_VERSION(3,0,0)
	return gtk_widget_get_window(w);
#else
	return w->window;
#endif
}

#ifdef _MSC_VER
// Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505)
#endif

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

enum encodingType { singleByte, UTF8, dbcs};

struct LOGFONT {
	int size;
	int weight;
	bool italic;
	int characterSet;
	char faceName[300];
};

#if USE_LOCK
static GMutex *fontMutex = NULL;

static void InitializeGLIBThreads() {
#if !GLIB_CHECK_VERSION(2,31,0)
	if (!g_thread_supported()) {
		g_thread_init(NULL);
	}
#endif
}
#endif

static void FontMutexAllocate() {
#if USE_LOCK
	if (!fontMutex) {
		InitializeGLIBThreads();
#if GLIB_CHECK_VERSION(2,31,0)
		fontMutex = g_new(GMutex, 1);
		g_mutex_init(fontMutex);
#else
		fontMutex = g_mutex_new();
#endif
	}
#endif
}

static void FontMutexFree() {
#if USE_LOCK
	if (fontMutex) {
#if GLIB_CHECK_VERSION(2,31,0)
		g_mutex_clear(fontMutex);
		g_free(fontMutex);
#else
		g_mutex_free(fontMutex);
#endif
		fontMutex = NULL;
	}
#endif
}

static void FontMutexLock() {
#if USE_LOCK
	g_mutex_lock(fontMutex);
#endif
}

static void FontMutexUnlock() {
#if USE_LOCK
	if (fontMutex) {
		g_mutex_unlock(fontMutex);
	}
#endif
}

// Holds a PangoFontDescription*.
class FontHandle {
	XYPOSITION width[128];
	encodingType et;
public:
	int ascent;
	PangoFontDescription *pfd;
	int characterSet;
	FontHandle() : et(singleByte), ascent(0), pfd(0), characterSet(-1) {
		ResetWidths(et);
	}
	FontHandle(PangoFontDescription *pfd_, int characterSet_) {
		et = singleByte;
		ascent = 0;
		pfd = pfd_;
		characterSet = characterSet_;
		ResetWidths(et);
	}
	~FontHandle() {
		if (pfd)
			pango_font_description_free(pfd);
		pfd = 0;
	}
	void ResetWidths(encodingType et_) {
		et = et_;
		for (int i=0; i<=127; i++) {
			width[i] = 0;
		}
	}
	XYPOSITION CharWidth(unsigned char ch, encodingType et_) {
		XYPOSITION w = 0;
		FontMutexLock();
		if ((ch <= 127) && (et == et_)) {
			w = width[ch];
		}
		FontMutexUnlock();
		return w;
	}
	void SetCharWidth(unsigned char ch, XYPOSITION w, encodingType et_) {
		if (ch <= 127) {
			FontMutexLock();
			if (et != et_) {
				ResetWidths(et_);
			}
			width[ch] = w;
			FontMutexUnlock();
		}
	}
};

// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
static const int maxCoordinate = 32000;

static FontHandle *PFont(Font &f) {
	return reinterpret_cast<FontHandle *>(f.GetID());
}

static GtkWidget *PWidget(WindowID wid) {
	return reinterpret_cast<GtkWidget *>(wid);
}

Point Point::FromLong(long lpoint) {
	return Point(
	           Platform::LowShortFromLong(lpoint),
	           Platform::HighShortFromLong(lpoint));
}

static void SetLogFont(LOGFONT &lf, const char *faceName, int characterSet, float size, int weight, bool italic) {
	memset(&lf, 0, sizeof(lf));
	lf.size = size;
	lf.weight = weight;
	lf.italic = italic;
	lf.characterSet = characterSet;
	strncpy(lf.faceName, faceName, sizeof(lf.faceName) - 1);
}

/**
 * Create a hash from the parameters for a font to allow easy checking for identity.
 * If one font is the same as another, its hash will be the same, but if the hash is the
 * same then they may still be different.
 */
static int HashFont(const FontParameters &fp) {
	return
	    static_cast<int>(fp.size+0.5) ^
	    (fp.characterSet << 10) ^
	    ((fp.weight / 100) << 12) ^
	    (fp.italic ? 0x20000000 : 0) ^
	    fp.faceName[0];
}

class FontCached : Font {
	FontCached *next;
	int usage;
	LOGFONT lf;
	int hash;
	FontCached(const FontParameters &fp);
	~FontCached() {}
	bool SameAs(const FontParameters &fp);
	virtual void Release();
	static FontID CreateNewFont(const FontParameters &fp);
	static FontCached *first;
public:
	static FontID FindOrCreate(const FontParameters &fp);
	static void ReleaseId(FontID fid_);
};

FontCached *FontCached::first = 0;

FontCached::FontCached(const FontParameters &fp) :
next(0), usage(0), hash(0) {
	::SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic);
	hash = HashFont(fp);
	fid = CreateNewFont(fp);
	usage = 1;
}

bool FontCached::SameAs(const FontParameters &fp) {
	return
	    lf.size == fp.size &&
	    lf.weight == fp.weight &&
	    lf.italic == fp.italic &&
	    lf.characterSet == fp.characterSet &&
	    0 == strcmp(lf.faceName, fp.faceName);
}

void FontCached::Release() {
	if (fid)
		delete PFont(*this);
	fid = 0;
}

FontID FontCached::FindOrCreate(const FontParameters &fp) {
	FontID ret = 0;
	FontMutexLock();
	int hashFind = HashFont(fp);
	for (FontCached *cur = first; cur; cur = cur->next) {
		if ((cur->hash == hashFind) &&
		        cur->SameAs(fp)) {
			cur->usage++;
			ret = cur->fid;
		}
	}
	if (ret == 0) {
		FontCached *fc = new FontCached(fp);
		if (fc) {
			fc->next = first;
			first = fc;
			ret = fc->fid;
		}
	}
	FontMutexUnlock();
	return ret;
}

void FontCached::ReleaseId(FontID fid_) {
	FontMutexLock();
	FontCached **pcur = &first;
	for (FontCached *cur = first; cur; cur = cur->next) {
		if (cur->fid == fid_) {
			cur->usage--;
			if (cur->usage == 0) {
				*pcur = cur->next;
				cur->Release();
				cur->next = 0;
				delete cur;
			}
			break;
		}
		pcur = &cur->next;
	}
	FontMutexUnlock();
}

FontID FontCached::CreateNewFont(const FontParameters &fp) {
	PangoFontDescription *pfd = pango_font_description_new();
	if (pfd) {
		pango_font_description_set_family(pfd, 
			(fp.faceName[0] == '!') ? fp.faceName+1 : fp.faceName);
		pango_font_description_set_size(pfd, pangoUnitsFromDouble(fp.size));
		pango_font_description_set_weight(pfd, static_cast<PangoWeight>(fp.weight));
		pango_font_description_set_style(pfd, fp.italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
		return new FontHandle(pfd, fp.characterSet);
	}

	return new FontHandle();
}

Font::Font() : fid(0) {}

Font::~Font() {}

void Font::Create(const FontParameters &fp) {
	Release();
	fid = FontCached::FindOrCreate(fp);
}

void Font::Release() {
	if (fid)
		FontCached::ReleaseId(fid);
	fid = 0;
}

// Required on OS X
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

// SurfaceID is a cairo_t*
class SurfaceImpl : public Surface {
	encodingType et;
	cairo_t *context;
	cairo_surface_t *psurf;
	int x;
	int y;
	bool inited;
	bool createdGC;
	PangoContext *pcontext;
	PangoLayout *layout;
	Converter conv;
	int characterSet;
	void SetConverter(int characterSet_);
public:
	SurfaceImpl();
	virtual ~SurfaceImpl();

	void Init(WindowID wid);
	void Init(SurfaceID sid, WindowID wid);
	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);

	void Release();
	bool Initialised();
	void PenColour(ColourDesired fore);
	int LogPixelsY();
	int DeviceHeightFont(int points);
	void MoveTo(int x_, int y_);
	void LineTo(int x_, int y_);
	void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back);
	void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back);
	void FillRectangle(PRectangle rc, ColourDesired back);
	void FillRectangle(PRectangle rc, Surface &surfacePattern);
	void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back);
	void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags);
	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back);
	void Copy(PRectangle rc, Point from, Surface &surfaceSource);

	void DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
	XYPOSITION WidthText(Font &font_, const char *s, int len);
	XYPOSITION WidthChar(Font &font_, char ch);
	XYPOSITION Ascent(Font &font_);
	XYPOSITION Descent(Font &font_);
	XYPOSITION InternalLeading(Font &font_);
	XYPOSITION ExternalLeading(Font &font_);
	XYPOSITION Height(Font &font_);
	XYPOSITION AverageCharWidth(Font &font_);

	void SetClip(PRectangle rc);
	void FlushCachedState();

	void SetUnicodeMode(bool unicodeMode_);
	void SetDBCSMode(int codePage);
};
#ifdef SCI_NAMESPACE
}
#endif

const char *CharacterSetID(int characterSet) {
	switch (characterSet) {
	case SC_CHARSET_ANSI:
		return "";
	case SC_CHARSET_DEFAULT:
		return "ISO-8859-1";
	case SC_CHARSET_BALTIC:
		return "ISO-8859-13";
	case SC_CHARSET_CHINESEBIG5:
		return "BIG-5";
	case SC_CHARSET_EASTEUROPE:
		return "ISO-8859-2";
	case SC_CHARSET_GB2312:
		return "CP936";
	case SC_CHARSET_GREEK:
		return "ISO-8859-7";
	case SC_CHARSET_HANGUL:
		return "CP949";
	case SC_CHARSET_MAC:
		return "MACINTOSH";
	case SC_CHARSET_OEM:
		return "ASCII";
	case SC_CHARSET_RUSSIAN:
		return "KOI8-R";
	case SC_CHARSET_CYRILLIC:
		return "CP1251";
	case SC_CHARSET_SHIFTJIS:
		return "SHIFT-JIS";
	case SC_CHARSET_SYMBOL:
		return "";
	case SC_CHARSET_TURKISH:
		return "ISO-8859-9";
	case SC_CHARSET_JOHAB:
		return "CP1361";
	case SC_CHARSET_HEBREW:
		return "ISO-8859-8";
	case SC_CHARSET_ARABIC:
		return "ISO-8859-6";
	case SC_CHARSET_VIETNAMESE:
		return "";
	case SC_CHARSET_THAI:
		return "ISO-8859-11";
	case SC_CHARSET_8859_15:
		return "ISO-8859-15";
	default:
		return "";
	}
}

void SurfaceImpl::SetConverter(int characterSet_) {
	if (characterSet != characterSet_) {
		characterSet = characterSet_;
		conv.Open("UTF-8", CharacterSetID(characterSet), false);
	}
}

SurfaceImpl::SurfaceImpl() : et(singleByte),
context(0),
psurf(0),
x(0), y(0), inited(false), createdGC(false)
, pcontext(0), layout(0), characterSet(-1) {
}

SurfaceImpl::~SurfaceImpl() {
	Release();
}

void SurfaceImpl::Release() {
	et = singleByte;
	if (createdGC) {
		createdGC = false;
		cairo_destroy(context);
	}
	context = 0;
	if (psurf)
		cairo_surface_destroy(psurf);
	psurf = 0;
	if (layout)
		g_object_unref(layout);
	layout = 0;
	if (pcontext)
		g_object_unref(pcontext);
	pcontext = 0;
	conv.Close();
	characterSet = -1;
	x = 0;
	y = 0;
	inited = false;
	createdGC = false;
}

bool SurfaceImpl::Initialised() {
	return inited;
}

void SurfaceImpl::Init(WindowID wid) {
	Release();
	PLATFORM_ASSERT(wid);
#if GTK_CHECK_VERSION(3,0,0)
	GdkWindow *drawable_ = gtk_widget_get_window(PWidget(wid));
#else
	GdkDrawable *drawable_ = GDK_DRAWABLE(PWidget(wid)->window);
#endif
	if (drawable_) {
		context = gdk_cairo_create(drawable_);
		PLATFORM_ASSERT(context);
	} else {
		// Shouldn't happen with valid window but may when calls made before
		// window completely allocated and mapped.
		psurf = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1);
		context = cairo_create(psurf);
	}
	createdGC = true;
	pcontext = gtk_widget_create_pango_context(PWidget(wid));
	PLATFORM_ASSERT(pcontext);
	layout = pango_layout_new(pcontext);
	PLATFORM_ASSERT(layout);
	inited = true;
}

void SurfaceImpl::Init(SurfaceID sid, WindowID wid) {
	PLATFORM_ASSERT(sid);
	Release();
	PLATFORM_ASSERT(wid);
	context = cairo_reference(reinterpret_cast<cairo_t *>(sid));
	pcontext = gtk_widget_create_pango_context(PWidget(wid));
	// update the Pango context in case sid isn't the widget's surface
	pango_cairo_update_context(context, pcontext);
	layout = pango_layout_new(pcontext);
	cairo_set_line_width(context, 1);
	createdGC = true;
	inited = true;
}

void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID wid) {
	PLATFORM_ASSERT(surface_);
	Release();
	SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
	PLATFORM_ASSERT(wid);
	context = cairo_reference(surfImpl->context);
	pcontext = gtk_widget_create_pango_context(PWidget(wid));
	// update the Pango context in case surface_ isn't the widget's surface
	pango_cairo_update_context(context, pcontext);
	PLATFORM_ASSERT(pcontext);
	layout = pango_layout_new(pcontext);
	PLATFORM_ASSERT(layout);
	if (height > 0 && width > 0)
		psurf = CreateSimilarSurface(
			WindowFromWidget(PWidget(wid)),
			CAIRO_CONTENT_COLOR_ALPHA, width, height);
	cairo_destroy(context);
	context = cairo_create(psurf);
	cairo_rectangle(context, 0, 0, width, height);
	cairo_set_source_rgb(context, 1.0, 0, 0);
	cairo_fill(context);
	// This produces sharp drawing more similar to GDK:
	//cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
	cairo_set_line_width(context, 1);
	createdGC = true;
	inited = true;
}

void SurfaceImpl::PenColour(ColourDesired fore) {
	if (context) {
		ColourDesired cdFore(fore.AsLong());
		cairo_set_source_rgb(context,
			cdFore.GetRed() / 255.0,
			cdFore.GetGreen() / 255.0,
			cdFore.GetBlue() / 255.0);
	}
}

int SurfaceImpl::LogPixelsY() {
	return 72;
}

int SurfaceImpl::DeviceHeightFont(int points) {
	int logPix = LogPixelsY();
	return (points * logPix + logPix / 2) / 72;
}

void SurfaceImpl::MoveTo(int x_, int y_) {
	x = x_;
	y = y_;
}

static int Delta(int difference) {
	if (difference < 0)
		return -1;
	else if (difference > 0)
		return 1;
	else
		return 0;
}

void SurfaceImpl::LineTo(int x_, int y_) {
	// cairo_line_to draws the end position, unlike Win32 or GDK with GDK_CAP_NOT_LAST.
	// For simple cases, move back one pixel from end.
	if (context) {
		int xDiff = x_ - x;
		int xDelta = Delta(xDiff);
		int yDiff = y_ - y;
		int yDelta = Delta(yDiff);
		if ((xDiff == 0) || (yDiff == 0)) {
			// Horizontal or vertical lines can be more precisely drawn as a filled rectangle
			int xEnd = x_ - xDelta;
			int left = Platform::Minimum(x, xEnd);
			int width = abs(x - xEnd) + 1;
			int yEnd = y_ - yDelta;
			int top = Platform::Minimum(y, yEnd);
			int height = abs(y - yEnd) + 1;
			cairo_rectangle(context, left, top, width, height);
			cairo_fill(context);
		} else if ((abs(xDiff) == abs(yDiff))) {
			// 45 degree slope
			cairo_move_to(context, x + 0.5, y + 0.5);
			cairo_line_to(context, x_ + 0.5 - xDelta, y_ + 0.5 - yDelta);
		} else {
			// Line has a different slope so difficult to avoid last pixel
			cairo_move_to(context, x + 0.5, y + 0.5);
			cairo_line_to(context, x_ + 0.5, y_ + 0.5);
		}
		cairo_stroke(context);
	}
	x = x_;
	y = y_;
}

void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore,
                          ColourDesired back) {
	PenColour(back);
	cairo_move_to(context, pts[0].x + 0.5, pts[0].y + 0.5);
	for (int i = 1;i < npts;i++) {
		cairo_line_to(context, pts[i].x + 0.5, pts[i].y + 0.5);
	}
	cairo_close_path(context);
	cairo_fill_preserve(context);
	PenColour(fore);
	cairo_stroke(context);
}

void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) {
	if (context) {
		cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5,
	                     rc.right - rc.left - 1, rc.bottom - rc.top - 1);
		PenColour(back);
		cairo_fill_preserve(context);
		PenColour(fore);
		cairo_stroke(context);
	}
}

void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) {
	PenColour(back);
	if (context && (rc.left < maxCoordinate)) {	// Protect against out of range
		rc.left = lround(rc.left);
		rc.right = lround(rc.right);
		cairo_rectangle(context, rc.left, rc.top,
	                     rc.right - rc.left, rc.bottom - rc.top);
		cairo_fill(context);
	}
}

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
	SurfaceImpl &surfi = static_cast<SurfaceImpl &>(surfacePattern);
	bool canDraw = surfi.psurf;
	if (canDraw) {
		// Tile pattern over rectangle
		// Currently assumes 8x8 pattern
		int widthPat = 8;
		int heightPat = 8;
		for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
			int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
			for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
				int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
				cairo_set_source_surface(context, surfi.psurf, xTile, yTile);
				cairo_rectangle(context, xTile, yTile, widthx, heighty);
				cairo_fill(context);
			}
		}
	} else {
		// Something is wrong so try to show anyway
		// Shows up black because colour not allocated
		FillRectangle(rc, ColourDesired(0));
	}
}

void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) {
	if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) {
		// Approximate a round rect with some cut off corners
		Point pts[] = {
		                  Point(rc.left + 2, rc.top),
		                  Point(rc.right - 2, rc.top),
		                  Point(rc.right, rc.top + 2),
		                  Point(rc.right, rc.bottom - 2),
		                  Point(rc.right - 2, rc.bottom),
		                  Point(rc.left + 2, rc.bottom),
		                  Point(rc.left, rc.bottom - 2),
		                  Point(rc.left, rc.top + 2),
		              };
		Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back);
	} else {
		RectangleDraw(rc, fore, back);
	}
}

static void PathRoundRectangle(cairo_t *context, double left, double top, double width, double height, int radius) {
	double degrees = M_PI / 180.0;

#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 2, 0)
	cairo_new_sub_path(context);
#else
	// First arc is in the top-right corner and starts from a point on the top line
	cairo_move_to(context, left + width - radius, top);
#endif
	cairo_arc(context, left + width - radius, top + radius, radius, -90 * degrees, 0 * degrees);
	cairo_arc(context, left + width - radius, top + height - radius, radius, 0 * degrees, 90 * degrees);
	cairo_arc(context, left + radius, top + height - radius, radius, 90 * degrees, 180 * degrees);
	cairo_arc(context, left + radius, top + radius, radius, 180 * degrees, 270 * degrees);
	cairo_close_path(context);
}

void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags) {
	if (context && rc.Width() > 0) {
		ColourDesired cdFill(fill.AsLong());
		cairo_set_source_rgba(context,
			cdFill.GetRed() / 255.0,
			cdFill.GetGreen() / 255.0,
			cdFill.GetBlue() / 255.0,
			alphaFill / 255.0);
		if (cornerSize > 0)
			PathRoundRectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0, cornerSize);
		else
			cairo_rectangle(context, rc.left + 1.0, rc.top + 1.0, rc.right - rc.left - 2.0, rc.bottom - rc.top - 2.0);
		cairo_fill(context);

		ColourDesired cdOutline(outline.AsLong());
		cairo_set_source_rgba(context,
			cdOutline.GetRed() / 255.0,
			cdOutline.GetGreen() / 255.0,
			cdOutline.GetBlue() / 255.0,
			alphaOutline / 255.0);
		if (cornerSize > 0)
			PathRoundRectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1, cornerSize);
		else
			cairo_rectangle(context, rc.left + 0.5, rc.top + 0.5, rc.right - rc.left - 1, rc.bottom - rc.top - 1);
		cairo_stroke(context);
	}
}

void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
	if (rc.Width() > width)
		rc.left += (rc.Width() - width) / 2;
	rc.right = rc.left + width;
	if (rc.Height() > height)
		rc.top += (rc.Height() - height) / 2;
	rc.bottom = rc.top + height;

#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0)
	int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
#else
	int stride = width * 4;
#endif
	int ucs = stride * height;
	std::vector<unsigned char> image(ucs);
	for (int y=0; y<height; y++) {
		for (int x=0; x<width; x++) {
			unsigned char *pixel = &image[0] + y*stride + x * 4;
			unsigned char alpha = pixelsImage[3];
			pixel[2] = (*pixelsImage++) * alpha / 255;
			pixel[1] = (*pixelsImage++) * alpha / 255;
			pixel[0] = (*pixelsImage++) * alpha / 255;
			pixel[3] = *pixelsImage++;
		}
	}

	cairo_surface_t *psurf = cairo_image_surface_create_for_data(&image[0], CAIRO_FORMAT_ARGB32, width, height, stride);
	cairo_set_source_surface(context, psurf, rc.left, rc.top);
	cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
	cairo_fill(context);

	cairo_surface_destroy(psurf);
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {
	PenColour(back);
	cairo_arc(context, (rc.left + rc.right) / 2 + 0.5, (rc.top + rc.bottom) / 2 + 0.5,
		Platform::Minimum(rc.Width(), rc.Height()) / 2, 0, 2*M_PI);
	cairo_fill_preserve(context);
	PenColour(fore);
	cairo_stroke(context);
}

void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
	SurfaceImpl &surfi = static_cast<SurfaceImpl &>(surfaceSource);
	bool canDraw = surfi.psurf;
	if (canDraw) {
		cairo_set_source_surface(context, surfi.psurf,
			rc.left - from.x, rc.top - from.y);
		cairo_rectangle(context, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
		cairo_fill(context);
	}
}

char *UTF8FromLatin1(const char *s, int &len) {
	char *utfForm = new char[len*2+1];
	size_t lenU = 0;
	for (int i=0;i<len;i++) {
		unsigned int uch = static_cast<unsigned char>(s[i]);
		if (uch < 0x80) {
			utfForm[lenU++] = uch;
		} else {
			utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
			utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
		}
	}
	utfForm[lenU] = '\0';
	len = lenU;
	return utfForm;
}

static char *UTF8FromIconv(const Converter &conv, const char *s, int &len) {
	if (conv) {
		char *utfForm = new char[len*3+1];
		char *pin = const_cast<char *>(s);
		size_t inLeft = len;
		char *pout = utfForm;
		size_t outLeft = len*3+1;
		size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
		if (conversions != ((size_t)(-1))) {
			*pout = '\0';
			len = pout - utfForm;
			return utfForm;
		}
		delete []utfForm;
	}
	return 0;
}

// Work out how many bytes are in a character by trying to convert using iconv,
// returning the first length that succeeds.
static size_t MultiByteLenFromIconv(const Converter &conv, const char *s, size_t len) {
	for (size_t lenMB=1; (lenMB<4) && (lenMB <= len); lenMB++) {
		char wcForm[2];
		char *pin = const_cast<char *>(s);
		size_t inLeft = lenMB;
		char *pout = wcForm;
		size_t outLeft = 2;
		size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
		if (conversions != ((size_t)(-1))) {
			return lenMB;
		}
	}
	return 1;
}

static size_t UTF8CharLength(const char *s) {
	const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
	unsigned char ch = *us;
	if (ch < 0x80) {
		return 1;
	} else if (ch < 0x80 + 0x40 + 0x20) {
		return 2;
	} else {
		return 3;
	}
}

void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                 ColourDesired fore) {
	PenColour(fore);
	if (context) {
		XYPOSITION xText = rc.left;
		if (PFont(font_)->pfd) {
			char *utfForm = 0;
			if (et == UTF8) {
				pango_layout_set_text(layout, s, len);
			} else {
				if (!utfForm) {
					SetConverter(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(conv, s, len);
				}
				if (!utfForm) {	// iconv failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, len);
			}
			pango_layout_set_font_description(layout, PFont(font_)->pfd);
			pango_cairo_update_layout(context, layout);
#ifdef PANGO_VERSION
			PangoLayoutLine *pll = pango_layout_get_line_readonly(layout,0);
#else
			PangoLayoutLine *pll = pango_layout_get_line(layout,0);
#endif
			cairo_move_to(context, xText, ybase);
			pango_cairo_show_layout_line(context, pll);
			delete []utfForm;
		}
	}
}

void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                 ColourDesired fore, ColourDesired back) {
	FillRectangle(rc, back);
	DrawTextBase(rc, font_, ybase, s, len, fore);
}

// On GTK+, exactly same as DrawTextNoClip
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                  ColourDesired fore, ColourDesired back) {
	FillRectangle(rc, back);
	DrawTextBase(rc, font_, ybase, s, len, fore);
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
                                  ColourDesired fore) {
	// Avoid drawing spaces in transparent mode
	for (int i=0;i<len;i++) {
		if (s[i] != ' ') {
			DrawTextBase(rc, font_, ybase, s, len, fore);
			return;
		}
	}
}

class ClusterIterator {
	PangoLayoutIter *iter;
	PangoRectangle pos;
	int lenPositions;
public:
	bool finished;
	XYPOSITION positionStart;
	XYPOSITION position;
	XYPOSITION distance;
	int curIndex;
	ClusterIterator(PangoLayout *layout, int len) : lenPositions(len), finished(false),
		positionStart(0), position(0), distance(0), curIndex(0) {
		iter = pango_layout_get_iter(layout);
		pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
	}
	~ClusterIterator() {
		pango_layout_iter_free(iter);
	}

	void Next() {
		positionStart = position;
		if (pango_layout_iter_next_cluster(iter)) {
			pango_layout_iter_get_cluster_extents(iter, NULL, &pos);
			position = doubleFromPangoUnits(pos.x);
			curIndex = pango_layout_iter_get_index(iter);
		} else {
			finished = true;
			position = doubleFromPangoUnits(pos.x + pos.width);
			curIndex = lenPositions;
		}
		distance = position - positionStart;
	}
};

void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
	if (font_.GetID()) {
		const int lenPositions = len;
		if (PFont(font_)->pfd) {
			if (len == 1) {
				int width = PFont(font_)->CharWidth(*s, et);
				if (width) {
					positions[0] = width;
					return;
				}
			}
			pango_layout_set_font_description(layout, PFont(font_)->pfd);
			if (et == UTF8) {
				// Simple and direct as UTF-8 is native Pango encoding
				int i = 0;
				pango_layout_set_text(layout, s, len);
				ClusterIterator iti(layout, lenPositions);
				while (!iti.finished) {
					iti.Next();
					int places = iti.curIndex - i;
					while (i < iti.curIndex) {
						// Evenly distribute space among bytes of this cluster.
						// Would be better to find number of characters and then
						// divide evenly between characters with each byte of a character
						// being at the same position.
						positions[i] = iti.position - (iti.curIndex - 1 - i) * iti.distance / places;
						i++;
					}
				}
				PLATFORM_ASSERT(i == lenPositions);
			} else {
				int positionsCalculated = 0;
				if (et == dbcs) {
					SetConverter(PFont(font_)->characterSet);
					char *utfForm = UTF8FromIconv(conv, s, len);
					if (utfForm) {
						// Convert to UTF-8 so can ask Pango for widths, then
						// Loop through UTF-8 and DBCS forms, taking account of different
						// character byte lengths.
						Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
						pango_layout_set_text(layout, utfForm, strlen(utfForm));
						int i = 0;
						int clusterStart = 0;
						ClusterIterator iti(layout, strlen(utfForm));
						while (!iti.finished) {
							iti.Next();
							int clusterEnd = iti.curIndex;
							int places = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
							int place = 1;
							while (clusterStart < clusterEnd) {
								size_t lenChar = MultiByteLenFromIconv(convMeasure, s+i, len-i);
								while (lenChar--) {
									positions[i++] = iti.position - (places - place) * iti.distance / places;
									positionsCalculated++;
								}
								clusterStart += UTF8CharLength(utfForm+clusterStart);
								place++;
							}
						}
						delete []utfForm;
						PLATFORM_ASSERT(i == lenPositions);
					}
				}
				if (positionsCalculated < 1 ) {
					// Either Latin1 or DBCS conversion failed so treat as Latin1.
					SetConverter(PFont(font_)->characterSet);
					char *utfForm = UTF8FromIconv(conv, s, len);
					if (!utfForm) {
						utfForm = UTF8FromLatin1(s, len);
					}
					pango_layout_set_text(layout, utfForm, len);
					int i = 0;
					int clusterStart = 0;
					// Each Latin1 input character may take 1 or 2 bytes in UTF-8
					// and groups of up to 3 may be represented as ligatures.
					ClusterIterator iti(layout, strlen(utfForm));
					while (!iti.finished) {
						iti.Next();
						int clusterEnd = iti.curIndex;
						int ligatureLength = g_utf8_strlen(utfForm + clusterStart, clusterEnd - clusterStart);
						PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
						for (int charInLig=0; charInLig<ligatureLength; charInLig++) {
							positions[i++] = iti.position - (ligatureLength - 1 - charInLig) * iti.distance / ligatureLength;
						}
						clusterStart = clusterEnd;
					}
					delete []utfForm;
					PLATFORM_ASSERT(i == lenPositions);
				}
			}
			if (len == 1) {
				PFont(font_)->SetCharWidth(*s, positions[0], et);
			}
			return;
		}
	} else {
		// No font so return an ascending range of values
		for (int i = 0; i < len; i++) {
			positions[i] = i + 1;
		}
	}
}

XYPOSITION SurfaceImpl::WidthText(Font &font_, const char *s, int len) {
	if (font_.GetID()) {
		if (PFont(font_)->pfd) {
			char *utfForm = 0;
			pango_layout_set_font_description(layout, PFont(font_)->pfd);
			PangoRectangle pos;
			if (et == UTF8) {
				pango_layout_set_text(layout, s, len);
			} else {
				if (!utfForm) {	// use iconv
					SetConverter(PFont(font_)->characterSet);
					utfForm = UTF8FromIconv(conv, s, len);
				}
				if (!utfForm) {	// iconv failed so treat as Latin1
					utfForm = UTF8FromLatin1(s, len);
				}
				pango_layout_set_text(layout, utfForm, len);
			}
#ifdef PANGO_VERSION
			PangoLayoutLine *pangoLine = pango_layout_get_line_readonly(layout,0);
#else
			PangoLayoutLine *pangoLine = pango_layout_get_line(layout,0);
#endif
			pango_layout_line_get_extents(pangoLine, NULL, &pos);
			delete []utfForm;
			return doubleFromPangoUnits(pos.width);
		}
		return 1;
	} else {
		return 1;
	}
}

XYPOSITION SurfaceImpl::WidthChar(Font &font_, char ch) {
	if (font_.GetID()) {
		if (PFont(font_)->pfd) {
			return WidthText(font_, &ch, 1);
		}
		return 1;
	} else {
		return 1;
	}
}

// Ascent and descent determined by Pango font metrics.

XYPOSITION SurfaceImpl::Ascent(Font &font_) {
	if (!(font_.GetID()))
		return 1;
	FontMutexLock();
	int ascent = PFont(font_)->ascent;
	if ((ascent == 0) && (PFont(font_)->pfd)) {
		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
			PFont(font_)->pfd, pango_context_get_language(pcontext));
		PFont(font_)->ascent =
			doubleFromPangoUnits(pango_font_metrics_get_ascent(metrics));
		pango_font_metrics_unref(metrics);
		ascent = PFont(font_)->ascent;
	}
	if (ascent == 0) {
		ascent = 1;
	}
	FontMutexUnlock();
	return ascent;
}

XYPOSITION SurfaceImpl::Descent(Font &font_) {
	if (!(font_.GetID()))
		return 1;
	if (PFont(font_)->pfd) {
		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
			PFont(font_)->pfd, pango_context_get_language(pcontext));
		int descent = doubleFromPangoUnits(pango_font_metrics_get_descent(metrics));
		pango_font_metrics_unref(metrics);
		return descent;
	}
	return 0;
}

XYPOSITION SurfaceImpl::InternalLeading(Font &) {
	return 0;
}

XYPOSITION SurfaceImpl::ExternalLeading(Font &) {
	return 0;
}

XYPOSITION SurfaceImpl::Height(Font &font_) {
	return Ascent(font_) + Descent(font_);
}

XYPOSITION SurfaceImpl::AverageCharWidth(Font &font_) {
	return WidthChar(font_, 'n');
}

void SurfaceImpl::SetClip(PRectangle rc) {
	cairo_rectangle(context, rc.left, rc.top, rc.right, rc.bottom);
	cairo_clip(context);
}

void SurfaceImpl::FlushCachedState() {}

void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
	if (unicodeMode_)
		et = UTF8;
}

void SurfaceImpl::SetDBCSMode(int codePage) {
	if (codePage && (codePage != SC_CP_UTF8))
		et = dbcs;
}

Surface *Surface::Allocate(int) {
	return new SurfaceImpl();
}

Window::~Window() {}

void Window::Destroy() {
	if (wid)
		gtk_widget_destroy(GTK_WIDGET(wid));
	wid = 0;
}

bool Window::HasFocus() {
	return IS_WIDGET_FOCUSSED(wid);
}

PRectangle Window::GetPosition() {
	// Before any size allocated pretend its 1000 wide so not scrolled
	PRectangle rc(0, 0, 1000, 1000);
	if (wid) {
		GtkAllocation allocation;
#if GTK_CHECK_VERSION(3,0,0)
		gtk_widget_get_allocation(PWidget(wid), &allocation);
#else
		allocation = PWidget(wid)->allocation;
#endif
		rc.left = allocation.x;
		rc.top = allocation.y;
		if (allocation.width > 20) {
			rc.right = rc.left + allocation.width;
			rc.bottom = rc.top + allocation.height;
		}
	}
	return rc;
}

void Window::SetPosition(PRectangle rc) {
	GtkAllocation alloc;
	alloc.x = rc.left;
	alloc.y = rc.top;
	alloc.width = rc.Width();
	alloc.height = rc.Height();
	gtk_widget_size_allocate(PWidget(wid), &alloc);
}

void Window::SetPositionRelative(PRectangle rc, Window relativeTo) {
	int ox = 0;
	int oy = 0;
	gdk_window_get_origin(WindowFromWidget(PWidget(relativeTo.wid)), &ox, &oy);
	ox += rc.left;
	if (ox < 0)
		ox = 0;
	oy += rc.top;
	if (oy < 0)
		oy = 0;

	/* do some corrections to fit into screen */
	int sizex = rc.right - rc.left;
	int sizey = rc.bottom - rc.top;
	int screenWidth = gdk_screen_width();
	int screenHeight = gdk_screen_height();
	if (sizex > screenWidth)
		ox = 0; /* the best we can do */
	else if (ox + sizex > screenWidth)
		ox = screenWidth - sizex;
	if (oy + sizey > screenHeight)
		oy = screenHeight - sizey;

	gtk_window_move(GTK_WINDOW(PWidget(wid)), ox, oy);

	gtk_widget_set_size_request(PWidget(wid), sizex, sizey);
}

PRectangle Window::GetClientPosition() {
	// On GTK+, the client position is the window position
	return GetPosition();
}

void Window::Show(bool show) {
	if (show)
		gtk_widget_show(PWidget(wid));
}

void Window::InvalidateAll() {
	if (wid) {
		gtk_widget_queue_draw(PWidget(wid));
	}
}

void Window::InvalidateRectangle(PRectangle rc) {
	if (wid) {
		gtk_widget_queue_draw_area(PWidget(wid),
		                           rc.left, rc.top,
		                           rc.right - rc.left, rc.bottom - rc.top);
	}
}

void Window::SetFont(Font &) {
	// Can not be done generically but only needed for ListBox
}

void Window::SetCursor(Cursor curs) {
	// We don't set the cursor to same value numerous times under gtk because
	// it stores the cursor in the window once it's set
	if (curs == cursorLast)
		return;

	cursorLast = curs;
	GdkCursor *gdkCurs;
	switch (curs) {
	case cursorText:
		gdkCurs = gdk_cursor_new(GDK_XTERM);
		break;
	case cursorArrow:
		gdkCurs = gdk_cursor_new(GDK_LEFT_PTR);
		break;
	case cursorUp:
		gdkCurs = gdk_cursor_new(GDK_CENTER_PTR);
		break;
	case cursorWait:
		gdkCurs = gdk_cursor_new(GDK_WATCH);
		break;
	case cursorHand:
		gdkCurs = gdk_cursor_new(GDK_HAND2);
		break;
	case cursorReverseArrow:
		gdkCurs = gdk_cursor_new(GDK_RIGHT_PTR);
		break;
	default:
		gdkCurs = gdk_cursor_new(GDK_LEFT_PTR);
		cursorLast = cursorArrow;
		break;
	}

	if (WindowFromWidget(PWidget(wid)))
		gdk_window_set_cursor(WindowFromWidget(PWidget(wid)), gdkCurs);
#if GTK_CHECK_VERSION(3,0,0)
	g_object_unref(gdkCurs);
#else
	gdk_cursor_unref(gdkCurs);
#endif
}

void Window::SetTitle(const char *s) {
	gtk_window_set_title(GTK_WINDOW(wid), s);
}

/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
   gdk window coordinates */
PRectangle Window::GetMonitorRect(Point pt) {
	gint x_offset, y_offset;

	gdk_window_get_origin(WindowFromWidget(PWidget(wid)), &x_offset, &y_offset);

	GdkScreen* screen;
	gint monitor_num;
	GdkRectangle rect;

	screen = gtk_widget_get_screen(PWidget(wid));
	monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + x_offset, pt.y + y_offset);
	gdk_screen_get_monitor_geometry(screen, monitor_num, &rect);
	rect.x -= x_offset;
	rect.y -= y_offset;
	return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
}

typedef std::map<int, RGBAImage*> ImageMap;

struct ListImage {
	const RGBAImage *rgba_data;
	GdkPixbuf *pixbuf;
};

static void list_image_free(gpointer, gpointer value, gpointer) {
	ListImage *list_image = static_cast<ListImage *>(value);
	if (list_image->pixbuf)
		g_object_unref(list_image->pixbuf);
	g_free(list_image);
}

ListBox::ListBox() {
}

ListBox::~ListBox() {
}

enum {
	PIXBUF_COLUMN,
	TEXT_COLUMN,
	N_COLUMNS
};

class ListBoxX : public ListBox {
	WindowID list;
	WindowID scroller;
	void *pixhash;
	GtkCellRenderer* pixbuf_renderer;
	RGBAImageSet images;
	int desiredVisibleRows;
	unsigned int maxItemCharacters;
	unsigned int aveCharWidth;
public:
	CallBackAction doubleClickAction;
	void *doubleClickActionData;

	ListBoxX() : list(0), scroller(0), pixhash(NULL), pixbuf_renderer(0),
		desiredVisibleRows(5), maxItemCharacters(0),
		aveCharWidth(1), doubleClickAction(NULL), doubleClickActionData(NULL) {
	}
	virtual ~ListBoxX() {
		if (pixhash) {
			g_hash_table_foreach((GHashTable *) pixhash, list_image_free, NULL);
			g_hash_table_destroy((GHashTable *) pixhash);
		}
	}
	virtual void SetFont(Font &font);
	virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_);
	virtual void SetAverageCharWidth(int width);
	virtual void SetVisibleRows(int rows);
	virtual int GetVisibleRows() const;
	virtual PRectangle GetDesiredRect();
	virtual int CaretFromEdge();
	virtual void Clear();
	virtual void Append(char *s, int type = -1);
	virtual int Length();
	virtual void Select(int n);
	virtual int GetSelection();
	virtual int Find(const char *prefix);
	virtual void GetValue(int n, char *value, int len);
	void RegisterRGBA(int type, RGBAImage *image);
	virtual void RegisterImage(int type, const char *xpm_data);
	virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
	virtual void ClearRegisteredImages();
	virtual void SetDoubleClickAction(CallBackAction action, void *data) {
		doubleClickAction = action;
		doubleClickActionData = data;
	}
	virtual void SetList(const char *listText, char separator, char typesep);
};

ListBox *ListBox::Allocate() {
	ListBoxX *lb = new ListBoxX();
	return lb;
}

static gboolean ButtonPress(GtkWidget *, GdkEventButton* ev, gpointer p) {
	try {
		ListBoxX* lb = reinterpret_cast<ListBoxX*>(p);
		if (ev->type == GDK_2BUTTON_PRESS && lb->doubleClickAction != NULL) {
			lb->doubleClickAction(lb->doubleClickActionData);
			return TRUE;
		}

	} catch (...) {
		// No pointer back to Scintilla to save status
	}
	return FALSE;
}

/* Change the active color to the selected color so the listbox uses the color
scheme that it would use if it had the focus. */
static void StyleSet(GtkWidget *w, GtkStyle*, void*) {

	g_return_if_fail(w != NULL);

	/* Copy the selected color to active.  Note that the modify calls will cause
	recursive calls to this function after the value is updated and w->style to
	be set to a new object */

#if GTK_CHECK_VERSION(3,0,0)
	GtkStyleContext *styleContext = gtk_widget_get_style_context(w);
	if (styleContext == NULL)
		return;

	GdkRGBA colourForeSelected;
	gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourForeSelected);
	GdkRGBA colourForeActive;
	gtk_style_context_get_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourForeActive);
	if (!gdk_rgba_equal(&colourForeSelected, &colourForeActive))
		gtk_widget_override_color(w, GTK_STATE_FLAG_ACTIVE, &colourForeSelected);

	styleContext = gtk_widget_get_style_context(w);
	if (styleContext == NULL)
		return;

	GdkRGBA colourBaseSelected;
	gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_SELECTED, &colourBaseSelected);
	GdkRGBA colourBaseActive;
	gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_ACTIVE, &colourBaseActive);
	if (!gdk_rgba_equal(&colourBaseSelected, &colourBaseActive))
		gtk_widget_override_background_color(w, GTK_STATE_FLAG_ACTIVE, &colourBaseSelected);
#else
	GtkStyle *style = gtk_widget_get_style(w);
	if (style == NULL)
		return;
	if (!gdk_color_equal(&style->base[GTK_STATE_SELECTED], &style->base[GTK_STATE_ACTIVE]))
		gtk_widget_modify_base(w, GTK_STATE_ACTIVE, &style->base[GTK_STATE_SELECTED]);
	style = gtk_widget_get_style(w);
	if (style == NULL)
		return;
	if (!gdk_color_equal(&style->text[GTK_STATE_SELECTED], &style->text[GTK_STATE_ACTIVE]))
		gtk_widget_modify_text(w, GTK_STATE_ACTIVE, &style->text[GTK_STATE_SELECTED]);
#endif
}

void ListBoxX::Create(Window &, int, Point, int, bool, int) {
	wid = gtk_window_new(GTK_WINDOW_POPUP);

	GtkWidget *frame = gtk_frame_new(NULL);
	gtk_widget_show(frame);
	gtk_container_add(GTK_CONTAINER(GetID()), frame);
	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
	gtk_container_set_border_width(GTK_CONTAINER(frame), 0);

	scroller = gtk_scrolled_window_new(NULL, NULL);
	gtk_container_set_border_width(GTK_CONTAINER(scroller), 0);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
	                               GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	gtk_container_add(GTK_CONTAINER(frame), PWidget(scroller));
	gtk_widget_show(PWidget(scroller));

	/* Tree and its model */
	GtkListStore *store =
		gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);

	list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
	g_signal_connect(G_OBJECT(list), "style-set", G_CALLBACK(StyleSet), NULL);

	GtkTreeSelection *selection =
		gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
	gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
	gtk_tree_view_set_reorderable(GTK_TREE_VIEW(list), FALSE);

	/* Columns */
	GtkTreeViewColumn *column = gtk_tree_view_column_new();
	gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
	gtk_tree_view_column_set_title(column, "Autocomplete");

	pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
	gtk_cell_renderer_set_fixed_size(pixbuf_renderer, 0, -1);
	gtk_tree_view_column_pack_start(column, pixbuf_renderer, FALSE);
	gtk_tree_view_column_add_attribute(column, pixbuf_renderer,
										"pixbuf", PIXBUF_COLUMN);

	GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
	gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer), 1);
	gtk_tree_view_column_pack_start(column, renderer, TRUE);
	gtk_tree_view_column_add_attribute(column, renderer,
										"text", TEXT_COLUMN);

	gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
	if (g_object_class_find_property(G_OBJECT_GET_CLASS(list), "fixed-height-mode"))
		g_object_set(G_OBJECT(list), "fixed-height-mode", TRUE, NULL);

	GtkWidget *wid = PWidget(list);	// No code inside the G_OBJECT macro
	gtk_container_add(GTK_CONTAINER(PWidget(scroller)), wid);
	gtk_widget_show(wid);
	g_signal_connect(G_OBJECT(wid), "button_press_event",
	                   G_CALLBACK(ButtonPress), this);
	gtk_widget_realize(PWidget(wid));
}

void ListBoxX::SetFont(Font &scint_font) {
	// Only do for Pango font as there have been crashes for GDK fonts
	if (Created() && PFont(scint_font)->pfd) {
		// Current font is Pango font
#if GTK_CHECK_VERSION(3,0,0)
		gtk_widget_override_font(PWidget(list), PFont(scint_font)->pfd);
#else
		gtk_widget_modify_font(PWidget(list), PFont(scint_font)->pfd);
#endif
	}
}

void ListBoxX::SetAverageCharWidth(int width) {
	aveCharWidth = width;
}

void ListBoxX::SetVisibleRows(int rows) {
	desiredVisibleRows = rows;
}

int ListBoxX::GetVisibleRows() const {
	return desiredVisibleRows;
}

PRectangle ListBoxX::GetDesiredRect() {
	// Before any size allocated pretend its 100 wide so not scrolled
	PRectangle rc(0, 0, 100, 100);
	if (wid) {
		int rows = Length();
		if ((rows == 0) || (rows > desiredVisibleRows))
			rows = desiredVisibleRows;

		GtkRequisition req;
#if GTK_CHECK_VERSION(3,0,0)
		// This, apparently unnecessary call, ensures gtk_tree_view_column_cell_get_size
		// returns reasonable values. 
		gtk_widget_get_preferred_size(GTK_WIDGET(scroller), NULL, &req);
#endif
		int height;

		// First calculate height of the clist for our desired visible
		// row count otherwise it tries to expand to the total # of rows
		// Get cell height
		int row_width=0;
		int row_height=0;
		GtkTreeViewColumn * column =
			gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0);
		gtk_tree_view_column_cell_get_size(column, NULL,
			NULL, NULL, &row_width, &row_height);
#if GTK_CHECK_VERSION(3,0,0)
		GtkStyleContext *styleContextList = gtk_widget_get_style_context(PWidget(list));
		GtkBorder padding;
		gtk_style_context_get_padding(styleContextList, GTK_STATE_FLAG_NORMAL, &padding);
		height = (rows * row_height
		          + padding.top + padding.bottom
		          + 2 * (gtk_container_get_border_width(GTK_CONTAINER(PWidget(list))) + 1));
#else
		int ythickness = PWidget(list)->style->ythickness;
		height = (rows * row_height
		          + 2 * (ythickness
		                 + GTK_CONTAINER(PWidget(list))->border_width + 1));
#endif
		gtk_widget_set_size_request(GTK_WIDGET(PWidget(list)), -1, height);

		// Get the size of the scroller because we set usize on the window
#if GTK_CHECK_VERSION(3,0,0)
		gtk_widget_get_preferred_size(GTK_WIDGET(scroller), NULL, &req);
#else
		gtk_widget_size_request(GTK_WIDGET(scroller), &req);
#endif
		rc.right = req.width;
		rc.bottom = Platform::Maximum(height, req.height);

		gtk_widget_set_size_request(GTK_WIDGET(list), -1, -1);
		int width = maxItemCharacters;
		if (width < 12)
			width = 12;
		rc.right = width * (aveCharWidth + aveCharWidth / 3);
		if (Length() > rows)
			rc.right = rc.right + 16;
	}
	return rc;
}

int ListBoxX::CaretFromEdge() {
	gint renderer_width, renderer_height;
	gtk_cell_renderer_get_fixed_size(pixbuf_renderer, &renderer_width,
						&renderer_height);
	return 4 + renderer_width;
}

void ListBoxX::Clear() {
	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
	gtk_list_store_clear(GTK_LIST_STORE(model));
	maxItemCharacters = 0;
}

static void init_pixmap(ListImage *list_image) {
	if (list_image->rgba_data) {
		// Drop any existing pixmap/bitmap as data may have changed
		if (list_image->pixbuf)
			g_object_unref(list_image->pixbuf);
		list_image->pixbuf =
			gdk_pixbuf_new_from_data(list_image->rgba_data->Pixels(),
                                                         GDK_COLORSPACE_RGB,
                                                         TRUE,
                                                         8,
                                                         list_image->rgba_data->GetWidth(),
                                                         list_image->rgba_data->GetHeight(),
                                                         list_image->rgba_data->GetWidth() * 4,
                                                         NULL,
                                                         NULL);
	}
}

#define SPACING 5

void ListBoxX::Append(char *s, int type) {
	ListImage *list_image = NULL;
	if ((type >= 0) && pixhash) {
		list_image = static_cast<ListImage *>(g_hash_table_lookup((GHashTable *) pixhash
		             , (gconstpointer) GINT_TO_POINTER(type)));
	}
	GtkTreeIter iter;
	GtkListStore *store =
		GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
	gtk_list_store_append(GTK_LIST_STORE(store), &iter);
	if (list_image) {
		if (NULL == list_image->pixbuf)
			init_pixmap(list_image);
		if (list_image->pixbuf) {
			gtk_list_store_set(GTK_LIST_STORE(store), &iter,
								PIXBUF_COLUMN, list_image->pixbuf,
								TEXT_COLUMN, s, -1);

			gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf);
			gint renderer_height, renderer_width;
			gtk_cell_renderer_get_fixed_size(pixbuf_renderer,
								&renderer_width, &renderer_height);
			if (pixbuf_width > renderer_width)
				gtk_cell_renderer_set_fixed_size(pixbuf_renderer,
								pixbuf_width, -1);
		} else {
			gtk_list_store_set(GTK_LIST_STORE(store), &iter,
								TEXT_COLUMN, s, -1);
		}
	} else {
			gtk_list_store_set(GTK_LIST_STORE(store), &iter,
								TEXT_COLUMN, s, -1);
	}
	size_t len = strlen(s);
	if (maxItemCharacters < len)
		maxItemCharacters = len;
}

int ListBoxX::Length() {
	if (wid)
		return gtk_tree_model_iter_n_children(gtk_tree_view_get_model
											   (GTK_TREE_VIEW(list)), NULL);
	return 0;
}

void ListBoxX::Select(int n) {
	GtkTreeIter iter;
	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
	GtkTreeSelection *selection =
		gtk_tree_view_get_selection(GTK_TREE_VIEW(list));

	if (n < 0) {
		gtk_tree_selection_unselect_all(selection);
		return;
	}

	bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE;
	if (valid) {
		gtk_tree_selection_select_iter(selection, &iter);

		// Move the scrollbar to show the selection.
		int total = Length();
#if GTK_CHECK_VERSION(3,0,0)
		GtkAdjustment *adj =
			gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(list));
		gfloat value = ((gfloat)n / total) * (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_lower(adj))
							+ gtk_adjustment_get_lower(adj) - gtk_adjustment_get_page_size(adj) / 2;
#else
		GtkAdjustment *adj =
			gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(list));
		gfloat value = ((gfloat)n / total) * (adj->upper - adj->lower)
							+ adj->lower - adj->page_size / 2;
#endif
		// Get cell height
		int row_width;
		int row_height;
		GtkTreeViewColumn * column =
			gtk_tree_view_get_column(GTK_TREE_VIEW(list), 0);
		gtk_tree_view_column_cell_get_size(column, NULL, NULL,
											NULL, &row_width, &row_height);

		int rows = Length();
		if ((rows == 0) || (rows > desiredVisibleRows))
			rows = desiredVisibleRows;
		if (rows & 0x1) {
			// Odd rows to display -- We are now in the middle.
			// Align it so that we don't chop off rows.
			value += (gfloat)row_height / 2.0;
		}
		// Clamp it.
		value = (value < 0)? 0 : value;
#if GTK_CHECK_VERSION(3,0,0)
		value = (value > (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)))?
					(gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj)) : value;
#else
		value = (value > (adj->upper - adj->page_size))?
					(adj->upper - adj->page_size) : value;
#endif

		// Set it.
		gtk_adjustment_set_value(adj, value);
	} else {
		gtk_tree_selection_unselect_all(selection);
	}
}

int ListBoxX::GetSelection() {
	GtkTreeIter iter;
	GtkTreeModel *model;
	GtkTreeSelection *selection;
	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
		GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
		int *indices = gtk_tree_path_get_indices(path);
		// Don't free indices.
		if (indices)
			return indices[0];
	}
	return -1;
}

int ListBoxX::Find(const char *prefix) {
	GtkTreeIter iter;
	GtkTreeModel *model =
		gtk_tree_view_get_model(GTK_TREE_VIEW(list));
	bool valid = gtk_tree_model_get_iter_first(model, &iter) != FALSE;
	int i = 0;
	while(valid) {
		gchar *s;
		gtk_tree_model_get(model, &iter, TEXT_COLUMN, &s, -1);
		if (s && (0 == strncmp(prefix, s, strlen(prefix)))) {
			g_free(s);
			return i;
		}
		g_free(s);
		valid = gtk_tree_model_iter_next(model, &iter) != FALSE;
		i++;
	}
	return -1;
}

void ListBoxX::GetValue(int n, char *value, int len) {
	char *text = NULL;
	GtkTreeIter iter;
	GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list));
	bool valid = gtk_tree_model_iter_nth_child(model, &iter, NULL, n) != FALSE;
	if (valid) {
		gtk_tree_model_get(model, &iter, TEXT_COLUMN, &text, -1);
	}
	if (text && len > 0) {
		strncpy(value, text, len);
		value[len - 1] = '\0';
	} else {
		value[0] = '\0';
	}
	g_free(text);
}

// g_return_if_fail causes unnecessary compiler warning in release compile.
#ifdef _MSC_VER
#pragma warning(disable: 4127)
#endif

void ListBoxX::RegisterRGBA(int type, RGBAImage *image) {
	images.Add(type, image);

	if (!pixhash) {
		pixhash = g_hash_table_new(g_direct_hash, g_direct_equal);
	}
	ListImage *list_image = static_cast<ListImage *>(g_hash_table_lookup((GHashTable *) pixhash,
		(gconstpointer) GINT_TO_POINTER(type)));
	if (list_image) {
		// Drop icon already registered
		if (list_image->pixbuf)
			g_object_unref(list_image->pixbuf);
		list_image->pixbuf = NULL;
		list_image->rgba_data = image;
	} else {
		list_image = g_new0(ListImage, 1);
		list_image->rgba_data = image;
		g_hash_table_insert((GHashTable *) pixhash, GINT_TO_POINTER(type),
			(gpointer) list_image);
	}
}

void ListBoxX::RegisterImage(int type, const char *xpm_data) {
	g_return_if_fail(xpm_data);
	XPM xpmImage(xpm_data);
	RegisterRGBA(type, new RGBAImage(xpmImage));
}

void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
	RegisterRGBA(type, new RGBAImage(width, height, 1.0, pixelsImage));
}

void ListBoxX::ClearRegisteredImages() {
	images.Clear();
}

void ListBoxX::SetList(const char *listText, char separator, char typesep) {
	Clear();
	int count = strlen(listText) + 1;
	char *words = new char[count];
	if (words) {
		memcpy(words, listText, count);
		char *startword = words;
		char *numword = NULL;
		int i = 0;
		for (; words[i]; i++) {
			if (words[i] == separator) {
				words[i] = '\0';
				if (numword)
					*numword = '\0';
				Append(startword, numword?atoi(numword + 1):-1);
				startword = words + i + 1;
				numword = NULL;
			} else if (words[i] == typesep) {
				numword = words + i;
			}
		}
		if (startword) {
			if (numword)
				*numword = '\0';
			Append(startword, numword?atoi(numword + 1):-1);
		}
		delete []words;
	}
}

Menu::Menu() : mid(0) {}

void Menu::CreatePopUp() {
	Destroy();
	mid = gtk_menu_new();
#if GLIB_CHECK_VERSION(2,10,0)
	 g_object_ref_sink(G_OBJECT(mid));
#else
	g_object_ref(G_OBJECT(mid));
	gtk_object_sink(GTK_OBJECT(G_OBJECT(mid)));
#endif
}

void Menu::Destroy() {
	if (mid)
		g_object_unref(G_OBJECT(mid));
	mid = 0;
}

static void  MenuPositionFunc(GtkMenu *, gint *x, gint *y, gboolean *, gpointer userData) {
	sptr_t intFromPointer = reinterpret_cast<sptr_t>(userData);
	*x = intFromPointer & 0xffff;
	*y = intFromPointer >> 16;
}

void Menu::Show(Point pt, Window &) {
	int screenHeight = gdk_screen_height();
	int screenWidth = gdk_screen_width();
	GtkMenu *widget = reinterpret_cast<GtkMenu *>(mid);
	gtk_widget_show_all(GTK_WIDGET(widget));
	GtkRequisition requisition;
#if GTK_CHECK_VERSION(3,0,0)
	gtk_widget_get_preferred_size(GTK_WIDGET(widget), NULL, &requisition);
#else
	gtk_widget_size_request(GTK_WIDGET(widget), &requisition);
#endif
	if ((pt.x + requisition.width) > screenWidth) {
		pt.x = screenWidth - requisition.width;
	}
	if ((pt.y + requisition.height) > screenHeight) {
		pt.y = screenHeight - requisition.height;
	}
	gtk_menu_popup(widget, NULL, NULL, MenuPositionFunc,
		reinterpret_cast<void *>((static_cast<int>(pt.y) << 16) | static_cast<int>(pt.x)), 0,
		gtk_get_current_event_time());
}

ElapsedTime::ElapsedTime() {
	GTimeVal curTime;
	g_get_current_time(&curTime);
	bigBit = curTime.tv_sec;
	littleBit = curTime.tv_usec;
}

class DynamicLibraryImpl : public DynamicLibrary {
protected:
	GModule* m;
public:
	DynamicLibraryImpl(const char *modulePath) {
		m = g_module_open(modulePath, G_MODULE_BIND_LAZY);
	}

	virtual ~DynamicLibraryImpl() {
		if (m != NULL)
			g_module_close(m);
	}

	// Use g_module_symbol to get a pointer to the relevant function.
	virtual Function FindFunction(const char *name) {
		if (m != NULL) {
			gpointer fn_address = NULL;
			gboolean status = g_module_symbol(m, name, &fn_address);
			if (status)
				return static_cast<Function>(fn_address);
			else
				return NULL;
		} else
			return NULL;
	}

	virtual bool IsValid() {
		return m != NULL;
	}
};

DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
	return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
}

double ElapsedTime::Duration(bool reset) {
	GTimeVal curTime;
	g_get_current_time(&curTime);
	long endBigBit = curTime.tv_sec;
	long endLittleBit = curTime.tv_usec;
	double result = 1000000.0 * (endBigBit - bigBit);
	result += endLittleBit - littleBit;
	result /= 1000000.0;
	if (reset) {
		bigBit = endBigBit;
		littleBit = endLittleBit;
	}
	return result;
}

ColourDesired Platform::Chrome() {
	return ColourDesired(0xe0, 0xe0, 0xe0);
}

ColourDesired Platform::ChromeHighlight() {
	return ColourDesired(0xff, 0xff, 0xff);
}

const char *Platform::DefaultFont() {
#ifdef G_OS_WIN32
	return "Lucida Console";
#else
	return "!Sans";
#endif
}

int Platform::DefaultFontSize() {
#ifdef G_OS_WIN32
	return 10;
#else
	return 12;
#endif
}

unsigned int Platform::DoubleClickTime() {
	return 500; 	// Half a second
}

bool Platform::MouseButtonBounce() {
	return true;
}

void Platform::DebugDisplay(const char *s) {
	fprintf(stderr, "%s", s);
}

bool Platform::IsKeyDown(int) {
	// TODO: discover state of keys in GTK+/X
	return false;
}

long Platform::SendScintilla(
    WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
	return scintilla_send_message(SCINTILLA(w), msg, wParam, lParam);
}

long Platform::SendScintillaPointer(
    WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
	return scintilla_send_message(SCINTILLA(w), msg, wParam,
	                              reinterpret_cast<sptr_t>(lParam));
}

bool Platform::IsDBCSLeadByte(int codePage, char ch) {
	// Byte ranges found in Wikipedia articles with relevant search strings in each case
	unsigned char uch = static_cast<unsigned char>(ch);
	switch (codePage) {
		case 932:
			// Shift_jis
			return ((uch >= 0x81) && (uch <= 0x9F)) ||
				((uch >= 0xE0) && (uch <= 0xFC));
				// Lead bytes F0 to FC may be a Microsoft addition.
		case 936:
			// GBK
			return (uch >= 0x81) && (uch <= 0xFE);
		case 950:
			// Big5
			return (uch >= 0x81) && (uch <= 0xFE);
		// Korean EUC-KR may be code page 949.
	}
	return false;
}

int Platform::DBCSCharLength(int codePage, const char *s) {
	if (codePage == 932 || codePage == 936 || codePage == 950) {
		return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1;
	} else {
		int bytes = mblen(s, MB_CUR_MAX);
		if (bytes >= 1)
			return bytes;
		else
			return 1;
	}
}

int Platform::DBCSCharMaxLength() {
	return MB_CUR_MAX;
	//return 2;
}

// These are utility functions not really tied to a platform

int Platform::Minimum(int a, int b) {
	if (a < b)
		return a;
	else
		return b;
}

int Platform::Maximum(int a, int b) {
	if (a > b)
		return a;
	else
		return b;
}

//#define TRACE

#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) {
	char buffer[2000];
	va_list pArguments;
	va_start(pArguments, format);
	vsprintf(buffer, format, pArguments);
	va_end(pArguments);
	Platform::DebugDisplay(buffer);
}
#else
void Platform::DebugPrintf(const char *, ...) {}

#endif

// Not supported for GTK+
static bool assertionPopUps = true;

bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
	bool ret = assertionPopUps;
	assertionPopUps = assertionPopUps_;
	return ret;
}

void Platform::Assert(const char *c, const char *file, int line) {
	char buffer[2000];
	sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
	strcat(buffer, "\r\n");
	Platform::DebugDisplay(buffer);
	abort();
}

int Platform::Clamp(int val, int minVal, int maxVal) {
	if (val > maxVal)
		val = maxVal;
	if (val < minVal)
		val = minVal;
	return val;
}

void Platform_Initialise() {
	FontMutexAllocate();
}

void Platform_Finalise() {
	FontMutexFree();
}

Added gtk/ScintillaGTK.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
// Scintilla source code edit control
// ScintillaGTK.cxx - GTK+ specific subclass of ScintillaBase
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <new>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <time.h>

#include <string>
#include <vector>
#include <map>

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "Platform.h"

#if PLAT_GTK_WIN32
#include <windows.h>
#endif

#include "ILexer.h"
#include "Scintilla.h"
#include "ScintillaWidget.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
#endif
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "Decoration.h"
#include "CharClassify.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"

#include "scintilla-marshal.h"

#ifdef SCI_LEXER
#include <glib.h>
#include <gmodule.h>
#include "LexerModule.h"
#include "ExternalLexer.h"
#endif

#include "Converter.h"

#if defined(__clang__)
// Clang 3.0 incorrectly displays  sentinel warnings. Fixed by clang 3.1.
#pragma GCC diagnostic ignored "-Wsentinel"
#endif

#if GTK_CHECK_VERSION(2,20,0)
#define IS_WIDGET_REALIZED(w) (gtk_widget_get_realized(GTK_WIDGET(w)))
#define IS_WIDGET_MAPPED(w) (gtk_widget_get_mapped(GTK_WIDGET(w)))
#define IS_WIDGET_VISIBLE(w) (gtk_widget_get_visible(GTK_WIDGET(w)))
#else
#define IS_WIDGET_REALIZED(w) (GTK_WIDGET_REALIZED(w))
#define IS_WIDGET_MAPPED(w) (GTK_WIDGET_MAPPED(w))
#define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w))
#endif

static GdkWindow *WindowFromWidget(GtkWidget *w) {
#if GTK_CHECK_VERSION(3,0,0)
	return gtk_widget_get_window(w);
#else
	return w->window;
#endif
}

static GdkWindow *PWindow(const Window &w) {
	GtkWidget *widget = reinterpret_cast<GtkWidget *>(w.GetID());
#if GTK_CHECK_VERSION(3,0,0)
	return gtk_widget_get_window(widget);
#else
	return widget->window;
#endif
}

#ifdef _MSC_VER
// Constant conditional expressions are because of GTK+ headers
#pragma warning(disable: 4127)
// Ignore unreferenced local functions in GTK+ headers
#pragma warning(disable: 4505)
#endif

#define OBJECT_CLASS GObjectClass

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

extern char *UTF8FromLatin1(const char *s, int &len);

class ScintillaGTK : public ScintillaBase {
	_ScintillaObject *sci;
	Window wText;
	Window scrollbarv;
	Window scrollbarh;
	GtkAdjustment *adjustmentv;
	GtkAdjustment *adjustmenth;
	int scrollBarWidth;
	int scrollBarHeight;

	SelectionText primary;

	GdkEventButton evbtn;
	bool capturedMouse;
	bool dragWasDropped;
	int lastKey;
	int rectangularSelectionModifier;

	GtkWidgetClass *parentClass;

	static GdkAtom atomClipboard;
	static GdkAtom atomUTF8;
	static GdkAtom atomString;
	static GdkAtom atomUriList;
	static GdkAtom atomDROPFILES_DND;
	GdkAtom atomSought;

#if PLAT_GTK_WIN32
	CLIPFORMAT cfColumnSelect;
#endif

	Window wPreedit;
	Window wPreeditDraw;
	GtkIMContext *im_context;

	// Wheel mouse support
	unsigned int linesPerScroll;
	GTimeVal lastWheelMouseTime;
	gint lastWheelMouseDirection;
	gint wheelMouseIntensity;

#if GTK_CHECK_VERSION(3,0,0)
	cairo_rectangle_list_t *rgnUpdate;
#else
	GdkRegion *rgnUpdate;
#endif

	// Private so ScintillaGTK objects can not be copied
	ScintillaGTK(const ScintillaGTK &);
	ScintillaGTK &operator=(const ScintillaGTK &);

public:
	ScintillaGTK(_ScintillaObject *sci_);
	virtual ~ScintillaGTK();
	static void ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
private:
	virtual void Initialise();
	virtual void Finalise();
	virtual void DisplayCursor(Window::Cursor c);
	virtual bool DragThreshold(Point ptStart, Point ptNow);
	virtual void StartDrag();
	int TargetAsUTF8(char *text);
	int EncodedFromUTF8(char *utf8, char *encoded);
	virtual bool ValidCodePage(int codePage) const;
public: 	// Public for scintilla_send_message
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
private:
	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	virtual void SetTicking(bool on);
	virtual bool SetIdle(bool on);
	virtual void SetMouseCapture(bool on);
	virtual bool HaveMouseCapture();
	virtual bool PaintContains(PRectangle rc);
	void FullPaint();
	virtual PRectangle GetClientRectangle();
	void SyncPaint(PRectangle rc);
	virtual void ScrollText(int linesToMove);
	virtual void SetVerticalScrollPos();
	virtual void SetHorizontalScrollPos();
	virtual bool ModifyScrollBars(int nMax, int nPage);
	void ReconfigureScrollBars();
	virtual void NotifyChange();
	virtual void NotifyFocus(bool focus);
	virtual void NotifyParent(SCNotification scn);
	void NotifyKey(int key, int modifiers);
	void NotifyURIDropped(const char *list);
	const char *CharacterSetID() const;
	virtual CaseFolder *CaseFolderForEncoding();
	virtual std::string CaseMapString(const std::string &s, int caseMapping);
	virtual int KeyDefault(int key, int modifiers);
	virtual void CopyToClipboard(const SelectionText &selectedText);
	virtual void Copy();
	virtual void Paste();
	virtual void CreateCallTipWindow(PRectangle rc);
	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
	bool OwnPrimarySelection();
	virtual void ClaimSelection();
	void GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText);
	void ReceivedSelection(GtkSelectionData *selection_data);
	void ReceivedDrop(GtkSelectionData *selection_data);
	static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
	void StoreOnClipboard(SelectionText *clipText);
	static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
	static void ClipboardClearSelection(GtkClipboard* clip, void *data);

	void UnclaimSelection(GdkEventSelection *selection_event);
	void Resize(int width, int height);

	// Callback functions
	void RealizeThis(GtkWidget *widget);
	static void Realize(GtkWidget *widget);
	void UnRealizeThis(GtkWidget *widget);
	static void UnRealize(GtkWidget *widget);
	void MapThis();
	static void Map(GtkWidget *widget);
	void UnMapThis();
	static void UnMap(GtkWidget *widget);
	gint FocusInThis(GtkWidget *widget);
	static gint FocusIn(GtkWidget *widget, GdkEventFocus *event);
	gint FocusOutThis(GtkWidget *widget);
	static gint FocusOut(GtkWidget *widget, GdkEventFocus *event);
	static void SizeRequest(GtkWidget *widget, GtkRequisition *requisition);
	static void GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth);
	static void GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight);
	static void SizeAllocate(GtkWidget *widget, GtkAllocation *allocation);
#if GTK_CHECK_VERSION(3,0,0)
	gboolean DrawTextThis(cairo_t *cr);
	static gboolean DrawText(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis);
	gboolean DrawThis(cairo_t *cr);
	static gboolean DrawMain(GtkWidget *widget, cairo_t *cr);
#else
	gboolean ExposeTextThis(GtkWidget *widget, GdkEventExpose *ose);
	static gboolean ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
	gboolean Expose(GtkWidget *widget, GdkEventExpose *ose);
	static gboolean ExposeMain(GtkWidget *widget, GdkEventExpose *ose);
#endif
	static void Draw(GtkWidget *widget, GdkRectangle *area);
	void ForAll(GtkCallback callback, gpointer callback_data);
	static void MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);

	static void ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
	static void ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis);
	gint PressThis(GdkEventButton *event);
	static gint Press(GtkWidget *widget, GdkEventButton *event);
	static gint MouseRelease(GtkWidget *widget, GdkEventButton *event);
	static gint ScrollEvent(GtkWidget *widget, GdkEventScroll *event);
	static gint Motion(GtkWidget *widget, GdkEventMotion *event);
	gboolean KeyThis(GdkEventKey *event);
	static gboolean KeyPress(GtkWidget *widget, GdkEventKey *event);
	static gboolean KeyRelease(GtkWidget *widget, GdkEventKey *event);
#if GTK_CHECK_VERSION(3,0,0)
	gboolean DrawPreeditThis(GtkWidget *widget, cairo_t *cr);
	static gboolean DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis);
#else
	gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
	static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
#endif
	void CommitThis(char *str);
	static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
	void PreeditChangedThis();
	static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
	static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
	static void RealizeText(GtkWidget *widget, void*);
	static void Destroy(GObject *object);
	static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
	                              guint time);
	static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
	                         guint info, guint time);
	static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
	static void DragBegin(GtkWidget *widget, GdkDragContext *context);
	gboolean DragMotionThis(GdkDragContext *context, gint x, gint y, guint dragtime);
	static gboolean DragMotion(GtkWidget *widget, GdkDragContext *context,
	                           gint x, gint y, guint dragtime);
	static void DragLeave(GtkWidget *widget, GdkDragContext *context,
	                      guint time);
	static void DragEnd(GtkWidget *widget, GdkDragContext *context);
	static gboolean Drop(GtkWidget *widget, GdkDragContext *context,
	                     gint x, gint y, guint time);
	static void DragDataReceived(GtkWidget *widget, GdkDragContext *context,
	                             gint x, gint y, GtkSelectionData *selection_data, guint info, guint time);
	static void DragDataGet(GtkWidget *widget, GdkDragContext *context,
	                        GtkSelectionData *selection_data, guint info, guint time);
	static gboolean TimeOut(ScintillaGTK *sciThis);
	static gboolean IdleCallback(ScintillaGTK *sciThis);
	static gboolean StyleIdle(ScintillaGTK *sciThis);
	virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo);
	static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis);

#if GTK_CHECK_VERSION(3,0,0)
	static gboolean DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip);
#else
	static gboolean ExposeCT(GtkWidget *widget, GdkEventExpose *ose, CallTip *ct);
#endif
	static gboolean PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis);

	static sptr_t DirectFunction(ScintillaGTK *sciThis,
	                             unsigned int iMessage, uptr_t wParam, sptr_t lParam);
};

enum {
    COMMAND_SIGNAL,
    NOTIFY_SIGNAL,
    LAST_SIGNAL
};

static gint scintilla_signals[LAST_SIGNAL] = { 0 };

enum {
    TARGET_STRING,
    TARGET_TEXT,
    TARGET_COMPOUND_TEXT,
    TARGET_UTF8_STRING,
    TARGET_URI
};

GdkAtom ScintillaGTK::atomClipboard = 0;
GdkAtom ScintillaGTK::atomUTF8 = 0;
GdkAtom ScintillaGTK::atomString = 0;
GdkAtom ScintillaGTK::atomUriList = 0;
GdkAtom ScintillaGTK::atomDROPFILES_DND = 0;

static const GtkTargetEntry clipboardCopyTargets[] = {
	{ (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
	{ (gchar *) "STRING", 0, TARGET_STRING },
};
static const gint nClipboardCopyTargets = sizeof(clipboardCopyTargets) / sizeof(clipboardCopyTargets[0]);

static const GtkTargetEntry clipboardPasteTargets[] = {
	{ (gchar *) "text/uri-list", 0, TARGET_URI },
	{ (gchar *) "UTF8_STRING", 0, TARGET_UTF8_STRING },
	{ (gchar *) "STRING", 0, TARGET_STRING },
};
static const gint nClipboardPasteTargets = sizeof(clipboardPasteTargets) / sizeof(clipboardPasteTargets[0]);

static GtkWidget *PWidget(Window &w) {
	return reinterpret_cast<GtkWidget *>(w.GetID());
}

static ScintillaGTK *ScintillaFromWidget(GtkWidget *widget) {
	ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(widget);
	return reinterpret_cast<ScintillaGTK *>(scio->pscin);
}

ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
		adjustmentv(0), adjustmenth(0),
		scrollBarWidth(30), scrollBarHeight(30),
		capturedMouse(false), dragWasDropped(false),
		lastKey(0), rectangularSelectionModifier(SCMOD_CTRL), parentClass(0),
		im_context(NULL),
		lastWheelMouseDirection(0),
		wheelMouseIntensity(0),
		rgnUpdate(0) {
	sci = sci_;
	wMain = GTK_WIDGET(sci);

#if PLAT_GTK_WIN32
	rectangularSelectionModifier = SCMOD_ALT;
#else
	rectangularSelectionModifier = SCMOD_CTRL;
#endif

#if PLAT_GTK_WIN32
 	// There does not seem to be a real standard for indicating that the clipboard
	// contains a rectangular selection, so copy Developer Studio.
	cfColumnSelect = static_cast<CLIPFORMAT>(
		::RegisterClipboardFormat("MSDEVColumnSelect"));

  	// Get intellimouse parameters when running on win32; otherwise use
	// reasonable default
#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES   104
#endif
	::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
#else
	linesPerScroll = 4;
#endif
	lastWheelMouseTime.tv_sec = 0;
	lastWheelMouseTime.tv_usec = 0;

	Initialise();
}

ScintillaGTK::~ScintillaGTK() {
	g_idle_remove_by_data(this);
}

static void UnRefCursor(GdkCursor *cursor) {
#if GTK_CHECK_VERSION(3,0,0)
	g_object_unref(cursor);
#else
	gdk_cursor_unref(cursor);
#endif
}

void ScintillaGTK::RealizeThis(GtkWidget *widget) {
	//Platform::DebugPrintf("ScintillaGTK::realize this\n");
#if GTK_CHECK_VERSION(2,20,0)
	gtk_widget_set_realized(widget, TRUE);
#else
	GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
#endif
	GdkWindowAttr attrs;
	attrs.window_type = GDK_WINDOW_CHILD;
	GtkAllocation allocation;
#if GTK_CHECK_VERSION(3,0,0)
	gtk_widget_get_allocation(widget, &allocation);
#else
	allocation = widget->allocation;
#endif
	attrs.x = allocation.x;
	attrs.y = allocation.y;
	attrs.width = allocation.width;
	attrs.height = allocation.height;
	attrs.wclass = GDK_INPUT_OUTPUT;
	attrs.visual = gtk_widget_get_visual(widget);
#if !GTK_CHECK_VERSION(3,0,0)
	attrs.colormap = gtk_widget_get_colormap(widget);
#endif
	attrs.event_mask = gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK;
	GdkCursor *cursor = gdk_cursor_new(GDK_XTERM);
	attrs.cursor = cursor;
#if GTK_CHECK_VERSION(3,0,0)
	gtk_widget_set_window(widget, gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
		GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_CURSOR));
	gdk_window_set_user_data(gtk_widget_get_window(widget), widget);
	GtkStyleContext *styleContext = gtk_widget_get_style_context(widget);
	if (styleContext) {
		GdkRGBA colourBackWidget;
		gtk_style_context_get_background_color(styleContext, GTK_STATE_FLAG_NORMAL, &colourBackWidget);
		gdk_window_set_background_rgba(gtk_widget_get_window(widget), &colourBackWidget);
	}
	gdk_window_show(gtk_widget_get_window(widget));
	UnRefCursor(cursor);
#else
	widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attrs,
		GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR);
	gdk_window_set_user_data(widget->window, widget);
	widget->style = gtk_style_attach(widget->style, widget->window);
	gdk_window_set_background(widget->window, &widget->style->bg[GTK_STATE_NORMAL]);
	gdk_window_show(widget->window);
	UnRefCursor(cursor);
#endif
	wPreedit = gtk_window_new(GTK_WINDOW_POPUP);
	wPreeditDraw = gtk_drawing_area_new();
	GtkWidget *predrw = PWidget(wPreeditDraw);	// No code inside the G_OBJECT macro
#if GTK_CHECK_VERSION(3,0,0)
	g_signal_connect(G_OBJECT(predrw), "draw",
		G_CALLBACK(DrawPreedit), this);
#else
	g_signal_connect(G_OBJECT(predrw), "expose_event",
		G_CALLBACK(ExposePreedit), this);
#endif
	gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
	gtk_widget_realize(PWidget(wPreedit));
	gtk_widget_realize(predrw);
	gtk_widget_show(predrw);

	im_context = gtk_im_multicontext_new();
	g_signal_connect(G_OBJECT(im_context), "commit",
		G_CALLBACK(Commit), this);
	g_signal_connect(G_OBJECT(im_context), "preedit_changed",
		G_CALLBACK(PreeditChanged), this);
	gtk_im_context_set_client_window(im_context, WindowFromWidget(widget));
	GtkWidget *widtxt = PWidget(wText);	//	// No code inside the G_OBJECT macro
	g_signal_connect_after(G_OBJECT(widtxt), "style_set",
		G_CALLBACK(ScintillaGTK::StyleSetText), NULL);
	g_signal_connect_after(G_OBJECT(widtxt), "realize",
		G_CALLBACK(ScintillaGTK::RealizeText), NULL);
	gtk_widget_realize(widtxt);
	gtk_widget_realize(PWidget(scrollbarv));
	gtk_widget_realize(PWidget(scrollbarh));

	cursor = gdk_cursor_new(GDK_XTERM);
	gdk_window_set_cursor(PWindow(wText), cursor);
	UnRefCursor(cursor);

	cursor = gdk_cursor_new(GDK_LEFT_PTR);
	gdk_window_set_cursor(PWindow(scrollbarv), cursor);
	UnRefCursor(cursor);

	cursor = gdk_cursor_new(GDK_LEFT_PTR);
	gdk_window_set_cursor(PWindow(scrollbarh), cursor);
	UnRefCursor(cursor);

	gtk_selection_add_targets(widget, GDK_SELECTION_PRIMARY,
	                          clipboardCopyTargets, nClipboardCopyTargets);
}

void ScintillaGTK::Realize(GtkWidget *widget) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	sciThis->RealizeThis(widget);
}

void ScintillaGTK::UnRealizeThis(GtkWidget *widget) {
	try {
		gtk_selection_clear_targets(widget, GDK_SELECTION_PRIMARY);

		if (IS_WIDGET_MAPPED(widget)) {
			gtk_widget_unmap(widget);
		}
#if GTK_CHECK_VERSION(2,20,0)
		gtk_widget_set_realized(widget, FALSE);
#else
		GTK_WIDGET_UNSET_FLAGS(widget, GTK_REALIZED);
#endif
		gtk_widget_unrealize(PWidget(wText));
		gtk_widget_unrealize(PWidget(scrollbarv));
		gtk_widget_unrealize(PWidget(scrollbarh));
		gtk_widget_unrealize(PWidget(wPreedit));
		gtk_widget_unrealize(PWidget(wPreeditDraw));
		g_object_unref(im_context);
		im_context = NULL;
		if (GTK_WIDGET_CLASS(parentClass)->unrealize)
			GTK_WIDGET_CLASS(parentClass)->unrealize(widget);

		Finalise();
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::UnRealize(GtkWidget *widget) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	sciThis->UnRealizeThis(widget);
}

static void MapWidget(GtkWidget *widget) {
	if (widget &&
	        IS_WIDGET_VISIBLE(widget) &&
	        !IS_WIDGET_MAPPED(widget)) {
		gtk_widget_map(widget);
	}
}

void ScintillaGTK::MapThis() {
	try {
		//Platform::DebugPrintf("ScintillaGTK::map this\n");
#if GTK_CHECK_VERSION(2,20,0)
		gtk_widget_set_mapped(PWidget(wMain), TRUE);
#else
		GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_MAPPED);
#endif
		MapWidget(PWidget(wText));
		MapWidget(PWidget(scrollbarh));
		MapWidget(PWidget(scrollbarv));
		wMain.SetCursor(Window::cursorArrow);
		scrollbarv.SetCursor(Window::cursorArrow);
		scrollbarh.SetCursor(Window::cursorArrow);
		ChangeSize();
		gdk_window_show(PWindow(wMain));
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::Map(GtkWidget *widget) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	sciThis->MapThis();
}

void ScintillaGTK::UnMapThis() {
	try {
		//Platform::DebugPrintf("ScintillaGTK::unmap this\n");
#if GTK_CHECK_VERSION(2,20,0)
		gtk_widget_set_mapped(PWidget(wMain), FALSE);
#else
		GTK_WIDGET_UNSET_FLAGS(PWidget(wMain), GTK_MAPPED);
#endif
		DropGraphics(false);
		gdk_window_hide(PWindow(wMain));
		gtk_widget_unmap(PWidget(wText));
		gtk_widget_unmap(PWidget(scrollbarh));
		gtk_widget_unmap(PWidget(scrollbarv));
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::UnMap(GtkWidget *widget) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	sciThis->UnMapThis();
}

void ScintillaGTK::ForAll(GtkCallback callback, gpointer callback_data) {
	try {
		(*callback) (PWidget(wText), callback_data);
		(*callback) (PWidget(scrollbarv), callback_data);
		(*callback) (PWidget(scrollbarh), callback_data);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::MainForAll(GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) {
	ScintillaGTK *sciThis = ScintillaFromWidget((GtkWidget *)container);

	if (callback != NULL && include_internals) {
		sciThis->ForAll(callback, callback_data);
	}
}

gint ScintillaGTK::FocusInThis(GtkWidget *widget) {
	try {
		SetFocusState(true);
		if (im_context != NULL) {
			gchar *str = NULL;
			gint cursor_pos;

			gtk_im_context_get_preedit_string(im_context, &str, NULL, &cursor_pos);
			if (PWidget(wPreedit) != NULL) {
				if (strlen(str) > 0) {
					gtk_widget_show(PWidget(wPreedit));
				} else {
					gtk_widget_hide(PWidget(wPreedit));
				}
			}
			g_free(str);
			gtk_im_context_focus_in(im_context);
		}

	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gint ScintillaGTK::FocusIn(GtkWidget *widget, GdkEventFocus * /*event*/) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->FocusInThis(widget);
}

gint ScintillaGTK::FocusOutThis(GtkWidget *widget) {
	try {
		SetFocusState(false);

		if (PWidget(wPreedit) != NULL)
			gtk_widget_hide(PWidget(wPreedit));
		if (im_context != NULL)
			gtk_im_context_focus_out(im_context);

	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gint ScintillaGTK::FocusOut(GtkWidget *widget, GdkEventFocus * /*event*/) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->FocusOutThis(widget);
}

void ScintillaGTK::SizeRequest(GtkWidget *widget, GtkRequisition *requisition) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	requisition->width = 1;
	requisition->height = 1;
	GtkRequisition child_requisition;
#if GTK_CHECK_VERSION(3,0,0)
	gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarh), NULL, &child_requisition);
	gtk_widget_get_preferred_size(PWidget(sciThis->scrollbarv), NULL, &child_requisition);
#else
	gtk_widget_size_request(PWidget(sciThis->scrollbarh), &child_requisition);
	gtk_widget_size_request(PWidget(sciThis->scrollbarv), &child_requisition);
#endif
}

void ScintillaGTK::GetPreferredWidth(GtkWidget *widget, gint *minimalWidth, gint *naturalWidth) {
	GtkRequisition requisition;
	SizeRequest(widget, &requisition);
	*minimalWidth = *naturalWidth = requisition.width;
}

void ScintillaGTK::GetPreferredHeight(GtkWidget *widget, gint *minimalHeight, gint *naturalHeight) {
	GtkRequisition requisition;
	SizeRequest(widget, &requisition);
	*minimalHeight = *naturalHeight = requisition.height;
}

void ScintillaGTK::SizeAllocate(GtkWidget *widget, GtkAllocation *allocation) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
#if GTK_CHECK_VERSION(2,20,0)
		gtk_widget_set_allocation(widget, allocation);
#else
		widget->allocation = *allocation;
#endif
		if (IS_WIDGET_REALIZED(widget))
			gdk_window_move_resize(WindowFromWidget(widget),
			        allocation->x,
			        allocation->y,
			        allocation->width,
			        allocation->height);

		sciThis->Resize(allocation->width, allocation->height);

	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::Initialise() {
	//Platform::DebugPrintf("ScintillaGTK::Initialise\n");
	parentClass = reinterpret_cast<GtkWidgetClass *>(
	                  g_type_class_ref(gtk_container_get_type()));

#if GTK_CHECK_VERSION(2,20,0)
	gtk_widget_set_can_focus(PWidget(wMain), TRUE);
	gtk_widget_set_sensitive(PWidget(wMain), TRUE);
#else
	GTK_WIDGET_SET_FLAGS(PWidget(wMain), GTK_CAN_FOCUS);
	GTK_WIDGET_SET_FLAGS(GTK_WIDGET(PWidget(wMain)), GTK_SENSITIVE);
#endif
	gtk_widget_set_events(PWidget(wMain),
	                      GDK_EXPOSURE_MASK
	                      | GDK_SCROLL_MASK
	                      | GDK_STRUCTURE_MASK
	                      | GDK_KEY_PRESS_MASK
	                      | GDK_KEY_RELEASE_MASK
	                      | GDK_FOCUS_CHANGE_MASK
	                      | GDK_LEAVE_NOTIFY_MASK
	                      | GDK_BUTTON_PRESS_MASK
	                      | GDK_BUTTON_RELEASE_MASK
	                      | GDK_POINTER_MOTION_MASK
	                      | GDK_POINTER_MOTION_HINT_MASK);

	wText = gtk_drawing_area_new();
	gtk_widget_set_parent(PWidget(wText), PWidget(wMain));
	GtkWidget *widtxt = PWidget(wText);	// No code inside the G_OBJECT macro
	gtk_widget_show(widtxt);
#if GTK_CHECK_VERSION(3,0,0)
	g_signal_connect(G_OBJECT(widtxt), "draw",
			   G_CALLBACK(ScintillaGTK::DrawText), this);
#else
	g_signal_connect(G_OBJECT(widtxt), "expose_event",
			   G_CALLBACK(ScintillaGTK::ExposeText), this);
#endif
	gtk_widget_set_events(widtxt, GDK_EXPOSURE_MASK);
	// Avoid background drawing flash
	gtk_widget_set_double_buffered(widtxt, FALSE);
	gtk_widget_set_size_request(widtxt, 100, 100);
	adjustmentv = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 201.0, 1.0, 20.0, 20.0));
#if GTK_CHECK_VERSION(3,0,0)
	scrollbarv = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(adjustmentv));
#else
	scrollbarv = gtk_vscrollbar_new(GTK_ADJUSTMENT(adjustmentv));
#endif
#if GTK_CHECK_VERSION(2,20,0)
	gtk_widget_set_can_focus(PWidget(scrollbarv), FALSE);
#else
	GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarv), GTK_CAN_FOCUS);
#endif
	g_signal_connect(G_OBJECT(adjustmentv), "value_changed",
			   G_CALLBACK(ScrollSignal), this);
	gtk_widget_set_parent(PWidget(scrollbarv), PWidget(wMain));
	gtk_widget_show(PWidget(scrollbarv));

	adjustmenth = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 101.0, 1.0, 20.0, 20.0));
#if GTK_CHECK_VERSION(3,0,0)
	scrollbarh = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT(adjustmenth));
#else
	scrollbarh = gtk_hscrollbar_new(GTK_ADJUSTMENT(adjustmenth));
#endif
#if GTK_CHECK_VERSION(2,20,0)
	gtk_widget_set_can_focus(PWidget(scrollbarh), FALSE);
#else
	GTK_WIDGET_UNSET_FLAGS(PWidget(scrollbarh), GTK_CAN_FOCUS);
#endif
	g_signal_connect(G_OBJECT(adjustmenth), "value_changed",
			   G_CALLBACK(ScrollHSignal), this);
	gtk_widget_set_parent(PWidget(scrollbarh), PWidget(wMain));
	gtk_widget_show(PWidget(scrollbarh));

	gtk_widget_grab_focus(PWidget(wMain));

	gtk_drag_dest_set(GTK_WIDGET(PWidget(wMain)),
	                  GTK_DEST_DEFAULT_ALL, clipboardPasteTargets, nClipboardPasteTargets,
	                  static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE));

	// Set caret period based on GTK settings
	gboolean blinkOn = false;
	if (g_object_class_find_property(G_OBJECT_GET_CLASS(
			G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
		g_object_get(G_OBJECT(
			gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, NULL);
	}
	if (blinkOn &&
		g_object_class_find_property(G_OBJECT_GET_CLASS(
			G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
		gint value;
		g_object_get(G_OBJECT(
			gtk_settings_get_default()), "gtk-cursor-blink-time", &value, NULL);
		caret.period = gint(value / 1.75);
	} else {
		caret.period = 0;
	}

	SetTicking(true);
}

void ScintillaGTK::Finalise() {
	SetTicking(false);
	ScintillaBase::Finalise();
}

void ScintillaGTK::DisplayCursor(Window::Cursor c) {
	if (cursorMode == SC_CURSORNORMAL)
		wText.SetCursor(c);
	else
		wText.SetCursor(static_cast<Window::Cursor>(cursorMode));
}

bool ScintillaGTK::DragThreshold(Point ptStart, Point ptNow) {
	return gtk_drag_check_threshold(GTK_WIDGET(PWidget(wMain)),
		ptStart.x, ptStart.y, ptNow.x, ptNow.y);
}

void ScintillaGTK::StartDrag() {
	dragWasDropped = false;
	inDragDrop = ddDragging;
	GtkTargetList *tl = gtk_target_list_new(clipboardCopyTargets, nClipboardCopyTargets);
	gtk_drag_begin(GTK_WIDGET(PWidget(wMain)),
	               tl,
	               static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_MOVE),
	               evbtn.button,
	               reinterpret_cast<GdkEvent *>(&evbtn));
}

static char *ConvertText(int *lenResult, char *s, size_t len, const char *charSetDest,
	const char *charSetSource, bool transliterations, bool silent=false) {
	// s is not const because of different versions of iconv disagreeing about const
	*lenResult = 0;
	char *destForm = 0;
	Converter conv(charSetDest, charSetSource, transliterations);
	if (conv) {
		destForm = new char[len*3+1];
		char *pin = s;
		size_t inLeft = len;
		char *pout = destForm;
		size_t outLeft = len*3+1;
		size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
		if (conversions == ((size_t)(-1))) {
			if (!silent)
				fprintf(stderr, "iconv %s->%s failed for %s\n",
					charSetSource, charSetDest, static_cast<char *>(s));
			delete []destForm;
			destForm = 0;
		} else {
//fprintf(stderr, "iconv OK %s %d\n", destForm, pout - destForm);
			*pout = '\0';
			*lenResult = pout - destForm;
		}
	} else {
fprintf(stderr, "Can not iconv %s %s\n", charSetDest, charSetSource);
	}
	if (!destForm) {
		destForm = new char[1];
		destForm[0] = '\0';
		*lenResult = 0;
	}
	return destForm;
}

// Returns the target converted to UTF8.
// Return the length in bytes.
int ScintillaGTK::TargetAsUTF8(char *text) {
	int targetLength = targetEnd - targetStart;
	if (IsUnicodeMode()) {
		if (text) {
			pdoc->GetCharRange(text, targetStart, targetLength);
		}
	} else {
		// Need to convert
		const char *charSetBuffer = CharacterSetID();
		if (*charSetBuffer) {
//~ fprintf(stderr, "AsUTF8 %s %d  %0d-%0d\n", charSetBuffer, targetLength, targetStart, targetEnd);
			char *s = new char[targetLength];
			if (s) {
				pdoc->GetCharRange(s, targetStart, targetLength);
//~ fprintf(stderr, "    \"%s\"\n", s);
				if (text) {
					char *tmputf = ConvertText(&targetLength, s, targetLength, "UTF-8", charSetBuffer, false);
					memcpy(text, tmputf, targetLength);
					delete []tmputf;
//~ fprintf(stderr, "    \"%s\"\n", text);
				}
				delete []s;
			}
		} else {
			if (text) {
				pdoc->GetCharRange(text, targetStart, targetLength);
			}
		}
	}
//~ fprintf(stderr, "Length = %d bytes\n", targetLength);
	return targetLength;
}

// Translates a nul terminated UTF8 string into the document encoding.
// Return the length of the result in bytes.
int ScintillaGTK::EncodedFromUTF8(char *utf8, char *encoded) {
	int inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8);
	if (IsUnicodeMode()) {
		if (encoded) {
			memcpy(encoded, utf8, inputLength);
		}
		return inputLength;
	} else {
		// Need to convert
		const char *charSetBuffer = CharacterSetID();
		if (*charSetBuffer) {
			int outLength = 0;
			char *tmpEncoded = ConvertText(&outLength, utf8, inputLength, charSetBuffer, "UTF-8", true);
			if (tmpEncoded) {
				if (encoded) {
					memcpy(encoded, tmpEncoded, outLength);
				}
				delete []tmpEncoded;
			}
			return outLength;
		} else {
			if (encoded) {
				memcpy(encoded, utf8, inputLength);
			}
			return inputLength;
		}
	}
	// Fail
	return 0;
}

bool ScintillaGTK::ValidCodePage(int codePage) const {
	return codePage == 0
	|| codePage == SC_CP_UTF8
	|| codePage == 932
	|| codePage == 936
	|| codePage == 949
	|| codePage == 950
	|| codePage == 1361;
}

sptr_t ScintillaGTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	try {
		switch (iMessage) {

		case SCI_GRABFOCUS:
			gtk_widget_grab_focus(PWidget(wMain));
			break;

		case SCI_GETDIRECTFUNCTION:
			return reinterpret_cast<sptr_t>(DirectFunction);

		case SCI_GETDIRECTPOINTER:
			return reinterpret_cast<sptr_t>(this);

#ifdef SCI_LEXER
		case SCI_LOADLEXERLIBRARY:
                        LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
			break;
#endif
		case SCI_TARGETASUTF8:
			return TargetAsUTF8(reinterpret_cast<char*>(lParam));

		case SCI_ENCODEDFROMUTF8:
			return EncodedFromUTF8(reinterpret_cast<char*>(wParam),
			        reinterpret_cast<char*>(lParam));

		case SCI_SETRECTANGULARSELECTIONMODIFIER:
			rectangularSelectionModifier = wParam;
			break;

		case SCI_GETRECTANGULARSELECTIONMODIFIER:
			return rectangularSelectionModifier;

		default:
			return ScintillaBase::WndProc(iMessage, wParam, lParam);
		}
	} catch (std::bad_alloc&) {
		errorStatus = SC_STATUS_BADALLOC;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return 0l;
}

sptr_t ScintillaGTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
	return 0;
}

void ScintillaGTK::SetTicking(bool on) {
	if (timer.ticking != on) {
		timer.ticking = on;
		if (timer.ticking) {
			timer.tickerID = reinterpret_cast<TickerID>(g_timeout_add(timer.tickSize,
				reinterpret_cast<GSourceFunc>(TimeOut), this));
		} else {
			g_source_remove(GPOINTER_TO_UINT(timer.tickerID));
		}
	}
	timer.ticksToWait = caret.period;
}

bool ScintillaGTK::SetIdle(bool on) {
	if (on) {
		// Start idler, if it's not running.
		if (!idler.state) {
			idler.state = true;
			idler.idlerID = reinterpret_cast<IdlerID>(
				g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
					reinterpret_cast<GSourceFunc>(IdleCallback), this, NULL));
		}
	} else {
		// Stop idler, if it's running
		if (idler.state) {
			idler.state = false;
			g_source_remove(GPOINTER_TO_UINT(idler.idlerID));
		}
	}
	return true;
}

void ScintillaGTK::SetMouseCapture(bool on) {
	if (mouseDownCaptures) {
		if (on) {
			gtk_grab_add(GTK_WIDGET(PWidget(wMain)));
		} else {
			gtk_grab_remove(GTK_WIDGET(PWidget(wMain)));
		}
	}
	capturedMouse = on;
}

bool ScintillaGTK::HaveMouseCapture() {
	return capturedMouse;
}

#if GTK_CHECK_VERSION(3,0,0)

// Is crcTest completely in crcContainer?
static bool CRectContains(const cairo_rectangle_t &crcContainer, const cairo_rectangle_t &crcTest) {
	return
		(crcTest.x >= crcContainer.x) && ((crcTest.x + crcTest.width) <= (crcContainer.x + crcContainer.width)) &&
		(crcTest.y >= crcContainer.y) && ((crcTest.y + crcTest.height) <= (crcContainer.y + crcContainer.height));
}

// Is crcTest completely in crcListContainer?
// May incorrectly return false if complex shape
static bool CRectListContains(const cairo_rectangle_list_t *crcListContainer, const cairo_rectangle_t &crcTest) {
	for (int r=0; r<crcListContainer->num_rectangles; r++) {
		if (CRectContains(crcListContainer->rectangles[r], crcTest))
			return true;
	}
	return false;
}

#endif

bool ScintillaGTK::PaintContains(PRectangle rc) {
	// This allows optimization when a rectangle is completely in the update region.
	// It is OK to return false when too difficult to determine as that just performs extra drawing
	bool contains = true;
	if (paintState == painting) {
		if (!rcPaint.Contains(rc)) {
			contains = false;
		} else if (rgnUpdate) {
#if GTK_CHECK_VERSION(3,0,0)
			cairo_rectangle_t grc = {rc.left, rc.top,
				rc.right - rc.left, rc.bottom - rc.top};
			contains = CRectListContains(rgnUpdate, grc);
#else
			GdkRectangle grc = {static_cast<gint>(rc.left), static_cast<gint>(rc.top),
				static_cast<gint>(rc.right - rc.left), static_cast<gint>(rc.bottom - rc.top)};
			if (gdk_region_rect_in(rgnUpdate, &grc) != GDK_OVERLAP_RECTANGLE_IN) {
				contains = false;
			}
#endif
		}
	}
	return contains;
}

// Redraw all of text area. This paint will not be abandoned.
void ScintillaGTK::FullPaint() {
	wText.InvalidateAll();
}

PRectangle ScintillaGTK::GetClientRectangle() {
	PRectangle rc = wMain.GetClientPosition();
	if (verticalScrollBarVisible)
		rc.right -= scrollBarWidth;
	if (horizontalScrollBarVisible && (wrapState == eWrapNone))
		rc.bottom -= scrollBarHeight;
	// Move to origin
	rc.right -= rc.left;
	rc.bottom -= rc.top;
	rc.left = 0;
	rc.top = 0;
	return rc;
}

// Synchronously paint a rectangle of the window.
void ScintillaGTK::SyncPaint(PRectangle rc) {
	paintState = painting;
	rcPaint = rc;
	PRectangle rcClient = GetClientRectangle();
	paintingAllText = rcPaint.Contains(rcClient);
	if (PWindow(wText)) {
		Surface *sw = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
		if (sw) {
			cairo_t *cr = gdk_cairo_create(PWindow(wText));
			sw->Init(cr, PWidget(wText));
			Paint(sw, rc);
			sw->Release();
			delete sw;
			cairo_destroy(cr);
		}
	}
	if (paintState == paintAbandoned) {
		// Painting area was insufficient to cover new styling or brace highlight positions
		FullPaint();
	}
	paintState = notPainting;
}

void ScintillaGTK::ScrollText(int linesToMove) {
	int diff = vs.lineHeight * -linesToMove;
	//Platform::DebugPrintf("ScintillaGTK::ScrollText %d %d %0d,%0d %0d,%0d\n", linesToMove, diff,
	//	rc.left, rc.top, rc.right, rc.bottom);
	GtkWidget *wi = PWidget(wText);
	NotifyUpdateUI();

	if (IS_WIDGET_REALIZED(wi)) {
		gdk_window_scroll(WindowFromWidget(wi), 0, -diff);
		gdk_window_process_updates(WindowFromWidget(wi), FALSE);
	}
}

void ScintillaGTK::SetVerticalScrollPos() {
	DwellEnd(true);
	gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), topLine);
}

void ScintillaGTK::SetHorizontalScrollPos() {
	DwellEnd(true);
	gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmenth), xOffset / 2);
}

bool ScintillaGTK::ModifyScrollBars(int nMax, int nPage) {
	bool modified = false;
	int pageScroll = LinesToScroll();

#if GTK_CHECK_VERSION(3,0,0)
	if (gtk_adjustment_get_upper(adjustmentv) != (nMax + 1) ||
	        gtk_adjustment_get_page_size(adjustmentv) != nPage ||
	        gtk_adjustment_get_page_increment(adjustmentv) != pageScroll) {
		gtk_adjustment_set_upper(adjustmentv, nMax + 1);
	        gtk_adjustment_set_page_size(adjustmentv, nPage);
	        gtk_adjustment_set_page_increment(adjustmentv, pageScroll);
		gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
		modified = true;
	}
#else
	if (GTK_ADJUSTMENT(adjustmentv)->upper != (nMax + 1) ||
	        GTK_ADJUSTMENT(adjustmentv)->page_size != nPage ||
	        GTK_ADJUSTMENT(adjustmentv)->page_increment != pageScroll) {
		GTK_ADJUSTMENT(adjustmentv)->upper = nMax + 1;
		GTK_ADJUSTMENT(adjustmentv)->page_size = nPage;
		GTK_ADJUSTMENT(adjustmentv)->page_increment = pageScroll;
		gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmentv));
		modified = true;
	}
#endif

	PRectangle rcText = GetTextRectangle();
	int horizEndPreferred = scrollWidth;
	if (horizEndPreferred < 0)
		horizEndPreferred = 0;
	unsigned int pageWidth = rcText.Width();
	unsigned int pageIncrement = pageWidth / 3;
	unsigned int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
#if GTK_CHECK_VERSION(3,0,0)
	if (gtk_adjustment_get_upper(adjustmenth) != horizEndPreferred ||
	        gtk_adjustment_get_page_size(adjustmenth) != pageWidth ||
	        gtk_adjustment_get_page_increment(adjustmenth) != pageIncrement ||
	        gtk_adjustment_get_step_increment(adjustmenth) != charWidth) {
		gtk_adjustment_set_upper(adjustmenth, horizEndPreferred);
	        gtk_adjustment_set_page_size(adjustmenth, pageWidth);
	        gtk_adjustment_set_page_increment(adjustmenth, pageIncrement);
	        gtk_adjustment_set_step_increment(adjustmenth, charWidth);
		gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
		modified = true;
	}
#else
	if (GTK_ADJUSTMENT(adjustmenth)->upper != horizEndPreferred ||
	        GTK_ADJUSTMENT(adjustmenth)->page_size != pageWidth ||
	        GTK_ADJUSTMENT(adjustmenth)->page_increment != pageIncrement ||
	        GTK_ADJUSTMENT(adjustmenth)->step_increment != charWidth) {
		GTK_ADJUSTMENT(adjustmenth)->upper = horizEndPreferred;
		GTK_ADJUSTMENT(adjustmenth)->step_increment = charWidth;
		GTK_ADJUSTMENT(adjustmenth)->page_size = pageWidth;
		GTK_ADJUSTMENT(adjustmenth)->page_increment = pageIncrement;
		gtk_adjustment_changed(GTK_ADJUSTMENT(adjustmenth));
		modified = true;
	}
#endif
	if (modified && (paintState == painting)) {
		paintState = paintAbandoned;
	}

	return modified;
}

void ScintillaGTK::ReconfigureScrollBars() {
	PRectangle rc = wMain.GetClientPosition();
	Resize(rc.Width(), rc.Height());
}

void ScintillaGTK::NotifyChange() {
	g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
	                Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE), PWidget(wMain));
}

void ScintillaGTK::NotifyFocus(bool focus) {
	g_signal_emit(G_OBJECT(sci), scintilla_signals[COMMAND_SIGNAL], 0,
	                Platform::LongFromTwoShorts
					(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), PWidget(wMain));
}

void ScintillaGTK::NotifyParent(SCNotification scn) {
	scn.nmhdr.hwndFrom = PWidget(wMain);
	scn.nmhdr.idFrom = GetCtrlID();
	g_signal_emit(G_OBJECT(sci), scintilla_signals[NOTIFY_SIGNAL], 0,
	                GetCtrlID(), &scn);
}

void ScintillaGTK::NotifyKey(int key, int modifiers) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_KEY;
	scn.ch = key;
	scn.modifiers = modifiers;

	NotifyParent(scn);
}

void ScintillaGTK::NotifyURIDropped(const char *list) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_URIDROPPED;
	scn.text = list;

	NotifyParent(scn);
}

const char *CharacterSetID(int characterSet);

const char *ScintillaGTK::CharacterSetID() const {
	return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
}

class CaseFolderUTF8 : public CaseFolderTable {
public:
	CaseFolderUTF8() {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
			gchar *mapped = g_utf8_casefold(mixed, lenMixed);
			size_t lenMapped = strlen(mapped);
			if (lenMapped < sizeFolded) {
				memcpy(folded, mapped,  lenMapped);
			} else {
				lenMapped = 0;
			}
			g_free(mapped);
			return lenMapped;
		}
	}
};

class CaseFolderDBCS : public CaseFolderTable {
	const char *charSet;
public:
	CaseFolderDBCS(const char *charSet_) : charSet(charSet_) {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else if (*charSet) {
			int convertedLength = lenMixed;
			char *sUTF8 = ConvertText(&convertedLength, const_cast<char *>(mixed), lenMixed,
				"UTF-8", charSet, false);
			if (sUTF8) {
				gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
				size_t lenMapped = strlen(mapped);
				if (lenMapped < sizeFolded) {
					memcpy(folded, mapped,  lenMapped);
				} else {
					folded[0] = '\0';
					lenMapped = 1;
				}
				g_free(mapped);
				delete []sUTF8;
				return lenMapped;
			}
		}
		// Something failed so return a single NUL byte
		folded[0] = '\0';
		return 1;
	}
};

CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
	if (pdoc->dbcsCodePage == SC_CP_UTF8) {
		return new CaseFolderUTF8();
	} else {
		const char *charSetBuffer = CharacterSetID();
		if (charSetBuffer) {
			if (pdoc->dbcsCodePage == 0) {
				CaseFolderTable *pcf = new CaseFolderTable();
				pcf->StandardASCII();
				// Only for single byte encodings
				for (int i=0x80; i<0x100; i++) {
					char sCharacter[2] = "A";
					sCharacter[0] = i;
					int convertedLength = 1;
					const char *sUTF8 = ConvertText(&convertedLength, sCharacter, 1,
						"UTF-8", charSetBuffer, false);
					if (sUTF8) {
						gchar *mapped = g_utf8_casefold(sUTF8, strlen(sUTF8));
						if (mapped) {
							int mappedLength = strlen(mapped);
							const char *mappedBack = ConvertText(&mappedLength, mapped,
								mappedLength, charSetBuffer, "UTF-8", false, true);
							if (mappedBack && (strlen(mappedBack) == 1) && (mappedBack[0] != sCharacter[0])) {
								pcf->SetTranslation(sCharacter[0], mappedBack[0]);
							}
							delete []mappedBack;
							g_free(mapped);
						}
					}
					delete []sUTF8;
				}
				return pcf;
			} else {
				return new CaseFolderDBCS(charSetBuffer);
			}
		}
		return 0;
	}
}

std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
	if (s.size() == 0)
		return std::string();

	if (caseMapping == cmSame)
		return s;

	const char *needsFree1 = 0;	// Must be freed with delete []
	const char *charSetBuffer = CharacterSetID();
	const char *sUTF8 = s.c_str();
	int rangeBytes = s.size();

	int convertedLength = rangeBytes;
	// Change text to UTF-8
	if (!IsUnicodeMode()) {
		// Need to convert
		if (*charSetBuffer) {
			sUTF8 = ConvertText(&convertedLength, const_cast<char *>(s.c_str()), rangeBytes,
				"UTF-8", charSetBuffer, false);
			needsFree1 = sUTF8;
		}
	}
	gchar *mapped;	// Must be freed with g_free
	if (caseMapping == cmUpper) {
		mapped = g_utf8_strup(sUTF8, convertedLength);
	} else {
		mapped = g_utf8_strdown(sUTF8, convertedLength);
	}
	int mappedLength = strlen(mapped);
	char *mappedBack = mapped;

	char *needsFree2 = 0;	// Must be freed with delete []
	if (!IsUnicodeMode()) {
		if (*charSetBuffer) {
			mappedBack = ConvertText(&mappedLength, mapped, mappedLength, charSetBuffer, "UTF-8", false);
			needsFree2 = mappedBack;
		}
	}

	std::string ret(mappedBack, mappedLength);
	g_free(mapped);
	delete []needsFree1;
	delete []needsFree2;
	return ret;
}

int ScintillaGTK::KeyDefault(int key, int modifiers) {
	// Pass up to container in case it is an accelerator
	NotifyKey(key, modifiers);
	return 0;
}

void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
	SelectionText *clipText = new SelectionText();
	clipText->Copy(selectedText);
	StoreOnClipboard(clipText);
}

void ScintillaGTK::Copy() {
	if (!sel.Empty()) {
		SelectionText *clipText = new SelectionText();
		CopySelectionRange(clipText);
		StoreOnClipboard(clipText);
#if PLAT_GTK_WIN32
		if (sel.IsRectangular()) {
			::OpenClipboard(NULL);
			::SetClipboardData(cfColumnSelect, 0);
			::CloseClipboard();
		}
#endif
	}
}

void ScintillaGTK::Paste() {
	atomSought = atomUTF8;
	gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
	                      atomClipboard, atomSought, GDK_CURRENT_TIME);
}

void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
	if (!ct.wCallTip.Created()) {
		ct.wCallTip = gtk_window_new(GTK_WINDOW_POPUP);
		ct.wDraw = gtk_drawing_area_new();
		GtkWidget *widcdrw = PWidget(ct.wDraw);	//	// No code inside the G_OBJECT macro
		gtk_container_add(GTK_CONTAINER(PWidget(ct.wCallTip)), widcdrw);
#if GTK_CHECK_VERSION(3,0,0)
		g_signal_connect(G_OBJECT(widcdrw), "draw",
				   G_CALLBACK(ScintillaGTK::DrawCT), &ct);
#else
		g_signal_connect(G_OBJECT(widcdrw), "expose_event",
				   G_CALLBACK(ScintillaGTK::ExposeCT), &ct);
#endif
		g_signal_connect(G_OBJECT(widcdrw), "button_press_event",
				   G_CALLBACK(ScintillaGTK::PressCT), static_cast<void *>(this));
		gtk_widget_set_events(widcdrw,
			GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
	}
	gtk_widget_set_size_request(PWidget(ct.wDraw), rc.Width(), rc.Height());
	ct.wDraw.Show();
	if (PWindow(ct.wCallTip)) {
		gdk_window_resize(PWindow(ct.wCallTip), rc.Width(), rc.Height());
	}
}

void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) {
	GtkWidget *menuItem;
	if (label[0])
		menuItem = gtk_menu_item_new_with_label(label);
	else
		menuItem = gtk_separator_menu_item_new();
	gtk_menu_shell_append(GTK_MENU_SHELL(popup.GetID()), menuItem);
	g_object_set_data(G_OBJECT(menuItem), "CmdNum", reinterpret_cast<void *>(cmd));
	g_signal_connect(G_OBJECT(menuItem),"activate", G_CALLBACK(PopUpCB), this);

	if (cmd) {
		if (menuItem)
			gtk_widget_set_sensitive(menuItem, enabled);
	}
}

bool ScintillaGTK::OwnPrimarySelection() {
	return ((gdk_selection_owner_get(GDK_SELECTION_PRIMARY)
		== PWindow(wMain)) &&
			(PWindow(wMain) != NULL));
}

void ScintillaGTK::ClaimSelection() {
	// X Windows has a 'primary selection' as well as the clipboard.
	// Whenever the user selects some text, we become the primary selection
	if (!sel.Empty() && IS_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
		primarySelection = true;
		gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
		                        GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
		primary.Free();
	} else if (OwnPrimarySelection()) {
		primarySelection = true;
		if (primary.s == NULL)
			gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
	} else {
		primarySelection = false;
		primary.Free();
	}
}

#if GTK_CHECK_VERSION(3,0,0)
static const guchar *DataOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data(sd); }
static gint LengthOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_length(sd); }
static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_data_type(sd); }
static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return gtk_selection_data_get_selection(sd); }
#else
static const guchar *DataOfGSD(GtkSelectionData *sd) { return sd->data; }
static gint LengthOfGSD(GtkSelectionData *sd) { return sd->length; }
static GdkAtom TypeOfGSD(GtkSelectionData *sd) { return sd->type; }
static GdkAtom SelectionOfGSD(GtkSelectionData *sd) { return sd->selection; }
#endif

// Detect rectangular text, convert line ends to current mode, convert from or to UTF-8
void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, SelectionText &selText) {
	const char *data = reinterpret_cast<const char *>(DataOfGSD(selectionData));
	int len = LengthOfGSD(selectionData);
	GdkAtom selectionTypeData = TypeOfGSD(selectionData);

	// Return empty string if selection is not a string
	if ((selectionTypeData != GDK_TARGET_STRING) && (selectionTypeData != atomUTF8)) {
		char *empty = new char[1];
		empty[0] = '\0';
		selText.Set(empty, 0, SC_CP_UTF8, 0, false, false);
		return;
	}

	// Check for "\n\0" ending to string indicating that selection is rectangular
	bool isRectangular;
#if PLAT_GTK_WIN32
	isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
#else
	isRectangular = ((len > 2) && (data[len - 1] == 0 && data[len - 2] == '\n'));
	if (isRectangular)
		len--;	// Forget the extra '\0'
#endif

	char *dest;
	if (selectionTypeData == GDK_TARGET_STRING) {
		dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
		if (IsUnicodeMode()) {
			// Unknown encoding so assume in Latin1
			char *destPrevious = dest;
			dest = UTF8FromLatin1(dest, len);
			selText.Set(dest, len, SC_CP_UTF8, 0, selText.rectangular, false);
			delete []destPrevious;
		} else {
			// Assume buffer is in same encoding as selection
			selText.Set(dest, len, pdoc->dbcsCodePage,
				vs.styles[STYLE_DEFAULT].characterSet, isRectangular, false);
		}
	} else {	// UTF-8
		dest = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
		selText.Set(dest, len, SC_CP_UTF8, 0, isRectangular, false);
		const char *charSetBuffer = CharacterSetID();
		if (!IsUnicodeMode() && *charSetBuffer) {
			// Convert to locale
			dest = ConvertText(&len, selText.s, selText.len, charSetBuffer, "UTF-8", true);
			selText.Set(dest, len, pdoc->dbcsCodePage,
				vs.styles[STYLE_DEFAULT].characterSet, selText.rectangular, false);
		}
	}
}

void ScintillaGTK::ReceivedSelection(GtkSelectionData *selection_data) {
	try {
		if ((SelectionOfGSD(selection_data) == atomClipboard) ||
		        (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY)) {
			if ((atomSought == atomUTF8) && (LengthOfGSD(selection_data) <= 0)) {
				atomSought = atomString;
				gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
				        SelectionOfGSD(selection_data), atomSought, GDK_CURRENT_TIME);
			} else if ((LengthOfGSD(selection_data) > 0) &&
			        ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8))) {
				SelectionText selText;
				GetGtkSelectionText(selection_data, selText);

				UndoGroup ug(pdoc);
				if (SelectionOfGSD(selection_data) != GDK_SELECTION_PRIMARY) {
					ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
				}
				SelectionPosition selStart = sel.IsRectangular() ?
					sel.Rectangular().Start() :
					sel.Range(sel.Main()).Start();

				if (selText.rectangular) {
					PasteRectangular(selStart, selText.s, selText.len);
				} else {
					InsertPaste(selStart, selText.s, selText.len);
				}
				EnsureCaretVisible();
			}
		}
//	else fprintf(stderr, "Target non string %d %d\n", (int)(selection_data->type),
//		(int)(atomUTF8));
		Redraw();
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::ReceivedDrop(GtkSelectionData *selection_data) {
	dragWasDropped = true;
	if (TypeOfGSD(selection_data) == atomUriList || TypeOfGSD(selection_data) == atomDROPFILES_DND) {
		char *ptr = new char[LengthOfGSD(selection_data) + 1];
		ptr[LengthOfGSD(selection_data)] = '\0';
		memcpy(ptr, DataOfGSD(selection_data), LengthOfGSD(selection_data));
 		NotifyURIDropped(ptr);
		delete []ptr;
	} else if ((TypeOfGSD(selection_data) == GDK_TARGET_STRING) || (TypeOfGSD(selection_data) == atomUTF8)) {
		if (TypeOfGSD(selection_data) > 0) {
			SelectionText selText;
			GetGtkSelectionText(selection_data, selText);
			DropAt(posDrop, selText.s, false, selText.rectangular);
		}
	} else if (LengthOfGSD(selection_data) > 0) {
		//~ fprintf(stderr, "ReceivedDrop other %p\n", static_cast<void *>(selection_data->type));
	}
	Redraw();
}



void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *text) {
#if PLAT_GTK_WIN32
	// GDK on Win32 expands any \n into \r\n, so make a copy of
	// the clip text now with newlines converted to \n.  Use { } to hide symbols
	// from code below
	SelectionText *newline_normalized = NULL;
	{
		int tmpstr_len;
		char *tmpstr = Document::TransformLineEnds(&tmpstr_len, text->s, text->len, SC_EOL_LF);
		newline_normalized = new SelectionText();
		newline_normalized->Set(tmpstr, tmpstr_len, SC_CP_UTF8, 0, text->rectangular, false);
		text = newline_normalized;
	}
#endif

	// Convert text to utf8 if it isn't already
	SelectionText *converted = 0;
	if ((text->codePage != SC_CP_UTF8) && (info == TARGET_UTF8_STRING)) {
		const char *charSet = ::CharacterSetID(text->characterSet);
		if (*charSet) {
			int new_len;
			char* tmputf = ConvertText(&new_len, text->s, text->len, "UTF-8", charSet, false);
			converted = new SelectionText();
			converted->Set(tmputf, new_len, SC_CP_UTF8, 0, text->rectangular, false);
			text = converted;
		}
	}

	// Here is a somewhat evil kludge.
	// As I can not work out how to store data on the clipboard in multiple formats
	// and need some way to mark the clipping as being stream or rectangular,
	// the terminating \0 is included in the length for rectangular clippings.
	// All other tested aplications behave benignly by ignoring the \0.
	// The #if is here because on Windows cfColumnSelect clip entry is used
	// instead as standard indicator of rectangularness (so no need to kludge)
	const char *textData = text->s ? text->s : "";
	int len = strlen(textData);
#if PLAT_GTK_WIN32 == 0
	if (text->rectangular)
		len++;
#endif

	if (info == TARGET_UTF8_STRING) {
		gtk_selection_data_set_text(selection_data, textData, len);
	} else {
		gtk_selection_data_set(selection_data,
			static_cast<GdkAtom>(GDK_SELECTION_TYPE_STRING),
			8, reinterpret_cast<const unsigned char *>(textData), len);
	}
	delete converted;

#if PLAT_GTK_WIN32
	delete newline_normalized;
#endif
}

void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) {
	GtkClipboard *clipBoard =
		gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
	if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
		return;

	if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
				    ClipboardGetSelection, ClipboardClearSelection, clipText)) {
		gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets);
	}
}

void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
	GetSelection(selection_data, info, static_cast<SelectionText*>(data));
}

void ScintillaGTK::ClipboardClearSelection(GtkClipboard *, void *data) {
	SelectionText *obj = static_cast<SelectionText*>(data);
	delete obj;
}

void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) {
	try {
		//Platform::DebugPrintf("UnclaimSelection\n");
		if (selection_event->selection == GDK_SELECTION_PRIMARY) {
			//Platform::DebugPrintf("UnclaimPrimarySelection\n");
			if (!OwnPrimarySelection()) {
				primary.Free();
				primarySelection = false;
				FullPaint();
			}
		}
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::Resize(int width, int height) {
	//Platform::DebugPrintf("Resize %d %d\n", width, height);
	//printf("Resize %d %d\n", width, height);

	// Not always needed, but some themes can have different sizes of scrollbars
#if GTK_CHECK_VERSION(3,0,0)
	GtkRequisition requisition;
	gtk_widget_get_requisition(PWidget(scrollbarv), &requisition);
	scrollBarWidth = requisition.width;
	gtk_widget_get_requisition(PWidget(scrollbarh), &requisition);
	scrollBarHeight = requisition.height;
#else
	scrollBarWidth = GTK_WIDGET(PWidget(scrollbarv))->requisition.width;
	scrollBarHeight = GTK_WIDGET(PWidget(scrollbarh))->requisition.height;
#endif

	// These allocations should never produce negative sizes as they would wrap around to huge
	// unsigned numbers inside GTK+ causing warnings.
	bool showSBHorizontal = horizontalScrollBarVisible && (wrapState == eWrapNone);
	int horizontalScrollBarHeight = scrollBarHeight;
	if (!showSBHorizontal)
		horizontalScrollBarHeight = 0;

	GtkAllocation alloc;
	if (showSBHorizontal) {
		gtk_widget_show(GTK_WIDGET(PWidget(scrollbarh)));
		alloc.x = 0;
		alloc.y = height - scrollBarHeight;
		alloc.width = Platform::Maximum(1, width - scrollBarWidth);
		alloc.height = horizontalScrollBarHeight;
		gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarh)), &alloc);
	} else {
		gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarh)));
	}

	if (verticalScrollBarVisible) {
		gtk_widget_show(GTK_WIDGET(PWidget(scrollbarv)));
		alloc.x = width - scrollBarWidth;
		alloc.y = 0;
		alloc.width = scrollBarWidth;
		alloc.height = Platform::Maximum(1, height - scrollBarHeight);
		if (!showSBHorizontal)
			alloc.height += scrollBarWidth-1;
		gtk_widget_size_allocate(GTK_WIDGET(PWidget(scrollbarv)), &alloc);
	} else {
		gtk_widget_hide(GTK_WIDGET(PWidget(scrollbarv)));
	}
	if (IS_WIDGET_MAPPED(PWidget(wMain))) {
		ChangeSize();
	}

	alloc.x = 0;
	alloc.y = 0;
	alloc.width = Platform::Maximum(1, width - scrollBarWidth);
	alloc.height = Platform::Maximum(1, height - scrollBarHeight);
	if (!showSBHorizontal)
		alloc.height += scrollBarHeight;
	if (!verticalScrollBarVisible)
		alloc.width += scrollBarWidth;
	gtk_widget_size_allocate(GTK_WIDGET(PWidget(wText)), &alloc);
}

static void SetAdjustmentValue(GtkAdjustment *object, int value) {
	GtkAdjustment *adjustment = GTK_ADJUSTMENT(object);
#if GTK_CHECK_VERSION(3,0,0)
	int maxValue = static_cast<int>(
		gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
#else
	int maxValue = static_cast<int>(
		adjustment->upper - adjustment->page_size);
#endif

	if (value > maxValue)
		value = maxValue;
	if (value < 0)
		value = 0;
	gtk_adjustment_set_value(adjustment, value);
}

static int modifierTranslated(int sciModifier) {
	switch (sciModifier) {
		case SCMOD_SHIFT:
			return GDK_SHIFT_MASK;
		case SCMOD_CTRL:
			return GDK_CONTROL_MASK;
		case SCMOD_ALT:
			return GDK_MOD1_MASK;
		case SCMOD_SUPER:
			return GDK_MOD4_MASK;
		default:
			return 0;
	}
}

gint ScintillaGTK::PressThis(GdkEventButton *event) {
	try {
		//Platform::DebugPrintf("Press %x time=%d state = %x button = %x\n",this,event->time, event->state, event->button);
		// Do not use GTK+ double click events as Scintilla has its own double click detection
		if (event->type != GDK_BUTTON_PRESS)
			return FALSE;

		evbtn = *event;
		Point pt;
		pt.x = int(event->x);
		pt.y = int(event->y);
		PRectangle rcClient = GetClientRectangle();
		//Platform::DebugPrintf("Press %0d,%0d in %0d,%0d %0d,%0d\n",
		//	pt.x, pt.y, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
		if ((pt.x > rcClient.right) || (pt.y > rcClient.bottom)) {
			Platform::DebugPrintf("Bad location\n");
			return FALSE;
		}

		bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;

		gtk_widget_grab_focus(PWidget(wMain));
		if (event->button == 1) {
			// On X, instead of sending literal modifiers use the user specified
			// modifier, defaulting to control instead of alt.
			// This is because most X window managers grab alt + click for moving
			ButtonDown(pt, event->time,
			        (event->state & GDK_SHIFT_MASK) != 0,
			        (event->state & GDK_CONTROL_MASK) != 0,
			        (event->state & modifierTranslated(rectangularSelectionModifier)) != 0);
		} else if (event->button == 2) {
			// Grab the primary selection if it exists
			SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
			if (OwnPrimarySelection() && primary.s == NULL)
				CopySelectionRange(&primary);

			sel.Clear();
			SetSelection(pos, pos);
			atomSought = atomUTF8;
			gtk_selection_convert(GTK_WIDGET(PWidget(wMain)), GDK_SELECTION_PRIMARY,
			        atomSought, event->time);
		} else if (event->button == 3) {
			if (!PointInSelection(pt))
				SetEmptySelection(PositionFromLocation(pt));
			if (displayPopupMenu) {
				// PopUp menu
				// Convert to screen
				int ox = 0;
				int oy = 0;
				gdk_window_get_origin(PWindow(wMain), &ox, &oy);
				ContextMenu(Point(pt.x + ox, pt.y + oy));
			} else {
				return FALSE;
			}
		} else if (event->button == 4) {
			// Wheel scrolling up (only GTK 1.x does it this way)
			if (ctrl)
				SetAdjustmentValue(adjustmenth, (xOffset / 2) - 6);
			else
				SetAdjustmentValue(adjustmentv, topLine - 3);
		} else if (event->button == 5) {
			// Wheel scrolling down (only GTK 1.x does it this way)
			if (ctrl)
				SetAdjustmentValue(adjustmenth, (xOffset / 2) + 6);
			else
				SetAdjustmentValue(adjustmentv, topLine + 3);
		}
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return TRUE;
}

gint ScintillaGTK::Press(GtkWidget *widget, GdkEventButton *event) {
	if (event->window != WindowFromWidget(widget))
		return FALSE;
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->PressThis(event);
}

gint ScintillaGTK::MouseRelease(GtkWidget *widget, GdkEventButton *event) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		//Platform::DebugPrintf("Release %x %d %d\n",sciThis,event->time,event->state);
		if (!sciThis->HaveMouseCapture())
			return FALSE;
		if (event->button == 1) {
			Point pt;
			pt.x = int(event->x);
			pt.y = int(event->y);
			//Platform::DebugPrintf("Up %x %x %d %d %d\n",
			//	sciThis,event->window,event->time, pt.x, pt.y);
			if (event->window != PWindow(sciThis->wMain))
				// If mouse released on scroll bar then the position is relative to the
				// scrollbar, not the drawing window so just repeat the most recent point.
				pt = sciThis->ptMouseLast;
			sciThis->ButtonUp(pt, event->time, (event->state & 4) != 0);
		}
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

// win32gtk and GTK >= 2 use SCROLL_* events instead of passing the
// button4/5/6/7 events to the GTK app
gint ScintillaGTK::ScrollEvent(GtkWidget *widget,
                               GdkEventScroll *event) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {

		if (widget == NULL || event == NULL)
			return FALSE;

		// Compute amount and direction to scroll (even tho on win32 there is
		// intensity of scrolling info in the native message, gtk doesn't
		// support this so we simulate similarly adaptive scrolling)
		// Note that this is disabled on OS X (Darwin) where the X11 server already has
		// and adaptive scrolling algorithm that fights with this one
		int cLineScroll;
#if defined(__MWERKS__) || defined(__APPLE_CPP__) || defined(__APPLE_CC__)
		cLineScroll = sciThis->linesPerScroll;
		if (cLineScroll == 0)
			cLineScroll = 4;
		sciThis->wheelMouseIntensity = cLineScroll;
#else
		int timeDelta = 1000000;
		GTimeVal curTime;
		g_get_current_time(&curTime);
		if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec)
			timeDelta = curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec;
		else if (curTime.tv_sec == sciThis->lastWheelMouseTime.tv_sec + 1)
			timeDelta = 1000000 + (curTime.tv_usec - sciThis->lastWheelMouseTime.tv_usec);
		if ((event->direction == sciThis->lastWheelMouseDirection) && (timeDelta < 250000)) {
			if (sciThis->wheelMouseIntensity < 12)
				sciThis->wheelMouseIntensity++;
			cLineScroll = sciThis->wheelMouseIntensity;
		} else {
			cLineScroll = sciThis->linesPerScroll;
			if (cLineScroll == 0)
				cLineScroll = 4;
			sciThis->wheelMouseIntensity = cLineScroll;
		}
#endif
		if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT) {
			cLineScroll *= -1;
		}
		g_get_current_time(&sciThis->lastWheelMouseTime);
		sciThis->lastWheelMouseDirection = event->direction;

		// Note:  Unpatched versions of win32gtk don't set the 'state' value so
		// only regular scrolling is supported there.  Also, unpatched win32gtk
		// issues spurious button 2 mouse events during wheeling, which can cause
		// problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)

		// Data zoom not supported
		if (event->state & GDK_SHIFT_MASK) {
			return FALSE;
		}

#if GTK_CHECK_VERSION(3,4,0)
		// Smooth scrolling not supported
		if (event->direction == GDK_SCROLL_SMOOTH) {
			return FALSE;
		}
#endif

		// Horizontal scrolling
		if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) {
			sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll);

			// Text font size zoom
		} else if (event->state & GDK_CONTROL_MASK) {
			if (cLineScroll < 0) {
				sciThis->KeyCommand(SCI_ZOOMIN);
			} else {
				sciThis->KeyCommand(SCI_ZOOMOUT);
			}

			// Regular scrolling
		} else {
			sciThis->ScrollTo(sciThis->topLine + cLineScroll);
		}
		return TRUE;
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gint ScintillaGTK::Motion(GtkWidget *widget, GdkEventMotion *event) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		//Platform::DebugPrintf("Motion %x %d\n",sciThis,event->time);
		if (event->window != WindowFromWidget(widget))
			return FALSE;
		int x = 0;
		int y = 0;
		GdkModifierType state;
		if (event->is_hint) {
#if GTK_CHECK_VERSION(3,0,0)
			gdk_window_get_device_position(event->window, 
				event->device, &x, &y, &state);
#else
			gdk_window_get_pointer(event->window, &x, &y, &state);
#endif
		} else {
			x = static_cast<int>(event->x);
			y = static_cast<int>(event->y);
			state = static_cast<GdkModifierType>(event->state);
		}
		//Platform::DebugPrintf("Move %x %x %d %c %d %d\n",
		//	sciThis,event->window,event->time,event->is_hint? 'h' :'.', x, y);
		Point pt(x, y);
		sciThis->ButtonMove(pt);
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

// Map the keypad keys to their equivalent functions
static int KeyTranslate(int keyIn) {
	switch (keyIn) {
#if GTK_CHECK_VERSION(3,0,0)
	case GDK_KEY_ISO_Left_Tab:
		return SCK_TAB;
	case GDK_KEY_KP_Down:
		return SCK_DOWN;
	case GDK_KEY_KP_Up:
		return SCK_UP;
	case GDK_KEY_KP_Left:
		return SCK_LEFT;
	case GDK_KEY_KP_Right:
		return SCK_RIGHT;
	case GDK_KEY_KP_Home:
		return SCK_HOME;
	case GDK_KEY_KP_End:
		return SCK_END;
	case GDK_KEY_KP_Page_Up:
		return SCK_PRIOR;
	case GDK_KEY_KP_Page_Down:
		return SCK_NEXT;
	case GDK_KEY_KP_Delete:
		return SCK_DELETE;
	case GDK_KEY_KP_Insert:
		return SCK_INSERT;
	case GDK_KEY_KP_Enter:
		return SCK_RETURN;

	case GDK_KEY_Down:
		return SCK_DOWN;
	case GDK_KEY_Up:
		return SCK_UP;
	case GDK_KEY_Left:
		return SCK_LEFT;
	case GDK_KEY_Right:
		return SCK_RIGHT;
	case GDK_KEY_Home:
		return SCK_HOME;
	case GDK_KEY_End:
		return SCK_END;
	case GDK_KEY_Page_Up:
		return SCK_PRIOR;
	case GDK_KEY_Page_Down:
		return SCK_NEXT;
	case GDK_KEY_Delete:
		return SCK_DELETE;
	case GDK_KEY_Insert:
		return SCK_INSERT;
	case GDK_KEY_Escape:
		return SCK_ESCAPE;
	case GDK_KEY_BackSpace:
		return SCK_BACK;
	case GDK_KEY_Tab:
		return SCK_TAB;
	case GDK_KEY_Return:
		return SCK_RETURN;
	case GDK_KEY_KP_Add:
		return SCK_ADD;
	case GDK_KEY_KP_Subtract:
		return SCK_SUBTRACT;
	case GDK_KEY_KP_Divide:
		return SCK_DIVIDE;
	case GDK_KEY_Super_L:
		return SCK_WIN;
	case GDK_KEY_Super_R:
		return SCK_RWIN;
	case GDK_KEY_Menu:
		return SCK_MENU;

#else

	case GDK_ISO_Left_Tab:
		return SCK_TAB;
	case GDK_KP_Down:
		return SCK_DOWN;
	case GDK_KP_Up:
		return SCK_UP;
	case GDK_KP_Left:
		return SCK_LEFT;
	case GDK_KP_Right:
		return SCK_RIGHT;
	case GDK_KP_Home:
		return SCK_HOME;
	case GDK_KP_End:
		return SCK_END;
	case GDK_KP_Page_Up:
		return SCK_PRIOR;
	case GDK_KP_Page_Down:
		return SCK_NEXT;
	case GDK_KP_Delete:
		return SCK_DELETE;
	case GDK_KP_Insert:
		return SCK_INSERT;
	case GDK_KP_Enter:
		return SCK_RETURN;

	case GDK_Down:
		return SCK_DOWN;
	case GDK_Up:
		return SCK_UP;
	case GDK_Left:
		return SCK_LEFT;
	case GDK_Right:
		return SCK_RIGHT;
	case GDK_Home:
		return SCK_HOME;
	case GDK_End:
		return SCK_END;
	case GDK_Page_Up:
		return SCK_PRIOR;
	case GDK_Page_Down:
		return SCK_NEXT;
	case GDK_Delete:
		return SCK_DELETE;
	case GDK_Insert:
		return SCK_INSERT;
	case GDK_Escape:
		return SCK_ESCAPE;
	case GDK_BackSpace:
		return SCK_BACK;
	case GDK_Tab:
		return SCK_TAB;
	case GDK_Return:
		return SCK_RETURN;
	case GDK_KP_Add:
		return SCK_ADD;
	case GDK_KP_Subtract:
		return SCK_SUBTRACT;
	case GDK_KP_Divide:
		return SCK_DIVIDE;
	case GDK_Super_L:
		return SCK_WIN;
	case GDK_Super_R:
		return SCK_RWIN;
	case GDK_Menu:
		return SCK_MENU;
#endif
	default:
		return keyIn;
	}
}

gboolean ScintillaGTK::KeyThis(GdkEventKey *event) {
	try {
		//fprintf(stderr, "SC-key: %d %x [%s]\n",
		//	event->keyval, event->state, (event->length > 0) ? event->string : "empty");
		if (gtk_im_context_filter_keypress(im_context, event)) {
			return 1;
		}
		if (!event->keyval) {
			return true;
		}

		bool shift = (event->state & GDK_SHIFT_MASK) != 0;
		bool ctrl = (event->state & GDK_CONTROL_MASK) != 0;
		bool alt = (event->state & GDK_MOD1_MASK) != 0;
		guint key = event->keyval;
		if ((ctrl || alt) && (key < 128))
			key = toupper(key);
#if GTK_CHECK_VERSION(3,0,0)
		else if (!ctrl && (key >= GDK_KEY_KP_Multiply && key <= GDK_KEY_KP_9))
#else
		else if (!ctrl && (key >= GDK_KP_Multiply && key <= GDK_KP_9))
#endif
			key &= 0x7F;
		// Hack for keys over 256 and below command keys but makes Hungarian work.
		// This will have to change for Unicode
		else if (key >= 0xFE00)
			key = KeyTranslate(key);

		bool consumed = false;
#if !(PLAT_GTK_MACOSX)
		bool added = KeyDown(key, shift, ctrl, alt, &consumed) != 0;
#else
		bool meta = ctrl;
		ctrl = (event->state & GDK_META_MASK) != 0;
		bool added = KeyDownWithModifiers(key, (shift ? SCI_SHIFT : 0) |
		                                       (ctrl ? SCI_CTRL : 0) |
		                                       (alt ? SCI_ALT : 0) |
		                                       (meta ? SCI_META : 0), &consumed) != 0;
#endif
		if (!consumed)
			consumed = added;
		//fprintf(stderr, "SK-key: %d %x %x\n",event->keyval, event->state, consumed);
		if (event->keyval == 0xffffff && event->length > 0) {
			ClearSelection();
			if (pdoc->InsertCString(CurrentPosition(), event->string)) {
				MovePositionTo(CurrentPosition() + event->length);
			}
		}
		return consumed;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gboolean ScintillaGTK::KeyPress(GtkWidget *widget, GdkEventKey *event) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->KeyThis(event);
}

gboolean ScintillaGTK::KeyRelease(GtkWidget *widget, GdkEventKey *event) {
	//Platform::DebugPrintf("SC-keyrel: %d %x %3s\n",event->keyval, event->state, event->string);
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	if (gtk_im_context_filter_keypress(sciThis->im_context, event)) {
		return TRUE;
	}
	return FALSE;
}

#if GTK_CHECK_VERSION(3,0,0)

gboolean ScintillaGTK::DrawPreeditThis(GtkWidget *widget, cairo_t *cr) {
	try {
		gchar *str;
		gint cursor_pos;
		PangoAttrList *attrs;

		gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
		PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
		pango_layout_set_attributes(layout, attrs);

		cairo_move_to(cr, 0, 0);
		pango_cairo_show_layout(cr, layout);

		g_free(str);
		pango_attr_list_unref(attrs);
		g_object_unref(layout);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return TRUE;
}

gboolean ScintillaGTK::DrawPreedit(GtkWidget *widget, cairo_t *cr, ScintillaGTK *sciThis) {
	return sciThis->DrawPreeditThis(widget, cr);
}

#else

gboolean ScintillaGTK::ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose) {
	try {
		gchar *str;
		gint cursor_pos;
		PangoAttrList *attrs;

		gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
		PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
		pango_layout_set_attributes(layout, attrs);

		cairo_t *context = gdk_cairo_create(reinterpret_cast<GdkDrawable *>(WindowFromWidget(widget)));
		cairo_move_to(context, 0, 0);
		pango_cairo_show_layout(context, layout);
		cairo_destroy(context);
		g_free(str);
		pango_attr_list_unref(attrs);
		g_object_unref(layout);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return TRUE;
}

gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
	return sciThis->ExposePreeditThis(widget, ose);
}

#endif

void ScintillaGTK::CommitThis(char *utfVal) {
	try {
		//~ fprintf(stderr, "Commit '%s'\n", utfVal);
		if (IsUnicodeMode()) {
			AddCharUTF(utfVal, strlen(utfVal));
		} else {
			const char *source = CharacterSetID();
			if (*source) {
				Converter conv(source, "UTF-8", true);
				if (conv) {
					char localeVal[4] = "\0\0\0";
					char *pin = utfVal;
					size_t inLeft = strlen(utfVal);
					char *pout = localeVal;
					size_t outLeft = sizeof(localeVal);
					size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
					if (conversions != ((size_t)(-1))) {
						*pout = '\0';
						for (int i = 0; localeVal[i]; i++) {
							AddChar(localeVal[i]);
						}
					} else {
						fprintf(stderr, "Conversion failed '%s'\n", utfVal);
					}
				}
			}
		}
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::Commit(GtkIMContext *, char  *str, ScintillaGTK *sciThis) {
	sciThis->CommitThis(str);
}

void ScintillaGTK::PreeditChangedThis() {
	try {
		gchar *str;
		PangoAttrList *attrs;
		gint cursor_pos;
		gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
		if (strlen(str) > 0) {
			PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), str);
			pango_layout_set_attributes(layout, attrs);

			gint w, h;
			pango_layout_get_pixel_size(layout, &w, &h);
			g_object_unref(layout);

			gint x, y;
			gdk_window_get_origin(PWindow(wText), &x, &y);

			Point pt = PointMainCaret();
			if (pt.x < 0)
				pt.x = 0;
			if (pt.y < 0)
				pt.y = 0;

			gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
			gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
			gtk_widget_show(PWidget(wPreedit));
			gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
		} else {
			gtk_widget_hide(PWidget(wPreedit));
		}
		g_free(str);
		pango_attr_list_unref(attrs);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
	sciThis->PreeditChangedThis();
}

void ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {
	RealizeText(widget, NULL);
}

void ScintillaGTK::RealizeText(GtkWidget *widget, void*) {
	// Set NULL background to avoid automatic clearing so Scintilla responsible for all drawing
	if (WindowFromWidget(widget)) {
#if GTK_CHECK_VERSION(3,0,0)
		gdk_window_set_background_pattern(WindowFromWidget(widget), NULL);
#else
		gdk_window_set_back_pixmap(WindowFromWidget(widget), NULL, FALSE);
#endif
	}
}

void ScintillaGTK::Destroy(GObject *object) {
	try {
		ScintillaObject *scio = reinterpret_cast<ScintillaObject *>(object);
		// This avoids a double destruction
		if (!scio->pscin)
			return;
		ScintillaGTK *sciThis = reinterpret_cast<ScintillaGTK *>(scio->pscin);
		//Platform::DebugPrintf("Destroying %x %x\n", sciThis, object);
		sciThis->Finalise();

		delete sciThis;
		scio->pscin = 0;
	} catch (...) {
		// Its dead so nowhere to save the status
	}
}

#if GTK_CHECK_VERSION(3,0,0)

gboolean ScintillaGTK::DrawTextThis(cairo_t *cr) {
	try {
		paintState = painting;

		rcPaint = GetClientRectangle();

		PLATFORM_ASSERT(rgnUpdate == NULL);
		rgnUpdate = cairo_copy_clip_rectangle_list(cr);
		if (rgnUpdate && rgnUpdate->status != CAIRO_STATUS_SUCCESS) {
			// If not successful then ignore
			fprintf(stderr, "DrawTextThis failed to copy update region %d [%d]\n", rgnUpdate->status, rgnUpdate->num_rectangles);
			cairo_rectangle_list_destroy(rgnUpdate);
			rgnUpdate = 0;
		}

		double x1, y1, x2, y2;
		cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
		rcPaint.left = x1;
		rcPaint.top = y1;
		rcPaint.right = x2;
		rcPaint.bottom = y2;
		PRectangle rcClient = GetClientRectangle();
		paintingAllText = rcPaint.Contains(rcClient);
		Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
		if (surfaceWindow) {
			surfaceWindow->Init(cr, PWidget(wText));
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
			delete surfaceWindow;
		}
		if (paintState == paintAbandoned) {
			// Painting area was insufficient to cover new styling or brace highlight positions
			FullPaint();
		}
		paintState = notPainting;

		if (rgnUpdate) {
			cairo_rectangle_list_destroy(rgnUpdate);
		}
		rgnUpdate = 0;
		paintState = notPainting;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}

	return FALSE;
}

gboolean ScintillaGTK::DrawText(GtkWidget *, cairo_t *cr, ScintillaGTK *sciThis) {
	return sciThis->DrawTextThis(cr);
}

gboolean ScintillaGTK::DrawThis(cairo_t *cr) {
	try {
		gtk_container_propagate_draw(
		    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), cr);
		gtk_container_propagate_draw(
		    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), cr);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gboolean ScintillaGTK::DrawMain(GtkWidget *widget, cairo_t *cr) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->DrawThis(cr);
}

#else

gboolean ScintillaGTK::ExposeTextThis(GtkWidget * /*widget*/, GdkEventExpose *ose) {
	try {
		paintState = painting;

		rcPaint.left = ose->area.x;
		rcPaint.top = ose->area.y;
		rcPaint.right = ose->area.x + ose->area.width;
		rcPaint.bottom = ose->area.y + ose->area.height;

		PLATFORM_ASSERT(rgnUpdate == NULL);
		rgnUpdate = gdk_region_copy(ose->region);
		PRectangle rcClient = GetClientRectangle();
		paintingAllText = rcPaint.Contains(rcClient);
		Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
		if (surfaceWindow) {
			cairo_t *cr = gdk_cairo_create(PWindow(wText));
			surfaceWindow->Init(cr, PWidget(wText));
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
			delete surfaceWindow;
			cairo_destroy(cr);
		}
		if (paintState == paintAbandoned) {
			// Painting area was insufficient to cover new styling or brace highlight positions
			FullPaint();
		}
		paintState = notPainting;

		if (rgnUpdate) {
			gdk_region_destroy(rgnUpdate);
		}
		rgnUpdate = 0;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}

	return FALSE;
}

gboolean ScintillaGTK::ExposeText(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis) {
	return sciThis->ExposeTextThis(widget, ose);
}

gboolean ScintillaGTK::ExposeMain(GtkWidget *widget, GdkEventExpose *ose) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	//Platform::DebugPrintf("Expose Main %0d,%0d %0d,%0d\n",
	//ose->area.x, ose->area.y, ose->area.width, ose->area.height);
	return sciThis->Expose(widget, ose);
}

gboolean ScintillaGTK::Expose(GtkWidget *, GdkEventExpose *ose) {
	try {
		//fprintf(stderr, "Expose %0d,%0d %0d,%0d\n",
		//ose->area.x, ose->area.y, ose->area.width, ose->area.height);

		// The text is painted in ExposeText
		gtk_container_propagate_expose(
		    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarh), ose);
		gtk_container_propagate_expose(
		    GTK_CONTAINER(PWidget(wMain)), PWidget(scrollbarv), ose);

	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

#endif

void ScintillaGTK::ScrollSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
	try {
#if GTK_CHECK_VERSION(3,0,0)
		sciThis->ScrollTo(static_cast<int>(gtk_adjustment_get_value(adj)), false);
#else
		sciThis->ScrollTo(static_cast<int>(adj->value), false);
#endif
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::ScrollHSignal(GtkAdjustment *adj, ScintillaGTK *sciThis) {
	try {
#if GTK_CHECK_VERSION(3,0,0)
		sciThis->HorizontalScrollTo(static_cast<int>(gtk_adjustment_get_value(adj) * 2));
#else
		sciThis->HorizontalScrollTo(static_cast<int>(adj->value * 2));
#endif
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::SelectionReceived(GtkWidget *widget,
                                     GtkSelectionData *selection_data, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	//Platform::DebugPrintf("Selection received\n");
	sciThis->ReceivedSelection(selection_data);
}

void ScintillaGTK::SelectionGet(GtkWidget *widget,
                                GtkSelectionData *selection_data, guint info, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		//Platform::DebugPrintf("Selection get\n");
		if (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY) {
			if (sciThis->primary.s == NULL) {
				sciThis->CopySelectionRange(&sciThis->primary);
			}
			sciThis->GetSelection(selection_data, info, &sciThis->primary);
		}
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

gint ScintillaGTK::SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	//Platform::DebugPrintf("Selection clear\n");
	sciThis->UnclaimSelection(selection_event);
	if (GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event) {
		return GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event(widget, selection_event);
	}
	return TRUE;
}

void ScintillaGTK::DragBegin(GtkWidget *, GdkDragContext *) {
	//Platform::DebugPrintf("DragBegin\n");
}

gboolean ScintillaGTK::DragMotionThis(GdkDragContext *context,
                                 gint x, gint y, guint dragtime) {
	try {
		Point npt(x, y);
		SetDragPosition(SPositionFromLocation(npt, false, false, UserVirtualSpace()));
#if GTK_CHECK_VERSION(3,0,0)
		GdkDragAction preferredAction = gdk_drag_context_get_suggested_action(context);
		GdkDragAction actions = gdk_drag_context_get_actions(context);
#else
		GdkDragAction preferredAction = context->suggested_action;
		GdkDragAction actions = context->actions;
#endif
		SelectionPosition pos = SPositionFromLocation(npt);
		if ((inDragDrop == ddDragging) && (PositionInSelection(pos.Position()))) {
			// Avoid dragging selection onto itself as that produces a move
			// with no real effect but which creates undo actions.
			preferredAction = static_cast<GdkDragAction>(0);
		} else if (actions == static_cast<GdkDragAction>
		        (GDK_ACTION_COPY | GDK_ACTION_MOVE)) {
			preferredAction = GDK_ACTION_MOVE;
		}
		gdk_drag_status(context, preferredAction, dragtime);
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

gboolean ScintillaGTK::DragMotion(GtkWidget *widget, GdkDragContext *context,
                                 gint x, gint y, guint dragtime) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	return sciThis->DragMotionThis(context, x, y, dragtime);
}

void ScintillaGTK::DragLeave(GtkWidget *widget, GdkDragContext * /*context*/, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		sciThis->SetDragPosition(SelectionPosition(invalidPosition));
		//Platform::DebugPrintf("DragLeave %x\n", sciThis);
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::DragEnd(GtkWidget *widget, GdkDragContext * /*context*/) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		// If drag did not result in drop here or elsewhere
		if (!sciThis->dragWasDropped)
			sciThis->SetEmptySelection(sciThis->posDrag);
		sciThis->SetDragPosition(SelectionPosition(invalidPosition));
		//Platform::DebugPrintf("DragEnd %x %d\n", sciThis, sciThis->dragWasDropped);
		sciThis->inDragDrop = ddNone;
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

gboolean ScintillaGTK::Drop(GtkWidget *widget, GdkDragContext * /*context*/,
                            gint, gint, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		//Platform::DebugPrintf("Drop %x\n", sciThis);
		sciThis->SetDragPosition(SelectionPosition(invalidPosition));
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
	return FALSE;
}

void ScintillaGTK::DragDataReceived(GtkWidget *widget, GdkDragContext * /*context*/,
                                    gint, gint, GtkSelectionData *selection_data, guint /*info*/, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		sciThis->ReceivedDrop(selection_data);
		sciThis->SetDragPosition(SelectionPosition(invalidPosition));
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

void ScintillaGTK::DragDataGet(GtkWidget *widget, GdkDragContext *context,
                               GtkSelectionData *selection_data, guint info, guint) {
	ScintillaGTK *sciThis = ScintillaFromWidget(widget);
	try {
		sciThis->dragWasDropped = true;
		if (!sciThis->sel.Empty()) {
			sciThis->GetSelection(selection_data, info, &sciThis->drag);
		}
#if GTK_CHECK_VERSION(3,0,0)
		GdkDragAction action = gdk_drag_context_get_selected_action(context);
#else
		GdkDragAction action = context->action;
#endif
		if (action == GDK_ACTION_MOVE) {
			for (size_t r=0; r<sciThis->sel.Count(); r++) {
				if (sciThis->posDrop >= sciThis->sel.Range(r).Start()) {
					if (sciThis->posDrop > sciThis->sel.Range(r).End()) {
						sciThis->posDrop.Add(-sciThis->sel.Range(r).Length());
					} else {
						sciThis->posDrop.Add(-SelectionRange(sciThis->posDrop, sciThis->sel.Range(r).Start()).Length());
					}
				}
			}
			sciThis->ClearSelection();
		}
		sciThis->SetDragPosition(SelectionPosition(invalidPosition));
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
}

int ScintillaGTK::TimeOut(ScintillaGTK *sciThis) {
	sciThis->Tick();
	return 1;
}

gboolean ScintillaGTK::IdleCallback(ScintillaGTK *sciThis) {
	// Idler will be automatically stopped, if there is nothing
	// to do while idle.
#ifndef GDK_VERSION_3_6
	gdk_threads_enter();
#endif
	bool ret = sciThis->Idle();
	if (ret == false) {
		// FIXME: This will remove the idler from GTK, we don't want to
		// remove it as it is removed automatically when this function
		// returns false (although, it should be harmless).
		sciThis->SetIdle(false);
	}
#ifndef GDK_VERSION_3_6
	gdk_threads_leave();
#endif
	return ret;
}

gboolean ScintillaGTK::StyleIdle(ScintillaGTK *sciThis) {
#ifndef GDK_VERSION_3_6
	gdk_threads_enter();
#endif
	sciThis->IdleWork();
#ifndef GDK_VERSION_3_6
	gdk_threads_leave();
#endif
	// Idler will be automatically stopped
	return FALSE;
}

void ScintillaGTK::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
	Editor::QueueIdleWork(items, upTo);
	if (!workNeeded.active) {
		// Only allow one style needed to be queued
		workNeeded.active = true;
		g_idle_add_full(G_PRIORITY_HIGH_IDLE,
			reinterpret_cast<GSourceFunc>(StyleIdle), this, NULL);
	}
}

void ScintillaGTK::PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis) {
	guint action = (sptr_t)(g_object_get_data(G_OBJECT(menuItem), "CmdNum"));
	if (action) {
		sciThis->Command(action);
	}
}

gboolean ScintillaGTK::PressCT(GtkWidget *widget, GdkEventButton *event, ScintillaGTK *sciThis) {
	try {
		if (event->window != WindowFromWidget(widget))
			return FALSE;
		if (event->type != GDK_BUTTON_PRESS)
			return FALSE;
		Point pt;
		pt.x = int(event->x);
		pt.y = int(event->y);
		sciThis->ct.MouseClick(pt);
		sciThis->CallTipClick();
	} catch (...) {
	}
	return TRUE;
}

#if GTK_CHECK_VERSION(3,0,0)

gboolean ScintillaGTK::DrawCT(GtkWidget *widget, cairo_t *cr, CallTip *ctip) {
	try {
		Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
		if (surfaceWindow) {
			surfaceWindow->Init(cr, widget);
			surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage);
			surfaceWindow->SetDBCSMode(ctip->codePage);
			ctip->PaintCT(surfaceWindow);
			surfaceWindow->Release();
			delete surfaceWindow;
		}
	} catch (...) {
		// No pointer back to Scintilla to save status
	}
	return TRUE;
}

#else

gboolean ScintillaGTK::ExposeCT(GtkWidget *widget, GdkEventExpose * /*ose*/, CallTip *ctip) {
	try {
		Surface *surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
		if (surfaceWindow) {
			cairo_t *cr = gdk_cairo_create(WindowFromWidget(widget));
			surfaceWindow->Init(cr, widget);
			surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == ctip->codePage);
			surfaceWindow->SetDBCSMode(ctip->codePage);
			ctip->PaintCT(surfaceWindow);
			surfaceWindow->Release();
			delete surfaceWindow;
			cairo_destroy(cr);
		}
	} catch (...) {
		// No pointer back to Scintilla to save status
	}
	return TRUE;
}

#endif

sptr_t ScintillaGTK::DirectFunction(
    ScintillaGTK *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	return sciThis->WndProc(iMessage, wParam, lParam);
}

sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
	return psci->WndProc(iMessage, wParam, lParam);
}

static void scintilla_class_init(ScintillaClass *klass);
static void scintilla_init(ScintillaObject *sci);

extern void Platform_Initialise();
extern void Platform_Finalise();

GType scintilla_get_type() {
	static GType scintilla_type = 0;
	try {

		if (!scintilla_type) {
			scintilla_type = g_type_from_name("Scintilla");
			if (!scintilla_type) {
				static GTypeInfo scintilla_info = {
					(guint16) sizeof (ScintillaClass),
					NULL, //(GBaseInitFunc)
					NULL, //(GBaseFinalizeFunc)
					(GClassInitFunc) scintilla_class_init,
					NULL, //(GClassFinalizeFunc)
					NULL, //gconstpointer data
					(guint16) sizeof (ScintillaObject),
					0, //n_preallocs
					(GInstanceInitFunc) scintilla_init,
					NULL //(GTypeValueTable*)
				};

				scintilla_type = g_type_register_static(
				            GTK_TYPE_CONTAINER, "Scintilla", &scintilla_info, (GTypeFlags) 0);
			}
		}

	} catch (...) {
	}
	return scintilla_type;
}

void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class) {
	Platform_Initialise();
#ifdef SCI_LEXER
	Scintilla_LinkLexers();
#endif
	atomClipboard = gdk_atom_intern("CLIPBOARD", FALSE);
	atomUTF8 = gdk_atom_intern("UTF8_STRING", FALSE);
	atomString = GDK_SELECTION_TYPE_STRING;
	atomUriList = gdk_atom_intern("text/uri-list", FALSE);
	atomDROPFILES_DND = gdk_atom_intern("DROPFILES_DND", FALSE);

	// Define default signal handlers for the class:  Could move more
	// of the signal handlers here (those that currently attached to wDraw
	// in Initialise() may require coordinate translation?)

	object_class->finalize = Destroy;
#if GTK_CHECK_VERSION(3,0,0)
	widget_class->get_preferred_width = GetPreferredWidth;
	widget_class->get_preferred_height = GetPreferredHeight;
#else
	widget_class->size_request = SizeRequest;
#endif
	widget_class->size_allocate = SizeAllocate;
#if GTK_CHECK_VERSION(3,0,0)
	widget_class->draw = DrawMain;
#else
	widget_class->expose_event = ExposeMain;
#endif
	widget_class->motion_notify_event = Motion;
	widget_class->button_press_event = Press;
	widget_class->button_release_event = MouseRelease;
	widget_class->scroll_event = ScrollEvent;
	widget_class->key_press_event = KeyPress;
	widget_class->key_release_event = KeyRelease;
	widget_class->focus_in_event = FocusIn;
	widget_class->focus_out_event = FocusOut;
	widget_class->selection_received = SelectionReceived;
	widget_class->selection_get = SelectionGet;
	widget_class->selection_clear_event = SelectionClear;

	widget_class->drag_data_received = DragDataReceived;
	widget_class->drag_motion = DragMotion;
	widget_class->drag_leave = DragLeave;
	widget_class->drag_end = DragEnd;
	widget_class->drag_drop = Drop;
	widget_class->drag_data_get = DragDataGet;

	widget_class->realize = Realize;
	widget_class->unrealize = UnRealize;
	widget_class->map = Map;
	widget_class->unmap = UnMap;

	container_class->forall = MainForAll;
}

#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER
#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER

static void scintilla_class_init(ScintillaClass *klass) {
	try {
		OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass;
		GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
		GtkContainerClass *container_class = (GtkContainerClass*) klass;

		GSignalFlags sigflags = GSignalFlags(G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST);
		scintilla_signals[COMMAND_SIGNAL] = g_signal_new(
		            "command",
		            G_TYPE_FROM_CLASS(object_class),
		            sigflags,
		            G_STRUCT_OFFSET(ScintillaClass, command),
		            NULL, //(GSignalAccumulator)
		            NULL, //(gpointer)
		            SIG_MARSHAL,
		            G_TYPE_NONE,
		            2, MARSHAL_ARGUMENTS);

		scintilla_signals[NOTIFY_SIGNAL] = g_signal_new(
		            SCINTILLA_NOTIFY,
		            G_TYPE_FROM_CLASS(object_class),
		            sigflags,
		            G_STRUCT_OFFSET(ScintillaClass, notify),
		            NULL,
		            NULL,
		            SIG_MARSHAL,
		            G_TYPE_NONE,
		            2, MARSHAL_ARGUMENTS);

		klass->command = NULL;
		klass->notify = NULL;

		ScintillaGTK::ClassInit(object_class, widget_class, container_class);
	} catch (...) {
	}
}

static void scintilla_init(ScintillaObject *sci) {
	try {
#if GTK_CHECK_VERSION(2,20,0)
		gtk_widget_set_can_focus(GTK_WIDGET(sci), TRUE);
#else
		GTK_WIDGET_SET_FLAGS(sci, GTK_CAN_FOCUS);
#endif
		sci->pscin = new ScintillaGTK(sci);
	} catch (...) {
	}
}

GtkWidget* scintilla_new() {
	return GTK_WIDGET(g_object_new(scintilla_get_type(), NULL));
}

void scintilla_set_id(ScintillaObject *sci, uptr_t id) {
	ScintillaGTK *psci = reinterpret_cast<ScintillaGTK *>(sci->pscin);
	psci->ctrlID = id;
}

void scintilla_release_resources(void) {
	try {
		Platform_Finalise();
	} catch (...) {
	}
}

Added gtk/deps.mak.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
PlatGTK.o: PlatGTK.cxx \
 ../include/Scintilla.h ../include/ScintillaWidget.h \
 ../src/UniConversion.h ../src/XPM.h Converter.h
ScintillaGTK.o: ScintillaGTK.cxx \
 ../include/ILexer.h ../include/Scintilla.h ../include/ScintillaWidget.h \
 ../include/SciLexer.h ../src/SVector.h ../src/SplitVector.h \
 ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
 ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
 ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
 ../src/ViewStyle.h ../src/Decoration.h ../src/CharClassify.h \
 ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
 ../src/Editor.h ../src/ScintillaBase.h ../src/UniConversion.h \
 scintilla-marshal.h ../lexlib/LexerModule.h ../src/ExternalLexer.h \
 Converter.h
AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
 ../lexlib/CharacterSet.h ../src/AutoComplete.h ../include/Scintilla.h
CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/CallTip.h
Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \
 ../src/Catalogue.h
CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/CellBuffer.h ../src/UniConversion.h
CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h
ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \
 ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
 ../src/ContractionState.h
Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/Decoration.h
Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
 ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \
 ../src/Document.h ../src/RESearch.h ../src/UniConversion.h
Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
 ../src/Decoration.h ../src/Document.h ../src/UniConversion.h \
 ../src/Selection.h ../src/PositionCache.h ../src/Editor.h
ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
 ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \
 ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h
Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/XPM.h ../src/Indicator.h
KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
 ../src/KeyMap.h
LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
PerLine.o: ../src/PerLine.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/CellBuffer.h ../src/PerLine.h
PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
 ../src/Decoration.h ../include/ILexer.h ../src/Document.h \
 ../src/Selection.h ../src/PositionCache.h
RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h
ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
 ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \
 ../include/SciLexer.h ../lexlib/LexerModule.h ../src/Catalogue.h \
 ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
 ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \
 ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
 ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \
 ../src/ScintillaBase.h
Selection.o: ../src/Selection.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/Selection.h
Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
 ../src/Style.h
UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h
ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h
XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h

Added gtk/makefile.

































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Make file for Scintilla on Linux or compatible OS
# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
# The License.txt file describes the conditions under which this software may be distributed.
# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers.
# GNU make does not like \r\n line endings so should be saved to CVS in binary form.
# Builds for GTK+ 2 and no longer supports GTK+ 1.
# Also works with ming32-make on Windows.

.SUFFIXES: .cxx .c .o .h .a
ifdef CLANG
CC = clang --std=c++0x
CCOMP = clang
else
CC = g++
CCOMP = gcc
endif
AR = ar
RANLIB = touch

ifdef GTK3
GTKVERSION=gtk+-3.0
else
GTKVERSION=gtk+-2.0
endif

# Environment variable windir always defined on Win32

ifndef windir
ifeq ($(shell uname),Darwin)
RANLIB = ranlib
endif
endif

ifdef windir
DEL = del /q
COMPLIB=..\bin\scintilla.a
else
DEL = rm -f
COMPLIB=../bin/scintilla.a
endif

vpath %.h ../src ../include ../lexlib
vpath %.cxx ../src ../lexlib ../lexers

INCLUDEDIRS=-I ../include -I ../src -I ../lexlib
ifdef CHECK_DEPRECATED
DEPRECATED=-DGDK_PIXBUF_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DDISABLE_GDK_FONT
endif
CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -pedantic -DGTK -DSCI_LEXER $(INCLUDEDIRS) $(DEPRECATED)

ifdef NOTHREADS
THREADFLAGS=-DG_THREADS_IMPL_NONE
else
THREADFLAGS=
endif

ifdef DEBUG
CXXTFLAGS=-DDEBUG -g $(CXXBASEFLAGS) $(THREADFLAGS)
else
CXXTFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS) $(THREADFLAGS)
endif

CFLAGS:=$(CXXTFLAGS)

CONFIGFLAGS:=$(shell pkg-config --cflags $(GTKVERSION))
MARSHALLER=scintilla-marshal.o

.cxx.o:
	$(CC) $(CONFIGFLAGS) $(CXXTFLAGS) $(CXXFLAGS) -c $<
.c.o:
	$(CCOMP) $(CONFIGFLAGS) $(CFLAGS) -w -c $<

LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))

all: $(COMPLIB)

clean:
	$(DEL) *.o $(COMPLIB) *.plist

analyze:
	clang --analyze $(CONFIGFLAGS) $(CXXTFLAGS) $(CXXFLAGS) *.cxx ../src/*.cxx ../lexlib/*.cxx ../lexers/*.cxx

deps:
	$(CC) -MM $(CONFIGFLAGS) $(CXXTFLAGS) *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak

$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \
	CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o \
	ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \
	KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o ViewStyle.o \
	RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
	$(MARSHALLER) $(LEXOBJS)
	$(AR) rc $@ $^
	$(RANLIB) $@

# Automatically generate header dependencies with "make deps"
include deps.mak

Added gtk/scintilla-marshal.c.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

#include	<glib-object.h>


#ifdef G_ENABLE_DEBUG
#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
#define g_marshal_value_peek_char(v)     g_value_get_char (v)
#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
#define g_marshal_value_peek_int(v)      g_value_get_int (v)
#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
#define g_marshal_value_peek_long(v)     g_value_get_long (v)
#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
#define g_marshal_value_peek_float(v)    g_value_get_float (v)
#define g_marshal_value_peek_double(v)   g_value_get_double (v)
#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v)    g_value_get_param (v)
#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
#define g_marshal_value_peek_object(v)   g_value_get_object (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
 *          Do not access GValues directly in your code. Instead, use the
 *          g_value_get_*() functions
 */
#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v)     (v)->data[0].v_int
#define g_marshal_value_peek_flags(v)    (v)->data[0].v_uint
#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */


/* NONE:INT,POINTER (scintilla-marshal.list:1) */
void
scintilla_marshal_VOID__INT_POINTER (GClosure     *closure,
                                     GValue       *return_value,
                                     guint         n_param_values,
                                     const GValue *param_values,
                                     gpointer      invocation_hint,
                                     gpointer      marshal_data)
{
  typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer     data1,
                                                  gint         arg_1,
                                                  gpointer     arg_2,
                                                  gpointer     data2);
  register GMarshalFunc_VOID__INT_POINTER callback;
  register GCClosure *cc = (GCClosure*) closure;
  register gpointer data1, data2;

  g_return_if_fail (n_param_values == 3);

  if (G_CCLOSURE_SWAP_DATA (closure))
    {
      data1 = closure->data;
      data2 = g_value_peek_pointer (param_values + 0);
    }
  else
    {
      data1 = g_value_peek_pointer (param_values + 0);
      data2 = closure->data;
    }
  callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback);

  callback (data1,
            g_marshal_value_peek_int (param_values + 1),
            g_marshal_value_peek_pointer (param_values + 2),
            data2);
}

Added gtk/scintilla-marshal.h.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#ifndef __scintilla_marshal_MARSHAL_H__
#define __scintilla_marshal_MARSHAL_H__

#include	<glib-object.h>

G_BEGIN_DECLS

/* NONE:INT,POINTER (scintilla-marshal.list:1) */
extern void scintilla_marshal_VOID__INT_POINTER (GClosure     *closure,
                                                 GValue       *return_value,
                                                 guint         n_param_values,
                                                 const GValue *param_values,
                                                 gpointer      invocation_hint,
                                                 gpointer      marshal_data);
#define scintilla_marshal_NONE__INT_POINTER	scintilla_marshal_VOID__INT_POINTER

G_END_DECLS

#endif /* __scintilla_marshal_MARSHAL_H__ */

Added gtk/scintilla-marshal.list.



>
1
NONE:INT,POINTER

Added include/Face.py.





































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Module for reading and parsing Scintilla.iface file

def sanitiseLine(line):
	if line[-1:] == '\n': line = line[:-1]
	if line.find("##") != -1:
		line = line[:line.find("##")]
	line = line.strip()
	return line
	
def decodeFunction(featureVal):
	retType, rest = featureVal.split(" ", 1)
	nameIdent, params = rest.split("(")
	name, value = nameIdent.split("=")
	params, rest = params.split(")")
	param1, param2 = params.split(",")
	return retType, name, value, param1, param2
	
def decodeEvent(featureVal):
	retType, rest = featureVal.split(" ", 1)
	nameIdent, params = rest.split("(")
	name, value = nameIdent.split("=")
	return retType, name, value
	
def decodeParam(p):
	param = p.strip()
	type = ""
	name = ""
	value = ""
	if " " in param:
		type, nv = param.split(" ")
		if "=" in nv:
			name, value = nv.split("=")
		else:
			name = nv
	return type, name, value

class Face:

	def __init__(self):
		self.order = []
		self.features = {}
		self.values = {}
		self.events = {}
		
	def ReadFromFile(self, name):
		currentCategory = ""
		currentComment = []
		currentCommentFinished = 0
		file = open(name)
		for line in file.readlines():
			line = sanitiseLine(line)
			if line:
				if line[0] == "#":
					if line[1] == " ":
						if currentCommentFinished:
							currentComment = []
							currentCommentFinished = 0
						currentComment.append(line[2:])
				else:
					currentCommentFinished = 1
					featureType, featureVal = line.split(" ", 1)
					if featureType in ["fun", "get", "set"]:
						try:
							retType, name, value, param1, param2 = decodeFunction(featureVal)
						except ValueError:
							print("Failed to decode %s" % line)
							raise
						p1 = decodeParam(param1)
						p2 = decodeParam(param2)
						self.features[name] = { 
							"FeatureType": featureType, 
							"ReturnType": retType,
							"Value": value, 
							"Param1Type": p1[0], "Param1Name": p1[1], "Param1Value": p1[2], 
							"Param2Type": p2[0],	"Param2Name": p2[1], "Param2Value": p2[2],
							"Category": currentCategory, "Comment": currentComment
						}
						if value in self.values:
							raise Exception("Duplicate value " + value + " " + name)
						self.values[value] = 1
						self.order.append(name)
					elif featureType == "evt":
						retType, name, value = decodeEvent(featureVal)
						self.features[name] = { 
							"FeatureType": featureType, 
							"ReturnType": retType,
							"Value": value, 
							"Category": currentCategory, "Comment": currentComment
						}
						if value in self.events:
							raise Exception("Duplicate event " + value + " " + name)
						self.events[value] = 1
						self.order.append(name)
					elif featureType == "cat":
						currentCategory = featureVal
					elif featureType == "val":
						try:
							name, value = featureVal.split("=", 1)
						except ValueError:
							print("Failure %s" % featureVal)
							raise Exception()
						self.features[name] = { 
							"FeatureType": featureType, 
							"Category": currentCategory, 
							"Value": value }
						self.order.append(name)
					elif featureType == "enu" or featureType == "lex":
						name, value = featureVal.split("=", 1)
						self.features[name] = { 
							"FeatureType": featureType, 
							"Category": currentCategory, 
							"Value": value }
						self.order.append(name)

Added include/Face.pyc.

cannot compute difference between binary files

Added include/HFacer.py.



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#!/usr/bin/env python
# HFacer.py - regenerate the Scintilla.h and SciLexer.h files from the Scintilla.iface interface
# definition file.
# The header files are copied to a temporary file apart from the section between a /* ++Autogenerated*/
# comment and a /* --Autogenerated*/ comment which is generated by the printHFile and printLexHFile
# functions. After the temporary file is created, it is copied back to the original file name.

import sys
import os
import Face

def Contains(s,sub):
	return s.find(sub) != -1

def printLexHFile(f,out):
	for name in f.order:
		v = f.features[name]
		if v["FeatureType"] in ["val"]:
			if Contains(name, "SCE_") or Contains(name, "SCLEX_"):
				out.write("#define " + name + " " + v["Value"] + "\n")

def printHFile(f,out):
	previousCategory = ""
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			if v["Category"] == "Provisional" and previousCategory != "Provisional":
				out.write("#ifndef SCI_DISABLE_PROVISIONAL\n")
			previousCategory = v["Category"]
			if v["FeatureType"] in ["fun", "get", "set"]:
				featureDefineName = "SCI_" + name.upper()
				out.write("#define " + featureDefineName + " " + v["Value"] + "\n")
			elif v["FeatureType"] in ["evt"]:
				featureDefineName = "SCN_" + name.upper()
				out.write("#define " + featureDefineName + " " + v["Value"] + "\n")
			elif v["FeatureType"] in ["val"]:
				if not (Contains(name, "SCE_") or Contains(name, "SCLEX_")):
					out.write("#define " + name + " " + v["Value"] + "\n")
	out.write("#endif\n")

def CopyWithInsertion(input, output, genfn, definition):
	copying = 1
	for line in input.readlines():
		if copying:
			output.write(line)
		if Contains(line, "/* ++Autogenerated"):
			copying = 0
			genfn(definition, output)
		if Contains(line, "/* --Autogenerated"):
			copying = 1
			output.write(line)

def contents(filename):
	f = open(filename)
	t = f.read()
	f.close()
	return t

def Regenerate(filename, genfn, definition):
	inText = contents(filename)
	tempname = "HFacer.tmp"
	out = open(tempname,"w")
	hfile = open(filename)
	CopyWithInsertion(hfile, out, genfn, definition)
	out.close()
	hfile.close()
	outText = contents(tempname)
	if inText == outText:
		os.unlink(tempname)
	else:
		os.unlink(filename)
		os.rename(tempname, filename)

f = Face.Face()
try:
	f.ReadFromFile("Scintilla.iface")
	Regenerate("Scintilla.h", printHFile, f)
	Regenerate("SciLexer.h", printLexHFile, f)
	print("Maximum ID is %s" % max([x for x in f.values if int(x) < 3000]))
except:
	raise

Added include/ILexer.h.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ILexer.h
 ** Interface between Scintilla and lexers.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef ILEXER_H
#define ILEXER_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

#ifdef _WIN32
	#define SCI_METHOD __stdcall
#else
	#define SCI_METHOD
#endif

enum { dvOriginal=0, dvLineEnd=1 };

class IDocument {
public:
	virtual int SCI_METHOD Version() const = 0;
	virtual void SCI_METHOD SetErrorStatus(int status) = 0;
	virtual int SCI_METHOD Length() const = 0;
	virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0;
	virtual char SCI_METHOD StyleAt(int position) const = 0;
	virtual int SCI_METHOD LineFromPosition(int position) const = 0;
	virtual int SCI_METHOD LineStart(int line) const = 0;
	virtual int SCI_METHOD GetLevel(int line) const = 0;
	virtual int SCI_METHOD SetLevel(int line, int level) = 0;
	virtual int SCI_METHOD GetLineState(int line) const = 0;
	virtual int SCI_METHOD SetLineState(int line, int state) = 0;
	virtual void SCI_METHOD StartStyling(int position, char mask) = 0;
	virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0;
	virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0;
	virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0;
	virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0;
	virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0;
	virtual int SCI_METHOD CodePage() const = 0;
	virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0;
	virtual const char * SCI_METHOD BufferPointer() = 0;
	virtual int SCI_METHOD GetLineIndentation(int line) = 0;
    virtual ~IDocument() {}
};

class IDocumentWithLineEnd : public IDocument {
public:
	virtual int SCI_METHOD LineEnd(int line) const = 0;
};

enum { lvOriginal=0, lvSubStyles=1 };

class ILexer {
public:
	virtual int SCI_METHOD Version() const = 0;
	virtual void SCI_METHOD Release() = 0;
	virtual const char * SCI_METHOD PropertyNames() = 0;
	virtual int SCI_METHOD PropertyType(const char *name) = 0;
	virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0;
	virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0;
	virtual const char * SCI_METHOD DescribeWordListSets() = 0;
	virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0;
	virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
	virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
	virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0;
    virtual ~ILexer() {}
};

class ILexerWithSubStyles : public ILexer {
public:
	virtual int SCI_METHOD LineEndTypesSupported() = 0;
	virtual int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) = 0;
	virtual int SCI_METHOD SubStylesStart(int styleBase) = 0;
	virtual int SCI_METHOD SubStylesLength(int styleBase) = 0;
	virtual void SCI_METHOD FreeSubStyles() = 0;
	virtual void SCI_METHOD SetIdentifiers(int style, const char *identifiers) = 0;
	virtual int SCI_METHOD DistanceToSecondaryStyles() = 0;
	virtual const char * SCI_METHOD GetSubStyleBases() = 0;
};

class ILoader {
public:
	virtual int SCI_METHOD Release() = 0;
	// Returns a status code from SC_STATUS_*
	virtual int SCI_METHOD AddData(char *data, int length) = 0;
	virtual void * SCI_METHOD ConvertToDocument() = 0;
    virtual ~ILoader() {}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added include/Platform.h.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
// Scintilla source code edit control
/** @file Platform.h
 ** Interface to platform facilities. Also includes some basic utilities.
 ** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows.
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef PLATFORM_H
#define PLATFORM_H

// PLAT_TK = Tcl/TK on Linux or Win32
// PLAT_GTK = GTK+ on Linux or Win32
// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32
// PLAT_WIN = Win32 API on Win32 OS
// PLAT_WX is wxWindows on any supported platform

#define PLAT_TK 0
#define PLAT_GTK 0
#define PLAT_GTK_WIN32 0
#define PLAT_GTK_MACOSX 0
#define PLAT_MACOSX 0
#define PLAT_WIN 0
#define PLAT_WX  0
#define PLAT_QT 0
#define PLAT_FOX 0
#define PLAT_NCURSES 0

#if defined(FOX)
#undef PLAT_FOX
#define PLAT_FOX 1

#elif defined(__WX__)
#undef PLAT_WX
#define PLAT_WX  1

#elif defined(NCURSES)
#undef PLAT_NCURSES
#define PLAT_NCURSES 1

#elif defined(SCINTILLA_QT)
#undef PLAT_QT
#define PLAT_QT 1

#elif defined(TK)
#undef PLAT_TK
#define PLAT_TK 1

#elif defined(GTK)
#undef PLAT_GTK
#define PLAT_GTK 1

#if defined(__WIN32__) || defined(_MSC_VER)
#undef PLAT_GTK_WIN32
#define PLAT_GTK_WIN32 1
#endif

#if defined(__APPLE__)
#undef PLAT_GTK_MACOSX
#define PLAT_GTK_MACOSX 1
#endif

#elif defined(__APPLE__)

#undef PLAT_MACOSX
#define PLAT_MACOSX 1

#else
#undef PLAT_WIN
#define PLAT_WIN 1

#endif

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

#if defined(TK)
typedef int XYPOSITION;
#else
typedef float XYPOSITION;
#endif
typedef double XYACCUMULATOR;
//#define XYPOSITION int

// Underlying the implementation of the platform classes are platform specific types.
// Sometimes these need to be passed around by client code so they are defined here

typedef void *FontID;
typedef void *SurfaceID;
typedef void *WindowID;
typedef void *MenuID;
typedef void *TickerID;
typedef void *Function;
typedef void *IdlerID;

/**
 * A geometric point class.
 * Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably.
 */
class Point {
public:
	XYPOSITION x;
	XYPOSITION y;

	explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) {
	}

	// Other automatically defined methods (assignment, copy constructor, destructor) are fine

	static Point FromLong(long lpoint);
};

/**
 * A geometric rectangle class.
 * PRectangle is exactly the same as the Win32 RECT so can be used interchangeably.
 * PRectangles contain their top and left sides, but not their right and bottom sides.
 */
class PRectangle {
public:
	XYPOSITION left;
	XYPOSITION top;
	XYPOSITION right;
	XYPOSITION bottom;

	PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) :
		left(left_), top(top_), right(right_), bottom(bottom_) {
	}

	// Other automatically defined methods (assignment, copy constructor, destructor) are fine

	bool operator==(PRectangle &rc) {
		return (rc.left == left) && (rc.right == right) &&
			(rc.top == top) && (rc.bottom == bottom);
	}
	bool Contains(Point pt) {
		return (pt.x >= left) && (pt.x <= right) &&
			(pt.y >= top) && (pt.y <= bottom);
	}
	bool Contains(PRectangle rc) {
		return (rc.left >= left) && (rc.right <= right) &&
			(rc.top >= top) && (rc.bottom <= bottom);
	}
	bool Intersects(PRectangle other) {
		return (right > other.left) && (left < other.right) &&
			(bottom > other.top) && (top < other.bottom);
	}
	void Move(XYPOSITION xDelta, XYPOSITION yDelta) {
		left += xDelta;
		top += yDelta;
		right += xDelta;
		bottom += yDelta;
	}
	XYPOSITION Width() { return right - left; }
	XYPOSITION Height() { return bottom - top; }
	bool Empty() {
		return (Height() <= 0) || (Width() <= 0);
	}
};

/**
 * Holds a desired RGB colour.
 */
class ColourDesired {
	long co;
public:
	ColourDesired(long lcol=0) {
		co = lcol;
	}

	ColourDesired(unsigned int red, unsigned int green, unsigned int blue) {
		Set(red, green, blue);
	}

	bool operator==(const ColourDesired &other) const {
		return co == other.co;
	}

	void Set(long lcol) {
		co = lcol;
	}

	void Set(unsigned int red, unsigned int green, unsigned int blue) {
		co = red | (green << 8) | (blue << 16);
	}

	static inline unsigned int ValueOfHex(const char ch) {
		if (ch >= '0' && ch <= '9')
			return ch - '0';
		else if (ch >= 'A' && ch <= 'F')
			return ch - 'A' + 10;
		else if (ch >= 'a' && ch <= 'f')
			return ch - 'a' + 10;
		else
			return 0;
	}

	void Set(const char *val) {
		if (*val == '#') {
			val++;
		}
		unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
		unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
		unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
		Set(r, g, b);
	}

	long AsLong() const {
		return co;
	}

	unsigned int GetRed() {
		return co & 0xff;
	}

	unsigned int GetGreen() {
		return (co >> 8) & 0xff;
	}

	unsigned int GetBlue() {
		return (co >> 16) & 0xff;
	}
};

/**
 * Font management.
 */

struct FontParameters {
	const char *faceName;
	float size;
	int weight;
	bool italic;
	int extraFontFlag;
	int technology;
	int characterSet;

	FontParameters(
		const char *faceName_,
		float size_=10,
		int weight_=400,
		bool italic_=false,
		int extraFontFlag_=0,
		int technology_=0,
		int characterSet_=0) :

		faceName(faceName_),
		size(size_),
		weight(weight_),
		italic(italic_),
		extraFontFlag(extraFontFlag_),
		technology(technology_),
		characterSet(characterSet_)
	{
	}

};

class Font {
protected:
	FontID fid;
#if PLAT_WX
	int ascent;
#endif
	// Private so Font objects can not be copied
	Font(const Font &);
	Font &operator=(const Font &);
public:
	Font();
	virtual ~Font();

	virtual void Create(const FontParameters &fp);
	virtual void Release();

	FontID GetID() { return fid; }
	// Alias another font - caller guarantees not to Release
	void SetID(FontID fid_) { fid = fid_; }
#if PLAT_WX
	void SetAscent(int ascent_) { ascent = ascent_; }
#endif
	friend class Surface;
	friend class SurfaceImpl;
};

/**
 * A surface abstracts a place to draw.
 */
class Surface {
private:
	// Private so Surface objects can not be copied
	Surface(const Surface &) {}
	Surface &operator=(const Surface &) { return *this; }
public:
	Surface() {}
	virtual ~Surface() {}
	static Surface *Allocate(int technology);

	virtual void Init(WindowID wid)=0;
	virtual void Init(SurfaceID sid, WindowID wid)=0;
	virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0;

	virtual void Release()=0;
	virtual bool Initialised()=0;
	virtual void PenColour(ColourDesired fore)=0;
	virtual int LogPixelsY()=0;
	virtual int DeviceHeightFont(int points)=0;
	virtual void MoveTo(int x_, int y_)=0;
	virtual void LineTo(int x_, int y_)=0;
	virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0;
	virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
	virtual void FillRectangle(PRectangle rc, ColourDesired back)=0;
	virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0;
	virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
	virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags)=0;
	virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0;
	virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
	virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;

	virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
	virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
	virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0;
	virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0;
	virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0;
	virtual XYPOSITION WidthChar(Font &font_, char ch)=0;
	virtual XYPOSITION Ascent(Font &font_)=0;
	virtual XYPOSITION Descent(Font &font_)=0;
	virtual XYPOSITION InternalLeading(Font &font_)=0;
	virtual XYPOSITION ExternalLeading(Font &font_)=0;
	virtual XYPOSITION Height(Font &font_)=0;
	virtual XYPOSITION AverageCharWidth(Font &font_)=0;

	virtual void SetClip(PRectangle rc)=0;
	virtual void FlushCachedState()=0;

	virtual void SetUnicodeMode(bool unicodeMode_)=0;
	virtual void SetDBCSMode(int codePage)=0;
};

/**
 * A simple callback action passing one piece of untyped user data.
 */
typedef void (*CallBackAction)(void*);

/**
 * Class to hide the details of window manipulation.
 * Does not own the window which will normally have a longer life than this object.
 */
class Window {
protected:
	WindowID wid;
#if PLAT_MACOSX
	void *windowRef;
	void *control;
#endif
public:
	Window() : wid(0), cursorLast(cursorInvalid) {
#if PLAT_MACOSX
	  windowRef = 0;
	  control = 0;
#endif
	}
	Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) {
#if PLAT_MACOSX
	  windowRef = 0;
	  control = 0;
#endif
	}
	virtual ~Window();
	Window &operator=(WindowID wid_) {
		wid = wid_;
		return *this;
	}
	WindowID GetID() const { return wid; }
	bool Created() const { return wid != 0; }
	void Destroy();
	bool HasFocus();
	PRectangle GetPosition();
	void SetPosition(PRectangle rc);
	void SetPositionRelative(PRectangle rc, Window relativeTo);
	PRectangle GetClientPosition();
	void Show(bool show=true);
	void InvalidateAll();
	void InvalidateRectangle(PRectangle rc);
	virtual void SetFont(Font &font);
	enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
	void SetCursor(Cursor curs);
	void SetTitle(const char *s);
	PRectangle GetMonitorRect(Point pt);
#if PLAT_MACOSX
	void SetWindow(void *ref) { windowRef = ref; }
	void SetControl(void *_control) { control = _control; }
#endif
private:
	Cursor cursorLast;
};

/**
 * Listbox management.
 */

class ListBox : public Window {
public:
	ListBox();
	virtual ~ListBox();
	static ListBox *Allocate();

	virtual void SetFont(Font &font)=0;
	virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0;
	virtual void SetAverageCharWidth(int width)=0;
	virtual void SetVisibleRows(int rows)=0;
	virtual int GetVisibleRows() const=0;
	virtual PRectangle GetDesiredRect()=0;
	virtual int CaretFromEdge()=0;
	virtual void Clear()=0;
	virtual void Append(char *s, int type = -1)=0;
	virtual int Length()=0;
	virtual void Select(int n)=0;
	virtual int GetSelection()=0;
	virtual int Find(const char *prefix)=0;
	virtual void GetValue(int n, char *value, int len)=0;
	virtual void RegisterImage(int type, const char *xpm_data)=0;
	virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0;
	virtual void ClearRegisteredImages()=0;
	virtual void SetDoubleClickAction(CallBackAction, void *)=0;
	virtual void SetList(const char* list, char separator, char typesep)=0;
};

/**
 * Menu management.
 */
class Menu {
	MenuID mid;
public:
	Menu();
	MenuID GetID() { return mid; }
	void CreatePopUp();
	void Destroy();
	void Show(Point pt, Window &w);
};

class ElapsedTime {
	long bigBit;
	long littleBit;
public:
	ElapsedTime();
	double Duration(bool reset=false);
};

/**
 * Dynamic Library (DLL/SO/...) loading
 */
class DynamicLibrary {
public:
	virtual ~DynamicLibrary() {}

	/// @return Pointer to function "name", or NULL on failure.
	virtual Function FindFunction(const char *name) = 0;

	/// @return true if the library was loaded successfully.
	virtual bool IsValid() = 0;

	/// @return An instance of a DynamicLibrary subclass with "modulePath" loaded.
	static DynamicLibrary *Load(const char *modulePath);
};

/**
 * Platform class used to retrieve system wide parameters such as double click speed
 * and chrome colour. Not a creatable object, more of a module with several functions.
 */
class Platform {
	// Private so Platform objects can not be copied
	Platform(const Platform &) {}
	Platform &operator=(const Platform &) { return *this; }
public:
	// Should be private because no new Platforms are ever created
	// but gcc warns about this
	Platform() {}
	~Platform() {}
	static ColourDesired Chrome();
	static ColourDesired ChromeHighlight();
	static const char *DefaultFont();
	static int DefaultFontSize();
	static unsigned int DoubleClickTime();
	static bool MouseButtonBounce();
	static void DebugDisplay(const char *s);
	static bool IsKeyDown(int key);
	static long SendScintilla(
		WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
	static long SendScintillaPointer(
		WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0);
	static bool IsDBCSLeadByte(int codePage, char ch);
	static int DBCSCharLength(int codePage, const char *s);
	static int DBCSCharMaxLength();

	// These are utility functions not really tied to a platform
	static int Minimum(int a, int b);
	static int Maximum(int a, int b);
	// Next three assume 16 bit shorts and 32 bit longs
	static long LongFromTwoShorts(short a,short b) {
		return (a) | ((b) << 16);
	}
	static short HighShortFromLong(long x) {
		return static_cast<short>(x >> 16);
	}
	static short LowShortFromLong(long x) {
		return static_cast<short>(x & 0xffff);
	}
	static void DebugPrintf(const char *format, ...);
	static bool ShowAssertionPopUps(bool assertionPopUps_);
	static void Assert(const char *c, const char *file, int line);
	static int Clamp(int val, int minVal, int maxVal);
};

#ifdef  NDEBUG
#define PLATFORM_ASSERT(c) ((void)0)
#else
#ifdef SCI_NAMESPACE
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__))
#else
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
#endif
#endif

#ifdef SCI_NAMESPACE
}
#endif

// Shut up annoying Visual C++ warnings:
#ifdef _MSC_VER
#pragma warning(disable: 4244 4309 4514 4710)
#endif

#if defined(__GNUC__) && defined(SCINTILLA_QT)
#pragma GCC diagnostic ignored "-Wmissing-braces"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wchar-subscripts"
#endif

#endif

Added include/SciLexer.h.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
/* Scintilla source code edit control */
/** @file SciLexer.h
 ** Interface to the added lexer functions in the SciLexer version of the edit control.
 **/
/* Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed. */

/* Most of this file is automatically generated from the Scintilla.iface interface definition
 * file which contains any comments about the definitions. HFacer.py does the generation. */

#ifndef SCILEXER_H
#define SCILEXER_H

/* SciLexer features - not in standard Scintilla */

/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
#define SCLEX_CONTAINER 0
#define SCLEX_NULL 1
#define SCLEX_PYTHON 2
#define SCLEX_CPP 3
#define SCLEX_HTML 4
#define SCLEX_XML 5
#define SCLEX_PERL 6
#define SCLEX_SQL 7
#define SCLEX_VB 8
#define SCLEX_PROPERTIES 9
#define SCLEX_ERRORLIST 10
#define SCLEX_MAKEFILE 11
#define SCLEX_BATCH 12
#define SCLEX_XCODE 13
#define SCLEX_LATEX 14
#define SCLEX_LUA 15
#define SCLEX_DIFF 16
#define SCLEX_CONF 17
#define SCLEX_PASCAL 18
#define SCLEX_AVE 19
#define SCLEX_ADA 20
#define SCLEX_LISP 21
#define SCLEX_RUBY 22
#define SCLEX_EIFFEL 23
#define SCLEX_EIFFELKW 24
#define SCLEX_TCL 25
#define SCLEX_NNCRONTAB 26
#define SCLEX_BULLANT 27
#define SCLEX_VBSCRIPT 28
#define SCLEX_BAAN 31
#define SCLEX_MATLAB 32
#define SCLEX_SCRIPTOL 33
#define SCLEX_ASM 34
#define SCLEX_CPPNOCASE 35
#define SCLEX_FORTRAN 36
#define SCLEX_F77 37
#define SCLEX_CSS 38
#define SCLEX_POV 39
#define SCLEX_LOUT 40
#define SCLEX_ESCRIPT 41
#define SCLEX_PS 42
#define SCLEX_NSIS 43
#define SCLEX_MMIXAL 44
#define SCLEX_CLW 45
#define SCLEX_CLWNOCASE 46
#define SCLEX_LOT 47
#define SCLEX_YAML 48
#define SCLEX_TEX 49
#define SCLEX_METAPOST 50
#define SCLEX_POWERBASIC 51
#define SCLEX_FORTH 52
#define SCLEX_ERLANG 53
#define SCLEX_OCTAVE 54
#define SCLEX_MSSQL 55
#define SCLEX_VERILOG 56
#define SCLEX_KIX 57
#define SCLEX_GUI4CLI 58
#define SCLEX_SPECMAN 59
#define SCLEX_AU3 60
#define SCLEX_APDL 61
#define SCLEX_BASH 62
#define SCLEX_ASN1 63
#define SCLEX_VHDL 64
#define SCLEX_CAML 65
#define SCLEX_BLITZBASIC 66
#define SCLEX_PUREBASIC 67
#define SCLEX_HASKELL 68
#define SCLEX_PHPSCRIPT 69
#define SCLEX_TADS3 70
#define SCLEX_REBOL 71
#define SCLEX_SMALLTALK 72
#define SCLEX_FLAGSHIP 73
#define SCLEX_CSOUND 74
#define SCLEX_FREEBASIC 75
#define SCLEX_INNOSETUP 76
#define SCLEX_OPAL 77
#define SCLEX_SPICE 78
#define SCLEX_D 79
#define SCLEX_CMAKE 80
#define SCLEX_GAP 81
#define SCLEX_PLM 82
#define SCLEX_PROGRESS 83
#define SCLEX_ABAQUS 84
#define SCLEX_ASYMPTOTE 85
#define SCLEX_R 86
#define SCLEX_MAGIK 87
#define SCLEX_POWERSHELL 88
#define SCLEX_MYSQL 89
#define SCLEX_PO 90
#define SCLEX_TAL 91
#define SCLEX_COBOL 92
#define SCLEX_TACL 93
#define SCLEX_SORCUS 94
#define SCLEX_POWERPRO 95
#define SCLEX_NIMROD 96
#define SCLEX_SML 97
#define SCLEX_MARKDOWN 98
#define SCLEX_TXT2TAGS 99
#define SCLEX_A68K 100
#define SCLEX_MODULA 101
#define SCLEX_COFFEESCRIPT 102
#define SCLEX_TCMD 103
#define SCLEX_AVS 104
#define SCLEX_ECL 105
#define SCLEX_OSCRIPT 106
#define SCLEX_VISUALPROLOG 107
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
#define SCE_P_NUMBER 2
#define SCE_P_STRING 3
#define SCE_P_CHARACTER 4
#define SCE_P_WORD 5
#define SCE_P_TRIPLE 6
#define SCE_P_TRIPLEDOUBLE 7
#define SCE_P_CLASSNAME 8
#define SCE_P_DEFNAME 9
#define SCE_P_OPERATOR 10
#define SCE_P_IDENTIFIER 11
#define SCE_P_COMMENTBLOCK 12
#define SCE_P_STRINGEOL 13
#define SCE_P_WORD2 14
#define SCE_P_DECORATOR 15
#define SCE_C_DEFAULT 0
#define SCE_C_COMMENT 1
#define SCE_C_COMMENTLINE 2
#define SCE_C_COMMENTDOC 3
#define SCE_C_NUMBER 4
#define SCE_C_WORD 5
#define SCE_C_STRING 6
#define SCE_C_CHARACTER 7
#define SCE_C_UUID 8
#define SCE_C_PREPROCESSOR 9
#define SCE_C_OPERATOR 10
#define SCE_C_IDENTIFIER 11
#define SCE_C_STRINGEOL 12
#define SCE_C_VERBATIM 13
#define SCE_C_REGEX 14
#define SCE_C_COMMENTLINEDOC 15
#define SCE_C_WORD2 16
#define SCE_C_COMMENTDOCKEYWORD 17
#define SCE_C_COMMENTDOCKEYWORDERROR 18
#define SCE_C_GLOBALCLASS 19
#define SCE_C_STRINGRAW 20
#define SCE_C_TRIPLEVERBATIM 21
#define SCE_C_HASHQUOTEDSTRING 22
#define SCE_C_PREPROCESSORCOMMENT 23
#define SCE_D_DEFAULT 0
#define SCE_D_COMMENT 1
#define SCE_D_COMMENTLINE 2
#define SCE_D_COMMENTDOC 3
#define SCE_D_COMMENTNESTED 4
#define SCE_D_NUMBER 5
#define SCE_D_WORD 6
#define SCE_D_WORD2 7
#define SCE_D_WORD3 8
#define SCE_D_TYPEDEF 9
#define SCE_D_STRING 10
#define SCE_D_STRINGEOL 11
#define SCE_D_CHARACTER 12
#define SCE_D_OPERATOR 13
#define SCE_D_IDENTIFIER 14
#define SCE_D_COMMENTLINEDOC 15
#define SCE_D_COMMENTDOCKEYWORD 16
#define SCE_D_COMMENTDOCKEYWORDERROR 17
#define SCE_D_STRINGB 18
#define SCE_D_STRINGR 19
#define SCE_D_WORD5 20
#define SCE_D_WORD6 21
#define SCE_D_WORD7 22
#define SCE_TCL_DEFAULT 0
#define SCE_TCL_COMMENT 1
#define SCE_TCL_COMMENTLINE 2
#define SCE_TCL_NUMBER 3
#define SCE_TCL_WORD_IN_QUOTE 4
#define SCE_TCL_IN_QUOTE 5
#define SCE_TCL_OPERATOR 6
#define SCE_TCL_IDENTIFIER 7
#define SCE_TCL_SUBSTITUTION 8
#define SCE_TCL_SUB_BRACE 9
#define SCE_TCL_MODIFIER 10
#define SCE_TCL_EXPAND 11
#define SCE_TCL_WORD 12
#define SCE_TCL_WORD2 13
#define SCE_TCL_WORD3 14
#define SCE_TCL_WORD4 15
#define SCE_TCL_WORD5 16
#define SCE_TCL_WORD6 17
#define SCE_TCL_WORD7 18
#define SCE_TCL_WORD8 19
#define SCE_TCL_COMMENT_BOX 20
#define SCE_TCL_BLOCK_COMMENT 21
#define SCE_H_DEFAULT 0
#define SCE_H_TAG 1
#define SCE_H_TAGUNKNOWN 2
#define SCE_H_ATTRIBUTE 3
#define SCE_H_ATTRIBUTEUNKNOWN 4
#define SCE_H_NUMBER 5
#define SCE_H_DOUBLESTRING 6
#define SCE_H_SINGLESTRING 7
#define SCE_H_OTHER 8
#define SCE_H_COMMENT 9
#define SCE_H_ENTITY 10
#define SCE_H_TAGEND 11
#define SCE_H_XMLSTART 12
#define SCE_H_XMLEND 13
#define SCE_H_SCRIPT 14
#define SCE_H_ASP 15
#define SCE_H_ASPAT 16
#define SCE_H_CDATA 17
#define SCE_H_QUESTION 18
#define SCE_H_VALUE 19
#define SCE_H_XCCOMMENT 20
#define SCE_H_SGML_DEFAULT 21
#define SCE_H_SGML_COMMAND 22
#define SCE_H_SGML_1ST_PARAM 23
#define SCE_H_SGML_DOUBLESTRING 24
#define SCE_H_SGML_SIMPLESTRING 25
#define SCE_H_SGML_ERROR 26
#define SCE_H_SGML_SPECIAL 27
#define SCE_H_SGML_ENTITY 28
#define SCE_H_SGML_COMMENT 29
#define SCE_H_SGML_1ST_PARAM_COMMENT 30
#define SCE_H_SGML_BLOCK_DEFAULT 31
#define SCE_HJ_START 40
#define SCE_HJ_DEFAULT 41
#define SCE_HJ_COMMENT 42
#define SCE_HJ_COMMENTLINE 43
#define SCE_HJ_COMMENTDOC 44
#define SCE_HJ_NUMBER 45
#define SCE_HJ_WORD 46
#define SCE_HJ_KEYWORD 47
#define SCE_HJ_DOUBLESTRING 48
#define SCE_HJ_SINGLESTRING 49
#define SCE_HJ_SYMBOLS 50
#define SCE_HJ_STRINGEOL 51
#define SCE_HJ_REGEX 52
#define SCE_HJA_START 55
#define SCE_HJA_DEFAULT 56
#define SCE_HJA_COMMENT 57
#define SCE_HJA_COMMENTLINE 58
#define SCE_HJA_COMMENTDOC 59
#define SCE_HJA_NUMBER 60
#define SCE_HJA_WORD 61
#define SCE_HJA_KEYWORD 62
#define SCE_HJA_DOUBLESTRING 63
#define SCE_HJA_SINGLESTRING 64
#define SCE_HJA_SYMBOLS 65
#define SCE_HJA_STRINGEOL 66
#define SCE_HJA_REGEX 67
#define SCE_HB_START 70
#define SCE_HB_DEFAULT 71
#define SCE_HB_COMMENTLINE 72
#define SCE_HB_NUMBER 73
#define SCE_HB_WORD 74
#define SCE_HB_STRING 75
#define SCE_HB_IDENTIFIER 76
#define SCE_HB_STRINGEOL 77
#define SCE_HBA_START 80
#define SCE_HBA_DEFAULT 81
#define SCE_HBA_COMMENTLINE 82
#define SCE_HBA_NUMBER 83
#define SCE_HBA_WORD 84
#define SCE_HBA_STRING 85
#define SCE_HBA_IDENTIFIER 86
#define SCE_HBA_STRINGEOL 87
#define SCE_HP_START 90
#define SCE_HP_DEFAULT 91
#define SCE_HP_COMMENTLINE 92
#define SCE_HP_NUMBER 93
#define SCE_HP_STRING 94
#define SCE_HP_CHARACTER 95
#define SCE_HP_WORD 96
#define SCE_HP_TRIPLE 97
#define SCE_HP_TRIPLEDOUBLE 98
#define SCE_HP_CLASSNAME 99
#define SCE_HP_DEFNAME 100
#define SCE_HP_OPERATOR 101
#define SCE_HP_IDENTIFIER 102
#define SCE_HPHP_COMPLEX_VARIABLE 104
#define SCE_HPA_START 105
#define SCE_HPA_DEFAULT 106
#define SCE_HPA_COMMENTLINE 107
#define SCE_HPA_NUMBER 108
#define SCE_HPA_STRING 109
#define SCE_HPA_CHARACTER 110
#define SCE_HPA_WORD 111
#define SCE_HPA_TRIPLE 112
#define SCE_HPA_TRIPLEDOUBLE 113
#define SCE_HPA_CLASSNAME 114
#define SCE_HPA_DEFNAME 115
#define SCE_HPA_OPERATOR 116
#define SCE_HPA_IDENTIFIER 117
#define SCE_HPHP_DEFAULT 118
#define SCE_HPHP_HSTRING 119
#define SCE_HPHP_SIMPLESTRING 120
#define SCE_HPHP_WORD 121
#define SCE_HPHP_NUMBER 122
#define SCE_HPHP_VARIABLE 123
#define SCE_HPHP_COMMENT 124
#define SCE_HPHP_COMMENTLINE 125
#define SCE_HPHP_HSTRING_VARIABLE 126
#define SCE_HPHP_OPERATOR 127
#define SCE_PL_DEFAULT 0
#define SCE_PL_ERROR 1
#define SCE_PL_COMMENTLINE 2
#define SCE_PL_POD 3
#define SCE_PL_NUMBER 4
#define SCE_PL_WORD 5
#define SCE_PL_STRING 6
#define SCE_PL_CHARACTER 7
#define SCE_PL_PUNCTUATION 8
#define SCE_PL_PREPROCESSOR 9
#define SCE_PL_OPERATOR 10
#define SCE_PL_IDENTIFIER 11
#define SCE_PL_SCALAR 12
#define SCE_PL_ARRAY 13
#define SCE_PL_HASH 14
#define SCE_PL_SYMBOLTABLE 15
#define SCE_PL_VARIABLE_INDEXER 16
#define SCE_PL_REGEX 17
#define SCE_PL_REGSUBST 18
#define SCE_PL_LONGQUOTE 19
#define SCE_PL_BACKTICKS 20
#define SCE_PL_DATASECTION 21
#define SCE_PL_HERE_DELIM 22
#define SCE_PL_HERE_Q 23
#define SCE_PL_HERE_QQ 24
#define SCE_PL_HERE_QX 25
#define SCE_PL_STRING_Q 26
#define SCE_PL_STRING_QQ 27
#define SCE_PL_STRING_QX 28
#define SCE_PL_STRING_QR 29
#define SCE_PL_STRING_QW 30
#define SCE_PL_POD_VERB 31
#define SCE_PL_SUB_PROTOTYPE 40
#define SCE_PL_FORMAT_IDENT 41
#define SCE_PL_FORMAT 42
#define SCE_PL_STRING_VAR 43
#define SCE_PL_XLAT 44
#define SCE_PL_REGEX_VAR 54
#define SCE_PL_REGSUBST_VAR 55
#define SCE_PL_BACKTICKS_VAR 57
#define SCE_PL_HERE_QQ_VAR 61
#define SCE_PL_HERE_QX_VAR 62
#define SCE_PL_STRING_QQ_VAR 64
#define SCE_PL_STRING_QX_VAR 65
#define SCE_PL_STRING_QR_VAR 66
#define SCE_RB_DEFAULT 0
#define SCE_RB_ERROR 1
#define SCE_RB_COMMENTLINE 2
#define SCE_RB_POD 3
#define SCE_RB_NUMBER 4
#define SCE_RB_WORD 5
#define SCE_RB_STRING 6
#define SCE_RB_CHARACTER 7
#define SCE_RB_CLASSNAME 8
#define SCE_RB_DEFNAME 9
#define SCE_RB_OPERATOR 10
#define SCE_RB_IDENTIFIER 11
#define SCE_RB_REGEX 12
#define SCE_RB_GLOBAL 13
#define SCE_RB_SYMBOL 14
#define SCE_RB_MODULE_NAME 15
#define SCE_RB_INSTANCE_VAR 16
#define SCE_RB_CLASS_VAR 17
#define SCE_RB_BACKTICKS 18
#define SCE_RB_DATASECTION 19
#define SCE_RB_HERE_DELIM 20
#define SCE_RB_HERE_Q 21
#define SCE_RB_HERE_QQ 22
#define SCE_RB_HERE_QX 23
#define SCE_RB_STRING_Q 24
#define SCE_RB_STRING_QQ 25
#define SCE_RB_STRING_QX 26
#define SCE_RB_STRING_QR 27
#define SCE_RB_STRING_QW 28
#define SCE_RB_WORD_DEMOTED 29
#define SCE_RB_STDIN 30
#define SCE_RB_STDOUT 31
#define SCE_RB_STDERR 40
#define SCE_RB_UPPER_BOUND 41
#define SCE_B_DEFAULT 0
#define SCE_B_COMMENT 1
#define SCE_B_NUMBER 2
#define SCE_B_KEYWORD 3
#define SCE_B_STRING 4
#define SCE_B_PREPROCESSOR 5
#define SCE_B_OPERATOR 6
#define SCE_B_IDENTIFIER 7
#define SCE_B_DATE 8
#define SCE_B_STRINGEOL 9
#define SCE_B_KEYWORD2 10
#define SCE_B_KEYWORD3 11
#define SCE_B_KEYWORD4 12
#define SCE_B_CONSTANT 13
#define SCE_B_ASM 14
#define SCE_B_LABEL 15
#define SCE_B_ERROR 16
#define SCE_B_HEXNUMBER 17
#define SCE_B_BINNUMBER 18
#define SCE_PROPS_DEFAULT 0
#define SCE_PROPS_COMMENT 1
#define SCE_PROPS_SECTION 2
#define SCE_PROPS_ASSIGNMENT 3
#define SCE_PROPS_DEFVAL 4
#define SCE_PROPS_KEY 5
#define SCE_L_DEFAULT 0
#define SCE_L_COMMAND 1
#define SCE_L_TAG 2
#define SCE_L_MATH 3
#define SCE_L_COMMENT 4
#define SCE_L_TAG2 5
#define SCE_L_MATH2 6
#define SCE_L_COMMENT2 7
#define SCE_L_VERBATIM 8
#define SCE_L_SHORTCMD 9
#define SCE_L_SPECIAL 10
#define SCE_L_CMDOPT 11
#define SCE_L_ERROR 12
#define SCE_LUA_DEFAULT 0
#define SCE_LUA_COMMENT 1
#define SCE_LUA_COMMENTLINE 2
#define SCE_LUA_COMMENTDOC 3
#define SCE_LUA_NUMBER 4
#define SCE_LUA_WORD 5
#define SCE_LUA_STRING 6
#define SCE_LUA_CHARACTER 7
#define SCE_LUA_LITERALSTRING 8
#define SCE_LUA_PREPROCESSOR 9
#define SCE_LUA_OPERATOR 10
#define SCE_LUA_IDENTIFIER 11
#define SCE_LUA_STRINGEOL 12
#define SCE_LUA_WORD2 13
#define SCE_LUA_WORD3 14
#define SCE_LUA_WORD4 15
#define SCE_LUA_WORD5 16
#define SCE_LUA_WORD6 17
#define SCE_LUA_WORD7 18
#define SCE_LUA_WORD8 19
#define SCE_LUA_LABEL 20
#define SCE_ERR_DEFAULT 0
#define SCE_ERR_PYTHON 1
#define SCE_ERR_GCC 2
#define SCE_ERR_MS 3
#define SCE_ERR_CMD 4
#define SCE_ERR_BORLAND 5
#define SCE_ERR_PERL 6
#define SCE_ERR_NET 7
#define SCE_ERR_LUA 8
#define SCE_ERR_CTAG 9
#define SCE_ERR_DIFF_CHANGED 10
#define SCE_ERR_DIFF_ADDITION 11
#define SCE_ERR_DIFF_DELETION 12
#define SCE_ERR_DIFF_MESSAGE 13
#define SCE_ERR_PHP 14
#define SCE_ERR_ELF 15
#define SCE_ERR_IFC 16
#define SCE_ERR_IFORT 17
#define SCE_ERR_ABSF 18
#define SCE_ERR_TIDY 19
#define SCE_ERR_JAVA_STACK 20
#define SCE_ERR_VALUE 21
#define SCE_ERR_GCC_INCLUDED_FROM 22
#define SCE_BAT_DEFAULT 0
#define SCE_BAT_COMMENT 1
#define SCE_BAT_WORD 2
#define SCE_BAT_LABEL 3
#define SCE_BAT_HIDE 4
#define SCE_BAT_COMMAND 5
#define SCE_BAT_IDENTIFIER 6
#define SCE_BAT_OPERATOR 7
#define SCE_TCMD_DEFAULT 0
#define SCE_TCMD_COMMENT 1
#define SCE_TCMD_WORD 2
#define SCE_TCMD_LABEL 3
#define SCE_TCMD_HIDE 4
#define SCE_TCMD_COMMAND 5
#define SCE_TCMD_IDENTIFIER 6
#define SCE_TCMD_OPERATOR 7
#define SCE_TCMD_ENVIRONMENT 8
#define SCE_TCMD_EXPANSION 9
#define SCE_TCMD_CLABEL 10
#define SCE_MAKE_DEFAULT 0
#define SCE_MAKE_COMMENT 1
#define SCE_MAKE_PREPROCESSOR 2
#define SCE_MAKE_IDENTIFIER 3
#define SCE_MAKE_OPERATOR 4
#define SCE_MAKE_TARGET 5
#define SCE_MAKE_IDEOL 9
#define SCE_DIFF_DEFAULT 0
#define SCE_DIFF_COMMENT 1
#define SCE_DIFF_COMMAND 2
#define SCE_DIFF_HEADER 3
#define SCE_DIFF_POSITION 4
#define SCE_DIFF_DELETED 5
#define SCE_DIFF_ADDED 6
#define SCE_DIFF_CHANGED 7
#define SCE_CONF_DEFAULT 0
#define SCE_CONF_COMMENT 1
#define SCE_CONF_NUMBER 2
#define SCE_CONF_IDENTIFIER 3
#define SCE_CONF_EXTENSION 4
#define SCE_CONF_PARAMETER 5
#define SCE_CONF_STRING 6
#define SCE_CONF_OPERATOR 7
#define SCE_CONF_IP 8
#define SCE_CONF_DIRECTIVE 9
#define SCE_AVE_DEFAULT 0
#define SCE_AVE_COMMENT 1
#define SCE_AVE_NUMBER 2
#define SCE_AVE_WORD 3
#define SCE_AVE_STRING 6
#define SCE_AVE_ENUM 7
#define SCE_AVE_STRINGEOL 8
#define SCE_AVE_IDENTIFIER 9
#define SCE_AVE_OPERATOR 10
#define SCE_AVE_WORD1 11
#define SCE_AVE_WORD2 12
#define SCE_AVE_WORD3 13
#define SCE_AVE_WORD4 14
#define SCE_AVE_WORD5 15
#define SCE_AVE_WORD6 16
#define SCE_ADA_DEFAULT 0
#define SCE_ADA_WORD 1
#define SCE_ADA_IDENTIFIER 2
#define SCE_ADA_NUMBER 3
#define SCE_ADA_DELIMITER 4
#define SCE_ADA_CHARACTER 5
#define SCE_ADA_CHARACTEREOL 6
#define SCE_ADA_STRING 7
#define SCE_ADA_STRINGEOL 8
#define SCE_ADA_LABEL 9
#define SCE_ADA_COMMENTLINE 10
#define SCE_ADA_ILLEGAL 11
#define SCE_BAAN_DEFAULT 0
#define SCE_BAAN_COMMENT 1
#define SCE_BAAN_COMMENTDOC 2
#define SCE_BAAN_NUMBER 3
#define SCE_BAAN_WORD 4
#define SCE_BAAN_STRING 5
#define SCE_BAAN_PREPROCESSOR 6
#define SCE_BAAN_OPERATOR 7
#define SCE_BAAN_IDENTIFIER 8
#define SCE_BAAN_STRINGEOL 9
#define SCE_BAAN_WORD2 10
#define SCE_LISP_DEFAULT 0
#define SCE_LISP_COMMENT 1
#define SCE_LISP_NUMBER 2
#define SCE_LISP_KEYWORD 3
#define SCE_LISP_KEYWORD_KW 4
#define SCE_LISP_SYMBOL 5
#define SCE_LISP_STRING 6
#define SCE_LISP_STRINGEOL 8
#define SCE_LISP_IDENTIFIER 9
#define SCE_LISP_OPERATOR 10
#define SCE_LISP_SPECIAL 11
#define SCE_LISP_MULTI_COMMENT 12
#define SCE_EIFFEL_DEFAULT 0
#define SCE_EIFFEL_COMMENTLINE 1
#define SCE_EIFFEL_NUMBER 2
#define SCE_EIFFEL_WORD 3
#define SCE_EIFFEL_STRING 4
#define SCE_EIFFEL_CHARACTER 5
#define SCE_EIFFEL_OPERATOR 6
#define SCE_EIFFEL_IDENTIFIER 7
#define SCE_EIFFEL_STRINGEOL 8
#define SCE_NNCRONTAB_DEFAULT 0
#define SCE_NNCRONTAB_COMMENT 1
#define SCE_NNCRONTAB_TASK 2
#define SCE_NNCRONTAB_SECTION 3
#define SCE_NNCRONTAB_KEYWORD 4
#define SCE_NNCRONTAB_MODIFIER 5
#define SCE_NNCRONTAB_ASTERISK 6
#define SCE_NNCRONTAB_NUMBER 7
#define SCE_NNCRONTAB_STRING 8
#define SCE_NNCRONTAB_ENVIRONMENT 9
#define SCE_NNCRONTAB_IDENTIFIER 10
#define SCE_FORTH_DEFAULT 0
#define SCE_FORTH_COMMENT 1
#define SCE_FORTH_COMMENT_ML 2
#define SCE_FORTH_IDENTIFIER 3
#define SCE_FORTH_CONTROL 4
#define SCE_FORTH_KEYWORD 5
#define SCE_FORTH_DEFWORD 6
#define SCE_FORTH_PREWORD1 7
#define SCE_FORTH_PREWORD2 8
#define SCE_FORTH_NUMBER 9
#define SCE_FORTH_STRING 10
#define SCE_FORTH_LOCALE 11
#define SCE_MATLAB_DEFAULT 0
#define SCE_MATLAB_COMMENT 1
#define SCE_MATLAB_COMMAND 2
#define SCE_MATLAB_NUMBER 3
#define SCE_MATLAB_KEYWORD 4
#define SCE_MATLAB_STRING 5
#define SCE_MATLAB_OPERATOR 6
#define SCE_MATLAB_IDENTIFIER 7
#define SCE_MATLAB_DOUBLEQUOTESTRING 8
#define SCE_SCRIPTOL_DEFAULT 0
#define SCE_SCRIPTOL_WHITE 1
#define SCE_SCRIPTOL_COMMENTLINE 2
#define SCE_SCRIPTOL_PERSISTENT 3
#define SCE_SCRIPTOL_CSTYLE 4
#define SCE_SCRIPTOL_COMMENTBLOCK 5
#define SCE_SCRIPTOL_NUMBER 6
#define SCE_SCRIPTOL_STRING 7
#define SCE_SCRIPTOL_CHARACTER 8
#define SCE_SCRIPTOL_STRINGEOL 9
#define SCE_SCRIPTOL_KEYWORD 10
#define SCE_SCRIPTOL_OPERATOR 11
#define SCE_SCRIPTOL_IDENTIFIER 12
#define SCE_SCRIPTOL_TRIPLE 13
#define SCE_SCRIPTOL_CLASSNAME 14
#define SCE_SCRIPTOL_PREPROCESSOR 15
#define SCE_ASM_DEFAULT 0
#define SCE_ASM_COMMENT 1
#define SCE_ASM_NUMBER 2
#define SCE_ASM_STRING 3
#define SCE_ASM_OPERATOR 4
#define SCE_ASM_IDENTIFIER 5
#define SCE_ASM_CPUINSTRUCTION 6
#define SCE_ASM_MATHINSTRUCTION 7
#define SCE_ASM_REGISTER 8
#define SCE_ASM_DIRECTIVE 9
#define SCE_ASM_DIRECTIVEOPERAND 10
#define SCE_ASM_COMMENTBLOCK 11
#define SCE_ASM_CHARACTER 12
#define SCE_ASM_STRINGEOL 13
#define SCE_ASM_EXTINSTRUCTION 14
#define SCE_ASM_COMMENTDIRECTIVE 15
#define SCE_F_DEFAULT 0
#define SCE_F_COMMENT 1
#define SCE_F_NUMBER 2
#define SCE_F_STRING1 3
#define SCE_F_STRING2 4
#define SCE_F_STRINGEOL 5
#define SCE_F_OPERATOR 6
#define SCE_F_IDENTIFIER 7
#define SCE_F_WORD 8
#define SCE_F_WORD2 9
#define SCE_F_WORD3 10
#define SCE_F_PREPROCESSOR 11
#define SCE_F_OPERATOR2 12
#define SCE_F_LABEL 13
#define SCE_F_CONTINUATION 14
#define SCE_CSS_DEFAULT 0
#define SCE_CSS_TAG 1
#define SCE_CSS_CLASS 2
#define SCE_CSS_PSEUDOCLASS 3
#define SCE_CSS_UNKNOWN_PSEUDOCLASS 4
#define SCE_CSS_OPERATOR 5
#define SCE_CSS_IDENTIFIER 6
#define SCE_CSS_UNKNOWN_IDENTIFIER 7
#define SCE_CSS_VALUE 8
#define SCE_CSS_COMMENT 9
#define SCE_CSS_ID 10
#define SCE_CSS_IMPORTANT 11
#define SCE_CSS_DIRECTIVE 12
#define SCE_CSS_DOUBLESTRING 13
#define SCE_CSS_SINGLESTRING 14
#define SCE_CSS_IDENTIFIER2 15
#define SCE_CSS_ATTRIBUTE 16
#define SCE_CSS_IDENTIFIER3 17
#define SCE_CSS_PSEUDOELEMENT 18
#define SCE_CSS_EXTENDED_IDENTIFIER 19
#define SCE_CSS_EXTENDED_PSEUDOCLASS 20
#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21
#define SCE_CSS_MEDIA 22
#define SCE_CSS_VARIABLE 23
#define SCE_POV_DEFAULT 0
#define SCE_POV_COMMENT 1
#define SCE_POV_COMMENTLINE 2
#define SCE_POV_NUMBER 3
#define SCE_POV_OPERATOR 4
#define SCE_POV_IDENTIFIER 5
#define SCE_POV_STRING 6
#define SCE_POV_STRINGEOL 7
#define SCE_POV_DIRECTIVE 8
#define SCE_POV_BADDIRECTIVE 9
#define SCE_POV_WORD2 10
#define SCE_POV_WORD3 11
#define SCE_POV_WORD4 12
#define SCE_POV_WORD5 13
#define SCE_POV_WORD6 14
#define SCE_POV_WORD7 15
#define SCE_POV_WORD8 16
#define SCE_LOUT_DEFAULT 0
#define SCE_LOUT_COMMENT 1
#define SCE_LOUT_NUMBER 2
#define SCE_LOUT_WORD 3
#define SCE_LOUT_WORD2 4
#define SCE_LOUT_WORD3 5
#define SCE_LOUT_WORD4 6
#define SCE_LOUT_STRING 7
#define SCE_LOUT_OPERATOR 8
#define SCE_LOUT_IDENTIFIER 9
#define SCE_LOUT_STRINGEOL 10
#define SCE_ESCRIPT_DEFAULT 0
#define SCE_ESCRIPT_COMMENT 1
#define SCE_ESCRIPT_COMMENTLINE 2
#define SCE_ESCRIPT_COMMENTDOC 3
#define SCE_ESCRIPT_NUMBER 4
#define SCE_ESCRIPT_WORD 5
#define SCE_ESCRIPT_STRING 6
#define SCE_ESCRIPT_OPERATOR 7
#define SCE_ESCRIPT_IDENTIFIER 8
#define SCE_ESCRIPT_BRACE 9
#define SCE_ESCRIPT_WORD2 10
#define SCE_ESCRIPT_WORD3 11
#define SCE_PS_DEFAULT 0
#define SCE_PS_COMMENT 1
#define SCE_PS_DSC_COMMENT 2
#define SCE_PS_DSC_VALUE 3
#define SCE_PS_NUMBER 4
#define SCE_PS_NAME 5
#define SCE_PS_KEYWORD 6
#define SCE_PS_LITERAL 7
#define SCE_PS_IMMEVAL 8
#define SCE_PS_PAREN_ARRAY 9
#define SCE_PS_PAREN_DICT 10
#define SCE_PS_PAREN_PROC 11
#define SCE_PS_TEXT 12
#define SCE_PS_HEXSTRING 13
#define SCE_PS_BASE85STRING 14
#define SCE_PS_BADSTRINGCHAR 15
#define SCE_NSIS_DEFAULT 0
#define SCE_NSIS_COMMENT 1
#define SCE_NSIS_STRINGDQ 2
#define SCE_NSIS_STRINGLQ 3
#define SCE_NSIS_STRINGRQ 4
#define SCE_NSIS_FUNCTION 5
#define SCE_NSIS_VARIABLE 6
#define SCE_NSIS_LABEL 7
#define SCE_NSIS_USERDEFINED 8
#define SCE_NSIS_SECTIONDEF 9
#define SCE_NSIS_SUBSECTIONDEF 10
#define SCE_NSIS_IFDEFINEDEF 11
#define SCE_NSIS_MACRODEF 12
#define SCE_NSIS_STRINGVAR 13
#define SCE_NSIS_NUMBER 14
#define SCE_NSIS_SECTIONGROUP 15
#define SCE_NSIS_PAGEEX 16
#define SCE_NSIS_FUNCTIONDEF 17
#define SCE_NSIS_COMMENTBOX 18
#define SCE_MMIXAL_LEADWS 0
#define SCE_MMIXAL_COMMENT 1
#define SCE_MMIXAL_LABEL 2
#define SCE_MMIXAL_OPCODE 3
#define SCE_MMIXAL_OPCODE_PRE 4
#define SCE_MMIXAL_OPCODE_VALID 5
#define SCE_MMIXAL_OPCODE_UNKNOWN 6
#define SCE_MMIXAL_OPCODE_POST 7
#define SCE_MMIXAL_OPERANDS 8
#define SCE_MMIXAL_NUMBER 9
#define SCE_MMIXAL_REF 10
#define SCE_MMIXAL_CHAR 11
#define SCE_MMIXAL_STRING 12
#define SCE_MMIXAL_REGISTER 13
#define SCE_MMIXAL_HEX 14
#define SCE_MMIXAL_OPERATOR 15
#define SCE_MMIXAL_SYMBOL 16
#define SCE_MMIXAL_INCLUDE 17
#define SCE_CLW_DEFAULT 0
#define SCE_CLW_LABEL 1
#define SCE_CLW_COMMENT 2
#define SCE_CLW_STRING 3
#define SCE_CLW_USER_IDENTIFIER 4
#define SCE_CLW_INTEGER_CONSTANT 5
#define SCE_CLW_REAL_CONSTANT 6
#define SCE_CLW_PICTURE_STRING 7
#define SCE_CLW_KEYWORD 8
#define SCE_CLW_COMPILER_DIRECTIVE 9
#define SCE_CLW_RUNTIME_EXPRESSIONS 10
#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11
#define SCE_CLW_STRUCTURE_DATA_TYPE 12
#define SCE_CLW_ATTRIBUTE 13
#define SCE_CLW_STANDARD_EQUATE 14
#define SCE_CLW_ERROR 15
#define SCE_CLW_DEPRECATED 16
#define SCE_LOT_DEFAULT 0
#define SCE_LOT_HEADER 1
#define SCE_LOT_BREAK 2
#define SCE_LOT_SET 3
#define SCE_LOT_PASS 4
#define SCE_LOT_FAIL 5
#define SCE_LOT_ABORT 6
#define SCE_YAML_DEFAULT 0
#define SCE_YAML_COMMENT 1
#define SCE_YAML_IDENTIFIER 2
#define SCE_YAML_KEYWORD 3
#define SCE_YAML_NUMBER 4
#define SCE_YAML_REFERENCE 5
#define SCE_YAML_DOCUMENT 6
#define SCE_YAML_TEXT 7
#define SCE_YAML_ERROR 8
#define SCE_YAML_OPERATOR 9
#define SCE_TEX_DEFAULT 0
#define SCE_TEX_SPECIAL 1
#define SCE_TEX_GROUP 2
#define SCE_TEX_SYMBOL 3
#define SCE_TEX_COMMAND 4
#define SCE_TEX_TEXT 5
#define SCE_METAPOST_DEFAULT 0
#define SCE_METAPOST_SPECIAL 1
#define SCE_METAPOST_GROUP 2
#define SCE_METAPOST_SYMBOL 3
#define SCE_METAPOST_COMMAND 4
#define SCE_METAPOST_TEXT 5
#define SCE_METAPOST_EXTRA 6
#define SCE_ERLANG_DEFAULT 0
#define SCE_ERLANG_COMMENT 1
#define SCE_ERLANG_VARIABLE 2
#define SCE_ERLANG_NUMBER 3
#define SCE_ERLANG_KEYWORD 4
#define SCE_ERLANG_STRING 5
#define SCE_ERLANG_OPERATOR 6
#define SCE_ERLANG_ATOM 7
#define SCE_ERLANG_FUNCTION_NAME 8
#define SCE_ERLANG_CHARACTER 9
#define SCE_ERLANG_MACRO 10
#define SCE_ERLANG_RECORD 11
#define SCE_ERLANG_PREPROC 12
#define SCE_ERLANG_NODE_NAME 13
#define SCE_ERLANG_COMMENT_FUNCTION 14
#define SCE_ERLANG_COMMENT_MODULE 15
#define SCE_ERLANG_COMMENT_DOC 16
#define SCE_ERLANG_COMMENT_DOC_MACRO 17
#define SCE_ERLANG_ATOM_QUOTED 18
#define SCE_ERLANG_MACRO_QUOTED 19
#define SCE_ERLANG_RECORD_QUOTED 20
#define SCE_ERLANG_NODE_NAME_QUOTED 21
#define SCE_ERLANG_BIFS 22
#define SCE_ERLANG_MODULES 23
#define SCE_ERLANG_MODULES_ATT 24
#define SCE_ERLANG_UNKNOWN 31
#define SCE_MSSQL_DEFAULT 0
#define SCE_MSSQL_COMMENT 1
#define SCE_MSSQL_LINE_COMMENT 2
#define SCE_MSSQL_NUMBER 3
#define SCE_MSSQL_STRING 4
#define SCE_MSSQL_OPERATOR 5
#define SCE_MSSQL_IDENTIFIER 6
#define SCE_MSSQL_VARIABLE 7
#define SCE_MSSQL_COLUMN_NAME 8
#define SCE_MSSQL_STATEMENT 9
#define SCE_MSSQL_DATATYPE 10
#define SCE_MSSQL_SYSTABLE 11
#define SCE_MSSQL_GLOBAL_VARIABLE 12
#define SCE_MSSQL_FUNCTION 13
#define SCE_MSSQL_STORED_PROCEDURE 14
#define SCE_MSSQL_DEFAULT_PREF_DATATYPE 15
#define SCE_MSSQL_COLUMN_NAME_2 16
#define SCE_V_DEFAULT 0
#define SCE_V_COMMENT 1
#define SCE_V_COMMENTLINE 2
#define SCE_V_COMMENTLINEBANG 3
#define SCE_V_NUMBER 4
#define SCE_V_WORD 5
#define SCE_V_STRING 6
#define SCE_V_WORD2 7
#define SCE_V_WORD3 8
#define SCE_V_PREPROCESSOR 9
#define SCE_V_OPERATOR 10
#define SCE_V_IDENTIFIER 11
#define SCE_V_STRINGEOL 12
#define SCE_V_USER 19
#define SCE_KIX_DEFAULT 0
#define SCE_KIX_COMMENT 1
#define SCE_KIX_STRING1 2
#define SCE_KIX_STRING2 3
#define SCE_KIX_NUMBER 4
#define SCE_KIX_VAR 5
#define SCE_KIX_MACRO 6
#define SCE_KIX_KEYWORD 7
#define SCE_KIX_FUNCTIONS 8
#define SCE_KIX_OPERATOR 9
#define SCE_KIX_IDENTIFIER 31
#define SCE_GC_DEFAULT 0
#define SCE_GC_COMMENTLINE 1
#define SCE_GC_COMMENTBLOCK 2
#define SCE_GC_GLOBAL 3
#define SCE_GC_EVENT 4
#define SCE_GC_ATTRIBUTE 5
#define SCE_GC_CONTROL 6
#define SCE_GC_COMMAND 7
#define SCE_GC_STRING 8
#define SCE_GC_OPERATOR 9
#define SCE_SN_DEFAULT 0
#define SCE_SN_CODE 1
#define SCE_SN_COMMENTLINE 2
#define SCE_SN_COMMENTLINEBANG 3
#define SCE_SN_NUMBER 4
#define SCE_SN_WORD 5
#define SCE_SN_STRING 6
#define SCE_SN_WORD2 7
#define SCE_SN_WORD3 8
#define SCE_SN_PREPROCESSOR 9
#define SCE_SN_OPERATOR 10
#define SCE_SN_IDENTIFIER 11
#define SCE_SN_STRINGEOL 12
#define SCE_SN_REGEXTAG 13
#define SCE_SN_SIGNAL 14
#define SCE_SN_USER 19
#define SCE_AU3_DEFAULT 0
#define SCE_AU3_COMMENT 1
#define SCE_AU3_COMMENTBLOCK 2
#define SCE_AU3_NUMBER 3
#define SCE_AU3_FUNCTION 4
#define SCE_AU3_KEYWORD 5
#define SCE_AU3_MACRO 6
#define SCE_AU3_STRING 7
#define SCE_AU3_OPERATOR 8
#define SCE_AU3_VARIABLE 9
#define SCE_AU3_SENT 10
#define SCE_AU3_PREPROCESSOR 11
#define SCE_AU3_SPECIAL 12
#define SCE_AU3_EXPAND 13
#define SCE_AU3_COMOBJ 14
#define SCE_AU3_UDF 15
#define SCE_APDL_DEFAULT 0
#define SCE_APDL_COMMENT 1
#define SCE_APDL_COMMENTBLOCK 2
#define SCE_APDL_NUMBER 3
#define SCE_APDL_STRING 4
#define SCE_APDL_OPERATOR 5
#define SCE_APDL_WORD 6
#define SCE_APDL_PROCESSOR 7
#define SCE_APDL_COMMAND 8
#define SCE_APDL_SLASHCOMMAND 9
#define SCE_APDL_STARCOMMAND 10
#define SCE_APDL_ARGUMENT 11
#define SCE_APDL_FUNCTION 12
#define SCE_SH_DEFAULT 0
#define SCE_SH_ERROR 1
#define SCE_SH_COMMENTLINE 2
#define SCE_SH_NUMBER 3
#define SCE_SH_WORD 4
#define SCE_SH_STRING 5
#define SCE_SH_CHARACTER 6
#define SCE_SH_OPERATOR 7
#define SCE_SH_IDENTIFIER 8
#define SCE_SH_SCALAR 9
#define SCE_SH_PARAM 10
#define SCE_SH_BACKTICKS 11
#define SCE_SH_HERE_DELIM 12
#define SCE_SH_HERE_Q 13
#define SCE_ASN1_DEFAULT 0
#define SCE_ASN1_COMMENT 1
#define SCE_ASN1_IDENTIFIER 2
#define SCE_ASN1_STRING 3
#define SCE_ASN1_OID 4
#define SCE_ASN1_SCALAR 5
#define SCE_ASN1_KEYWORD 6
#define SCE_ASN1_ATTRIBUTE 7
#define SCE_ASN1_DESCRIPTOR 8
#define SCE_ASN1_TYPE 9
#define SCE_ASN1_OPERATOR 10
#define SCE_VHDL_DEFAULT 0
#define SCE_VHDL_COMMENT 1
#define SCE_VHDL_COMMENTLINEBANG 2
#define SCE_VHDL_NUMBER 3
#define SCE_VHDL_STRING 4
#define SCE_VHDL_OPERATOR 5
#define SCE_VHDL_IDENTIFIER 6
#define SCE_VHDL_STRINGEOL 7
#define SCE_VHDL_KEYWORD 8
#define SCE_VHDL_STDOPERATOR 9
#define SCE_VHDL_ATTRIBUTE 10
#define SCE_VHDL_STDFUNCTION 11
#define SCE_VHDL_STDPACKAGE 12
#define SCE_VHDL_STDTYPE 13
#define SCE_VHDL_USERWORD 14
#define SCE_CAML_DEFAULT 0
#define SCE_CAML_IDENTIFIER 1
#define SCE_CAML_TAGNAME 2
#define SCE_CAML_KEYWORD 3
#define SCE_CAML_KEYWORD2 4
#define SCE_CAML_KEYWORD3 5
#define SCE_CAML_LINENUM 6
#define SCE_CAML_OPERATOR 7
#define SCE_CAML_NUMBER 8
#define SCE_CAML_CHAR 9
#define SCE_CAML_WHITE 10
#define SCE_CAML_STRING 11
#define SCE_CAML_COMMENT 12
#define SCE_CAML_COMMENT1 13
#define SCE_CAML_COMMENT2 14
#define SCE_CAML_COMMENT3 15
#define SCE_HA_DEFAULT 0
#define SCE_HA_IDENTIFIER 1
#define SCE_HA_KEYWORD 2
#define SCE_HA_NUMBER 3
#define SCE_HA_STRING 4
#define SCE_HA_CHARACTER 5
#define SCE_HA_CLASS 6
#define SCE_HA_MODULE 7
#define SCE_HA_CAPITAL 8
#define SCE_HA_DATA 9
#define SCE_HA_IMPORT 10
#define SCE_HA_OPERATOR 11
#define SCE_HA_INSTANCE 12
#define SCE_HA_COMMENTLINE 13
#define SCE_HA_COMMENTBLOCK 14
#define SCE_HA_COMMENTBLOCK2 15
#define SCE_HA_COMMENTBLOCK3 16
#define SCE_T3_DEFAULT 0
#define SCE_T3_X_DEFAULT 1
#define SCE_T3_PREPROCESSOR 2
#define SCE_T3_BLOCK_COMMENT 3
#define SCE_T3_LINE_COMMENT 4
#define SCE_T3_OPERATOR 5
#define SCE_T3_KEYWORD 6
#define SCE_T3_NUMBER 7
#define SCE_T3_IDENTIFIER 8
#define SCE_T3_S_STRING 9
#define SCE_T3_D_STRING 10
#define SCE_T3_X_STRING 11
#define SCE_T3_LIB_DIRECTIVE 12
#define SCE_T3_MSG_PARAM 13
#define SCE_T3_HTML_TAG 14
#define SCE_T3_HTML_DEFAULT 15
#define SCE_T3_HTML_STRING 16
#define SCE_T3_USER1 17
#define SCE_T3_USER2 18
#define SCE_T3_USER3 19
#define SCE_T3_BRACE 20
#define SCE_REBOL_DEFAULT 0
#define SCE_REBOL_COMMENTLINE 1
#define SCE_REBOL_COMMENTBLOCK 2
#define SCE_REBOL_PREFACE 3
#define SCE_REBOL_OPERATOR 4
#define SCE_REBOL_CHARACTER 5
#define SCE_REBOL_QUOTEDSTRING 6
#define SCE_REBOL_BRACEDSTRING 7
#define SCE_REBOL_NUMBER 8
#define SCE_REBOL_PAIR 9
#define SCE_REBOL_TUPLE 10
#define SCE_REBOL_BINARY 11
#define SCE_REBOL_MONEY 12
#define SCE_REBOL_ISSUE 13
#define SCE_REBOL_TAG 14
#define SCE_REBOL_FILE 15
#define SCE_REBOL_EMAIL 16
#define SCE_REBOL_URL 17
#define SCE_REBOL_DATE 18
#define SCE_REBOL_TIME 19
#define SCE_REBOL_IDENTIFIER 20
#define SCE_REBOL_WORD 21
#define SCE_REBOL_WORD2 22
#define SCE_REBOL_WORD3 23
#define SCE_REBOL_WORD4 24
#define SCE_REBOL_WORD5 25
#define SCE_REBOL_WORD6 26
#define SCE_REBOL_WORD7 27
#define SCE_REBOL_WORD8 28
#define SCE_SQL_DEFAULT 0
#define SCE_SQL_COMMENT 1
#define SCE_SQL_COMMENTLINE 2
#define SCE_SQL_COMMENTDOC 3
#define SCE_SQL_NUMBER 4
#define SCE_SQL_WORD 5
#define SCE_SQL_STRING 6
#define SCE_SQL_CHARACTER 7
#define SCE_SQL_SQLPLUS 8
#define SCE_SQL_SQLPLUS_PROMPT 9
#define SCE_SQL_OPERATOR 10
#define SCE_SQL_IDENTIFIER 11
#define SCE_SQL_SQLPLUS_COMMENT 13
#define SCE_SQL_COMMENTLINEDOC 15
#define SCE_SQL_WORD2 16
#define SCE_SQL_COMMENTDOCKEYWORD 17
#define SCE_SQL_COMMENTDOCKEYWORDERROR 18
#define SCE_SQL_USER1 19
#define SCE_SQL_USER2 20
#define SCE_SQL_USER3 21
#define SCE_SQL_USER4 22
#define SCE_SQL_QUOTEDIDENTIFIER 23
#define SCE_ST_DEFAULT 0
#define SCE_ST_STRING 1
#define SCE_ST_NUMBER 2
#define SCE_ST_COMMENT 3
#define SCE_ST_SYMBOL 4
#define SCE_ST_BINARY 5
#define SCE_ST_BOOL 6
#define SCE_ST_SELF 7
#define SCE_ST_SUPER 8
#define SCE_ST_NIL 9
#define SCE_ST_GLOBAL 10
#define SCE_ST_RETURN 11
#define SCE_ST_SPECIAL 12
#define SCE_ST_KWSEND 13
#define SCE_ST_ASSIGN 14
#define SCE_ST_CHARACTER 15
#define SCE_ST_SPEC_SEL 16
#define SCE_FS_DEFAULT 0
#define SCE_FS_COMMENT 1
#define SCE_FS_COMMENTLINE 2
#define SCE_FS_COMMENTDOC 3
#define SCE_FS_COMMENTLINEDOC 4
#define SCE_FS_COMMENTDOCKEYWORD 5
#define SCE_FS_COMMENTDOCKEYWORDERROR 6
#define SCE_FS_KEYWORD 7
#define SCE_FS_KEYWORD2 8
#define SCE_FS_KEYWORD3 9
#define SCE_FS_KEYWORD4 10
#define SCE_FS_NUMBER 11
#define SCE_FS_STRING 12
#define SCE_FS_PREPROCESSOR 13
#define SCE_FS_OPERATOR 14
#define SCE_FS_IDENTIFIER 15
#define SCE_FS_DATE 16
#define SCE_FS_STRINGEOL 17
#define SCE_FS_CONSTANT 18
#define SCE_FS_WORDOPERATOR 19
#define SCE_FS_DISABLEDCODE 20
#define SCE_FS_DEFAULT_C 21
#define SCE_FS_COMMENTDOC_C 22
#define SCE_FS_COMMENTLINEDOC_C 23
#define SCE_FS_KEYWORD_C 24
#define SCE_FS_KEYWORD2_C 25
#define SCE_FS_NUMBER_C 26
#define SCE_FS_STRING_C 27
#define SCE_FS_PREPROCESSOR_C 28
#define SCE_FS_OPERATOR_C 29
#define SCE_FS_IDENTIFIER_C 30
#define SCE_FS_STRINGEOL_C 31
#define SCE_CSOUND_DEFAULT 0
#define SCE_CSOUND_COMMENT 1
#define SCE_CSOUND_NUMBER 2
#define SCE_CSOUND_OPERATOR 3
#define SCE_CSOUND_INSTR 4
#define SCE_CSOUND_IDENTIFIER 5
#define SCE_CSOUND_OPCODE 6
#define SCE_CSOUND_HEADERSTMT 7
#define SCE_CSOUND_USERKEYWORD 8
#define SCE_CSOUND_COMMENTBLOCK 9
#define SCE_CSOUND_PARAM 10
#define SCE_CSOUND_ARATE_VAR 11
#define SCE_CSOUND_KRATE_VAR 12
#define SCE_CSOUND_IRATE_VAR 13
#define SCE_CSOUND_GLOBAL_VAR 14
#define SCE_CSOUND_STRINGEOL 15
#define SCE_INNO_DEFAULT 0
#define SCE_INNO_COMMENT 1
#define SCE_INNO_KEYWORD 2
#define SCE_INNO_PARAMETER 3
#define SCE_INNO_SECTION 4
#define SCE_INNO_PREPROC 5
#define SCE_INNO_INLINE_EXPANSION 6
#define SCE_INNO_COMMENT_PASCAL 7
#define SCE_INNO_KEYWORD_PASCAL 8
#define SCE_INNO_KEYWORD_USER 9
#define SCE_INNO_STRING_DOUBLE 10
#define SCE_INNO_STRING_SINGLE 11
#define SCE_INNO_IDENTIFIER 12
#define SCE_OPAL_SPACE 0
#define SCE_OPAL_COMMENT_BLOCK 1
#define SCE_OPAL_COMMENT_LINE 2
#define SCE_OPAL_INTEGER 3
#define SCE_OPAL_KEYWORD 4
#define SCE_OPAL_SORT 5
#define SCE_OPAL_STRING 6
#define SCE_OPAL_PAR 7
#define SCE_OPAL_BOOL_CONST 8
#define SCE_OPAL_DEFAULT 32
#define SCE_SPICE_DEFAULT 0
#define SCE_SPICE_IDENTIFIER 1
#define SCE_SPICE_KEYWORD 2
#define SCE_SPICE_KEYWORD2 3
#define SCE_SPICE_KEYWORD3 4
#define SCE_SPICE_NUMBER 5
#define SCE_SPICE_DELIMITER 6
#define SCE_SPICE_VALUE 7
#define SCE_SPICE_COMMENTLINE 8
#define SCE_CMAKE_DEFAULT 0
#define SCE_CMAKE_COMMENT 1
#define SCE_CMAKE_STRINGDQ 2
#define SCE_CMAKE_STRINGLQ 3
#define SCE_CMAKE_STRINGRQ 4
#define SCE_CMAKE_COMMANDS 5
#define SCE_CMAKE_PARAMETERS 6
#define SCE_CMAKE_VARIABLE 7
#define SCE_CMAKE_USERDEFINED 8
#define SCE_CMAKE_WHILEDEF 9
#define SCE_CMAKE_FOREACHDEF 10
#define SCE_CMAKE_IFDEFINEDEF 11
#define SCE_CMAKE_MACRODEF 12
#define SCE_CMAKE_STRINGVAR 13
#define SCE_CMAKE_NUMBER 14
#define SCE_GAP_DEFAULT 0
#define SCE_GAP_IDENTIFIER 1
#define SCE_GAP_KEYWORD 2
#define SCE_GAP_KEYWORD2 3
#define SCE_GAP_KEYWORD3 4
#define SCE_GAP_KEYWORD4 5
#define SCE_GAP_STRING 6
#define SCE_GAP_CHAR 7
#define SCE_GAP_OPERATOR 8
#define SCE_GAP_COMMENT 9
#define SCE_GAP_NUMBER 10
#define SCE_GAP_STRINGEOL 11
#define SCE_PLM_DEFAULT 0
#define SCE_PLM_COMMENT 1
#define SCE_PLM_STRING 2
#define SCE_PLM_NUMBER 3
#define SCE_PLM_IDENTIFIER 4
#define SCE_PLM_OPERATOR 5
#define SCE_PLM_CONTROL 6
#define SCE_PLM_KEYWORD 7
#define SCE_4GL_DEFAULT 0
#define SCE_4GL_NUMBER 1
#define SCE_4GL_WORD 2
#define SCE_4GL_STRING 3
#define SCE_4GL_CHARACTER 4
#define SCE_4GL_PREPROCESSOR 5
#define SCE_4GL_OPERATOR 6
#define SCE_4GL_IDENTIFIER 7
#define SCE_4GL_BLOCK 8
#define SCE_4GL_END 9
#define SCE_4GL_COMMENT1 10
#define SCE_4GL_COMMENT2 11
#define SCE_4GL_COMMENT3 12
#define SCE_4GL_COMMENT4 13
#define SCE_4GL_COMMENT5 14
#define SCE_4GL_COMMENT6 15
#define SCE_4GL_DEFAULT_ 16
#define SCE_4GL_NUMBER_ 17
#define SCE_4GL_WORD_ 18
#define SCE_4GL_STRING_ 19
#define SCE_4GL_CHARACTER_ 20
#define SCE_4GL_PREPROCESSOR_ 21
#define SCE_4GL_OPERATOR_ 22
#define SCE_4GL_IDENTIFIER_ 23
#define SCE_4GL_BLOCK_ 24
#define SCE_4GL_END_ 25
#define SCE_4GL_COMMENT1_ 26
#define SCE_4GL_COMMENT2_ 27
#define SCE_4GL_COMMENT3_ 28
#define SCE_4GL_COMMENT4_ 29
#define SCE_4GL_COMMENT5_ 30
#define SCE_4GL_COMMENT6_ 31
#define SCE_ABAQUS_DEFAULT 0
#define SCE_ABAQUS_COMMENT 1
#define SCE_ABAQUS_COMMENTBLOCK 2
#define SCE_ABAQUS_NUMBER 3
#define SCE_ABAQUS_STRING 4
#define SCE_ABAQUS_OPERATOR 5
#define SCE_ABAQUS_WORD 6
#define SCE_ABAQUS_PROCESSOR 7
#define SCE_ABAQUS_COMMAND 8
#define SCE_ABAQUS_SLASHCOMMAND 9
#define SCE_ABAQUS_STARCOMMAND 10
#define SCE_ABAQUS_ARGUMENT 11
#define SCE_ABAQUS_FUNCTION 12
#define SCE_ASY_DEFAULT 0
#define SCE_ASY_COMMENT 1
#define SCE_ASY_COMMENTLINE 2
#define SCE_ASY_NUMBER 3
#define SCE_ASY_WORD 4
#define SCE_ASY_STRING 5
#define SCE_ASY_CHARACTER 6
#define SCE_ASY_OPERATOR 7
#define SCE_ASY_IDENTIFIER 8
#define SCE_ASY_STRINGEOL 9
#define SCE_ASY_COMMENTLINEDOC 10
#define SCE_ASY_WORD2 11
#define SCE_R_DEFAULT 0
#define SCE_R_COMMENT 1
#define SCE_R_KWORD 2
#define SCE_R_BASEKWORD 3
#define SCE_R_OTHERKWORD 4
#define SCE_R_NUMBER 5
#define SCE_R_STRING 6
#define SCE_R_STRING2 7
#define SCE_R_OPERATOR 8
#define SCE_R_IDENTIFIER 9
#define SCE_R_INFIX 10
#define SCE_R_INFIXEOL 11
#define SCE_MAGIK_DEFAULT 0
#define SCE_MAGIK_COMMENT 1
#define SCE_MAGIK_HYPER_COMMENT 16
#define SCE_MAGIK_STRING 2
#define SCE_MAGIK_CHARACTER 3
#define SCE_MAGIK_NUMBER 4
#define SCE_MAGIK_IDENTIFIER 5
#define SCE_MAGIK_OPERATOR 6
#define SCE_MAGIK_FLOW 7
#define SCE_MAGIK_CONTAINER 8
#define SCE_MAGIK_BRACKET_BLOCK 9
#define SCE_MAGIK_BRACE_BLOCK 10
#define SCE_MAGIK_SQBRACKET_BLOCK 11
#define SCE_MAGIK_UNKNOWN_KEYWORD 12
#define SCE_MAGIK_KEYWORD 13
#define SCE_MAGIK_PRAGMA 14
#define SCE_MAGIK_SYMBOL 15
#define SCE_POWERSHELL_DEFAULT 0
#define SCE_POWERSHELL_COMMENT 1
#define SCE_POWERSHELL_STRING 2
#define SCE_POWERSHELL_CHARACTER 3
#define SCE_POWERSHELL_NUMBER 4
#define SCE_POWERSHELL_VARIABLE 5
#define SCE_POWERSHELL_OPERATOR 6
#define SCE_POWERSHELL_IDENTIFIER 7
#define SCE_POWERSHELL_KEYWORD 8
#define SCE_POWERSHELL_CMDLET 9
#define SCE_POWERSHELL_ALIAS 10
#define SCE_POWERSHELL_FUNCTION 11
#define SCE_POWERSHELL_USER1 12
#define SCE_POWERSHELL_COMMENTSTREAM 13
#define SCE_MYSQL_DEFAULT 0
#define SCE_MYSQL_COMMENT 1
#define SCE_MYSQL_COMMENTLINE 2
#define SCE_MYSQL_VARIABLE 3
#define SCE_MYSQL_SYSTEMVARIABLE 4
#define SCE_MYSQL_KNOWNSYSTEMVARIABLE 5
#define SCE_MYSQL_NUMBER 6
#define SCE_MYSQL_MAJORKEYWORD 7
#define SCE_MYSQL_KEYWORD 8
#define SCE_MYSQL_DATABASEOBJECT 9
#define SCE_MYSQL_PROCEDUREKEYWORD 10
#define SCE_MYSQL_STRING 11
#define SCE_MYSQL_SQSTRING 12
#define SCE_MYSQL_DQSTRING 13
#define SCE_MYSQL_OPERATOR 14
#define SCE_MYSQL_FUNCTION 15
#define SCE_MYSQL_IDENTIFIER 16
#define SCE_MYSQL_QUOTEDIDENTIFIER 17
#define SCE_MYSQL_USER1 18
#define SCE_MYSQL_USER2 19
#define SCE_MYSQL_USER3 20
#define SCE_MYSQL_HIDDENCOMMAND 21
#define SCE_MYSQL_PLACEHOLDER 22
#define SCE_PO_DEFAULT 0
#define SCE_PO_COMMENT 1
#define SCE_PO_MSGID 2
#define SCE_PO_MSGID_TEXT 3
#define SCE_PO_MSGSTR 4
#define SCE_PO_MSGSTR_TEXT 5
#define SCE_PO_MSGCTXT 6
#define SCE_PO_MSGCTXT_TEXT 7
#define SCE_PO_FUZZY 8
#define SCE_PO_PROGRAMMER_COMMENT 9
#define SCE_PO_REFERENCE 10
#define SCE_PO_FLAGS 11
#define SCE_PO_MSGID_TEXT_EOL 12
#define SCE_PO_MSGSTR_TEXT_EOL 13
#define SCE_PO_MSGCTXT_TEXT_EOL 14
#define SCE_PO_ERROR 15
#define SCE_PAS_DEFAULT 0
#define SCE_PAS_IDENTIFIER 1
#define SCE_PAS_COMMENT 2
#define SCE_PAS_COMMENT2 3
#define SCE_PAS_COMMENTLINE 4
#define SCE_PAS_PREPROCESSOR 5
#define SCE_PAS_PREPROCESSOR2 6
#define SCE_PAS_NUMBER 7
#define SCE_PAS_HEXNUMBER 8
#define SCE_PAS_WORD 9
#define SCE_PAS_STRING 10
#define SCE_PAS_STRINGEOL 11
#define SCE_PAS_CHARACTER 12
#define SCE_PAS_OPERATOR 13
#define SCE_PAS_ASM 14
#define SCE_SORCUS_DEFAULT 0
#define SCE_SORCUS_COMMAND 1
#define SCE_SORCUS_PARAMETER 2
#define SCE_SORCUS_COMMENTLINE 3
#define SCE_SORCUS_STRING 4
#define SCE_SORCUS_STRINGEOL 5
#define SCE_SORCUS_IDENTIFIER 6
#define SCE_SORCUS_OPERATOR 7
#define SCE_SORCUS_NUMBER 8
#define SCE_SORCUS_CONSTANT 9
#define SCE_POWERPRO_DEFAULT 0
#define SCE_POWERPRO_COMMENTBLOCK 1
#define SCE_POWERPRO_COMMENTLINE 2
#define SCE_POWERPRO_NUMBER 3
#define SCE_POWERPRO_WORD 4
#define SCE_POWERPRO_WORD2 5
#define SCE_POWERPRO_WORD3 6
#define SCE_POWERPRO_WORD4 7
#define SCE_POWERPRO_DOUBLEQUOTEDSTRING 8
#define SCE_POWERPRO_SINGLEQUOTEDSTRING 9
#define SCE_POWERPRO_LINECONTINUE 10
#define SCE_POWERPRO_OPERATOR 11
#define SCE_POWERPRO_IDENTIFIER 12
#define SCE_POWERPRO_STRINGEOL 13
#define SCE_POWERPRO_VERBATIM 14
#define SCE_POWERPRO_ALTQUOTE 15
#define SCE_POWERPRO_FUNCTION 16
#define SCE_SML_DEFAULT 0
#define SCE_SML_IDENTIFIER 1
#define SCE_SML_TAGNAME 2
#define SCE_SML_KEYWORD 3
#define SCE_SML_KEYWORD2 4
#define SCE_SML_KEYWORD3 5
#define SCE_SML_LINENUM 6
#define SCE_SML_OPERATOR 7
#define SCE_SML_NUMBER 8
#define SCE_SML_CHAR 9
#define SCE_SML_STRING 11
#define SCE_SML_COMMENT 12
#define SCE_SML_COMMENT1 13
#define SCE_SML_COMMENT2 14
#define SCE_SML_COMMENT3 15
#define SCE_MARKDOWN_DEFAULT 0
#define SCE_MARKDOWN_LINE_BEGIN 1
#define SCE_MARKDOWN_STRONG1 2
#define SCE_MARKDOWN_STRONG2 3
#define SCE_MARKDOWN_EM1 4
#define SCE_MARKDOWN_EM2 5
#define SCE_MARKDOWN_HEADER1 6
#define SCE_MARKDOWN_HEADER2 7
#define SCE_MARKDOWN_HEADER3 8
#define SCE_MARKDOWN_HEADER4 9
#define SCE_MARKDOWN_HEADER5 10
#define SCE_MARKDOWN_HEADER6 11
#define SCE_MARKDOWN_PRECHAR 12
#define SCE_MARKDOWN_ULIST_ITEM 13
#define SCE_MARKDOWN_OLIST_ITEM 14
#define SCE_MARKDOWN_BLOCKQUOTE 15
#define SCE_MARKDOWN_STRIKEOUT 16
#define SCE_MARKDOWN_HRULE 17
#define SCE_MARKDOWN_LINK 18
#define SCE_MARKDOWN_CODE 19
#define SCE_MARKDOWN_CODE2 20
#define SCE_MARKDOWN_CODEBK 21
#define SCE_TXT2TAGS_DEFAULT 0
#define SCE_TXT2TAGS_LINE_BEGIN 1
#define SCE_TXT2TAGS_STRONG1 2
#define SCE_TXT2TAGS_STRONG2 3
#define SCE_TXT2TAGS_EM1 4
#define SCE_TXT2TAGS_EM2 5
#define SCE_TXT2TAGS_HEADER1 6
#define SCE_TXT2TAGS_HEADER2 7
#define SCE_TXT2TAGS_HEADER3 8
#define SCE_TXT2TAGS_HEADER4 9
#define SCE_TXT2TAGS_HEADER5 10
#define SCE_TXT2TAGS_HEADER6 11
#define SCE_TXT2TAGS_PRECHAR 12
#define SCE_TXT2TAGS_ULIST_ITEM 13
#define SCE_TXT2TAGS_OLIST_ITEM 14
#define SCE_TXT2TAGS_BLOCKQUOTE 15
#define SCE_TXT2TAGS_STRIKEOUT 16
#define SCE_TXT2TAGS_HRULE 17
#define SCE_TXT2TAGS_LINK 18
#define SCE_TXT2TAGS_CODE 19
#define SCE_TXT2TAGS_CODE2 20
#define SCE_TXT2TAGS_CODEBK 21
#define SCE_TXT2TAGS_COMMENT 22
#define SCE_TXT2TAGS_OPTION 23
#define SCE_TXT2TAGS_PREPROC 24
#define SCE_TXT2TAGS_POSTPROC 25
#define SCE_A68K_DEFAULT 0
#define SCE_A68K_COMMENT 1
#define SCE_A68K_NUMBER_DEC 2
#define SCE_A68K_NUMBER_BIN 3
#define SCE_A68K_NUMBER_HEX 4
#define SCE_A68K_STRING1 5
#define SCE_A68K_OPERATOR 6
#define SCE_A68K_CPUINSTRUCTION 7
#define SCE_A68K_EXTINSTRUCTION 8
#define SCE_A68K_REGISTER 9
#define SCE_A68K_DIRECTIVE 10
#define SCE_A68K_MACRO_ARG 11
#define SCE_A68K_LABEL 12
#define SCE_A68K_STRING2 13
#define SCE_A68K_IDENTIFIER 14
#define SCE_A68K_MACRO_DECLARATION 15
#define SCE_A68K_COMMENT_WORD 16
#define SCE_A68K_COMMENT_SPECIAL 17
#define SCE_A68K_COMMENT_DOXYGEN 18
#define SCE_MODULA_DEFAULT 0
#define SCE_MODULA_COMMENT 1
#define SCE_MODULA_DOXYCOMM 2
#define SCE_MODULA_DOXYKEY 3
#define SCE_MODULA_KEYWORD 4
#define SCE_MODULA_RESERVED 5
#define SCE_MODULA_NUMBER 6
#define SCE_MODULA_BASENUM 7
#define SCE_MODULA_FLOAT 8
#define SCE_MODULA_STRING 9
#define SCE_MODULA_STRSPEC 10
#define SCE_MODULA_CHAR 11
#define SCE_MODULA_CHARSPEC 12
#define SCE_MODULA_PROC 13
#define SCE_MODULA_PRAGMA 14
#define SCE_MODULA_PRGKEY 15
#define SCE_MODULA_OPERATOR 16
#define SCE_MODULA_BADSTR 17
#define SCE_COFFEESCRIPT_DEFAULT 0
#define SCE_COFFEESCRIPT_COMMENT 1
#define SCE_COFFEESCRIPT_COMMENTLINE 2
#define SCE_COFFEESCRIPT_COMMENTDOC 3
#define SCE_COFFEESCRIPT_NUMBER 4
#define SCE_COFFEESCRIPT_WORD 5
#define SCE_COFFEESCRIPT_STRING 6
#define SCE_COFFEESCRIPT_CHARACTER 7
#define SCE_COFFEESCRIPT_UUID 8
#define SCE_COFFEESCRIPT_PREPROCESSOR 9
#define SCE_COFFEESCRIPT_OPERATOR 10
#define SCE_COFFEESCRIPT_IDENTIFIER 11
#define SCE_COFFEESCRIPT_STRINGEOL 12
#define SCE_COFFEESCRIPT_VERBATIM 13
#define SCE_COFFEESCRIPT_REGEX 14
#define SCE_COFFEESCRIPT_COMMENTLINEDOC 15
#define SCE_COFFEESCRIPT_WORD2 16
#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORD 17
#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR 18
#define SCE_COFFEESCRIPT_GLOBALCLASS 19
#define SCE_COFFEESCRIPT_STRINGRAW 20
#define SCE_COFFEESCRIPT_TRIPLEVERBATIM 21
#define SCE_COFFEESCRIPT_HASHQUOTEDSTRING 22
#define SCE_COFFEESCRIPT_COMMENTBLOCK 22
#define SCE_COFFEESCRIPT_VERBOSE_REGEX 23
#define SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT 24
#define SCE_AVS_DEFAULT 0
#define SCE_AVS_COMMENTBLOCK 1
#define SCE_AVS_COMMENTBLOCKN 2
#define SCE_AVS_COMMENTLINE 3
#define SCE_AVS_NUMBER 4
#define SCE_AVS_OPERATOR 5
#define SCE_AVS_IDENTIFIER 6
#define SCE_AVS_STRING 7
#define SCE_AVS_TRIPLESTRING 8
#define SCE_AVS_KEYWORD 9
#define SCE_AVS_FILTER 10
#define SCE_AVS_PLUGIN 11
#define SCE_AVS_FUNCTION 12
#define SCE_AVS_CLIPPROP 13
#define SCE_AVS_USERDFN 14
#define SCE_ECL_DEFAULT 0
#define SCE_ECL_COMMENT 1
#define SCE_ECL_COMMENTLINE 2
#define SCE_ECL_NUMBER 3
#define SCE_ECL_STRING 4
#define SCE_ECL_WORD0 5
#define SCE_ECL_OPERATOR 6
#define SCE_ECL_CHARACTER 7
#define SCE_ECL_UUID 8
#define SCE_ECL_PREPROCESSOR 9
#define SCE_ECL_UNKNOWN 10
#define SCE_ECL_IDENTIFIER 11
#define SCE_ECL_STRINGEOL 12
#define SCE_ECL_VERBATIM 13
#define SCE_ECL_REGEX 14
#define SCE_ECL_COMMENTLINEDOC 15
#define SCE_ECL_WORD1 16
#define SCE_ECL_COMMENTDOCKEYWORD 17
#define SCE_ECL_COMMENTDOCKEYWORDERROR 18
#define SCE_ECL_WORD2 19
#define SCE_ECL_WORD3 20
#define SCE_ECL_WORD4 21
#define SCE_ECL_WORD5 22
#define SCE_ECL_COMMENTDOC 23
#define SCE_ECL_ADDED 24
#define SCE_ECL_DELETED 25
#define SCE_ECL_CHANGED 26
#define SCE_ECL_MOVED 27
#define SCE_OSCRIPT_DEFAULT 0
#define SCE_OSCRIPT_LINE_COMMENT 1
#define SCE_OSCRIPT_BLOCK_COMMENT 2
#define SCE_OSCRIPT_DOC_COMMENT 3
#define SCE_OSCRIPT_PREPROCESSOR 4
#define SCE_OSCRIPT_NUMBER 5
#define SCE_OSCRIPT_SINGLEQUOTE_STRING 6
#define SCE_OSCRIPT_DOUBLEQUOTE_STRING 7
#define SCE_OSCRIPT_CONSTANT 8
#define SCE_OSCRIPT_IDENTIFIER 9
#define SCE_OSCRIPT_GLOBAL 10
#define SCE_OSCRIPT_KEYWORD 11
#define SCE_OSCRIPT_OPERATOR 12
#define SCE_OSCRIPT_LABEL 13
#define SCE_OSCRIPT_TYPE 14
#define SCE_OSCRIPT_FUNCTION 15
#define SCE_OSCRIPT_OBJECT 16
#define SCE_OSCRIPT_PROPERTY 17
#define SCE_OSCRIPT_METHOD 18
#define SCE_VISUALPROLOG_DEFAULT 0
#define SCE_VISUALPROLOG_KEY_MAJOR 1
#define SCE_VISUALPROLOG_KEY_MINOR 2
#define SCE_VISUALPROLOG_KEY_DIRECTIVE 3
#define SCE_VISUALPROLOG_COMMENT_BLOCK 4
#define SCE_VISUALPROLOG_COMMENT_LINE 5
#define SCE_VISUALPROLOG_COMMENT_KEY 6
#define SCE_VISUALPROLOG_COMMENT_KEY_ERROR 7
#define SCE_VISUALPROLOG_IDENTIFIER 8
#define SCE_VISUALPROLOG_VARIABLE 9
#define SCE_VISUALPROLOG_ANONYMOUS 10
#define SCE_VISUALPROLOG_NUMBER 11
#define SCE_VISUALPROLOG_OPERATOR 12
#define SCE_VISUALPROLOG_CHARACTER 13
#define SCE_VISUALPROLOG_CHARACTER_TOO_MANY 14
#define SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR 15
#define SCE_VISUALPROLOG_STRING 16
#define SCE_VISUALPROLOG_STRING_ESCAPE 17
#define SCE_VISUALPROLOG_STRING_ESCAPE_ERROR 18
#define SCE_VISUALPROLOG_STRING_EOL_OPEN 19
#define SCE_VISUALPROLOG_STRING_VERBATIM 20
#define SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL 21
#define SCE_VISUALPROLOG_STRING_VERBATIM_EOL 22
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */

#endif

Added include/Scintilla.h.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
/* Scintilla source code edit control */
/** @file Scintilla.h
 ** Interface to the edit control.
 **/
/* Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed. */

/* Most of this file is automatically generated from the Scintilla.iface interface definition
 * file which contains any comments about the definitions. HFacer.py does the generation. */

#ifndef SCINTILLA_H
#define SCINTILLA_H

#ifdef __cplusplus
extern "C" {
#endif

#if defined(_WIN32)
/* Return false on failure: */
int Scintilla_RegisterClasses(void *hInstance);
int Scintilla_ReleaseResources();
#endif
int Scintilla_LinkLexers();

#ifdef __cplusplus
}
#endif

/* Here should be placed typedefs for uptr_t, an unsigned integer type large enough to
 * hold a pointer and sptr_t, a signed integer large enough to hold a pointer.
 * May need to be changed for 64 bit platforms. */
#if defined(_WIN32)
#include <basetsd.h>
#endif
#ifdef MAXULONG_PTR
typedef ULONG_PTR uptr_t;
typedef LONG_PTR sptr_t;
#else
typedef unsigned long uptr_t;
typedef long sptr_t;
#endif

typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam);

/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
#define INVALID_POSITION -1
#define SCI_START 2000
#define SCI_OPTIONAL_START 3000
#define SCI_LEXER_START 4000
#define SCI_ADDTEXT 2001
#define SCI_ADDSTYLEDTEXT 2002
#define SCI_INSERTTEXT 2003
#define SCI_CLEARALL 2004
#define SCI_DELETERANGE 2645
#define SCI_CLEARDOCUMENTSTYLE 2005
#define SCI_GETLENGTH 2006
#define SCI_GETCHARAT 2007
#define SCI_GETCURRENTPOS 2008
#define SCI_GETANCHOR 2009
#define SCI_GETSTYLEAT 2010
#define SCI_REDO 2011
#define SCI_SETUNDOCOLLECTION 2012
#define SCI_SELECTALL 2013
#define SCI_SETSAVEPOINT 2014
#define SCI_GETSTYLEDTEXT 2015
#define SCI_CANREDO 2016
#define SCI_MARKERLINEFROMHANDLE 2017
#define SCI_MARKERDELETEHANDLE 2018
#define SCI_GETUNDOCOLLECTION 2019
#define SCWS_INVISIBLE 0
#define SCWS_VISIBLEALWAYS 1
#define SCWS_VISIBLEAFTERINDENT 2
#define SCI_GETVIEWWS 2020
#define SCI_SETVIEWWS 2021
#define SCI_POSITIONFROMPOINT 2022
#define SCI_POSITIONFROMPOINTCLOSE 2023
#define SCI_GOTOLINE 2024
#define SCI_GOTOPOS 2025
#define SCI_SETANCHOR 2026
#define SCI_GETCURLINE 2027
#define SCI_GETENDSTYLED 2028
#define SC_EOL_CRLF 0
#define SC_EOL_CR 1
#define SC_EOL_LF 2
#define SCI_CONVERTEOLS 2029
#define SCI_GETEOLMODE 2030
#define SCI_SETEOLMODE 2031
#define SCI_STARTSTYLING 2032
#define SCI_SETSTYLING 2033
#define SCI_GETBUFFEREDDRAW 2034
#define SCI_SETBUFFEREDDRAW 2035
#define SCI_SETTABWIDTH 2036
#define SCI_GETTABWIDTH 2121
#define SC_CP_UTF8 65001
#define SCI_SETCODEPAGE 2037
#define MARKER_MAX 31
#define SC_MARK_CIRCLE 0
#define SC_MARK_ROUNDRECT 1
#define SC_MARK_ARROW 2
#define SC_MARK_SMALLRECT 3
#define SC_MARK_SHORTARROW 4
#define SC_MARK_EMPTY 5
#define SC_MARK_ARROWDOWN 6
#define SC_MARK_MINUS 7
#define SC_MARK_PLUS 8
#define SC_MARK_VLINE 9
#define SC_MARK_LCORNER 10
#define SC_MARK_TCORNER 11
#define SC_MARK_BOXPLUS 12
#define SC_MARK_BOXPLUSCONNECTED 13
#define SC_MARK_BOXMINUS 14
#define SC_MARK_BOXMINUSCONNECTED 15
#define SC_MARK_LCORNERCURVE 16
#define SC_MARK_TCORNERCURVE 17
#define SC_MARK_CIRCLEPLUS 18
#define SC_MARK_CIRCLEPLUSCONNECTED 19
#define SC_MARK_CIRCLEMINUS 20
#define SC_MARK_CIRCLEMINUSCONNECTED 21
#define SC_MARK_BACKGROUND 22
#define SC_MARK_DOTDOTDOT 23
#define SC_MARK_ARROWS 24
#define SC_MARK_PIXMAP 25
#define SC_MARK_FULLRECT 26
#define SC_MARK_LEFTRECT 27
#define SC_MARK_AVAILABLE 28
#define SC_MARK_UNDERLINE 29
#define SC_MARK_RGBAIMAGE 30
#define SC_MARK_CHARACTER 10000
#define SC_MARKNUM_FOLDEREND 25
#define SC_MARKNUM_FOLDEROPENMID 26
#define SC_MARKNUM_FOLDERMIDTAIL 27
#define SC_MARKNUM_FOLDERTAIL 28
#define SC_MARKNUM_FOLDERSUB 29
#define SC_MARKNUM_FOLDER 30
#define SC_MARKNUM_FOLDEROPEN 31
#define SC_MASK_FOLDERS 0xFE000000
#define SCI_MARKERDEFINE 2040
#define SCI_MARKERSETFORE 2041
#define SCI_MARKERSETBACK 2042
#define SCI_MARKERSETBACKSELECTED 2292
#define SCI_MARKERENABLEHIGHLIGHT 2293
#define SCI_MARKERADD 2043
#define SCI_MARKERDELETE 2044
#define SCI_MARKERDELETEALL 2045
#define SCI_MARKERGET 2046
#define SCI_MARKERNEXT 2047
#define SCI_MARKERPREVIOUS 2048
#define SCI_MARKERDEFINEPIXMAP 2049
#define SCI_MARKERADDSET 2466
#define SCI_MARKERSETALPHA 2476
#define SC_MAX_MARGIN 4
#define SC_MARGIN_SYMBOL 0
#define SC_MARGIN_NUMBER 1
#define SC_MARGIN_BACK 2
#define SC_MARGIN_FORE 3
#define SC_MARGIN_TEXT 4
#define SC_MARGIN_RTEXT 5
#define SCI_SETMARGINTYPEN 2240
#define SCI_GETMARGINTYPEN 2241
#define SCI_SETMARGINWIDTHN 2242
#define SCI_GETMARGINWIDTHN 2243
#define SCI_SETMARGINMASKN 2244
#define SCI_GETMARGINMASKN 2245
#define SCI_SETMARGINSENSITIVEN 2246
#define SCI_GETMARGINSENSITIVEN 2247
#define SCI_SETMARGINCURSORN 2248
#define SCI_GETMARGINCURSORN 2249
#define STYLE_DEFAULT 32
#define STYLE_LINENUMBER 33
#define STYLE_BRACELIGHT 34
#define STYLE_BRACEBAD 35
#define STYLE_CONTROLCHAR 36
#define STYLE_INDENTGUIDE 37
#define STYLE_CALLTIP 38
#define STYLE_LASTPREDEFINED 39
#define STYLE_MAX 255
#define SC_CHARSET_ANSI 0
#define SC_CHARSET_DEFAULT 1
#define SC_CHARSET_BALTIC 186
#define SC_CHARSET_CHINESEBIG5 136
#define SC_CHARSET_EASTEUROPE 238
#define SC_CHARSET_GB2312 134
#define SC_CHARSET_GREEK 161
#define SC_CHARSET_HANGUL 129
#define SC_CHARSET_MAC 77
#define SC_CHARSET_OEM 255
#define SC_CHARSET_RUSSIAN 204
#define SC_CHARSET_CYRILLIC 1251
#define SC_CHARSET_SHIFTJIS 128
#define SC_CHARSET_SYMBOL 2
#define SC_CHARSET_TURKISH 162
#define SC_CHARSET_JOHAB 130
#define SC_CHARSET_HEBREW 177
#define SC_CHARSET_ARABIC 178
#define SC_CHARSET_VIETNAMESE 163
#define SC_CHARSET_THAI 222
#define SC_CHARSET_8859_15 1000
#define SCI_STYLECLEARALL 2050
#define SCI_STYLESETFORE 2051
#define SCI_STYLESETBACK 2052
#define SCI_STYLESETBOLD 2053
#define SCI_STYLESETITALIC 2054
#define SCI_STYLESETSIZE 2055
#define SCI_STYLESETFONT 2056
#define SCI_STYLESETEOLFILLED 2057
#define SCI_STYLERESETDEFAULT 2058
#define SCI_STYLESETUNDERLINE 2059
#define SC_CASE_MIXED 0
#define SC_CASE_UPPER 1
#define SC_CASE_LOWER 2
#define SCI_STYLEGETFORE 2481
#define SCI_STYLEGETBACK 2482
#define SCI_STYLEGETBOLD 2483
#define SCI_STYLEGETITALIC 2484
#define SCI_STYLEGETSIZE 2485
#define SCI_STYLEGETFONT 2486
#define SCI_STYLEGETEOLFILLED 2487
#define SCI_STYLEGETUNDERLINE 2488
#define SCI_STYLEGETCASE 2489
#define SCI_STYLEGETCHARACTERSET 2490
#define SCI_STYLEGETVISIBLE 2491
#define SCI_STYLEGETCHANGEABLE 2492
#define SCI_STYLEGETHOTSPOT 2493
#define SCI_STYLESETCASE 2060
#define SC_FONT_SIZE_MULTIPLIER 100
#define SCI_STYLESETSIZEFRACTIONAL 2061
#define SCI_STYLEGETSIZEFRACTIONAL 2062
#define SC_WEIGHT_NORMAL 400
#define SC_WEIGHT_SEMIBOLD 600
#define SC_WEIGHT_BOLD 700
#define SCI_STYLESETWEIGHT 2063
#define SCI_STYLEGETWEIGHT 2064
#define SCI_STYLESETCHARACTERSET 2066
#define SCI_STYLESETHOTSPOT 2409
#define SCI_SETSELFORE 2067
#define SCI_SETSELBACK 2068
#define SCI_GETSELALPHA 2477
#define SCI_SETSELALPHA 2478
#define SCI_GETSELEOLFILLED 2479
#define SCI_SETSELEOLFILLED 2480
#define SCI_SETCARETFORE 2069
#define SCI_ASSIGNCMDKEY 2070
#define SCI_CLEARCMDKEY 2071
#define SCI_CLEARALLCMDKEYS 2072
#define SCI_SETSTYLINGEX 2073
#define SCI_STYLESETVISIBLE 2074
#define SCI_GETCARETPERIOD 2075
#define SCI_SETCARETPERIOD 2076
#define SCI_SETWORDCHARS 2077
#define SCI_GETWORDCHARS 2646
#define SCI_BEGINUNDOACTION 2078
#define SCI_ENDUNDOACTION 2079
#define INDIC_PLAIN 0
#define INDIC_SQUIGGLE 1
#define INDIC_TT 2
#define INDIC_DIAGONAL 3
#define INDIC_STRIKE 4
#define INDIC_HIDDEN 5
#define INDIC_BOX 6
#define INDIC_ROUNDBOX 7
#define INDIC_STRAIGHTBOX 8
#define INDIC_DASH 9
#define INDIC_DOTS 10
#define INDIC_SQUIGGLELOW 11
#define INDIC_DOTBOX 12
#define INDIC_SQUIGGLEPIXMAP 13
#define INDIC_MAX 31
#define INDIC_CONTAINER 8
#define INDIC0_MASK 0x20
#define INDIC1_MASK 0x40
#define INDIC2_MASK 0x80
#define INDICS_MASK 0xE0
#define SCI_INDICSETSTYLE 2080
#define SCI_INDICGETSTYLE 2081
#define SCI_INDICSETFORE 2082
#define SCI_INDICGETFORE 2083
#define SCI_INDICSETUNDER 2510
#define SCI_INDICGETUNDER 2511
#define SCI_SETWHITESPACEFORE 2084
#define SCI_SETWHITESPACEBACK 2085
#define SCI_SETWHITESPACESIZE 2086
#define SCI_GETWHITESPACESIZE 2087
#define SCI_SETSTYLEBITS 2090
#define SCI_GETSTYLEBITS 2091
#define SCI_SETLINESTATE 2092
#define SCI_GETLINESTATE 2093
#define SCI_GETMAXLINESTATE 2094
#define SCI_GETCARETLINEVISIBLE 2095
#define SCI_SETCARETLINEVISIBLE 2096
#define SCI_GETCARETLINEBACK 2097
#define SCI_SETCARETLINEBACK 2098
#define SCI_STYLESETCHANGEABLE 2099
#define SCI_AUTOCSHOW 2100
#define SCI_AUTOCCANCEL 2101
#define SCI_AUTOCACTIVE 2102
#define SCI_AUTOCPOSSTART 2103
#define SCI_AUTOCCOMPLETE 2104
#define SCI_AUTOCSTOPS 2105
#define SCI_AUTOCSETSEPARATOR 2106
#define SCI_AUTOCGETSEPARATOR 2107
#define SCI_AUTOCSELECT 2108
#define SCI_AUTOCSETCANCELATSTART 2110
#define SCI_AUTOCGETCANCELATSTART 2111
#define SCI_AUTOCSETFILLUPS 2112
#define SCI_AUTOCSETCHOOSESINGLE 2113
#define SCI_AUTOCGETCHOOSESINGLE 2114
#define SCI_AUTOCSETIGNORECASE 2115
#define SCI_AUTOCGETIGNORECASE 2116
#define SCI_USERLISTSHOW 2117
#define SCI_AUTOCSETAUTOHIDE 2118
#define SCI_AUTOCGETAUTOHIDE 2119
#define SCI_AUTOCSETDROPRESTOFWORD 2270
#define SCI_AUTOCGETDROPRESTOFWORD 2271
#define SCI_REGISTERIMAGE 2405
#define SCI_CLEARREGISTEREDIMAGES 2408
#define SCI_AUTOCGETTYPESEPARATOR 2285
#define SCI_AUTOCSETTYPESEPARATOR 2286
#define SCI_AUTOCSETMAXWIDTH 2208
#define SCI_AUTOCGETMAXWIDTH 2209
#define SCI_AUTOCSETMAXHEIGHT 2210
#define SCI_AUTOCGETMAXHEIGHT 2211
#define SCI_SETINDENT 2122
#define SCI_GETINDENT 2123
#define SCI_SETUSETABS 2124
#define SCI_GETUSETABS 2125
#define SCI_SETLINEINDENTATION 2126
#define SCI_GETLINEINDENTATION 2127
#define SCI_GETLINEINDENTPOSITION 2128
#define SCI_GETCOLUMN 2129
#define SCI_COUNTCHARACTERS 2633
#define SCI_SETHSCROLLBAR 2130
#define SCI_GETHSCROLLBAR 2131
#define SC_IV_NONE 0
#define SC_IV_REAL 1
#define SC_IV_LOOKFORWARD 2
#define SC_IV_LOOKBOTH 3
#define SCI_SETINDENTATIONGUIDES 2132
#define SCI_GETINDENTATIONGUIDES 2133
#define SCI_SETHIGHLIGHTGUIDE 2134
#define SCI_GETHIGHLIGHTGUIDE 2135
#define SCI_GETLINEENDPOSITION 2136
#define SCI_GETCODEPAGE 2137
#define SCI_GETCARETFORE 2138
#define SCI_GETREADONLY 2140
#define SCI_SETCURRENTPOS 2141
#define SCI_SETSELECTIONSTART 2142
#define SCI_GETSELECTIONSTART 2143
#define SCI_SETSELECTIONEND 2144
#define SCI_GETSELECTIONEND 2145
#define SCI_SETEMPTYSELECTION 2556
#define SCI_SETPRINTMAGNIFICATION 2146
#define SCI_GETPRINTMAGNIFICATION 2147
#define SC_PRINT_NORMAL 0
#define SC_PRINT_INVERTLIGHT 1
#define SC_PRINT_BLACKONWHITE 2
#define SC_PRINT_COLOURONWHITE 3
#define SC_PRINT_COLOURONWHITEDEFAULTBG 4
#define SCI_SETPRINTCOLOURMODE 2148
#define SCI_GETPRINTCOLOURMODE 2149
#define SCFIND_WHOLEWORD 2
#define SCFIND_MATCHCASE 4
#define SCFIND_WORDSTART 0x00100000
#define SCFIND_REGEXP 0x00200000
#define SCFIND_POSIX 0x00400000
#define SCI_FINDTEXT 2150
#define SCI_FORMATRANGE 2151
#define SCI_GETFIRSTVISIBLELINE 2152
#define SCI_GETLINE 2153
#define SCI_GETLINECOUNT 2154
#define SCI_SETMARGINLEFT 2155
#define SCI_GETMARGINLEFT 2156
#define SCI_SETMARGINRIGHT 2157
#define SCI_GETMARGINRIGHT 2158
#define SCI_GETMODIFY 2159
#define SCI_SETSEL 2160
#define SCI_GETSELTEXT 2161
#define SCI_GETTEXTRANGE 2162
#define SCI_HIDESELECTION 2163
#define SCI_POINTXFROMPOSITION 2164
#define SCI_POINTYFROMPOSITION 2165
#define SCI_LINEFROMPOSITION 2166
#define SCI_POSITIONFROMLINE 2167
#define SCI_LINESCROLL 2168
#define SCI_SCROLLCARET 2169
#define SCI_SCROLLRANGE 2569
#define SCI_REPLACESEL 2170
#define SCI_SETREADONLY 2171
#define SCI_NULL 2172
#define SCI_CANPASTE 2173
#define SCI_CANUNDO 2174
#define SCI_EMPTYUNDOBUFFER 2175
#define SCI_UNDO 2176
#define SCI_CUT 2177
#define SCI_COPY 2178
#define SCI_PASTE 2179
#define SCI_CLEAR 2180
#define SCI_SETTEXT 2181
#define SCI_GETTEXT 2182
#define SCI_GETTEXTLENGTH 2183
#define SCI_GETDIRECTFUNCTION 2184
#define SCI_GETDIRECTPOINTER 2185
#define SCI_SETOVERTYPE 2186
#define SCI_GETOVERTYPE 2187
#define SCI_SETCARETWIDTH 2188
#define SCI_GETCARETWIDTH 2189
#define SCI_SETTARGETSTART 2190
#define SCI_GETTARGETSTART 2191
#define SCI_SETTARGETEND 2192
#define SCI_GETTARGETEND 2193
#define SCI_REPLACETARGET 2194
#define SCI_REPLACETARGETRE 2195
#define SCI_SEARCHINTARGET 2197
#define SCI_SETSEARCHFLAGS 2198
#define SCI_GETSEARCHFLAGS 2199
#define SCI_CALLTIPSHOW 2200
#define SCI_CALLTIPCANCEL 2201
#define SCI_CALLTIPACTIVE 2202
#define SCI_CALLTIPPOSSTART 2203
#define SCI_CALLTIPSETHLT 2204
#define SCI_CALLTIPSETBACK 2205
#define SCI_CALLTIPSETFORE 2206
#define SCI_CALLTIPSETFOREHLT 2207
#define SCI_CALLTIPUSESTYLE 2212
#define SCI_CALLTIPSETPOSITION 2213
#define SCI_VISIBLEFROMDOCLINE 2220
#define SCI_DOCLINEFROMVISIBLE 2221
#define SCI_WRAPCOUNT 2235
#define SC_FOLDLEVELBASE 0x400
#define SC_FOLDLEVELWHITEFLAG 0x1000
#define SC_FOLDLEVELHEADERFLAG 0x2000
#define SC_FOLDLEVELNUMBERMASK 0x0FFF
#define SCI_SETFOLDLEVEL 2222
#define SCI_GETFOLDLEVEL 2223
#define SCI_GETLASTCHILD 2224
#define SCI_GETFOLDPARENT 2225
#define SCI_SHOWLINES 2226
#define SCI_HIDELINES 2227
#define SCI_GETLINEVISIBLE 2228
#define SCI_GETALLLINESVISIBLE 2236
#define SCI_SETFOLDEXPANDED 2229
#define SCI_GETFOLDEXPANDED 2230
#define SCI_TOGGLEFOLD 2231
#define SCI_ENSUREVISIBLE 2232
#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008
#define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010
#define SC_FOLDFLAG_LEVELNUMBERS 0x0040
#define SCI_SETFOLDFLAGS 2233
#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234
#define SCI_SETTABINDENTS 2260
#define SCI_GETTABINDENTS 2261
#define SCI_SETBACKSPACEUNINDENTS 2262
#define SCI_GETBACKSPACEUNINDENTS 2263
#define SC_TIME_FOREVER 10000000
#define SCI_SETMOUSEDWELLTIME 2264
#define SCI_GETMOUSEDWELLTIME 2265
#define SCI_WORDSTARTPOSITION 2266
#define SCI_WORDENDPOSITION 2267
#define SC_WRAP_NONE 0
#define SC_WRAP_WORD 1
#define SC_WRAP_CHAR 2
#define SCI_SETWRAPMODE 2268
#define SCI_GETWRAPMODE 2269
#define SC_WRAPVISUALFLAG_NONE 0x0000
#define SC_WRAPVISUALFLAG_END 0x0001
#define SC_WRAPVISUALFLAG_START 0x0002
#define SC_WRAPVISUALFLAG_MARGIN 0x0004
#define SCI_SETWRAPVISUALFLAGS 2460
#define SCI_GETWRAPVISUALFLAGS 2461
#define SC_WRAPVISUALFLAGLOC_DEFAULT 0x0000
#define SC_WRAPVISUALFLAGLOC_END_BY_TEXT 0x0001
#define SC_WRAPVISUALFLAGLOC_START_BY_TEXT 0x0002
#define SCI_SETWRAPVISUALFLAGSLOCATION 2462
#define SCI_GETWRAPVISUALFLAGSLOCATION 2463
#define SCI_SETWRAPSTARTINDENT 2464
#define SCI_GETWRAPSTARTINDENT 2465
#define SC_WRAPINDENT_FIXED 0
#define SC_WRAPINDENT_SAME 1
#define SC_WRAPINDENT_INDENT 2
#define SCI_SETWRAPINDENTMODE 2472
#define SCI_GETWRAPINDENTMODE 2473
#define SC_CACHE_NONE 0
#define SC_CACHE_CARET 1
#define SC_CACHE_PAGE 2
#define SC_CACHE_DOCUMENT 3
#define SCI_SETLAYOUTCACHE 2272
#define SCI_GETLAYOUTCACHE 2273
#define SCI_SETSCROLLWIDTH 2274
#define SCI_GETSCROLLWIDTH 2275
#define SCI_SETSCROLLWIDTHTRACKING 2516
#define SCI_GETSCROLLWIDTHTRACKING 2517
#define SCI_TEXTWIDTH 2276
#define SCI_SETENDATLASTLINE 2277
#define SCI_GETENDATLASTLINE 2278
#define SCI_TEXTHEIGHT 2279
#define SCI_SETVSCROLLBAR 2280
#define SCI_GETVSCROLLBAR 2281
#define SCI_APPENDTEXT 2282
#define SCI_GETTWOPHASEDRAW 2283
#define SCI_SETTWOPHASEDRAW 2284
#define SC_EFF_QUALITY_MASK 0xF
#define SC_EFF_QUALITY_DEFAULT 0
#define SC_EFF_QUALITY_NON_ANTIALIASED 1
#define SC_EFF_QUALITY_ANTIALIASED 2
#define SC_EFF_QUALITY_LCD_OPTIMIZED 3
#define SCI_SETFONTQUALITY 2611
#define SCI_GETFONTQUALITY 2612
#define SCI_SETFIRSTVISIBLELINE 2613
#define SC_MULTIPASTE_ONCE 0
#define SC_MULTIPASTE_EACH 1
#define SCI_SETMULTIPASTE 2614
#define SCI_GETMULTIPASTE 2615
#define SCI_GETTAG 2616
#define SCI_TARGETFROMSELECTION 2287
#define SCI_LINESJOIN 2288
#define SCI_LINESSPLIT 2289
#define SCI_SETFOLDMARGINCOLOUR 2290
#define SCI_SETFOLDMARGINHICOLOUR 2291
#define SCI_LINEDOWN 2300
#define SCI_LINEDOWNEXTEND 2301
#define SCI_LINEUP 2302
#define SCI_LINEUPEXTEND 2303
#define SCI_CHARLEFT 2304
#define SCI_CHARLEFTEXTEND 2305
#define SCI_CHARRIGHT 2306
#define SCI_CHARRIGHTEXTEND 2307
#define SCI_WORDLEFT 2308
#define SCI_WORDLEFTEXTEND 2309
#define SCI_WORDRIGHT 2310
#define SCI_WORDRIGHTEXTEND 2311
#define SCI_HOME 2312
#define SCI_HOMEEXTEND 2313
#define SCI_LINEEND 2314
#define SCI_LINEENDEXTEND 2315
#define SCI_DOCUMENTSTART 2316
#define SCI_DOCUMENTSTARTEXTEND 2317
#define SCI_DOCUMENTEND 2318
#define SCI_DOCUMENTENDEXTEND 2319
#define SCI_PAGEUP 2320
#define SCI_PAGEUPEXTEND 2321
#define SCI_PAGEDOWN 2322
#define SCI_PAGEDOWNEXTEND 2323
#define SCI_EDITTOGGLEOVERTYPE 2324
#define SCI_CANCEL 2325
#define SCI_DELETEBACK 2326
#define SCI_TAB 2327
#define SCI_BACKTAB 2328
#define SCI_NEWLINE 2329
#define SCI_FORMFEED 2330
#define SCI_VCHOME 2331
#define SCI_VCHOMEEXTEND 2332
#define SCI_ZOOMIN 2333
#define SCI_ZOOMOUT 2334
#define SCI_DELWORDLEFT 2335
#define SCI_DELWORDRIGHT 2336
#define SCI_DELWORDRIGHTEND 2518
#define SCI_LINECUT 2337
#define SCI_LINEDELETE 2338
#define SCI_LINETRANSPOSE 2339
#define SCI_LINEDUPLICATE 2404
#define SCI_LOWERCASE 2340
#define SCI_UPPERCASE 2341
#define SCI_LINESCROLLDOWN 2342
#define SCI_LINESCROLLUP 2343
#define SCI_DELETEBACKNOTLINE 2344
#define SCI_HOMEDISPLAY 2345
#define SCI_HOMEDISPLAYEXTEND 2346
#define SCI_LINEENDDISPLAY 2347
#define SCI_LINEENDDISPLAYEXTEND 2348
#define SCI_HOMEWRAP 2349
#define SCI_HOMEWRAPEXTEND 2450
#define SCI_LINEENDWRAP 2451
#define SCI_LINEENDWRAPEXTEND 2452
#define SCI_VCHOMEWRAP 2453
#define SCI_VCHOMEWRAPEXTEND 2454
#define SCI_LINECOPY 2455
#define SCI_MOVECARETINSIDEVIEW 2401
#define SCI_LINELENGTH 2350
#define SCI_BRACEHIGHLIGHT 2351
#define SCI_BRACEHIGHLIGHTINDICATOR 2498
#define SCI_BRACEBADLIGHT 2352
#define SCI_BRACEBADLIGHTINDICATOR 2499
#define SCI_BRACEMATCH 2353
#define SCI_GETVIEWEOL 2355
#define SCI_SETVIEWEOL 2356
#define SCI_GETDOCPOINTER 2357
#define SCI_SETDOCPOINTER 2358
#define SCI_SETMODEVENTMASK 2359
#define EDGE_NONE 0
#define EDGE_LINE 1
#define EDGE_BACKGROUND 2
#define SCI_GETEDGECOLUMN 2360
#define SCI_SETEDGECOLUMN 2361
#define SCI_GETEDGEMODE 2362
#define SCI_SETEDGEMODE 2363
#define SCI_GETEDGECOLOUR 2364
#define SCI_SETEDGECOLOUR 2365
#define SCI_SEARCHANCHOR 2366
#define SCI_SEARCHNEXT 2367
#define SCI_SEARCHPREV 2368
#define SCI_LINESONSCREEN 2370
#define SCI_USEPOPUP 2371
#define SCI_SELECTIONISRECTANGLE 2372
#define SCI_SETZOOM 2373
#define SCI_GETZOOM 2374
#define SCI_CREATEDOCUMENT 2375
#define SCI_ADDREFDOCUMENT 2376
#define SCI_RELEASEDOCUMENT 2377
#define SCI_GETMODEVENTMASK 2378
#define SCI_SETFOCUS 2380
#define SCI_GETFOCUS 2381
#define SC_STATUS_OK 0
#define SC_STATUS_FAILURE 1
#define SC_STATUS_BADALLOC 2
#define SCI_SETSTATUS 2382
#define SCI_GETSTATUS 2383
#define SCI_SETMOUSEDOWNCAPTURES 2384
#define SCI_GETMOUSEDOWNCAPTURES 2385
#define SC_CURSORNORMAL -1
#define SC_CURSORARROW 2
#define SC_CURSORWAIT 4
#define SC_CURSORREVERSEARROW 7
#define SCI_SETCURSOR 2386
#define SCI_GETCURSOR 2387
#define SCI_SETCONTROLCHARSYMBOL 2388
#define SCI_GETCONTROLCHARSYMBOL 2389
#define SCI_WORDPARTLEFT 2390
#define SCI_WORDPARTLEFTEXTEND 2391
#define SCI_WORDPARTRIGHT 2392
#define SCI_WORDPARTRIGHTEXTEND 2393
#define VISIBLE_SLOP 0x01
#define VISIBLE_STRICT 0x04
#define SCI_SETVISIBLEPOLICY 2394
#define SCI_DELLINELEFT 2395
#define SCI_DELLINERIGHT 2396
#define SCI_SETXOFFSET 2397
#define SCI_GETXOFFSET 2398
#define SCI_CHOOSECARETX 2399
#define SCI_GRABFOCUS 2400
#define CARET_SLOP 0x01
#define CARET_STRICT 0x04
#define CARET_JUMPS 0x10
#define CARET_EVEN 0x08
#define SCI_SETXCARETPOLICY 2402
#define SCI_SETYCARETPOLICY 2403
#define SCI_SETPRINTWRAPMODE 2406
#define SCI_GETPRINTWRAPMODE 2407
#define SCI_SETHOTSPOTACTIVEFORE 2410
#define SCI_GETHOTSPOTACTIVEFORE 2494
#define SCI_SETHOTSPOTACTIVEBACK 2411
#define SCI_GETHOTSPOTACTIVEBACK 2495
#define SCI_SETHOTSPOTACTIVEUNDERLINE 2412
#define SCI_GETHOTSPOTACTIVEUNDERLINE 2496
#define SCI_SETHOTSPOTSINGLELINE 2421
#define SCI_GETHOTSPOTSINGLELINE 2497
#define SCI_PARADOWN 2413
#define SCI_PARADOWNEXTEND 2414
#define SCI_PARAUP 2415
#define SCI_PARAUPEXTEND 2416
#define SCI_POSITIONBEFORE 2417
#define SCI_POSITIONAFTER 2418
#define SCI_COPYRANGE 2419
#define SCI_COPYTEXT 2420
#define SC_SEL_STREAM 0
#define SC_SEL_RECTANGLE 1
#define SC_SEL_LINES 2
#define SC_SEL_THIN 3
#define SCI_SETSELECTIONMODE 2422
#define SCI_GETSELECTIONMODE 2423
#define SCI_GETLINESELSTARTPOSITION 2424
#define SCI_GETLINESELENDPOSITION 2425
#define SCI_LINEDOWNRECTEXTEND 2426
#define SCI_LINEUPRECTEXTEND 2427
#define SCI_CHARLEFTRECTEXTEND 2428
#define SCI_CHARRIGHTRECTEXTEND 2429
#define SCI_HOMERECTEXTEND 2430
#define SCI_VCHOMERECTEXTEND 2431
#define SCI_LINEENDRECTEXTEND 2432
#define SCI_PAGEUPRECTEXTEND 2433
#define SCI_PAGEDOWNRECTEXTEND 2434
#define SCI_STUTTEREDPAGEUP 2435
#define SCI_STUTTEREDPAGEUPEXTEND 2436
#define SCI_STUTTEREDPAGEDOWN 2437
#define SCI_STUTTEREDPAGEDOWNEXTEND 2438
#define SCI_WORDLEFTEND 2439
#define SCI_WORDLEFTENDEXTEND 2440
#define SCI_WORDRIGHTEND 2441
#define SCI_WORDRIGHTENDEXTEND 2442
#define SCI_SETWHITESPACECHARS 2443
#define SCI_GETWHITESPACECHARS 2647
#define SCI_SETPUNCTUATIONCHARS 2648
#define SCI_GETPUNCTUATIONCHARS 2649
#define SCI_SETCHARSDEFAULT 2444
#define SCI_AUTOCGETCURRENT 2445
#define SCI_AUTOCGETCURRENTTEXT 2610
#define SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE 0
#define SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1
#define SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR 2634
#define SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR 2635
#define SCI_ALLOCATE 2446
#define SCI_TARGETASUTF8 2447
#define SCI_SETLENGTHFORENCODE 2448
#define SCI_ENCODEDFROMUTF8 2449
#define SCI_FINDCOLUMN 2456
#define SCI_GETCARETSTICKY 2457
#define SCI_SETCARETSTICKY 2458
#define SC_CARETSTICKY_OFF 0
#define SC_CARETSTICKY_ON 1
#define SC_CARETSTICKY_WHITESPACE 2
#define SCI_TOGGLECARETSTICKY 2459
#define SCI_SETPASTECONVERTENDINGS 2467
#define SCI_GETPASTECONVERTENDINGS 2468
#define SCI_SELECTIONDUPLICATE 2469
#define SC_ALPHA_TRANSPARENT 0
#define SC_ALPHA_OPAQUE 255
#define SC_ALPHA_NOALPHA 256
#define SCI_SETCARETLINEBACKALPHA 2470
#define SCI_GETCARETLINEBACKALPHA 2471
#define CARETSTYLE_INVISIBLE 0
#define CARETSTYLE_LINE 1
#define CARETSTYLE_BLOCK 2
#define SCI_SETCARETSTYLE 2512
#define SCI_GETCARETSTYLE 2513
#define SCI_SETINDICATORCURRENT 2500
#define SCI_GETINDICATORCURRENT 2501
#define SCI_SETINDICATORVALUE 2502
#define SCI_GETINDICATORVALUE 2503
#define SCI_INDICATORFILLRANGE 2504
#define SCI_INDICATORCLEARRANGE 2505
#define SCI_INDICATORALLONFOR 2506
#define SCI_INDICATORVALUEAT 2507
#define SCI_INDICATORSTART 2508
#define SCI_INDICATOREND 2509
#define SCI_SETPOSITIONCACHE 2514
#define SCI_GETPOSITIONCACHE 2515
#define SCI_COPYALLOWLINE 2519
#define SCI_GETCHARACTERPOINTER 2520
#define SCI_GETRANGEPOINTER 2643
#define SCI_GETGAPPOSITION 2644
#define SCI_SETKEYSUNICODE 2521
#define SCI_GETKEYSUNICODE 2522
#define SCI_INDICSETALPHA 2523
#define SCI_INDICGETALPHA 2524
#define SCI_INDICSETOUTLINEALPHA 2558
#define SCI_INDICGETOUTLINEALPHA 2559
#define SCI_SETEXTRAASCENT 2525
#define SCI_GETEXTRAASCENT 2526
#define SCI_SETEXTRADESCENT 2527
#define SCI_GETEXTRADESCENT 2528
#define SCI_MARKERSYMBOLDEFINED 2529
#define SCI_MARGINSETTEXT 2530
#define SCI_MARGINGETTEXT 2531
#define SCI_MARGINSETSTYLE 2532
#define SCI_MARGINGETSTYLE 2533
#define SCI_MARGINSETSTYLES 2534
#define SCI_MARGINGETSTYLES 2535
#define SCI_MARGINTEXTCLEARALL 2536
#define SCI_MARGINSETSTYLEOFFSET 2537
#define SCI_MARGINGETSTYLEOFFSET 2538
#define SC_MARGINOPTION_NONE 0
#define SC_MARGINOPTION_SUBLINESELECT 1
#define SCI_SETMARGINOPTIONS 2539
#define SCI_GETMARGINOPTIONS 2557
#define SCI_ANNOTATIONSETTEXT 2540
#define SCI_ANNOTATIONGETTEXT 2541
#define SCI_ANNOTATIONSETSTYLE 2542
#define SCI_ANNOTATIONGETSTYLE 2543
#define SCI_ANNOTATIONSETSTYLES 2544
#define SCI_ANNOTATIONGETSTYLES 2545
#define SCI_ANNOTATIONGETLINES 2546
#define SCI_ANNOTATIONCLEARALL 2547
#define ANNOTATION_HIDDEN 0
#define ANNOTATION_STANDARD 1
#define ANNOTATION_BOXED 2
#define SCI_ANNOTATIONSETVISIBLE 2548
#define SCI_ANNOTATIONGETVISIBLE 2549
#define SCI_ANNOTATIONSETSTYLEOFFSET 2550
#define SCI_ANNOTATIONGETSTYLEOFFSET 2551
#define SCI_RELEASEALLEXTENDEDSTYLES 2552
#define SCI_ALLOCATEEXTENDEDSTYLES 2553
#define UNDO_MAY_COALESCE 1
#define SCI_ADDUNDOACTION 2560
#define SCI_CHARPOSITIONFROMPOINT 2561
#define SCI_CHARPOSITIONFROMPOINTCLOSE 2562
#define SCI_SETMULTIPLESELECTION 2563
#define SCI_GETMULTIPLESELECTION 2564
#define SCI_SETADDITIONALSELECTIONTYPING 2565
#define SCI_GETADDITIONALSELECTIONTYPING 2566
#define SCI_SETADDITIONALCARETSBLINK 2567
#define SCI_GETADDITIONALCARETSBLINK 2568
#define SCI_SETADDITIONALCARETSVISIBLE 2608
#define SCI_GETADDITIONALCARETSVISIBLE 2609
#define SCI_GETSELECTIONS 2570
#define SCI_GETSELECTIONEMPTY 2650
#define SCI_CLEARSELECTIONS 2571
#define SCI_SETSELECTION 2572
#define SCI_ADDSELECTION 2573
#define SCI_SETMAINSELECTION 2574
#define SCI_GETMAINSELECTION 2575
#define SCI_SETSELECTIONNCARET 2576
#define SCI_GETSELECTIONNCARET 2577
#define SCI_SETSELECTIONNANCHOR 2578
#define SCI_GETSELECTIONNANCHOR 2579
#define SCI_SETSELECTIONNCARETVIRTUALSPACE 2580
#define SCI_GETSELECTIONNCARETVIRTUALSPACE 2581
#define SCI_SETSELECTIONNANCHORVIRTUALSPACE 2582
#define SCI_GETSELECTIONNANCHORVIRTUALSPACE 2583
#define SCI_SETSELECTIONNSTART 2584
#define SCI_GETSELECTIONNSTART 2585
#define SCI_SETSELECTIONNEND 2586
#define SCI_GETSELECTIONNEND 2587
#define SCI_SETRECTANGULARSELECTIONCARET 2588
#define SCI_GETRECTANGULARSELECTIONCARET 2589
#define SCI_SETRECTANGULARSELECTIONANCHOR 2590
#define SCI_GETRECTANGULARSELECTIONANCHOR 2591
#define SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE 2592
#define SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE 2593
#define SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2594
#define SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE 2595
#define SCVS_NONE 0
#define SCVS_RECTANGULARSELECTION 1
#define SCVS_USERACCESSIBLE 2
#define SCI_SETVIRTUALSPACEOPTIONS 2596
#define SCI_GETVIRTUALSPACEOPTIONS 2597
#define SCI_SETRECTANGULARSELECTIONMODIFIER 2598
#define SCI_GETRECTANGULARSELECTIONMODIFIER 2599
#define SCI_SETADDITIONALSELFORE 2600
#define SCI_SETADDITIONALSELBACK 2601
#define SCI_SETADDITIONALSELALPHA 2602
#define SCI_GETADDITIONALSELALPHA 2603
#define SCI_SETADDITIONALCARETFORE 2604
#define SCI_GETADDITIONALCARETFORE 2605
#define SCI_ROTATESELECTION 2606
#define SCI_SWAPMAINANCHORCARET 2607
#define SCI_CHANGELEXERSTATE 2617
#define SCI_CONTRACTEDFOLDNEXT 2618
#define SCI_VERTICALCENTRECARET 2619
#define SCI_MOVESELECTEDLINESUP 2620
#define SCI_MOVESELECTEDLINESDOWN 2621
#define SCI_SETIDENTIFIER 2622
#define SCI_GETIDENTIFIER 2623
#define SCI_RGBAIMAGESETWIDTH 2624
#define SCI_RGBAIMAGESETHEIGHT 2625
#define SCI_RGBAIMAGESETSCALE 2651
#define SCI_MARKERDEFINERGBAIMAGE 2626
#define SCI_REGISTERRGBAIMAGE 2627
#define SCI_SCROLLTOSTART 2628
#define SCI_SCROLLTOEND 2629
#define SC_TECHNOLOGY_DEFAULT 0
#define SC_TECHNOLOGY_DIRECTWRITE 1
#define SCI_SETTECHNOLOGY 2630
#define SCI_GETTECHNOLOGY 2631
#define SCI_CREATELOADER 2632
#define SCI_FINDINDICATORSHOW 2640
#define SCI_FINDINDICATORFLASH 2641
#define SCI_FINDINDICATORHIDE 2642
#define SCI_VCHOMEDISPLAY 2652
#define SCI_VCHOMEDISPLAYEXTEND 2653
#define SCI_GETCARETLINEVISIBLEALWAYS 2654
#define SCI_SETCARETLINEVISIBLEALWAYS 2655
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_SETLEXER 4001
#define SCI_GETLEXER 4002
#define SCI_COLOURISE 4003
#define SCI_SETPROPERTY 4004
#define KEYWORDSET_MAX 8
#define SCI_SETKEYWORDS 4005
#define SCI_SETLEXERLANGUAGE 4006
#define SCI_LOADLEXERLIBRARY 4007
#define SCI_GETPROPERTY 4008
#define SCI_GETPROPERTYEXPANDED 4009
#define SCI_GETPROPERTYINT 4010
#define SCI_GETSTYLEBITSNEEDED 4011
#define SCI_GETLEXERLANGUAGE 4012
#define SCI_PRIVATELEXERCALL 4013
#define SCI_PROPERTYNAMES 4014
#define SC_TYPE_BOOLEAN 0
#define SC_TYPE_INTEGER 1
#define SC_TYPE_STRING 2
#define SCI_PROPERTYTYPE 4015
#define SCI_DESCRIBEPROPERTY 4016
#define SCI_DESCRIBEKEYWORDSETS 4017
#define SC_MOD_INSERTTEXT 0x1
#define SC_MOD_DELETETEXT 0x2
#define SC_MOD_CHANGESTYLE 0x4
#define SC_MOD_CHANGEFOLD 0x8
#define SC_PERFORMED_USER 0x10
#define SC_PERFORMED_UNDO 0x20
#define SC_PERFORMED_REDO 0x40
#define SC_MULTISTEPUNDOREDO 0x80
#define SC_LASTSTEPINUNDOREDO 0x100
#define SC_MOD_CHANGEMARKER 0x200
#define SC_MOD_BEFOREINSERT 0x400
#define SC_MOD_BEFOREDELETE 0x800
#define SC_MULTILINEUNDOREDO 0x1000
#define SC_STARTACTION 0x2000
#define SC_MOD_CHANGEINDICATOR 0x4000
#define SC_MOD_CHANGELINESTATE 0x8000
#define SC_MOD_CHANGEMARGIN 0x10000
#define SC_MOD_CHANGEANNOTATION 0x20000
#define SC_MOD_CONTAINER 0x40000
#define SC_MOD_LEXERSTATE 0x80000
#define SC_MODEVENTMASKALL 0xFFFFF
#define SC_UPDATE_CONTENT 0x1
#define SC_UPDATE_SELECTION 0x2
#define SC_UPDATE_V_SCROLL 0x4
#define SC_UPDATE_H_SCROLL 0x8
#define SCEN_CHANGE 768
#define SCEN_SETFOCUS 512
#define SCEN_KILLFOCUS 256
#define SCK_DOWN 300
#define SCK_UP 301
#define SCK_LEFT 302
#define SCK_RIGHT 303
#define SCK_HOME 304
#define SCK_END 305
#define SCK_PRIOR 306
#define SCK_NEXT 307
#define SCK_DELETE 308
#define SCK_INSERT 309
#define SCK_ESCAPE 7
#define SCK_BACK 8
#define SCK_TAB 9
#define SCK_RETURN 13
#define SCK_ADD 310
#define SCK_SUBTRACT 311
#define SCK_DIVIDE 312
#define SCK_WIN 313
#define SCK_RWIN 314
#define SCK_MENU 315
#define SCMOD_NORM 0
#define SCMOD_SHIFT 1
#define SCMOD_CTRL 2
#define SCMOD_ALT 4
#define SCMOD_SUPER 8
#define SCMOD_META 16
#define SCN_STYLENEEDED 2000
#define SCN_CHARADDED 2001
#define SCN_SAVEPOINTREACHED 2002
#define SCN_SAVEPOINTLEFT 2003
#define SCN_MODIFYATTEMPTRO 2004
#define SCN_KEY 2005
#define SCN_DOUBLECLICK 2006
#define SCN_UPDATEUI 2007
#define SCN_MODIFIED 2008
#define SCN_MACRORECORD 2009
#define SCN_MARGINCLICK 2010
#define SCN_NEEDSHOWN 2011
#define SCN_PAINTED 2013
#define SCN_USERLISTSELECTION 2014
#define SCN_URIDROPPED 2015
#define SCN_DWELLSTART 2016
#define SCN_DWELLEND 2017
#define SCN_ZOOM 2018
#define SCN_HOTSPOTCLICK 2019
#define SCN_HOTSPOTDOUBLECLICK 2020
#define SCN_CALLTIPCLICK 2021
#define SCN_AUTOCSELECTION 2022
#define SCN_INDICATORCLICK 2023
#define SCN_INDICATORRELEASE 2024
#define SCN_AUTOCCANCELLED 2025
#define SCN_AUTOCCHARDELETED 2026
#define SCN_HOTSPOTRELEASECLICK 2027
#ifndef SCI_DISABLE_PROVISIONAL
#define SC_LINE_END_TYPE_DEFAULT 0
#define SC_LINE_END_TYPE_UNICODE 1
#define SCI_SETLINEENDTYPESALLOWED 2656
#define SCI_GETLINEENDTYPESALLOWED 2657
#define SCI_GETLINEENDTYPESACTIVE 2658
#define SCI_GETLINEENDTYPESSUPPORTED 4018
#define SCI_ALLOCATESUBSTYLES 4020
#define SCI_GETSUBSTYLESSTART 4021
#define SCI_GETSUBSTYLESLENGTH 4022
#define SCI_FREESUBSTYLES 4023
#define SCI_SETIDENTIFIERS 4024
#define SCI_DISTANCETOSECONDARYSTYLES 4025
#define SCI_GETSUBSTYLEBASES 4026
#endif
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */

/* These structures are defined to be exactly the same shape as the Win32
 * CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs.
 * So older code that treats Scintilla as a RichEdit will work. */

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

struct Sci_CharacterRange {
	long cpMin;
	long cpMax;
};

struct Sci_TextRange {
	struct Sci_CharacterRange chrg;
	char *lpstrText;
};

struct Sci_TextToFind {
	struct Sci_CharacterRange chrg;
	char *lpstrText;
	struct Sci_CharacterRange chrgText;
};

#define CharacterRange Sci_CharacterRange
#define TextRange Sci_TextRange
#define TextToFind Sci_TextToFind

typedef void *Sci_SurfaceID;

struct Sci_Rectangle {
	int left;
	int top;
	int right;
	int bottom;
};

/* This structure is used in printing and requires some of the graphics types
 * from Platform.h.  Not needed by most client code. */

struct Sci_RangeToFormat {
	Sci_SurfaceID hdc;
	Sci_SurfaceID hdcTarget;
	struct Sci_Rectangle rc;
	struct Sci_Rectangle rcPage;
	struct Sci_CharacterRange chrg;
};

#define RangeToFormat Sci_RangeToFormat

struct Sci_NotifyHeader {
	/* Compatible with Windows NMHDR.
	 * hwndFrom is really an environment specific window handle or pointer
	 * but most clients of Scintilla.h do not have this type visible. */
	void *hwndFrom;
	uptr_t idFrom;
	unsigned int code;
};

#define NotifyHeader Sci_NotifyHeader

struct SCNotification {
	struct Sci_NotifyHeader nmhdr;
	int position;
	/* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */
	/* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */
	/* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */
	/* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */
	/* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */

	int ch;		/* SCN_CHARADDED, SCN_KEY */
	int modifiers;
	/* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */
	/* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */

	int modificationType;	/* SCN_MODIFIED */
	const char *text;
	/* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */

	int length;		/* SCN_MODIFIED */
	int linesAdded;	/* SCN_MODIFIED */
	int message;	/* SCN_MACRORECORD */
	uptr_t wParam;	/* SCN_MACRORECORD */
	sptr_t lParam;	/* SCN_MACRORECORD */
	int line;		/* SCN_MODIFIED */
	int foldLevelNow;	/* SCN_MODIFIED */
	int foldLevelPrev;	/* SCN_MODIFIED */
	int margin;		/* SCN_MARGINCLICK */
	int listType;	/* SCN_USERLISTSELECTION */
	int x;			/* SCN_DWELLSTART, SCN_DWELLEND */
	int y;		/* SCN_DWELLSTART, SCN_DWELLEND */
	int token;		/* SCN_MODIFIED with SC_MOD_CONTAINER */
	int annotationLinesAdded;	/* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */
	int updated;	/* SCN_UPDATEUI */
};

#ifdef SCI_NAMESPACE
}
#endif

#ifdef INCLUDE_DEPRECATED_FEATURES

#define SC_CP_DBCS 1
#define SCI_SETUSEPALETTE 2039
#define SCI_GETUSEPALETTE 2139

#endif

#endif

Added include/Scintilla.iface.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
## First line may be used for shbang

## This file defines the interface to Scintilla

## Copyright 2000-2003 by Neil Hodgson <neilh@scintilla.org>
## The License.txt file describes the conditions under which this software may be distributed.

## A line starting with ## is a pure comment and should be stripped by readers.
## A line starting with #! is for future shbang use
## A line starting with # followed by a space is a documentation comment and refers
## to the next feature definition.

## Each feature is defined by a line starting with fun, get, set, val or evt.
##     cat -> start a category
##     fun -> a function
##     get -> a property get function
##     set -> a property set function
##     val -> definition of a constant
##     evt -> an event
##     enu -> associate an enumeration with a set of vals with a prefix
##     lex -> associate a lexer with the lexical classes it produces
##
## All other feature names should be ignored. They may be defined in the future.
## A property may have a set function, a get function or both. Each will have
## "Get" or "Set" in their names and the corresponding name will have the obvious switch.
## A property may be subscripted, in which case the first parameter is the subscript.
## fun, get, and set features have a strict syntax:
## <featureType><ws><returnType><ws><name>[=<number](<param>,<param>)
## where <ws> stands for white space.
## param may be empty (null value) or is <paramType><ws><paramName>[=<value>]
## Additional white space is allowed between elements.
## The syntax for evt is <featureType><ws><returnType><ws><name>[=<number]([<param>[,<param>]*])
## Feature names that contain an underscore are defined by Windows, so in these
## cases, using the Windows definition is preferred where available.
## The feature numbers are stable so features will not be renumbered.
## Features may be removed but they will go through a period of deprecation
## before removal which is signalled by moving them into the Deprecated category.
##
## enu has the syntax enu<ws><enumeration>=<prefix>[<ws><prefix>]* where all the val
## features in this file starting with a given <prefix> are considered part of the
## enumeration.
##
## lex has the syntax lex<ws><name>=<lexerVal><ws><prefix>[<ws><prefix>]*
## where name is a reasonably capitalised (Python, XML) identifier or UI name,
## lexerVal is the val used to specify the lexer, and the list of prefixes is similar
## to enu. The name may not be the same as that used within the lexer so the lexerVal
## should be used to tie these entities together.

## Types:
##     void
##     int
##     bool -> integer, 1=true, 0=false
##     position -> integer position in a document
##     colour -> colour integer containing red, green and blue bytes.
##     string -> pointer to const character
##     stringresult -> pointer to character, NULL-> return size of result
##     cells -> pointer to array of cells, each cell containing a style byte and character byte
##     textrange -> range of a min and a max position with an output string
##     findtext -> searchrange, text -> foundposition
##     keymod -> integer containing key in low half and modifiers in high half
##     formatrange
## Types no longer used:
##     findtextex -> searchrange
##     charrange -> range of a min and a max position
##     charrangeresult -> like charrange, but output param
##     countedstring
##     point -> x,y
##     pointresult  -> like point, but output param
##     rectangle -> left,top,right,bottom
## Client code should ignore definitions containing types it does not understand, except
## for possibly #defining the constants

## Line numbers and positions start at 0.
## String arguments may contain NUL ('\0') characters where the calls provide a length
## argument and retrieve NUL characters. All retrieved strings except for those retrieved
## by GetLine also have a NUL appended but client code should calculate the size that
## will be returned rather than relying upon the NUL whenever possible. Allow for the
## extra NUL character when allocating buffers. The size to allocate for a stringresult
## can be determined by calling with a NULL (0) pointer.

cat Basics

################################################
## For Scintilla.h
val INVALID_POSITION=-1
# Define start of Scintilla messages to be greater than all Windows edit (EM_*) messages
# as many EM_ messages can be used although that use is deprecated.
val SCI_START=2000
val SCI_OPTIONAL_START=3000
val SCI_LEXER_START=4000

# Add text to the document at current position.
fun void AddText=2001(int length, string text)

# Add array of cells to document.
fun void AddStyledText=2002(int length, cells c)

# Insert string at a position.
fun void InsertText=2003(position pos, string text)

# Delete all text in the document.
fun void ClearAll=2004(,)

# Delete a range of text in the document.
fun void DeleteRange=2645(position pos, int deleteLength)

# Set all style bytes to 0, remove all folding information.
fun void ClearDocumentStyle=2005(,)

# Returns the number of bytes in the document.
get int GetLength=2006(,)

# Returns the character byte at the position.
get int GetCharAt=2007(position pos,)

# Returns the position of the caret.
get position GetCurrentPos=2008(,)

# Returns the position of the opposite end of the selection to the caret.
get position GetAnchor=2009(,)

# Returns the style byte at the position.
get int GetStyleAt=2010(position pos,)

# Redoes the next action on the undo history.
fun void Redo=2011(,)

# Choose between collecting actions into the undo
# history and discarding them.
set void SetUndoCollection=2012(bool collectUndo,)

# Select all the text in the document.
fun void SelectAll=2013(,)

# Remember the current position in the undo history as the position
# at which the document was saved.
fun void SetSavePoint=2014(,)

# Retrieve a buffer of cells.
# Returns the number of bytes in the buffer not including terminating NULs.
fun int GetStyledText=2015(, textrange tr)

# Are there any redoable actions in the undo history?
fun bool CanRedo=2016(,)

# Retrieve the line number at which a particular marker is located.
fun int MarkerLineFromHandle=2017(int handle,)

# Delete a marker.
fun void MarkerDeleteHandle=2018(int handle,)

# Is undo history being collected?
get bool GetUndoCollection=2019(,)

enu WhiteSpace=SCWS_
val SCWS_INVISIBLE=0
val SCWS_VISIBLEALWAYS=1
val SCWS_VISIBLEAFTERINDENT=2

# Are white space characters currently visible?
# Returns one of SCWS_* constants.
get int GetViewWS=2020(,)

# Make white space characters invisible, always visible or visible outside indentation.
set void SetViewWS=2021(int viewWS,)

# Find the position from a point within the window.
fun position PositionFromPoint=2022(int x, int y)

# Find the position from a point within the window but return
# INVALID_POSITION if not close to text.
fun position PositionFromPointClose=2023(int x, int y)

# Set caret to start of a line and ensure it is visible.
fun void GotoLine=2024(int line,)

# Set caret to a position and ensure it is visible.
fun void GotoPos=2025(position pos,)

# Set the selection anchor to a position. The anchor is the opposite
# end of the selection from the caret.
set void SetAnchor=2026(position posAnchor,)

# Retrieve the text of the line containing the caret.
# Returns the index of the caret on the line.
fun int GetCurLine=2027(int length, stringresult text)

# Retrieve the position of the last correctly styled character.
get position GetEndStyled=2028(,)

enu EndOfLine=SC_EOL_
val SC_EOL_CRLF=0
val SC_EOL_CR=1
val SC_EOL_LF=2

# Convert all line endings in the document to one mode.
fun void ConvertEOLs=2029(int eolMode,)

# Retrieve the current end of line mode - one of CRLF, CR, or LF.
get int GetEOLMode=2030(,)

# Set the current end of line mode.
set void SetEOLMode=2031(int eolMode,)

# Set the current styling position to pos and the styling mask to mask.
# The styling mask can be used to protect some bits in each styling byte from modification.
fun void StartStyling=2032(position pos, int mask)

# Change style from current styling position for length characters to a style
# and move the current styling position to after this newly styled segment.
fun void SetStyling=2033(int length, int style)

# Is drawing done first into a buffer or direct to the screen?
get bool GetBufferedDraw=2034(,)

# If drawing is buffered then each line of text is drawn into a bitmap buffer
# before drawing it to the screen to avoid flicker.
set void SetBufferedDraw=2035(bool buffered,)

# Change the visible size of a tab to be a multiple of the width of a space character.
set void SetTabWidth=2036(int tabWidth,)

# Retrieve the visible size of a tab.
get int GetTabWidth=2121(,)

# The SC_CP_UTF8 value can be used to enter Unicode mode.
# This is the same value as CP_UTF8 in Windows
val SC_CP_UTF8=65001

# Set the code page used to interpret the bytes of the document as characters.
# The SC_CP_UTF8 value can be used to enter Unicode mode.
set void SetCodePage=2037(int codePage,)

enu MarkerSymbol=SC_MARK_
val MARKER_MAX=31
val SC_MARK_CIRCLE=0
val SC_MARK_ROUNDRECT=1
val SC_MARK_ARROW=2
val SC_MARK_SMALLRECT=3
val SC_MARK_SHORTARROW=4
val SC_MARK_EMPTY=5
val SC_MARK_ARROWDOWN=6
val SC_MARK_MINUS=7
val SC_MARK_PLUS=8

# Shapes used for outlining column.
val SC_MARK_VLINE=9
val SC_MARK_LCORNER=10
val SC_MARK_TCORNER=11
val SC_MARK_BOXPLUS=12
val SC_MARK_BOXPLUSCONNECTED=13
val SC_MARK_BOXMINUS=14
val SC_MARK_BOXMINUSCONNECTED=15
val SC_MARK_LCORNERCURVE=16
val SC_MARK_TCORNERCURVE=17
val SC_MARK_CIRCLEPLUS=18
val SC_MARK_CIRCLEPLUSCONNECTED=19
val SC_MARK_CIRCLEMINUS=20
val SC_MARK_CIRCLEMINUSCONNECTED=21

# Invisible mark that only sets the line background colour.
val SC_MARK_BACKGROUND=22
val SC_MARK_DOTDOTDOT=23
val SC_MARK_ARROWS=24
val SC_MARK_PIXMAP=25
val SC_MARK_FULLRECT=26
val SC_MARK_LEFTRECT=27
val SC_MARK_AVAILABLE=28
val SC_MARK_UNDERLINE=29
val SC_MARK_RGBAIMAGE=30

val SC_MARK_CHARACTER=10000

enu MarkerOutline=SC_MARKNUM_
# Markers used for outlining column.
val SC_MARKNUM_FOLDEREND=25
val SC_MARKNUM_FOLDEROPENMID=26
val SC_MARKNUM_FOLDERMIDTAIL=27
val SC_MARKNUM_FOLDERTAIL=28
val SC_MARKNUM_FOLDERSUB=29
val SC_MARKNUM_FOLDER=30
val SC_MARKNUM_FOLDEROPEN=31

val SC_MASK_FOLDERS=0xFE000000

# Set the symbol used for a particular marker number.
fun void MarkerDefine=2040(int markerNumber, int markerSymbol)

# Set the foreground colour used for a particular marker number.
set void MarkerSetFore=2041(int markerNumber, colour fore)

# Set the background colour used for a particular marker number.
set void MarkerSetBack=2042(int markerNumber, colour back)

# Set the background colour used for a particular marker number when its folding block is selected.
set void MarkerSetBackSelected=2292(int markerNumber, colour back)

# Enable/disable highlight for current folding bloc (smallest one that contains the caret)
fun void MarkerEnableHighlight=2293(bool enabled,)

# Add a marker to a line, returning an ID which can be used to find or delete the marker.
fun int MarkerAdd=2043(int line, int markerNumber)

# Delete a marker from a line.
fun void MarkerDelete=2044(int line, int markerNumber)

# Delete all markers with a particular number from all lines.
fun void MarkerDeleteAll=2045(int markerNumber,)

# Get a bit mask of all the markers set on a line.
fun int MarkerGet=2046(int line,)

# Find the next line at or after lineStart that includes a marker in mask.
# Return -1 when no more lines.
fun int MarkerNext=2047(int lineStart, int markerMask)

# Find the previous line before lineStart that includes a marker in mask.
fun int MarkerPrevious=2048(int lineStart, int markerMask)

# Define a marker from a pixmap.
fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap)

# Add a set of markers to a line.
fun void MarkerAddSet=2466(int line, int set)

# Set the alpha used for a marker that is drawn in the text area, not the margin.
set void MarkerSetAlpha=2476(int markerNumber, int alpha)

val SC_MAX_MARGIN=4

enu MarginType=SC_MARGIN_
val SC_MARGIN_SYMBOL=0
val SC_MARGIN_NUMBER=1
val SC_MARGIN_BACK=2
val SC_MARGIN_FORE=3
val SC_MARGIN_TEXT=4
val SC_MARGIN_RTEXT=5

# Set a margin to be either numeric or symbolic.
set void SetMarginTypeN=2240(int margin, int marginType)

# Retrieve the type of a margin.
get int GetMarginTypeN=2241(int margin,)

# Set the width of a margin to a width expressed in pixels.
set void SetMarginWidthN=2242(int margin, int pixelWidth)

# Retrieve the width of a margin in pixels.
get int GetMarginWidthN=2243(int margin,)

# Set a mask that determines which markers are displayed in a margin.
set void SetMarginMaskN=2244(int margin, int mask)

# Retrieve the marker mask of a margin.
get int GetMarginMaskN=2245(int margin,)

# Make a margin sensitive or insensitive to mouse clicks.
set void SetMarginSensitiveN=2246(int margin, bool sensitive)

# Retrieve the mouse click sensitivity of a margin.
get bool GetMarginSensitiveN=2247(int margin,)

# Set the cursor shown when the mouse is inside a margin.
set void SetMarginCursorN=2248(int margin, int cursor)

# Retrieve the cursor shown in a margin.
get int GetMarginCursorN=2249(int margin,)

# Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles.
# Style 39 is for future use.
enu StylesCommon=STYLE_
val STYLE_DEFAULT=32
val STYLE_LINENUMBER=33
val STYLE_BRACELIGHT=34
val STYLE_BRACEBAD=35
val STYLE_CONTROLCHAR=36
val STYLE_INDENTGUIDE=37
val STYLE_CALLTIP=38
val STYLE_LASTPREDEFINED=39
val STYLE_MAX=255

# Character set identifiers are used in StyleSetCharacterSet.
# The values are the same as the Windows *_CHARSET values.
enu CharacterSet=SC_CHARSET_
val SC_CHARSET_ANSI=0
val SC_CHARSET_DEFAULT=1
val SC_CHARSET_BALTIC=186
val SC_CHARSET_CHINESEBIG5=136
val SC_CHARSET_EASTEUROPE=238
val SC_CHARSET_GB2312=134
val SC_CHARSET_GREEK=161
val SC_CHARSET_HANGUL=129
val SC_CHARSET_MAC=77
val SC_CHARSET_OEM=255
val SC_CHARSET_RUSSIAN=204
val SC_CHARSET_CYRILLIC=1251
val SC_CHARSET_SHIFTJIS=128
val SC_CHARSET_SYMBOL=2
val SC_CHARSET_TURKISH=162
val SC_CHARSET_JOHAB=130
val SC_CHARSET_HEBREW=177
val SC_CHARSET_ARABIC=178
val SC_CHARSET_VIETNAMESE=163
val SC_CHARSET_THAI=222
val SC_CHARSET_8859_15=1000

# Clear all the styles and make equivalent to the global default style.
fun void StyleClearAll=2050(,)

# Set the foreground colour of a style.
set void StyleSetFore=2051(int style, colour fore)

# Set the background colour of a style.
set void StyleSetBack=2052(int style, colour back)

# Set a style to be bold or not.
set void StyleSetBold=2053(int style, bool bold)

# Set a style to be italic or not.
set void StyleSetItalic=2054(int style, bool italic)

# Set the size of characters of a style.
set void StyleSetSize=2055(int style, int sizePoints)

# Set the font of a style.
set void StyleSetFont=2056(int style, string fontName)

# Set a style to have its end of line filled or not.
set void StyleSetEOLFilled=2057(int style, bool filled)

# Reset the default style to its state at startup
fun void StyleResetDefault=2058(,)

# Set a style to be underlined or not.
set void StyleSetUnderline=2059(int style, bool underline)

enu CaseVisible=SC_CASE_
val SC_CASE_MIXED=0
val SC_CASE_UPPER=1
val SC_CASE_LOWER=2

# Get the foreground colour of a style.
get colour StyleGetFore=2481(int style,)

# Get the background colour of a style.
get colour StyleGetBack=2482(int style,)

# Get is a style bold or not.
get bool StyleGetBold=2483(int style,)

# Get is a style italic or not.
get bool StyleGetItalic=2484(int style,)

# Get the size of characters of a style.
get int StyleGetSize=2485(int style,)

# Get the font of a style.
# Returns the length of the fontName
get int StyleGetFont=2486(int style, stringresult fontName)

# Get is a style to have its end of line filled or not.
get bool StyleGetEOLFilled=2487(int style,)

# Get is a style underlined or not.
get bool StyleGetUnderline=2488(int style,)

# Get is a style mixed case, or to force upper or lower case.
get int StyleGetCase=2489(int style,)

# Get the character get of the font in a style.
get int StyleGetCharacterSet=2490(int style,)

# Get is a style visible or not.
get bool StyleGetVisible=2491(int style,)

# Get is a style changeable or not (read only).
# Experimental feature, currently buggy.
get bool StyleGetChangeable=2492(int style,)

# Get is a style a hotspot or not.
get bool StyleGetHotSpot=2493(int style,)

# Set a style to be mixed case, or to force upper or lower case.
set void StyleSetCase=2060(int style, int caseForce)

val SC_FONT_SIZE_MULTIPLIER=100

# Set the size of characters of a style. Size is in points multiplied by 100.
set void StyleSetSizeFractional=2061(int style, int caseForce)

# Get the size of characters of a style in points multiplied by 100
get int StyleGetSizeFractional=2062(int style,)

enu FontWeight=SC_WEIGHT_
val SC_WEIGHT_NORMAL=400
val SC_WEIGHT_SEMIBOLD=600
val SC_WEIGHT_BOLD=700

# Set the weight of characters of a style.
set void StyleSetWeight=2063(int style, int weight)

# Get the weight of characters of a style.
get int StyleGetWeight=2064(int style,)

# Set the character set of the font in a style.
set void StyleSetCharacterSet=2066(int style, int characterSet)

# Set a style to be a hotspot or not.
set void StyleSetHotSpot=2409(int style, bool hotspot)

# Set the foreground colour of the main and additional selections and whether to use this setting.
fun void SetSelFore=2067(bool useSetting, colour fore)

# Set the background colour of the main and additional selections and whether to use this setting.
fun void SetSelBack=2068(bool useSetting, colour back)

# Get the alpha of the selection.
get int GetSelAlpha=2477(,)

# Set the alpha of the selection.
set void SetSelAlpha=2478(int alpha,)

# Is the selection end of line filled?
get bool GetSelEOLFilled=2479(,)

# Set the selection to have its end of line filled or not.
set void SetSelEOLFilled=2480(bool filled,)

# Set the foreground colour of the caret.
set void SetCaretFore=2069(colour fore,)

# When key+modifier combination km is pressed perform msg.
fun void AssignCmdKey=2070(keymod km, int msg)

# When key+modifier combination km is pressed do nothing.
fun void ClearCmdKey=2071(keymod km,)

# Drop all key mappings.
fun void ClearAllCmdKeys=2072(,)

# Set the styles for a segment of the document.
fun void SetStylingEx=2073(int length, string styles)

# Set a style to be visible or not.
set void StyleSetVisible=2074(int style, bool visible)

# Get the time in milliseconds that the caret is on and off.
get int GetCaretPeriod=2075(,)

# Get the time in milliseconds that the caret is on and off. 0 = steady on.
set void SetCaretPeriod=2076(int periodMilliseconds,)

# Set the set of characters making up words for when moving or selecting by word.
# First sets defaults like SetCharsDefault.
set void SetWordChars=2077(, string characters)

# Get the set of characters making up words for when moving or selecting by word.
# Retuns the number of characters
get int GetWordChars=2646(, stringresult characters)

# Start a sequence of actions that is undone and redone as a unit.
# May be nested.
fun void BeginUndoAction=2078(,)

# End a sequence of actions that is undone and redone as a unit.
fun void EndUndoAction=2079(,)

# Indicator style enumeration and some constants
enu IndicatorStyle=INDIC_
val INDIC_PLAIN=0
val INDIC_SQUIGGLE=1
val INDIC_TT=2
val INDIC_DIAGONAL=3
val INDIC_STRIKE=4
val INDIC_HIDDEN=5
val INDIC_BOX=6
val INDIC_ROUNDBOX=7
val INDIC_STRAIGHTBOX=8
val INDIC_DASH=9
val INDIC_DOTS=10
val INDIC_SQUIGGLELOW=11
val INDIC_DOTBOX=12
val INDIC_SQUIGGLEPIXMAP=13
val INDIC_MAX=31
val INDIC_CONTAINER=8
val INDIC0_MASK=0x20
val INDIC1_MASK=0x40
val INDIC2_MASK=0x80
val INDICS_MASK=0xE0

# Set an indicator to plain, squiggle or TT.
set void IndicSetStyle=2080(int indic, int style)

# Retrieve the style of an indicator.
get int IndicGetStyle=2081(int indic,)

# Set the foreground colour of an indicator.
set void IndicSetFore=2082(int indic, colour fore)

# Retrieve the foreground colour of an indicator.
get colour IndicGetFore=2083(int indic,)

# Set an indicator to draw under text or over(default).
set void IndicSetUnder=2510(int indic, bool under)

# Retrieve whether indicator drawn under or over text.
get bool IndicGetUnder=2511(int indic,)

# Set the foreground colour of all whitespace and whether to use this setting.
fun void SetWhitespaceFore=2084(bool useSetting, colour fore)

# Set the background colour of all whitespace and whether to use this setting.
fun void SetWhitespaceBack=2085(bool useSetting, colour back)

# Set the size of the dots used to mark space characters.
set void SetWhitespaceSize=2086(int size,)

# Get the size of the dots used to mark space characters.
get int GetWhitespaceSize=2087(,)

# Divide each styling byte into lexical class bits (default: 5) and indicator
# bits (default: 3). If a lexer requires more than 32 lexical states, then this
# is used to expand the possible states.
set void SetStyleBits=2090(int bits,)

# Retrieve number of bits in style bytes used to hold the lexical state.
get int GetStyleBits=2091(,)

# Used to hold extra styling information for each line.
set void SetLineState=2092(int line, int state)

# Retrieve the extra styling information for a line.
get int GetLineState=2093(int line,)

# Retrieve the last line number that has line state.
get int GetMaxLineState=2094(,)

# Is the background of the line containing the caret in a different colour?
get bool GetCaretLineVisible=2095(,)

# Display the background of the line containing the caret in a different colour.
set void SetCaretLineVisible=2096(bool show,)

# Get the colour of the background of the line containing the caret.
get colour GetCaretLineBack=2097(,)

# Set the colour of the background of the line containing the caret.
set void SetCaretLineBack=2098(colour back,)

# Set a style to be changeable or not (read only).
# Experimental feature, currently buggy.
set void StyleSetChangeable=2099(int style, bool changeable)

# Display a auto-completion list.
# The lenEntered parameter indicates how many characters before
# the caret should be used to provide context.
fun void AutoCShow=2100(int lenEntered, string itemList)

# Remove the auto-completion list from the screen.
fun void AutoCCancel=2101(,)

# Is there an auto-completion list visible?
fun bool AutoCActive=2102(,)

# Retrieve the position of the caret when the auto-completion list was displayed.
fun position AutoCPosStart=2103(,)

# User has selected an item so remove the list and insert the selection.
fun void AutoCComplete=2104(,)

# Define a set of character that when typed cancel the auto-completion list.
fun void AutoCStops=2105(, string characterSet)

# Change the separator character in the string setting up an auto-completion list.
# Default is space but can be changed if items contain space.
set void AutoCSetSeparator=2106(int separatorCharacter,)

# Retrieve the auto-completion list separator character.
get int AutoCGetSeparator=2107(,)

# Select the item in the auto-completion list that starts with a string.
fun void AutoCSelect=2108(, string text)

# Should the auto-completion list be cancelled if the user backspaces to a
# position before where the box was created.
set void AutoCSetCancelAtStart=2110(bool cancel,)

# Retrieve whether auto-completion cancelled by backspacing before start.
get bool AutoCGetCancelAtStart=2111(,)

# Define a set of characters that when typed will cause the autocompletion to
# choose the selected item.
set void AutoCSetFillUps=2112(, string characterSet)

# Should a single item auto-completion list automatically choose the item.
set void AutoCSetChooseSingle=2113(bool chooseSingle,)

# Retrieve whether a single item auto-completion list automatically choose the item.
get bool AutoCGetChooseSingle=2114(,)

# Set whether case is significant when performing auto-completion searches.
set void AutoCSetIgnoreCase=2115(bool ignoreCase,)

# Retrieve state of ignore case flag.
get bool AutoCGetIgnoreCase=2116(,)

# Display a list of strings and send notification when user chooses one.
fun void UserListShow=2117(int listType, string itemList)

# Set whether or not autocompletion is hidden automatically when nothing matches.
set void AutoCSetAutoHide=2118(bool autoHide,)

# Retrieve whether or not autocompletion is hidden automatically when nothing matches.
get bool AutoCGetAutoHide=2119(,)

# Set whether or not autocompletion deletes any word characters
# after the inserted text upon completion.
set void AutoCSetDropRestOfWord=2270(bool dropRestOfWord,)

# Retrieve whether or not autocompletion deletes any word characters
# after the inserted text upon completion.
get bool AutoCGetDropRestOfWord=2271(,)

# Register an XPM image for use in autocompletion lists.
fun void RegisterImage=2405(int type, string xpmData)

# Clear all the registered XPM images.
fun void ClearRegisteredImages=2408(,)

# Retrieve the auto-completion list type-separator character.
get int AutoCGetTypeSeparator=2285(,)

# Change the type-separator character in the string setting up an auto-completion list.
# Default is '?' but can be changed if items contain '?'.
set void AutoCSetTypeSeparator=2286(int separatorCharacter,)

# Set the maximum width, in characters, of auto-completion and user lists.
# Set to 0 to autosize to fit longest item, which is the default.
set void AutoCSetMaxWidth=2208(int characterCount,)

# Get the maximum width, in characters, of auto-completion and user lists.
get int AutoCGetMaxWidth=2209(,)

# Set the maximum height, in rows, of auto-completion and user lists.
# The default is 5 rows.
set void AutoCSetMaxHeight=2210(int rowCount,)

# Set the maximum height, in rows, of auto-completion and user lists.
get int AutoCGetMaxHeight=2211(,)

# Set the number of spaces used for one level of indentation.
set void SetIndent=2122(int indentSize,)

# Retrieve indentation size.
get int GetIndent=2123(,)

# Indentation will only use space characters if useTabs is false, otherwise
# it will use a combination of tabs and spaces.
set void SetUseTabs=2124(bool useTabs,)

# Retrieve whether tabs will be used in indentation.
get bool GetUseTabs=2125(,)

# Change the indentation of a line to a number of columns.
set void SetLineIndentation=2126(int line, int indentSize)

# Retrieve the number of columns that a line is indented.
get int GetLineIndentation=2127(int line,)

# Retrieve the position before the first non indentation character on a line.
get position GetLineIndentPosition=2128(int line,)

# Retrieve the column number of a position, taking tab width into account.
get int GetColumn=2129(position pos,)

# Count characters between two positions.
fun int CountCharacters=2633(int startPos, int endPos)

# Show or hide the horizontal scroll bar.
set void SetHScrollBar=2130(bool show,)
# Is the horizontal scroll bar visible?
get bool GetHScrollBar=2131(,)

enu IndentView=SC_IV_
val SC_IV_NONE=0
val SC_IV_REAL=1
val SC_IV_LOOKFORWARD=2
val SC_IV_LOOKBOTH=3

# Show or hide indentation guides.
set void SetIndentationGuides=2132(int indentView,)

# Are the indentation guides visible?
get int GetIndentationGuides=2133(,)

# Set the highlighted indentation guide column.
# 0 = no highlighted guide.
set void SetHighlightGuide=2134(int column,)

# Get the highlighted indentation guide column.
get int GetHighlightGuide=2135(,)

# Get the position after the last visible characters on a line.
get position GetLineEndPosition=2136(int line,)

# Get the code page used to interpret the bytes of the document as characters.
get int GetCodePage=2137(,)

# Get the foreground colour of the caret.
get colour GetCaretFore=2138(,)

# In read-only mode?
get bool GetReadOnly=2140(,)

# Sets the position of the caret.
set void SetCurrentPos=2141(position pos,)

# Sets the position that starts the selection - this becomes the anchor.
set void SetSelectionStart=2142(position pos,)

# Returns the position at the start of the selection.
get position GetSelectionStart=2143(,)

# Sets the position that ends the selection - this becomes the currentPosition.
set void SetSelectionEnd=2144(position pos,)

# Returns the position at the end of the selection.
get position GetSelectionEnd=2145(,)

# Set caret to a position, while removing any existing selection.
fun void SetEmptySelection=2556(position pos,)

# Sets the print magnification added to the point size of each style for printing.
set void SetPrintMagnification=2146(int magnification,)

# Returns the print magnification.
get int GetPrintMagnification=2147(,)

enu PrintOption=SC_PRINT_
# PrintColourMode - use same colours as screen.
val SC_PRINT_NORMAL=0
# PrintColourMode - invert the light value of each style for printing.
val SC_PRINT_INVERTLIGHT=1
# PrintColourMode - force black text on white background for printing.
val SC_PRINT_BLACKONWHITE=2
# PrintColourMode - text stays coloured, but all background is forced to be white for printing.
val SC_PRINT_COLOURONWHITE=3
# PrintColourMode - only the default-background is forced to be white for printing.
val SC_PRINT_COLOURONWHITEDEFAULTBG=4

# Modify colours when printing for clearer printed text.
set void SetPrintColourMode=2148(int mode,)

# Returns the print colour mode.
get int GetPrintColourMode=2149(,)

enu FindOption=SCFIND_
val SCFIND_WHOLEWORD=2
val SCFIND_MATCHCASE=4
val SCFIND_WORDSTART=0x00100000
val SCFIND_REGEXP=0x00200000
val SCFIND_POSIX=0x00400000

# Find some text in the document.
fun position FindText=2150(int flags, findtext ft)

# On Windows, will draw the document into a display context such as a printer.
fun position FormatRange=2151(bool draw, formatrange fr)

# Retrieve the display line at the top of the display.
get int GetFirstVisibleLine=2152(,)

# Retrieve the contents of a line.
# Returns the length of the line.
fun int GetLine=2153(int line, stringresult text)

# Returns the number of lines in the document. There is always at least one.
get int GetLineCount=2154(,)

# Sets the size in pixels of the left margin.
set void SetMarginLeft=2155(, int pixelWidth)

# Returns the size in pixels of the left margin.
get int GetMarginLeft=2156(,)

# Sets the size in pixels of the right margin.
set void SetMarginRight=2157(, int pixelWidth)

# Returns the size in pixels of the right margin.
get int GetMarginRight=2158(,)

# Is the document different from when it was last saved?
get bool GetModify=2159(,)

# Select a range of text.
fun void SetSel=2160(position start, position end)

# Retrieve the selected text.
# Return the length of the text.
fun int GetSelText=2161(, stringresult text)

# Retrieve a range of text.
# Return the length of the text.
fun int GetTextRange=2162(, textrange tr)

# Draw the selection in normal style or with selection highlighted.
fun void HideSelection=2163(bool normal,)

# Retrieve the x value of the point in the window where a position is displayed.
fun int PointXFromPosition=2164(, position pos)

# Retrieve the y value of the point in the window where a position is displayed.
fun int PointYFromPosition=2165(, position pos)

# Retrieve the line containing a position.
fun int LineFromPosition=2166(position pos,)

# Retrieve the position at the start of a line.
fun position PositionFromLine=2167(int line,)

# Scroll horizontally and vertically.
fun void LineScroll=2168(int columns, int lines)

# Ensure the caret is visible.
fun void ScrollCaret=2169(,)

# Scroll the argument positions and the range between them into view giving
# priority to the primary position then the secondary position.
# This may be used to make a search match visible.
fun void ScrollRange=2569(position secondary, position primary)

# Replace the selected text with the argument text.
fun void ReplaceSel=2170(, string text)

# Set to read only or read write.
set void SetReadOnly=2171(bool readOnly,)

# Null operation.
fun void Null=2172(,)

# Will a paste succeed?
fun bool CanPaste=2173(,)

# Are there any undoable actions in the undo history?
fun bool CanUndo=2174(,)

# Delete the undo history.
fun void EmptyUndoBuffer=2175(,)

# Undo one action in the undo history.
fun void Undo=2176(,)

# Cut the selection to the clipboard.
fun void Cut=2177(,)

# Copy the selection to the clipboard.
fun void Copy=2178(,)

# Paste the contents of the clipboard into the document replacing the selection.
fun void Paste=2179(,)

# Clear the selection.
fun void Clear=2180(,)

# Replace the contents of the document with the argument text.
fun void SetText=2181(, string text)

# Retrieve all the text in the document.
# Returns number of characters retrieved.
fun int GetText=2182(int length, stringresult text)

# Retrieve the number of characters in the document.
get int GetTextLength=2183(,)

# Retrieve a pointer to a function that processes messages for this Scintilla.
get int GetDirectFunction=2184(,)

# Retrieve a pointer value to use as the first argument when calling
# the function returned by GetDirectFunction.
get int GetDirectPointer=2185(,)

# Set to overtype (true) or insert mode.
set void SetOvertype=2186(bool overtype,)

# Returns true if overtype mode is active otherwise false is returned.
get bool GetOvertype=2187(,)

# Set the width of the insert mode caret.
set void SetCaretWidth=2188(int pixelWidth,)

# Returns the width of the insert mode caret.
get int GetCaretWidth=2189(,)

# Sets the position that starts the target which is used for updating the
# document without affecting the scroll position.
set void SetTargetStart=2190(position pos,)

# Get the position that starts the target.
get position GetTargetStart=2191(,)

# Sets the position that ends the target which is used for updating the
# document without affecting the scroll position.
set void SetTargetEnd=2192(position pos,)

# Get the position that ends the target.
get position GetTargetEnd=2193(,)

# Replace the target text with the argument text.
# Text is counted so it can contain NULs.
# Returns the length of the replacement text.
fun int ReplaceTarget=2194(int length, string text)

# Replace the target text with the argument text after \d processing.
# Text is counted so it can contain NULs.
# Looks for \d where d is between 1 and 9 and replaces these with the strings
# matched in the last search operation which were surrounded by \( and \).
# Returns the length of the replacement text including any change
# caused by processing the \d patterns.
fun int ReplaceTargetRE=2195(int length, string text)

# Search for a counted string in the target and set the target to the found
# range. Text is counted so it can contain NULs.
# Returns length of range or -1 for failure in which case target is not moved.
fun int SearchInTarget=2197(int length, string text)

# Set the search flags used by SearchInTarget.
set void SetSearchFlags=2198(int flags,)

# Get the search flags used by SearchInTarget.
get int GetSearchFlags=2199(,)

# Show a call tip containing a definition near position pos.
fun void CallTipShow=2200(position pos, string definition)

# Remove the call tip from the screen.
fun void CallTipCancel=2201(,)

# Is there an active call tip?
fun bool CallTipActive=2202(,)

# Retrieve the position where the caret was before displaying the call tip.
fun position CallTipPosStart=2203(,)

# Highlight a segment of the definition.
fun void CallTipSetHlt=2204(int start, int end)

# Set the background colour for the call tip.
set void CallTipSetBack=2205(colour back,)

# Set the foreground colour for the call tip.
set void CallTipSetFore=2206(colour fore,)

# Set the foreground colour for the highlighted part of the call tip.
set void CallTipSetForeHlt=2207(colour fore,)

# Enable use of STYLE_CALLTIP and set call tip tab size in pixels.
set void CallTipUseStyle=2212(int tabSize,)

# Set position of calltip, above or below text.
set void CallTipSetPosition=2213(bool above,)

# Find the display line of a document line taking hidden lines into account.
fun int VisibleFromDocLine=2220(int line,)

# Find the document line of a display line taking hidden lines into account.
fun int DocLineFromVisible=2221(int lineDisplay,)

# The number of display lines needed to wrap a document line
fun int WrapCount=2235(int line,)

enu FoldLevel=SC_FOLDLEVEL
val SC_FOLDLEVELBASE=0x400
val SC_FOLDLEVELWHITEFLAG=0x1000
val SC_FOLDLEVELHEADERFLAG=0x2000
val SC_FOLDLEVELNUMBERMASK=0x0FFF

# Set the fold level of a line.
# This encodes an integer level along with flags indicating whether the
# line is a header and whether it is effectively white space.
set void SetFoldLevel=2222(int line, int level)

# Retrieve the fold level of a line.
get int GetFoldLevel=2223(int line,)

# Find the last child line of a header line.
get int GetLastChild=2224(int line, int level)

# Find the parent line of a child line.
get int GetFoldParent=2225(int line,)

# Make a range of lines visible.
fun void ShowLines=2226(int lineStart, int lineEnd)

# Make a range of lines invisible.
fun void HideLines=2227(int lineStart, int lineEnd)

# Is a line visible?
get bool GetLineVisible=2228(int line,)

# Are all lines visible?
get bool GetAllLinesVisible=2236(,)

# Show the children of a header line.
set void SetFoldExpanded=2229(int line, bool expanded)

# Is a header line expanded?
get bool GetFoldExpanded=2230(int line,)

# Switch a header line between expanded and contracted.
fun void ToggleFold=2231(int line,)

# Ensure a particular line is visible by expanding any header line hiding it.
fun void EnsureVisible=2232(int line,)

enu FoldFlag=SC_FOLDFLAG_
val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002
val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004
val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008
val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010
val SC_FOLDFLAG_LEVELNUMBERS=0x0040

# Set some style options for folding.
set void SetFoldFlags=2233(int flags,)

# Ensure a particular line is visible by expanding any header line hiding it.
# Use the currently set visibility policy to determine which range to display.
fun void EnsureVisibleEnforcePolicy=2234(int line,)

# Sets whether a tab pressed when caret is within indentation indents.
set void SetTabIndents=2260(bool tabIndents,)

# Does a tab pressed when caret is within indentation indent?
get bool GetTabIndents=2261(,)

# Sets whether a backspace pressed when caret is within indentation unindents.
set void SetBackSpaceUnIndents=2262(bool bsUnIndents,)

# Does a backspace pressed when caret is within indentation unindent?
get bool GetBackSpaceUnIndents=2263(,)

val SC_TIME_FOREVER=10000000

# Sets the time the mouse must sit still to generate a mouse dwell event.
set void SetMouseDwellTime=2264(int periodMilliseconds,)

# Retrieve the time the mouse must sit still to generate a mouse dwell event.
get int GetMouseDwellTime=2265(,)

# Get position of start of word.
fun int WordStartPosition=2266(position pos, bool onlyWordCharacters)

# Get position of end of word.
fun int WordEndPosition=2267(position pos, bool onlyWordCharacters)

enu Wrap=SC_WRAP_
val SC_WRAP_NONE=0
val SC_WRAP_WORD=1
val SC_WRAP_CHAR=2

# Sets whether text is word wrapped.
set void SetWrapMode=2268(int mode,)

# Retrieve whether text is word wrapped.
get int GetWrapMode=2269(,)

enu WrapVisualFlag=SC_WRAPVISUALFLAG_
val SC_WRAPVISUALFLAG_NONE=0x0000
val SC_WRAPVISUALFLAG_END=0x0001
val SC_WRAPVISUALFLAG_START=0x0002
val SC_WRAPVISUALFLAG_MARGIN=0x0004

# Set the display mode of visual flags for wrapped lines.
set void SetWrapVisualFlags=2460(int wrapVisualFlags,)

# Retrive the display mode of visual flags for wrapped lines.
get int GetWrapVisualFlags=2461(,)

enu WrapVisualLocation=SC_WRAPVISUALFLAGLOC_
val SC_WRAPVISUALFLAGLOC_DEFAULT=0x0000
val SC_WRAPVISUALFLAGLOC_END_BY_TEXT=0x0001
val SC_WRAPVISUALFLAGLOC_START_BY_TEXT=0x0002

# Set the location of visual flags for wrapped lines.
set void SetWrapVisualFlagsLocation=2462(int wrapVisualFlagsLocation,)

# Retrive the location of visual flags for wrapped lines.
get int GetWrapVisualFlagsLocation=2463(,)

# Set the start indent for wrapped lines.
set void SetWrapStartIndent=2464(int indent,)

# Retrive the start indent for wrapped lines.
get int GetWrapStartIndent=2465(,)

enu WrapIndentMode=SC_WRAPINDENT_
val SC_WRAPINDENT_FIXED=0
val SC_WRAPINDENT_SAME=1
val SC_WRAPINDENT_INDENT=2

# Sets how wrapped sublines are placed. Default is fixed.
set void SetWrapIndentMode=2472(int mode,)

# Retrieve how wrapped sublines are placed. Default is fixed.
get int GetWrapIndentMode=2473(,)

enu LineCache=SC_CACHE_
val SC_CACHE_NONE=0
val SC_CACHE_CARET=1
val SC_CACHE_PAGE=2
val SC_CACHE_DOCUMENT=3

# Sets the degree of caching of layout information.
set void SetLayoutCache=2272(int mode,)

# Retrieve the degree of caching of layout information.
get int GetLayoutCache=2273(,)

# Sets the document width assumed for scrolling.
set void SetScrollWidth=2274(int pixelWidth,)

# Retrieve the document width assumed for scrolling.
get int GetScrollWidth=2275(,)

# Sets whether the maximum width line displayed is used to set scroll width.
set void SetScrollWidthTracking=2516(bool tracking,)

# Retrieve whether the scroll width tracks wide lines.
get bool GetScrollWidthTracking=2517(,)

# Measure the pixel width of some text in a particular style.
# NUL terminated text argument.
# Does not handle tab or control characters.
fun int TextWidth=2276(int style, string text)

# Sets the scroll range so that maximum scroll position has
# the last line at the bottom of the view (default).
# Setting this to false allows scrolling one page below the last line.
set void SetEndAtLastLine=2277(bool endAtLastLine,)

# Retrieve whether the maximum scroll position has the last
# line at the bottom of the view.
get bool GetEndAtLastLine=2278(,)

# Retrieve the height of a particular line of text in pixels.
fun int TextHeight=2279(int line,)

# Show or hide the vertical scroll bar.
set void SetVScrollBar=2280(bool show,)

# Is the vertical scroll bar visible?
get bool GetVScrollBar=2281(,)

# Append a string to the end of the document without changing the selection.
fun void AppendText=2282(int length, string text)

# Is drawing done in two phases with backgrounds drawn before faoregrounds?
get bool GetTwoPhaseDraw=2283(,)

# In twoPhaseDraw mode, drawing is performed in two phases, first the background
# and then the foreground. This avoids chopping off characters that overlap the next run.
set void SetTwoPhaseDraw=2284(bool twoPhase,)

# Control font anti-aliasing.

enu FontQuality=SC_EFF_
val SC_EFF_QUALITY_MASK=0xF
val SC_EFF_QUALITY_DEFAULT=0
val SC_EFF_QUALITY_NON_ANTIALIASED=1
val SC_EFF_QUALITY_ANTIALIASED=2
val SC_EFF_QUALITY_LCD_OPTIMIZED=3

# Choose the quality level for text from the FontQuality enumeration.
set void SetFontQuality=2611(int fontQuality,)

# Retrieve the quality level for text.
get int GetFontQuality=2612(,)

# Scroll so that a display line is at the top of the display.
set void SetFirstVisibleLine=2613(int lineDisplay,)

enu MultiPaste=SC_MULTIPASTE_
val SC_MULTIPASTE_ONCE=0
val SC_MULTIPASTE_EACH=1

# Change the effect of pasting when there are multiple selections.
set void SetMultiPaste=2614(int multiPaste,)

# Retrieve the effect of pasting when there are multiple selections..
get int GetMultiPaste=2615(,)

# Retrieve the value of a tag from a regular expression search.
get int GetTag=2616(int tagNumber, stringresult tagValue)

# Make the target range start and end be the same as the selection range start and end.
fun void TargetFromSelection=2287(,)

# Join the lines in the target.
fun void LinesJoin=2288(,)

# Split the lines in the target into lines that are less wide than pixelWidth
# where possible.
fun void LinesSplit=2289(int pixelWidth,)

# Set the colours used as a chequerboard pattern in the fold margin
fun void SetFoldMarginColour=2290(bool useSetting, colour back)
fun void SetFoldMarginHiColour=2291(bool useSetting, colour fore)

## New messages go here

## Start of key messages
# Move caret down one line.
fun void LineDown=2300(,)

# Move caret down one line extending selection to new caret position.
fun void LineDownExtend=2301(,)

# Move caret up one line.
fun void LineUp=2302(,)

# Move caret up one line extending selection to new caret position.
fun void LineUpExtend=2303(,)

# Move caret left one character.
fun void CharLeft=2304(,)

# Move caret left one character extending selection to new caret position.
fun void CharLeftExtend=2305(,)

# Move caret right one character.
fun void CharRight=2306(,)

# Move caret right one character extending selection to new caret position.
fun void CharRightExtend=2307(,)

# Move caret left one word.
fun void WordLeft=2308(,)

# Move caret left one word extending selection to new caret position.
fun void WordLeftExtend=2309(,)

# Move caret right one word.
fun void WordRight=2310(,)

# Move caret right one word extending selection to new caret position.
fun void WordRightExtend=2311(,)

# Move caret to first position on line.
fun void Home=2312(,)

# Move caret to first position on line extending selection to new caret position.
fun void HomeExtend=2313(,)

# Move caret to last position on line.
fun void LineEnd=2314(,)

# Move caret to last position on line extending selection to new caret position.
fun void LineEndExtend=2315(,)

# Move caret to first position in document.
fun void DocumentStart=2316(,)

# Move caret to first position in document extending selection to new caret position.
fun void DocumentStartExtend=2317(,)

# Move caret to last position in document.
fun void DocumentEnd=2318(,)

# Move caret to last position in document extending selection to new caret position.
fun void DocumentEndExtend=2319(,)

# Move caret one page up.
fun void PageUp=2320(,)

# Move caret one page up extending selection to new caret position.
fun void PageUpExtend=2321(,)

# Move caret one page down.
fun void PageDown=2322(,)

# Move caret one page down extending selection to new caret position.
fun void PageDownExtend=2323(,)

# Switch from insert to overtype mode or the reverse.
fun void EditToggleOvertype=2324(,)

# Cancel any modes such as call tip or auto-completion list display.
fun void Cancel=2325(,)

# Delete the selection or if no selection, the character before the caret.
fun void DeleteBack=2326(,)

# If selection is empty or all on one line replace the selection with a tab character.
# If more than one line selected, indent the lines.
fun void Tab=2327(,)

# Dedent the selected lines.
fun void BackTab=2328(,)

# Insert a new line, may use a CRLF, CR or LF depending on EOL mode.
fun void NewLine=2329(,)

# Insert a Form Feed character.
fun void FormFeed=2330(,)

# Move caret to before first visible character on line.
# If already there move to first character on line.
fun void VCHome=2331(,)

# Like VCHome but extending selection to new caret position.
fun void VCHomeExtend=2332(,)

# Magnify the displayed text by increasing the sizes by 1 point.
fun void ZoomIn=2333(,)

# Make the displayed text smaller by decreasing the sizes by 1 point.
fun void ZoomOut=2334(,)

# Delete the word to the left of the caret.
fun void DelWordLeft=2335(,)

# Delete the word to the right of the caret.
fun void DelWordRight=2336(,)

# Delete the word to the right of the caret, but not the trailing non-word characters.
fun void DelWordRightEnd=2518(,)

# Cut the line containing the caret.
fun void LineCut=2337(,)

# Delete the line containing the caret.
fun void LineDelete=2338(,)

# Switch the current line with the previous.
fun void LineTranspose=2339(,)

# Duplicate the current line.
fun void LineDuplicate=2404(,)

# Transform the selection to lower case.
fun void LowerCase=2340(,)

# Transform the selection to upper case.
fun void UpperCase=2341(,)

# Scroll the document down, keeping the caret visible.
fun void LineScrollDown=2342(,)

# Scroll the document up, keeping the caret visible.
fun void LineScrollUp=2343(,)

# Delete the selection or if no selection, the character before the caret.
# Will not delete the character before at the start of a line.
fun void DeleteBackNotLine=2344(,)

# Move caret to first position on display line.
fun void HomeDisplay=2345(,)

# Move caret to first position on display line extending selection to
# new caret position.
fun void HomeDisplayExtend=2346(,)

# Move caret to last position on display line.
fun void LineEndDisplay=2347(,)

# Move caret to last position on display line extending selection to new
# caret position.
fun void LineEndDisplayExtend=2348(,)

# These are like their namesakes Home(Extend)?, LineEnd(Extend)?, VCHome(Extend)?
# except they behave differently when word-wrap is enabled:
# They go first to the start / end of the display line, like (Home|LineEnd)Display
# The difference is that, the cursor is already at the point, it goes on to the start
# or end of the document line, as appropriate for (Home|LineEnd|VCHome)(Extend)?.

fun void HomeWrap=2349(,)
fun void HomeWrapExtend=2450(,)
fun void LineEndWrap=2451(,)
fun void LineEndWrapExtend=2452(,)
fun void VCHomeWrap=2453(,)
fun void VCHomeWrapExtend=2454(,)

# Copy the line containing the caret.
fun void LineCopy=2455(,)

# Move the caret inside current view if it's not there already.
fun void MoveCaretInsideView=2401(,)

# How many characters are on a line, including end of line characters?
fun int LineLength=2350(int line,)

# Highlight the characters at two positions.
fun void BraceHighlight=2351(position pos1, position pos2)

# Use specified indicator to highlight matching braces instead of changing their style.
fun void BraceHighlightIndicator=2498(bool useBraceHighlightIndicator, int indicator)

# Highlight the character at a position indicating there is no matching brace.
fun void BraceBadLight=2352(position pos,)

# Use specified indicator to highlight non matching brace instead of changing its style.
fun void BraceBadLightIndicator=2499(bool useBraceBadLightIndicator, int indicator)

# Find the position of a matching brace or INVALID_POSITION if no match.
fun position BraceMatch=2353(position pos,)

# Are the end of line characters visible?
get bool GetViewEOL=2355(,)

# Make the end of line characters visible or invisible.
set void SetViewEOL=2356(bool visible,)

# Retrieve a pointer to the document object.
get int GetDocPointer=2357(,)

# Change the document object used.
set void SetDocPointer=2358(, int pointer)

# Set which document modification events are sent to the container.
set void SetModEventMask=2359(int mask,)

enu EdgeVisualStyle=EDGE_
val EDGE_NONE=0
val EDGE_LINE=1
val EDGE_BACKGROUND=2

# Retrieve the column number which text should be kept within.
get int GetEdgeColumn=2360(,)

# Set the column number of the edge.
# If text goes past the edge then it is highlighted.
set void SetEdgeColumn=2361(int column,)

# Retrieve the edge highlight mode.
get int GetEdgeMode=2362(,)

# The edge may be displayed by a line (EDGE_LINE) or by highlighting text that
# goes beyond it (EDGE_BACKGROUND) or not displayed at all (EDGE_NONE).
set void SetEdgeMode=2363(int mode,)

# Retrieve the colour used in edge indication.
get colour GetEdgeColour=2364(,)

# Change the colour used in edge indication.
set void SetEdgeColour=2365(colour edgeColour,)

# Sets the current caret position to be the search anchor.
fun void SearchAnchor=2366(,)

# Find some text starting at the search anchor.
# Does not ensure the selection is visible.
fun int SearchNext=2367(int flags, string text)

# Find some text starting at the search anchor and moving backwards.
# Does not ensure the selection is visible.
fun int SearchPrev=2368(int flags, string text)

# Retrieves the number of lines completely visible.
get int LinesOnScreen=2370(,)

# Set whether a pop up menu is displayed automatically when the user presses
# the wrong mouse button.
fun void UsePopUp=2371(bool allowPopUp,)

# Is the selection rectangular? The alternative is the more common stream selection.
get bool SelectionIsRectangle=2372(,)

# Set the zoom level. This number of points is added to the size of all fonts.
# It may be positive to magnify or negative to reduce.
set void SetZoom=2373(int zoom,)
# Retrieve the zoom level.
get int GetZoom=2374(,)

# Create a new document object.
# Starts with reference count of 1 and not selected into editor.
fun int CreateDocument=2375(,)
# Extend life of document.
fun void AddRefDocument=2376(, int doc)
# Release a reference to the document, deleting document if it fades to black.
fun void ReleaseDocument=2377(, int doc)

# Get which document modification events are sent to the container.
get int GetModEventMask=2378(,)

# Change internal focus flag.
set void SetFocus=2380(bool focus,)
# Get internal focus flag.
get bool GetFocus=2381(,)

enu Status=SC_STATUS_
val SC_STATUS_OK=0
val SC_STATUS_FAILURE=1
val SC_STATUS_BADALLOC=2

# Change error status - 0 = OK.
set void SetStatus=2382(int statusCode,)
# Get error status.
get int GetStatus=2383(,)

# Set whether the mouse is captured when its button is pressed.
set void SetMouseDownCaptures=2384(bool captures,)
# Get whether mouse gets captured.
get bool GetMouseDownCaptures=2385(,)

enu CursorShape=SC_CURSOR
val SC_CURSORNORMAL=-1
val SC_CURSORARROW=2
val SC_CURSORWAIT=4
val SC_CURSORREVERSEARROW=7
# Sets the cursor to one of the SC_CURSOR* values.
set void SetCursor=2386(int cursorType,)
# Get cursor type.
get int GetCursor=2387(,)

# Change the way control characters are displayed:
# If symbol is < 32, keep the drawn way, else, use the given character.
set void SetControlCharSymbol=2388(int symbol,)
# Get the way control characters are displayed.
get int GetControlCharSymbol=2389(,)

# Move to the previous change in capitalisation.
fun void WordPartLeft=2390(,)
# Move to the previous change in capitalisation extending selection
# to new caret position.
fun void WordPartLeftExtend=2391(,)
# Move to the change next in capitalisation.
fun void WordPartRight=2392(,)
# Move to the next change in capitalisation extending selection
# to new caret position.
fun void WordPartRightExtend=2393(,)

# Constants for use with SetVisiblePolicy, similar to SetCaretPolicy.
val VISIBLE_SLOP=0x01
val VISIBLE_STRICT=0x04
# Set the way the display area is determined when a particular line
# is to be moved to by Find, FindNext, GotoLine, etc.
fun void SetVisiblePolicy=2394(int visiblePolicy, int visibleSlop)

# Delete back from the current position to the start of the line.
fun void DelLineLeft=2395(,)

# Delete forwards from the current position to the end of the line.
fun void DelLineRight=2396(,)

# Get and Set the xOffset (ie, horizontal scroll position).
set void SetXOffset=2397(int newOffset,)
get int GetXOffset=2398(,)

# Set the last x chosen value to be the caret x position.
fun void ChooseCaretX=2399(,)

# Set the focus to this Scintilla widget.
fun void GrabFocus=2400(,)

enu CaretPolicy=CARET_
# Caret policy, used by SetXCaretPolicy and SetYCaretPolicy.
# If CARET_SLOP is set, we can define a slop value: caretSlop.
# This value defines an unwanted zone (UZ) where the caret is... unwanted.
# This zone is defined as a number of pixels near the vertical margins,
# and as a number of lines near the horizontal margins.
# By keeping the caret away from the edges, it is seen within its context,
# so it is likely that the identifier that the caret is on can be completely seen,
# and that the current line is seen with some of the lines following it which are
# often dependent on that line.
val CARET_SLOP=0x01
# If CARET_STRICT is set, the policy is enforced... strictly.
# The caret is centred on the display if slop is not set,
# and cannot go in the UZ if slop is set.
val CARET_STRICT=0x04
# If CARET_JUMPS is set, the display is moved more energetically
# so the caret can move in the same direction longer before the policy is applied again.
val CARET_JUMPS=0x10
# If CARET_EVEN is not set, instead of having symmetrical UZs,
# the left and bottom UZs are extended up to right and top UZs respectively.
# This way, we favour the displaying of useful information: the begining of lines,
# where most code reside, and the lines after the caret, eg. the body of a function.
val CARET_EVEN=0x08

# Set the way the caret is kept visible when going sideways.
# The exclusion zone is given in pixels.
fun void SetXCaretPolicy=2402(int caretPolicy, int caretSlop)

# Set the way the line the caret is on is kept visible.
# The exclusion zone is given in lines.
fun void SetYCaretPolicy=2403(int caretPolicy, int caretSlop)

# Set printing to line wrapped (SC_WRAP_WORD) or not line wrapped (SC_WRAP_NONE).
set void SetPrintWrapMode=2406(int mode,)

# Is printing line wrapped?
get int GetPrintWrapMode=2407(,)

# Set a fore colour for active hotspots.
set void SetHotspotActiveFore=2410(bool useSetting, colour fore)

# Get the fore colour for active hotspots.
get colour GetHotspotActiveFore=2494(,)

# Set a back colour for active hotspots.
set void SetHotspotActiveBack=2411(bool useSetting, colour back)

# Get the back colour for active hotspots.
get colour GetHotspotActiveBack=2495(,)

# Enable / Disable underlining active hotspots.
set void SetHotspotActiveUnderline=2412(bool underline,)

# Get whether underlining for active hotspots.
get bool GetHotspotActiveUnderline=2496(,)

# Limit hotspots to single line so hotspots on two lines don't merge.
set void SetHotspotSingleLine=2421(bool singleLine,)

# Get the HotspotSingleLine property
get bool GetHotspotSingleLine=2497(,)

# Move caret between paragraphs (delimited by empty lines).
fun void ParaDown=2413(,)
fun void ParaDownExtend=2414(,)
fun void ParaUp=2415(,)
fun void ParaUpExtend=2416(,)

# Given a valid document position, return the previous position taking code
# page into account. Returns 0 if passed 0.
fun position PositionBefore=2417(position pos,)

# Given a valid document position, return the next position taking code
# page into account. Maximum value returned is the last position in the document.
fun position PositionAfter=2418(position pos,)

# Copy a range of text to the clipboard. Positions are clipped into the document.
fun void CopyRange=2419(position start, position end)

# Copy argument text to the clipboard.
fun void CopyText=2420(int length, string text)

enu SelectionMode=SC_SEL_
val SC_SEL_STREAM=0
val SC_SEL_RECTANGLE=1
val SC_SEL_LINES=2
val SC_SEL_THIN=3

# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or
# by lines (SC_SEL_LINES).
set void SetSelectionMode=2422(int mode,)

# Get the mode of the current selection.
get int GetSelectionMode=2423(,)

# Retrieve the position of the start of the selection at the given line (INVALID_POSITION if no selection on this line).
fun position GetLineSelStartPosition=2424(int line,)

# Retrieve the position of the end of the selection at the given line (INVALID_POSITION if no selection on this line).
fun position GetLineSelEndPosition=2425(int line,)

## RectExtended rectangular selection moves
# Move caret down one line, extending rectangular selection to new caret position.
fun void LineDownRectExtend=2426(,)

# Move caret up one line, extending rectangular selection to new caret position.
fun void LineUpRectExtend=2427(,)

# Move caret left one character, extending rectangular selection to new caret position.
fun void CharLeftRectExtend=2428(,)

# Move caret right one character, extending rectangular selection to new caret position.
fun void CharRightRectExtend=2429(,)

# Move caret to first position on line, extending rectangular selection to new caret position.
fun void HomeRectExtend=2430(,)

# Move caret to before first visible character on line.
# If already there move to first character on line.
# In either case, extend rectangular selection to new caret position.
fun void VCHomeRectExtend=2431(,)

# Move caret to last position on line, extending rectangular selection to new caret position.
fun void LineEndRectExtend=2432(,)

# Move caret one page up, extending rectangular selection to new caret position.
fun void PageUpRectExtend=2433(,)

# Move caret one page down, extending rectangular selection to new caret position.
fun void PageDownRectExtend=2434(,)


# Move caret to top of page, or one page up if already at top of page.
fun void StutteredPageUp=2435(,)

# Move caret to top of page, or one page up if already at top of page, extending selection to new caret position.
fun void StutteredPageUpExtend=2436(,)

# Move caret to bottom of page, or one page down if already at bottom of page.
fun void StutteredPageDown=2437(,)

# Move caret to bottom of page, or one page down if already at bottom of page, extending selection to new caret position.
fun void StutteredPageDownExtend=2438(,)


# Move caret left one word, position cursor at end of word.
fun void WordLeftEnd=2439(,)

# Move caret left one word, position cursor at end of word, extending selection to new caret position.
fun void WordLeftEndExtend=2440(,)

# Move caret right one word, position cursor at end of word.
fun void WordRightEnd=2441(,)

# Move caret right one word, position cursor at end of word, extending selection to new caret position.
fun void WordRightEndExtend=2442(,)

# Set the set of characters making up whitespace for when moving or selecting by word.
# Should be called after SetWordChars.
set void SetWhitespaceChars=2443(, string characters)

# Get the set of characters making up whitespace for when moving or selecting by word.
get int GetWhitespaceChars=2647(, stringresult characters)

# Set the set of characters making up punctuation characters
# Should be called after SetWordChars.
set void SetPunctuationChars=2648(, string characters)

# Get the set of characters making up punctuation characters
get int GetPunctuationChars=2649(, stringresult characters)

# Reset the set of characters for whitespace and word characters to the defaults.
fun void SetCharsDefault=2444(,)

# Get currently selected item position in the auto-completion list
get int AutoCGetCurrent=2445(,)

# Get currently selected item text in the auto-completion list
# Returns the length of the item text
get int AutoCGetCurrentText=2610(, stringresult s)

enu CaseInsensitiveBehaviour=SC_CASEINSENSITIVEBEHAVIOUR_
val SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE=0
val SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE=1

# Set auto-completion case insensitive behaviour to either prefer case-sensitive matches or have no preference.
set void AutoCSetCaseInsensitiveBehaviour=2634(int behaviour,)

# Get auto-completion case insensitive behaviour.
get int AutoCGetCaseInsensitiveBehaviour=2635(,)

# Enlarge the document to a particular size of text bytes.
fun void Allocate=2446(int bytes,)

# Returns the target converted to UTF8.
# Return the length in bytes.
fun int TargetAsUTF8=2447(, stringresult s)

# Set the length of the utf8 argument for calling EncodedFromUTF8.
# Set to -1 and the string will be measured to the first nul.
fun void SetLengthForEncode=2448(int bytes,)

# Translates a UTF8 string into the document encoding.
# Return the length of the result in bytes.
# On error return 0.
fun int EncodedFromUTF8=2449(string utf8, stringresult encoded)

# Find the position of a column on a line taking into account tabs and
# multi-byte characters. If beyond end of line, return line end position.
fun int FindColumn=2456(int line, int column)

# Can the caret preferred x position only be changed by explicit movement commands?
get int GetCaretSticky=2457(,)

# Stop the caret preferred x position changing when the user types.
set void SetCaretSticky=2458(int useCaretStickyBehaviour,)

enu CaretSticky=SC_CARETSTICKY_
val SC_CARETSTICKY_OFF=0
val SC_CARETSTICKY_ON=1
val SC_CARETSTICKY_WHITESPACE=2

# Switch between sticky and non-sticky: meant to be bound to a key.
fun void ToggleCaretSticky=2459(,)

# Enable/Disable convert-on-paste for line endings
set void SetPasteConvertEndings=2467(bool convert,)

# Get convert-on-paste setting
get bool GetPasteConvertEndings=2468(,)

# Duplicate the selection. If selection empty duplicate the line containing the caret.
fun void SelectionDuplicate=2469(,)

val SC_ALPHA_TRANSPARENT=0
val SC_ALPHA_OPAQUE=255
val SC_ALPHA_NOALPHA=256

# Set background alpha of the caret line.
set void SetCaretLineBackAlpha=2470(int alpha,)

# Get the background alpha of the caret line.
get int GetCaretLineBackAlpha=2471(,)

enu CaretStyle=CARETSTYLE_
val CARETSTYLE_INVISIBLE=0
val CARETSTYLE_LINE=1
val CARETSTYLE_BLOCK=2

# Set the style of the caret to be drawn.
set void SetCaretStyle=2512(int caretStyle,)

# Returns the current style of the caret.
get int GetCaretStyle=2513(,)

# Set the indicator used for IndicatorFillRange and IndicatorClearRange
set void SetIndicatorCurrent=2500(int indicator,)

# Get the current indicator
get int GetIndicatorCurrent=2501(,)

# Set the value used for IndicatorFillRange
set void SetIndicatorValue=2502(int value,)

# Get the current indicator value
get int GetIndicatorValue=2503(,)

# Turn a indicator on over a range.
fun void IndicatorFillRange=2504(int position, int fillLength)

# Turn a indicator off over a range.
fun void IndicatorClearRange=2505(int position, int clearLength)

# Are any indicators present at position?
fun int IndicatorAllOnFor=2506(int position,)

# What value does a particular indicator have at at a position?
fun int IndicatorValueAt=2507(int indicator, int position)

# Where does a particular indicator start?
fun int IndicatorStart=2508(int indicator, int position)

# Where does a particular indicator end?
fun int IndicatorEnd=2509(int indicator, int position)

# Set number of entries in position cache
set void SetPositionCache=2514(int size,)

# How many entries are allocated to the position cache?
get int GetPositionCache=2515(,)

# Copy the selection, if selection empty copy the line with the caret
fun void CopyAllowLine=2519(,)

# Compact the document buffer and return a read-only pointer to the
# characters in the document.
get int GetCharacterPointer=2520(,)

# Return a read-only pointer to a range of characters in the document.
# May move the gap so that the range is contiguous, but will only move up
# to rangeLength bytes.
get int GetRangePointer=2643(int position, int rangeLength)

# Return a position which, to avoid performance costs, should not be within
# the range of a call to GetRangePointer.
get position GetGapPosition=2644(,)

# Always interpret keyboard input as Unicode
set void SetKeysUnicode=2521(bool keysUnicode,)

# Are keys always interpreted as Unicode?
get bool GetKeysUnicode=2522(,)

# Set the alpha fill colour of the given indicator.
set void IndicSetAlpha=2523(int indicator, int alpha)

# Get the alpha fill colour of the given indicator.
get int IndicGetAlpha=2524(int indicator,)

# Set the alpha outline colour of the given indicator.
set void IndicSetOutlineAlpha=2558(int indicator, int alpha)

# Get the alpha outline colour of the given indicator.
get int IndicGetOutlineAlpha=2559(int indicator,)

# Set extra ascent for each line
set void SetExtraAscent=2525(int extraAscent,)

# Get extra ascent for each line
get int GetExtraAscent=2526(,)

# Set extra descent for each line
set void SetExtraDescent=2527(int extraDescent,)

# Get extra descent for each line
get int GetExtraDescent=2528(,)

# Which symbol was defined for markerNumber with MarkerDefine
fun int MarkerSymbolDefined=2529(int markerNumber,)

# Set the text in the text margin for a line
set void MarginSetText=2530(int line, string text)

# Get the text in the text margin for a line
get int MarginGetText=2531(int line, stringresult text)

# Set the style number for the text margin for a line
set void MarginSetStyle=2532(int line, int style)

# Get the style number for the text margin for a line
get int MarginGetStyle=2533(int line,)

# Set the style in the text margin for a line
set void MarginSetStyles=2534(int line, string styles)

# Get the styles in the text margin for a line
get int MarginGetStyles=2535(int line, stringresult styles)

# Clear the margin text on all lines
fun void MarginTextClearAll=2536(,)

# Get the start of the range of style numbers used for margin text
set void MarginSetStyleOffset=2537(int style,)

# Get the start of the range of style numbers used for margin text
get int MarginGetStyleOffset=2538(,)

enu MarginOption=SC_MARGINOPTION_
val SC_MARGINOPTION_NONE=0
val SC_MARGINOPTION_SUBLINESELECT=1

# Set the margin options.
set void SetMarginOptions=2539(int marginOptions,)

# Get the margin options.
get int GetMarginOptions=2557(,)

# Set the annotation text for a line
set void AnnotationSetText=2540(int line, string text)

# Get the annotation text for a line
get int AnnotationGetText=2541(int line, stringresult text)

# Set the style number for the annotations for a line
set void AnnotationSetStyle=2542(int line, int style)

# Get the style number for the annotations for a line
get int AnnotationGetStyle=2543(int line,)

# Set the annotation styles for a line
set void AnnotationSetStyles=2544(int line, string styles)

# Get the annotation styles for a line
get int AnnotationGetStyles=2545(int line, stringresult styles)

# Get the number of annotation lines for a line
get int AnnotationGetLines=2546(int line,)

# Clear the annotations from all lines
fun void AnnotationClearAll=2547(,)

enu AnnotationVisible=ANNOTATION_
val ANNOTATION_HIDDEN=0
val ANNOTATION_STANDARD=1
val ANNOTATION_BOXED=2

# Set the visibility for the annotations for a view
set void AnnotationSetVisible=2548(int visible,)

# Get the visibility for the annotations for a view
get int AnnotationGetVisible=2549(,)

# Get the start of the range of style numbers used for annotations
set void AnnotationSetStyleOffset=2550(int style,)

# Get the start of the range of style numbers used for annotations
get int AnnotationGetStyleOffset=2551(,)

# Release all extended (>255) style numbers
fun void ReleaseAllExtendedStyles=2552(,)

# Allocate some extended (>255) style numbers and return the start of the range
fun int AllocateExtendedStyles=2553(int numberStyles,)

val UNDO_MAY_COALESCE=1

# Add a container action to the undo stack
fun void AddUndoAction=2560(int token, int flags)

# Find the position of a character from a point within the window.
fun position CharPositionFromPoint=2561(int x, int y)

# Find the position of a character from a point within the window.
# Return INVALID_POSITION if not close to text.
fun position CharPositionFromPointClose=2562(int x, int y)

# Set whether multiple selections can be made
set void SetMultipleSelection=2563(bool multipleSelection,)

# Whether multiple selections can be made
get bool GetMultipleSelection=2564(,)

# Set whether typing can be performed into multiple selections
set void SetAdditionalSelectionTyping=2565(bool additionalSelectionTyping,)

# Whether typing can be performed into multiple selections
get bool GetAdditionalSelectionTyping=2566(,)

# Set whether additional carets will blink
set void SetAdditionalCaretsBlink=2567(bool additionalCaretsBlink,)

# Whether additional carets will blink
get bool GetAdditionalCaretsBlink=2568(,)

# Set whether additional carets are visible
set void SetAdditionalCaretsVisible=2608(bool additionalCaretsBlink,)

# Whether additional carets are visible
get bool GetAdditionalCaretsVisible=2609(,)

# How many selections are there?
get int GetSelections=2570(,)

# Is every selected range empty?
get bool GetSelectionEmpty=2650(,)

# Clear selections to a single empty stream selection
fun void ClearSelections=2571(,)

# Set a simple selection
fun int SetSelection=2572(int caret, int anchor)

# Add a selection
fun int AddSelection=2573(int caret, int anchor)

# Set the main selection
set void SetMainSelection=2574(int selection,)

# Which selection is the main selection
get int GetMainSelection=2575(,)

set void SetSelectionNCaret=2576(int selection, position pos)
get position GetSelectionNCaret=2577(int selection,)
set void SetSelectionNAnchor=2578(int selection, position posAnchor)
get position GetSelectionNAnchor=2579(int selection,)
set void SetSelectionNCaretVirtualSpace=2580(int selection, int space)
get int GetSelectionNCaretVirtualSpace=2581(int selection,)
set void SetSelectionNAnchorVirtualSpace=2582(int selection, int space)
get int GetSelectionNAnchorVirtualSpace=2583(int selection,)

# Sets the position that starts the selection - this becomes the anchor.
set void SetSelectionNStart=2584(int selection, position pos)

# Returns the position at the start of the selection.
get position GetSelectionNStart=2585(int selection,)

# Sets the position that ends the selection - this becomes the currentPosition.
set void SetSelectionNEnd=2586(int selection, position pos)

# Returns the position at the end of the selection.
get position GetSelectionNEnd=2587(int selection,)

set void SetRectangularSelectionCaret=2588(position pos,)
get position GetRectangularSelectionCaret=2589(,)
set void SetRectangularSelectionAnchor=2590(position posAnchor,)
get position GetRectangularSelectionAnchor=2591(,)
set void SetRectangularSelectionCaretVirtualSpace=2592(int space,)
get int GetRectangularSelectionCaretVirtualSpace=2593(,)
set void SetRectangularSelectionAnchorVirtualSpace=2594(int space,)
get int GetRectangularSelectionAnchorVirtualSpace=2595(,)

enu VirtualSpace=SCVS_
val SCVS_NONE=0
val SCVS_RECTANGULARSELECTION=1
val SCVS_USERACCESSIBLE=2

set void SetVirtualSpaceOptions=2596(int virtualSpaceOptions,)
get int GetVirtualSpaceOptions=2597(,)

# On GTK+, allow selecting the modifier key to use for mouse-based
# rectangular selection. Often the window manager requires Alt+Mouse Drag
# for moving windows.
# Valid values are SCMOD_CTRL(default), SCMOD_ALT, or SCMOD_SUPER.

set void SetRectangularSelectionModifier=2598(int modifier,)

# Get the modifier key used for rectangular selection.
get int GetRectangularSelectionModifier=2599(,)

# Set the foreground colour of additional selections.
# Must have previously called SetSelFore with non-zero first argument for this to have an effect.
set void SetAdditionalSelFore=2600(colour fore,)

# Set the background colour of additional selections.
# Must have previously called SetSelBack with non-zero first argument for this to have an effect.
set void SetAdditionalSelBack=2601(colour back,)

# Set the alpha of the selection.
set void SetAdditionalSelAlpha=2602(int alpha,)

# Get the alpha of the selection.
get int GetAdditionalSelAlpha=2603(,)

# Set the foreground colour of additional carets.
set void SetAdditionalCaretFore=2604(colour fore,)

# Get the foreground colour of additional carets.
get colour GetAdditionalCaretFore=2605(,)

# Set the main selection to the next selection.
fun void RotateSelection=2606(,)

# Swap that caret and anchor of the main selection.
fun void SwapMainAnchorCaret=2607(,)

# Indicate that the internal state of a lexer has changed over a range and therefore
# there may be a need to redraw.
fun int ChangeLexerState=2617(position start, position end)

# Find the next line at or after lineStart that is a contracted fold header line.
# Return -1 when no more lines.
fun int ContractedFoldNext=2618(int lineStart,)

# Centre current line in window.
fun void VerticalCentreCaret=2619(,)

# Move the selected lines up one line, shifting the line above after the selection
fun void MoveSelectedLinesUp=2620(,)

# Move the selected lines down one line, shifting the line below before the selection
fun void MoveSelectedLinesDown=2621(,)

# Set the identifier reported as idFrom in notification messages.
set void SetIdentifier=2622(int identifier,)

# Get the identifier.
get int GetIdentifier=2623(,)

# Set the width for future RGBA image data.
set void RGBAImageSetWidth=2624(int width,)

# Set the height for future RGBA image data.
set void RGBAImageSetHeight=2625(int height,)

# Set the scale factor in percent for future RGBA image data.
set void RGBAImageSetScale=2651(int scalePercent,)

# Define a marker from RGBA data.
# It has the width and height from RGBAImageSetWidth/Height
fun void MarkerDefineRGBAImage=2626(int markerNumber, string pixels)

# Register an RGBA image for use in autocompletion lists.
# It has the width and height from RGBAImageSetWidth/Height
fun void RegisterRGBAImage=2627(int type, string pixels)

# Scroll to start of document.
fun void ScrollToStart=2628(,)

# Scroll to end of document.
fun void ScrollToEnd=2629(,)

val SC_TECHNOLOGY_DEFAULT=0
val SC_TECHNOLOGY_DIRECTWRITE=1

# Set the technology used.
set void SetTechnology=2630(int technology,)

# Get the tech.
get int GetTechnology=2631(,)

# Create an ILoader*.
fun int CreateLoader=2632(int bytes,)

# On OS X, show a find indicator.
fun void FindIndicatorShow=2640(position start, position end)

# On OS X, flash a find indicator, then fade out.
fun void FindIndicatorFlash=2641(position start, position end)

# On OS X, hide the find indicator.
fun void FindIndicatorHide=2642(,)

# Move caret to before first visible character on display line.
# If already there move to first character on display line.
fun void VCHomeDisplay=2652(,)

# Like VCHomeDisplay but extending selection to new caret position.
fun void VCHomeDisplayExtend=2653(,)

# Is the caret line always visible?
get bool GetCaretLineVisibleAlways=2654(,)

# Sets the caret line to always visible.
set void SetCaretLineVisibleAlways=2655(bool alwaysVisible,)

# Start notifying the container of all key presses and commands.
fun void StartRecord=3001(,)

# Stop notifying the container of all key presses and commands.
fun void StopRecord=3002(,)

# Set the lexing language of the document.
set void SetLexer=4001(int lexer,)

# Retrieve the lexing language of the document.
get int GetLexer=4002(,)

# Colourise a segment of the document using the current lexing language.
fun void Colourise=4003(position start, position end)

# Set up a value that may be used by a lexer for some optional feature.
set void SetProperty=4004(string key, string value)

# Maximum value of keywordSet parameter of SetKeyWords.
val KEYWORDSET_MAX=8

# Set up the key words used by the lexer.
set void SetKeyWords=4005(int keywordSet, string keyWords)

# Set the lexing language of the document based on string name.
set void SetLexerLanguage=4006(, string language)

# Load a lexer library (dll / so).
fun void LoadLexerLibrary=4007(, string path)

# Retrieve a "property" value previously set with SetProperty.
get int GetProperty=4008(string key, stringresult buf)

# Retrieve a "property" value previously set with SetProperty,
# with "$()" variable replacement on returned buffer.
get int GetPropertyExpanded=4009(string key, stringresult buf)

# Retrieve a "property" value previously set with SetProperty,
# interpreted as an int AFTER any "$()" variable replacement.
get int GetPropertyInt=4010(string key,)

# Retrieve the number of bits the current lexer needs for styling.
get int GetStyleBitsNeeded=4011(,)

# Retrieve the name of the lexer.
# Return the length of the text.
get int GetLexerLanguage=4012(, stringresult text)

# For private communication between an application and a known lexer.
fun int PrivateLexerCall=4013(int operation, int pointer)

# Retrieve a '\n' separated list of properties understood by the current lexer.
fun int PropertyNames=4014(, stringresult names)

enu TypeProperty=SC_TYPE_
val SC_TYPE_BOOLEAN=0
val SC_TYPE_INTEGER=1
val SC_TYPE_STRING=2

# Retrieve the type of a property.
fun int PropertyType=4015(string name,)

# Describe a property.
fun int DescribeProperty=4016(string name, stringresult description)

# Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer.
fun int DescribeKeyWordSets=4017(, stringresult descriptions)

# Notifications
# Type of modification and the action which caused the modification.
# These are defined as a bit mask to make it easy to specify which notifications are wanted.
# One bit is set from each of SC_MOD_* and SC_PERFORMED_*.
enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_MULTISTEPUNDOREDO SC_LASTSTEPINUNDOREDO SC_MULTILINEUNDOREDO SC_STARTACTION SC_MODEVENTMASKALL
val SC_MOD_INSERTTEXT=0x1
val SC_MOD_DELETETEXT=0x2
val SC_MOD_CHANGESTYLE=0x4
val SC_MOD_CHANGEFOLD=0x8
val SC_PERFORMED_USER=0x10
val SC_PERFORMED_UNDO=0x20
val SC_PERFORMED_REDO=0x40
val SC_MULTISTEPUNDOREDO=0x80
val SC_LASTSTEPINUNDOREDO=0x100
val SC_MOD_CHANGEMARKER=0x200
val SC_MOD_BEFOREINSERT=0x400
val SC_MOD_BEFOREDELETE=0x800
val SC_MULTILINEUNDOREDO=0x1000
val SC_STARTACTION=0x2000
val SC_MOD_CHANGEINDICATOR=0x4000
val SC_MOD_CHANGELINESTATE=0x8000
val SC_MOD_CHANGEMARGIN=0x10000
val SC_MOD_CHANGEANNOTATION=0x20000
val SC_MOD_CONTAINER=0x40000
val SC_MOD_LEXERSTATE=0x80000
val SC_MODEVENTMASKALL=0xFFFFF

enu Update=SC_UPDATE_
val SC_UPDATE_CONTENT=0x1
val SC_UPDATE_SELECTION=0x2
val SC_UPDATE_V_SCROLL=0x4
val SC_UPDATE_H_SCROLL=0x8

# For compatibility, these go through the COMMAND notification rather than NOTIFY
# and should have had exactly the same values as the EN_* constants.
# Unfortunately the SETFOCUS and KILLFOCUS are flipped over from EN_*
# As clients depend on these constants, this will not be changed.
val SCEN_CHANGE=768
val SCEN_SETFOCUS=512
val SCEN_KILLFOCUS=256

# Symbolic key codes and modifier flags.
# ASCII and other printable characters below 256.
# Extended keys above 300.

enu Keys=SCK_
val SCK_DOWN=300
val SCK_UP=301
val SCK_LEFT=302
val SCK_RIGHT=303
val SCK_HOME=304
val SCK_END=305
val SCK_PRIOR=306
val SCK_NEXT=307
val SCK_DELETE=308
val SCK_INSERT=309
val SCK_ESCAPE=7
val SCK_BACK=8
val SCK_TAB=9
val SCK_RETURN=13
val SCK_ADD=310
val SCK_SUBTRACT=311
val SCK_DIVIDE=312
val SCK_WIN=313
val SCK_RWIN=314
val SCK_MENU=315

enu KeyMod=SCMOD_
val SCMOD_NORM=0
val SCMOD_SHIFT=1
val SCMOD_CTRL=2
val SCMOD_ALT=4
val SCMOD_SUPER=8
val SCMOD_META=16

################################################
# For SciLexer.h
enu Lexer=SCLEX_
val SCLEX_CONTAINER=0
val SCLEX_NULL=1
val SCLEX_PYTHON=2
val SCLEX_CPP=3
val SCLEX_HTML=4
val SCLEX_XML=5
val SCLEX_PERL=6
val SCLEX_SQL=7
val SCLEX_VB=8
val SCLEX_PROPERTIES=9
val SCLEX_ERRORLIST=10
val SCLEX_MAKEFILE=11
val SCLEX_BATCH=12
val SCLEX_XCODE=13
val SCLEX_LATEX=14
val SCLEX_LUA=15
val SCLEX_DIFF=16
val SCLEX_CONF=17
val SCLEX_PASCAL=18
val SCLEX_AVE=19
val SCLEX_ADA=20
val SCLEX_LISP=21
val SCLEX_RUBY=22
val SCLEX_EIFFEL=23
val SCLEX_EIFFELKW=24
val SCLEX_TCL=25
val SCLEX_NNCRONTAB=26
val SCLEX_BULLANT=27
val SCLEX_VBSCRIPT=28
val SCLEX_BAAN=31
val SCLEX_MATLAB=32
val SCLEX_SCRIPTOL=33
val SCLEX_ASM=34
val SCLEX_CPPNOCASE=35
val SCLEX_FORTRAN=36
val SCLEX_F77=37
val SCLEX_CSS=38
val SCLEX_POV=39
val SCLEX_LOUT=40
val SCLEX_ESCRIPT=41
val SCLEX_PS=42
val SCLEX_NSIS=43
val SCLEX_MMIXAL=44
val SCLEX_CLW=45
val SCLEX_CLWNOCASE=46
val SCLEX_LOT=47
val SCLEX_YAML=48
val SCLEX_TEX=49
val SCLEX_METAPOST=50
val SCLEX_POWERBASIC=51
val SCLEX_FORTH=52
val SCLEX_ERLANG=53
val SCLEX_OCTAVE=54
val SCLEX_MSSQL=55
val SCLEX_VERILOG=56
val SCLEX_KIX=57
val SCLEX_GUI4CLI=58
val SCLEX_SPECMAN=59
val SCLEX_AU3=60
val SCLEX_APDL=61
val SCLEX_BASH=62
val SCLEX_ASN1=63
val SCLEX_VHDL=64
val SCLEX_CAML=65
val SCLEX_BLITZBASIC=66
val SCLEX_PUREBASIC=67
val SCLEX_HASKELL=68
val SCLEX_PHPSCRIPT=69
val SCLEX_TADS3=70
val SCLEX_REBOL=71
val SCLEX_SMALLTALK=72
val SCLEX_FLAGSHIP=73
val SCLEX_CSOUND=74
val SCLEX_FREEBASIC=75
val SCLEX_INNOSETUP=76
val SCLEX_OPAL=77
val SCLEX_SPICE=78
val SCLEX_D=79
val SCLEX_CMAKE=80
val SCLEX_GAP=81
val SCLEX_PLM=82
val SCLEX_PROGRESS=83
val SCLEX_ABAQUS=84
val SCLEX_ASYMPTOTE=85
val SCLEX_R=86
val SCLEX_MAGIK=87
val SCLEX_POWERSHELL=88
val SCLEX_MYSQL=89
val SCLEX_PO=90
val SCLEX_TAL=91
val SCLEX_COBOL=92
val SCLEX_TACL=93
val SCLEX_SORCUS=94
val SCLEX_POWERPRO=95
val SCLEX_NIMROD=96
val SCLEX_SML=97
val SCLEX_MARKDOWN=98
val SCLEX_TXT2TAGS=99
val SCLEX_A68K=100
val SCLEX_MODULA=101
val SCLEX_COFFEESCRIPT=102
val SCLEX_TCMD=103
val SCLEX_AVS=104
val SCLEX_ECL=105
val SCLEX_OSCRIPT=106
val SCLEX_VISUALPROLOG=107

# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1.
val SCLEX_AUTOMATIC=1000
# Lexical states for SCLEX_PYTHON
lex Python=SCLEX_PYTHON SCE_P_
lex Nimrod=SCLEX_NIMROD SCE_P_
val SCE_P_DEFAULT=0
val SCE_P_COMMENTLINE=1
val SCE_P_NUMBER=2
val SCE_P_STRING=3
val SCE_P_CHARACTER=4
val SCE_P_WORD=5
val SCE_P_TRIPLE=6
val SCE_P_TRIPLEDOUBLE=7
val SCE_P_CLASSNAME=8
val SCE_P_DEFNAME=9
val SCE_P_OPERATOR=10
val SCE_P_IDENTIFIER=11
val SCE_P_COMMENTBLOCK=12
val SCE_P_STRINGEOL=13
val SCE_P_WORD2=14
val SCE_P_DECORATOR=15
# Lexical states for SCLEX_CPP
lex Cpp=SCLEX_CPP SCE_C_
lex BullAnt=SCLEX_BULLANT SCE_C_
val SCE_C_DEFAULT=0
val SCE_C_COMMENT=1
val SCE_C_COMMENTLINE=2
val SCE_C_COMMENTDOC=3
val SCE_C_NUMBER=4
val SCE_C_WORD=5
val SCE_C_STRING=6
val SCE_C_CHARACTER=7
val SCE_C_UUID=8
val SCE_C_PREPROCESSOR=9
val SCE_C_OPERATOR=10
val SCE_C_IDENTIFIER=11
val SCE_C_STRINGEOL=12
val SCE_C_VERBATIM=13
val SCE_C_REGEX=14
val SCE_C_COMMENTLINEDOC=15
val SCE_C_WORD2=16
val SCE_C_COMMENTDOCKEYWORD=17
val SCE_C_COMMENTDOCKEYWORDERROR=18
val SCE_C_GLOBALCLASS=19
val SCE_C_STRINGRAW=20
val SCE_C_TRIPLEVERBATIM=21
val SCE_C_HASHQUOTEDSTRING=22
val SCE_C_PREPROCESSORCOMMENT=23
# Lexical states for SCLEX_D
lex D=SCLEX_D SCE_D_
val SCE_D_DEFAULT=0
val SCE_D_COMMENT=1
val SCE_D_COMMENTLINE=2
val SCE_D_COMMENTDOC=3
val SCE_D_COMMENTNESTED=4
val SCE_D_NUMBER=5
val SCE_D_WORD=6
val SCE_D_WORD2=7
val SCE_D_WORD3=8
val SCE_D_TYPEDEF=9
val SCE_D_STRING=10
val SCE_D_STRINGEOL=11
val SCE_D_CHARACTER=12
val SCE_D_OPERATOR=13
val SCE_D_IDENTIFIER=14
val SCE_D_COMMENTLINEDOC=15
val SCE_D_COMMENTDOCKEYWORD=16
val SCE_D_COMMENTDOCKEYWORDERROR=17
val SCE_D_STRINGB=18
val SCE_D_STRINGR=19
val SCE_D_WORD5=20
val SCE_D_WORD6=21
val SCE_D_WORD7=22
# Lexical states for SCLEX_TCL
lex TCL=SCLEX_TCL SCE_TCL_
val SCE_TCL_DEFAULT=0
val SCE_TCL_COMMENT=1
val SCE_TCL_COMMENTLINE=2
val SCE_TCL_NUMBER=3
val SCE_TCL_WORD_IN_QUOTE=4
val SCE_TCL_IN_QUOTE=5
val SCE_TCL_OPERATOR=6
val SCE_TCL_IDENTIFIER=7
val SCE_TCL_SUBSTITUTION=8
val SCE_TCL_SUB_BRACE=9
val SCE_TCL_MODIFIER=10
val SCE_TCL_EXPAND=11
val SCE_TCL_WORD=12
val SCE_TCL_WORD2=13
val SCE_TCL_WORD3=14
val SCE_TCL_WORD4=15
val SCE_TCL_WORD5=16
val SCE_TCL_WORD6=17
val SCE_TCL_WORD7=18
val SCE_TCL_WORD8=19
val SCE_TCL_COMMENT_BOX=20
val SCE_TCL_BLOCK_COMMENT=21
# Lexical states for SCLEX_HTML, SCLEX_XML
lex HTML=SCLEX_HTML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_
lex XML=SCLEX_XML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_
lex ASP=SCLEX_ASP SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_
lex PHP=SCLEX_PHP SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_
val SCE_H_DEFAULT=0
val SCE_H_TAG=1
val SCE_H_TAGUNKNOWN=2
val SCE_H_ATTRIBUTE=3
val SCE_H_ATTRIBUTEUNKNOWN=4
val SCE_H_NUMBER=5
val SCE_H_DOUBLESTRING=6
val SCE_H_SINGLESTRING=7
val SCE_H_OTHER=8
val SCE_H_COMMENT=9
val SCE_H_ENTITY=10
# XML and ASP
val SCE_H_TAGEND=11
val SCE_H_XMLSTART=12
val SCE_H_XMLEND=13
val SCE_H_SCRIPT=14
val SCE_H_ASP=15
val SCE_H_ASPAT=16
val SCE_H_CDATA=17
val SCE_H_QUESTION=18
# More HTML
val SCE_H_VALUE=19
# X-Code
val SCE_H_XCCOMMENT=20
# SGML
val SCE_H_SGML_DEFAULT=21
val SCE_H_SGML_COMMAND=22
val SCE_H_SGML_1ST_PARAM=23
val SCE_H_SGML_DOUBLESTRING=24
val SCE_H_SGML_SIMPLESTRING=25
val SCE_H_SGML_ERROR=26
val SCE_H_SGML_SPECIAL=27
val SCE_H_SGML_ENTITY=28
val SCE_H_SGML_COMMENT=29
val SCE_H_SGML_1ST_PARAM_COMMENT=30
val SCE_H_SGML_BLOCK_DEFAULT=31
# Embedded Javascript
val SCE_HJ_START=40
val SCE_HJ_DEFAULT=41
val SCE_HJ_COMMENT=42
val SCE_HJ_COMMENTLINE=43
val SCE_HJ_COMMENTDOC=44
val SCE_HJ_NUMBER=45
val SCE_HJ_WORD=46
val SCE_HJ_KEYWORD=47
val SCE_HJ_DOUBLESTRING=48
val SCE_HJ_SINGLESTRING=49
val SCE_HJ_SYMBOLS=50
val SCE_HJ_STRINGEOL=51
val SCE_HJ_REGEX=52
# ASP Javascript
val SCE_HJA_START=55
val SCE_HJA_DEFAULT=56
val SCE_HJA_COMMENT=57
val SCE_HJA_COMMENTLINE=58
val SCE_HJA_COMMENTDOC=59
val SCE_HJA_NUMBER=60
val SCE_HJA_WORD=61
val SCE_HJA_KEYWORD=62
val SCE_HJA_DOUBLESTRING=63
val SCE_HJA_SINGLESTRING=64
val SCE_HJA_SYMBOLS=65
val SCE_HJA_STRINGEOL=66
val SCE_HJA_REGEX=67
# Embedded VBScript
val SCE_HB_START=70
val SCE_HB_DEFAULT=71
val SCE_HB_COMMENTLINE=72
val SCE_HB_NUMBER=73
val SCE_HB_WORD=74
val SCE_HB_STRING=75
val SCE_HB_IDENTIFIER=76
val SCE_HB_STRINGEOL=77
# ASP VBScript
val SCE_HBA_START=80
val SCE_HBA_DEFAULT=81
val SCE_HBA_COMMENTLINE=82
val SCE_HBA_NUMBER=83
val SCE_HBA_WORD=84
val SCE_HBA_STRING=85
val SCE_HBA_IDENTIFIER=86
val SCE_HBA_STRINGEOL=87
# Embedded Python
val SCE_HP_START=90
val SCE_HP_DEFAULT=91
val SCE_HP_COMMENTLINE=92
val SCE_HP_NUMBER=93
val SCE_HP_STRING=94
val SCE_HP_CHARACTER=95
val SCE_HP_WORD=96
val SCE_HP_TRIPLE=97
val SCE_HP_TRIPLEDOUBLE=98
val SCE_HP_CLASSNAME=99
val SCE_HP_DEFNAME=100
val SCE_HP_OPERATOR=101
val SCE_HP_IDENTIFIER=102
# PHP
val SCE_HPHP_COMPLEX_VARIABLE=104
# ASP Python
val SCE_HPA_START=105
val SCE_HPA_DEFAULT=106
val SCE_HPA_COMMENTLINE=107
val SCE_HPA_NUMBER=108
val SCE_HPA_STRING=109
val SCE_HPA_CHARACTER=110
val SCE_HPA_WORD=111
val SCE_HPA_TRIPLE=112
val SCE_HPA_TRIPLEDOUBLE=113
val SCE_HPA_CLASSNAME=114
val SCE_HPA_DEFNAME=115
val SCE_HPA_OPERATOR=116
val SCE_HPA_IDENTIFIER=117
# PHP
val SCE_HPHP_DEFAULT=118
val SCE_HPHP_HSTRING=119
val SCE_HPHP_SIMPLESTRING=120
val SCE_HPHP_WORD=121
val SCE_HPHP_NUMBER=122
val SCE_HPHP_VARIABLE=123
val SCE_HPHP_COMMENT=124
val SCE_HPHP_COMMENTLINE=125
val SCE_HPHP_HSTRING_VARIABLE=126
val SCE_HPHP_OPERATOR=127
# Lexical states for SCLEX_PERL
lex Perl=SCLEX_PERL SCE_PL_
val SCE_PL_DEFAULT=0
val SCE_PL_ERROR=1
val SCE_PL_COMMENTLINE=2
val SCE_PL_POD=3
val SCE_PL_NUMBER=4
val SCE_PL_WORD=5
val SCE_PL_STRING=6
val SCE_PL_CHARACTER=7
val SCE_PL_PUNCTUATION=8
val SCE_PL_PREPROCESSOR=9
val SCE_PL_OPERATOR=10
val SCE_PL_IDENTIFIER=11
val SCE_PL_SCALAR=12
val SCE_PL_ARRAY=13
val SCE_PL_HASH=14
val SCE_PL_SYMBOLTABLE=15
val SCE_PL_VARIABLE_INDEXER=16
val SCE_PL_REGEX=17
val SCE_PL_REGSUBST=18
val SCE_PL_LONGQUOTE=19
val SCE_PL_BACKTICKS=20
val SCE_PL_DATASECTION=21
val SCE_PL_HERE_DELIM=22
val SCE_PL_HERE_Q=23
val SCE_PL_HERE_QQ=24
val SCE_PL_HERE_QX=25
val SCE_PL_STRING_Q=26
val SCE_PL_STRING_QQ=27
val SCE_PL_STRING_QX=28
val SCE_PL_STRING_QR=29
val SCE_PL_STRING_QW=30
val SCE_PL_POD_VERB=31
val SCE_PL_SUB_PROTOTYPE=40
val SCE_PL_FORMAT_IDENT=41
val SCE_PL_FORMAT=42
val SCE_PL_STRING_VAR=43
val SCE_PL_XLAT=44
val SCE_PL_REGEX_VAR=54
val SCE_PL_REGSUBST_VAR=55
val SCE_PL_BACKTICKS_VAR=57
val SCE_PL_HERE_QQ_VAR=61
val SCE_PL_HERE_QX_VAR=62
val SCE_PL_STRING_QQ_VAR=64
val SCE_PL_STRING_QX_VAR=65
val SCE_PL_STRING_QR_VAR=66
# Lexical states for SCLEX_RUBY
lex Ruby=SCLEX_RUBY SCE_RB_
val SCE_RB_DEFAULT=0
val SCE_RB_ERROR=1
val SCE_RB_COMMENTLINE=2
val SCE_RB_POD=3
val SCE_RB_NUMBER=4
val SCE_RB_WORD=5
val SCE_RB_STRING=6
val SCE_RB_CHARACTER=7
val SCE_RB_CLASSNAME=8
val SCE_RB_DEFNAME=9
val SCE_RB_OPERATOR=10
val SCE_RB_IDENTIFIER=11
val SCE_RB_REGEX=12
val SCE_RB_GLOBAL=13
val SCE_RB_SYMBOL=14
val SCE_RB_MODULE_NAME=15
val SCE_RB_INSTANCE_VAR=16
val SCE_RB_CLASS_VAR=17
val SCE_RB_BACKTICKS=18
val SCE_RB_DATASECTION=19
val SCE_RB_HERE_DELIM=20
val SCE_RB_HERE_Q=21
val SCE_RB_HERE_QQ=22
val SCE_RB_HERE_QX=23
val SCE_RB_STRING_Q=24
val SCE_RB_STRING_QQ=25
val SCE_RB_STRING_QX=26
val SCE_RB_STRING_QR=27
val SCE_RB_STRING_QW=28
val SCE_RB_WORD_DEMOTED=29
val SCE_RB_STDIN=30
val SCE_RB_STDOUT=31
val SCE_RB_STDERR=40
val SCE_RB_UPPER_BOUND=41
# Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC
lex VB=SCLEX_VB SCE_B_
lex VBScript=SCLEX_VBSCRIPT SCE_B_
lex PowerBasic=SCLEX_POWERBASIC SCE_B_
val SCE_B_DEFAULT=0
val SCE_B_COMMENT=1
val SCE_B_NUMBER=2
val SCE_B_KEYWORD=3
val SCE_B_STRING=4
val SCE_B_PREPROCESSOR=5
val SCE_B_OPERATOR=6
val SCE_B_IDENTIFIER=7
val SCE_B_DATE=8
val SCE_B_STRINGEOL=9
val SCE_B_KEYWORD2=10
val SCE_B_KEYWORD3=11
val SCE_B_KEYWORD4=12
val SCE_B_CONSTANT=13
val SCE_B_ASM=14
val SCE_B_LABEL=15
val SCE_B_ERROR=16
val SCE_B_HEXNUMBER=17
val SCE_B_BINNUMBER=18
# Lexical states for SCLEX_PROPERTIES
lex Properties=SCLEX_PROPERTIES SCE_PROPS_
val SCE_PROPS_DEFAULT=0
val SCE_PROPS_COMMENT=1
val SCE_PROPS_SECTION=2
val SCE_PROPS_ASSIGNMENT=3
val SCE_PROPS_DEFVAL=4
val SCE_PROPS_KEY=5
# Lexical states for SCLEX_LATEX
lex LaTeX=SCLEX_LATEX SCE_L_
val SCE_L_DEFAULT=0
val SCE_L_COMMAND=1
val SCE_L_TAG=2
val SCE_L_MATH=3
val SCE_L_COMMENT=4
val SCE_L_TAG2=5
val SCE_L_MATH2=6
val SCE_L_COMMENT2=7
val SCE_L_VERBATIM=8
val SCE_L_SHORTCMD=9
val SCE_L_SPECIAL=10
val SCE_L_CMDOPT=11
val SCE_L_ERROR=12
# Lexical states for SCLEX_LUA
lex Lua=SCLEX_LUA SCE_LUA_
val SCE_LUA_DEFAULT=0
val SCE_LUA_COMMENT=1
val SCE_LUA_COMMENTLINE=2
val SCE_LUA_COMMENTDOC=3
val SCE_LUA_NUMBER=4
val SCE_LUA_WORD=5
val SCE_LUA_STRING=6
val SCE_LUA_CHARACTER=7
val SCE_LUA_LITERALSTRING=8
val SCE_LUA_PREPROCESSOR=9
val SCE_LUA_OPERATOR=10
val SCE_LUA_IDENTIFIER=11
val SCE_LUA_STRINGEOL=12
val SCE_LUA_WORD2=13
val SCE_LUA_WORD3=14
val SCE_LUA_WORD4=15
val SCE_LUA_WORD5=16
val SCE_LUA_WORD6=17
val SCE_LUA_WORD7=18
val SCE_LUA_WORD8=19
val SCE_LUA_LABEL=20
# Lexical states for SCLEX_ERRORLIST
lex ErrorList=SCLEX_ERRORLIST SCE_ERR_
val SCE_ERR_DEFAULT=0
val SCE_ERR_PYTHON=1
val SCE_ERR_GCC=2
val SCE_ERR_MS=3
val SCE_ERR_CMD=4
val SCE_ERR_BORLAND=5
val SCE_ERR_PERL=6
val SCE_ERR_NET=7
val SCE_ERR_LUA=8
val SCE_ERR_CTAG=9
val SCE_ERR_DIFF_CHANGED=10
val SCE_ERR_DIFF_ADDITION=11
val SCE_ERR_DIFF_DELETION=12
val SCE_ERR_DIFF_MESSAGE=13
val SCE_ERR_PHP=14
val SCE_ERR_ELF=15
val SCE_ERR_IFC=16
val SCE_ERR_IFORT=17
val SCE_ERR_ABSF=18
val SCE_ERR_TIDY=19
val SCE_ERR_JAVA_STACK=20
val SCE_ERR_VALUE=21
val SCE_ERR_GCC_INCLUDED_FROM=22
# Lexical states for SCLEX_BATCH
lex Batch=SCLEX_BATCH SCE_BAT_
val SCE_BAT_DEFAULT=0
val SCE_BAT_COMMENT=1
val SCE_BAT_WORD=2
val SCE_BAT_LABEL=3
val SCE_BAT_HIDE=4
val SCE_BAT_COMMAND=5
val SCE_BAT_IDENTIFIER=6
val SCE_BAT_OPERATOR=7
# Lexical states for SCLEX_TCMD
lex TCMD=SCLEX_TCMD SCE_TCMD_
val SCE_TCMD_DEFAULT=0
val SCE_TCMD_COMMENT=1
val SCE_TCMD_WORD=2
val SCE_TCMD_LABEL=3
val SCE_TCMD_HIDE=4
val SCE_TCMD_COMMAND=5
val SCE_TCMD_IDENTIFIER=6
val SCE_TCMD_OPERATOR=7
val SCE_TCMD_ENVIRONMENT=8
val SCE_TCMD_EXPANSION=9
val SCE_TCMD_CLABEL=10
# Lexical states for SCLEX_MAKEFILE
lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_
val SCE_MAKE_DEFAULT=0
val SCE_MAKE_COMMENT=1
val SCE_MAKE_PREPROCESSOR=2
val SCE_MAKE_IDENTIFIER=3
val SCE_MAKE_OPERATOR=4
val SCE_MAKE_TARGET=5
val SCE_MAKE_IDEOL=9
# Lexical states for SCLEX_DIFF
lex Diff=SCLEX_DIFF SCE_DIFF_
val SCE_DIFF_DEFAULT=0
val SCE_DIFF_COMMENT=1
val SCE_DIFF_COMMAND=2
val SCE_DIFF_HEADER=3
val SCE_DIFF_POSITION=4
val SCE_DIFF_DELETED=5
val SCE_DIFF_ADDED=6
val SCE_DIFF_CHANGED=7
# Lexical states for SCLEX_CONF (Apache Configuration Files Lexer)
lex Conf=SCLEX_CONF SCE_CONF_
val SCE_CONF_DEFAULT=0
val SCE_CONF_COMMENT=1
val SCE_CONF_NUMBER=2
val SCE_CONF_IDENTIFIER=3
val SCE_CONF_EXTENSION=4
val SCE_CONF_PARAMETER=5
val SCE_CONF_STRING=6
val SCE_CONF_OPERATOR=7
val SCE_CONF_IP=8
val SCE_CONF_DIRECTIVE=9
# Lexical states for SCLEX_AVE, Avenue
lex Avenue=SCLEX_AVE SCE_AVE_
val SCE_AVE_DEFAULT=0
val SCE_AVE_COMMENT=1
val SCE_AVE_NUMBER=2
val SCE_AVE_WORD=3
val SCE_AVE_STRING=6
val SCE_AVE_ENUM=7
val SCE_AVE_STRINGEOL=8
val SCE_AVE_IDENTIFIER=9
val SCE_AVE_OPERATOR=10
val SCE_AVE_WORD1=11
val SCE_AVE_WORD2=12
val SCE_AVE_WORD3=13
val SCE_AVE_WORD4=14
val SCE_AVE_WORD5=15
val SCE_AVE_WORD6=16
# Lexical states for SCLEX_ADA
lex Ada=SCLEX_ADA SCE_ADA_
val SCE_ADA_DEFAULT=0
val SCE_ADA_WORD=1
val SCE_ADA_IDENTIFIER=2
val SCE_ADA_NUMBER=3
val SCE_ADA_DELIMITER=4
val SCE_ADA_CHARACTER=5
val SCE_ADA_CHARACTEREOL=6
val SCE_ADA_STRING=7
val SCE_ADA_STRINGEOL=8
val SCE_ADA_LABEL=9
val SCE_ADA_COMMENTLINE=10
val SCE_ADA_ILLEGAL=11
# Lexical states for SCLEX_BAAN
lex Baan=SCLEX_BAAN SCE_BAAN_
val SCE_BAAN_DEFAULT=0
val SCE_BAAN_COMMENT=1
val SCE_BAAN_COMMENTDOC=2
val SCE_BAAN_NUMBER=3
val SCE_BAAN_WORD=4
val SCE_BAAN_STRING=5
val SCE_BAAN_PREPROCESSOR=6
val SCE_BAAN_OPERATOR=7
val SCE_BAAN_IDENTIFIER=8
val SCE_BAAN_STRINGEOL=9
val SCE_BAAN_WORD2=10
# Lexical states for SCLEX_LISP
lex Lisp=SCLEX_LISP SCE_LISP_
val SCE_LISP_DEFAULT=0
val SCE_LISP_COMMENT=1
val SCE_LISP_NUMBER=2
val SCE_LISP_KEYWORD=3
val SCE_LISP_KEYWORD_KW=4
val SCE_LISP_SYMBOL=5
val SCE_LISP_STRING=6
val SCE_LISP_STRINGEOL=8
val SCE_LISP_IDENTIFIER=9
val SCE_LISP_OPERATOR=10
val SCE_LISP_SPECIAL=11
val SCE_LISP_MULTI_COMMENT=12
# Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW
lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_
lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_
val SCE_EIFFEL_DEFAULT=0
val SCE_EIFFEL_COMMENTLINE=1
val SCE_EIFFEL_NUMBER=2
val SCE_EIFFEL_WORD=3
val SCE_EIFFEL_STRING=4
val SCE_EIFFEL_CHARACTER=5
val SCE_EIFFEL_OPERATOR=6
val SCE_EIFFEL_IDENTIFIER=7
val SCE_EIFFEL_STRINGEOL=8
# Lexical states for SCLEX_NNCRONTAB (nnCron crontab Lexer)
lex NNCronTab=SCLEX_NNCRONTAB SCE_NNCRONTAB_
val SCE_NNCRONTAB_DEFAULT=0
val SCE_NNCRONTAB_COMMENT=1
val SCE_NNCRONTAB_TASK=2
val SCE_NNCRONTAB_SECTION=3
val SCE_NNCRONTAB_KEYWORD=4
val SCE_NNCRONTAB_MODIFIER=5
val SCE_NNCRONTAB_ASTERISK=6
val SCE_NNCRONTAB_NUMBER=7
val SCE_NNCRONTAB_STRING=8
val SCE_NNCRONTAB_ENVIRONMENT=9
val SCE_NNCRONTAB_IDENTIFIER=10
# Lexical states for SCLEX_FORTH (Forth Lexer)
lex Forth=SCLEX_FORTH SCE_FORTH_
val SCE_FORTH_DEFAULT=0
val SCE_FORTH_COMMENT=1
val SCE_FORTH_COMMENT_ML=2
val SCE_FORTH_IDENTIFIER=3
val SCE_FORTH_CONTROL=4
val SCE_FORTH_KEYWORD=5
val SCE_FORTH_DEFWORD=6
val SCE_FORTH_PREWORD1=7
val SCE_FORTH_PREWORD2=8
val SCE_FORTH_NUMBER=9
val SCE_FORTH_STRING=10
val SCE_FORTH_LOCALE=11
# Lexical states for SCLEX_MATLAB
lex MatLab=SCLEX_MATLAB SCE_MATLAB_
val SCE_MATLAB_DEFAULT=0
val SCE_MATLAB_COMMENT=1
val SCE_MATLAB_COMMAND=2
val SCE_MATLAB_NUMBER=3
val SCE_MATLAB_KEYWORD=4
# single quoted string
val SCE_MATLAB_STRING=5
val SCE_MATLAB_OPERATOR=6
val SCE_MATLAB_IDENTIFIER=7
val SCE_MATLAB_DOUBLEQUOTESTRING=8
# Lexical states for SCLEX_SCRIPTOL
lex Sol=SCLEX_SCRIPTOL SCE_SCRIPTOL_
val SCE_SCRIPTOL_DEFAULT=0
val SCE_SCRIPTOL_WHITE=1
val SCE_SCRIPTOL_COMMENTLINE=2
val SCE_SCRIPTOL_PERSISTENT=3
val SCE_SCRIPTOL_CSTYLE=4
val SCE_SCRIPTOL_COMMENTBLOCK=5
val SCE_SCRIPTOL_NUMBER=6
val SCE_SCRIPTOL_STRING=7
val SCE_SCRIPTOL_CHARACTER=8
val SCE_SCRIPTOL_STRINGEOL=9
val SCE_SCRIPTOL_KEYWORD=10
val SCE_SCRIPTOL_OPERATOR=11
val SCE_SCRIPTOL_IDENTIFIER=12
val SCE_SCRIPTOL_TRIPLE=13
val SCE_SCRIPTOL_CLASSNAME=14
val SCE_SCRIPTOL_PREPROCESSOR=15
# Lexical states for SCLEX_ASM
lex Asm=SCLEX_ASM SCE_ASM_
val SCE_ASM_DEFAULT=0
val SCE_ASM_COMMENT=1
val SCE_ASM_NUMBER=2
val SCE_ASM_STRING=3
val SCE_ASM_OPERATOR=4
val SCE_ASM_IDENTIFIER=5
val SCE_ASM_CPUINSTRUCTION=6
val SCE_ASM_MATHINSTRUCTION=7
val SCE_ASM_REGISTER=8
val SCE_ASM_DIRECTIVE=9
val SCE_ASM_DIRECTIVEOPERAND=10
val SCE_ASM_COMMENTBLOCK=11
val SCE_ASM_CHARACTER=12
val SCE_ASM_STRINGEOL=13
val SCE_ASM_EXTINSTRUCTION=14
val SCE_ASM_COMMENTDIRECTIVE=15
# Lexical states for SCLEX_FORTRAN
lex Fortran=SCLEX_FORTRAN SCE_F_
lex F77=SCLEX_F77 SCE_F_
val SCE_F_DEFAULT=0
val SCE_F_COMMENT=1
val SCE_F_NUMBER=2
val SCE_F_STRING1=3
val SCE_F_STRING2=4
val SCE_F_STRINGEOL=5
val SCE_F_OPERATOR=6
val SCE_F_IDENTIFIER=7
val SCE_F_WORD=8
val SCE_F_WORD2=9
val SCE_F_WORD3=10
val SCE_F_PREPROCESSOR=11
val SCE_F_OPERATOR2=12
val SCE_F_LABEL=13
val SCE_F_CONTINUATION=14
# Lexical states for SCLEX_CSS
lex CSS=SCLEX_CSS SCE_CSS_
val SCE_CSS_DEFAULT=0
val SCE_CSS_TAG=1
val SCE_CSS_CLASS=2
val SCE_CSS_PSEUDOCLASS=3
val SCE_CSS_UNKNOWN_PSEUDOCLASS=4
val SCE_CSS_OPERATOR=5
val SCE_CSS_IDENTIFIER=6
val SCE_CSS_UNKNOWN_IDENTIFIER=7
val SCE_CSS_VALUE=8
val SCE_CSS_COMMENT=9
val SCE_CSS_ID=10
val SCE_CSS_IMPORTANT=11
val SCE_CSS_DIRECTIVE=12
val SCE_CSS_DOUBLESTRING=13
val SCE_CSS_SINGLESTRING=14
val SCE_CSS_IDENTIFIER2=15
val SCE_CSS_ATTRIBUTE=16
val SCE_CSS_IDENTIFIER3=17
val SCE_CSS_PSEUDOELEMENT=18
val SCE_CSS_EXTENDED_IDENTIFIER=19
val SCE_CSS_EXTENDED_PSEUDOCLASS=20
val SCE_CSS_EXTENDED_PSEUDOELEMENT=21
val SCE_CSS_MEDIA=22
val SCE_CSS_VARIABLE=23
# Lexical states for SCLEX_POV
lex POV=SCLEX_POV SCE_POV_
val SCE_POV_DEFAULT=0
val SCE_POV_COMMENT=1
val SCE_POV_COMMENTLINE=2
val SCE_POV_NUMBER=3
val SCE_POV_OPERATOR=4
val SCE_POV_IDENTIFIER=5
val SCE_POV_STRING=6
val SCE_POV_STRINGEOL=7
val SCE_POV_DIRECTIVE=8
val SCE_POV_BADDIRECTIVE=9
val SCE_POV_WORD2=10
val SCE_POV_WORD3=11
val SCE_POV_WORD4=12
val SCE_POV_WORD5=13
val SCE_POV_WORD6=14
val SCE_POV_WORD7=15
val SCE_POV_WORD8=16
# Lexical states for SCLEX_LOUT
lex LOUT=SCLEX_LOUT SCE_LOUT_
val SCE_LOUT_DEFAULT=0
val SCE_LOUT_COMMENT=1
val SCE_LOUT_NUMBER=2
val SCE_LOUT_WORD=3
val SCE_LOUT_WORD2=4
val SCE_LOUT_WORD3=5
val SCE_LOUT_WORD4=6
val SCE_LOUT_STRING=7
val SCE_LOUT_OPERATOR=8
val SCE_LOUT_IDENTIFIER=9
val SCE_LOUT_STRINGEOL=10
# Lexical states for SCLEX_ESCRIPT
lex ESCRIPT=SCLEX_ESCRIPT SCE_ESCRIPT_
val SCE_ESCRIPT_DEFAULT=0
val SCE_ESCRIPT_COMMENT=1
val SCE_ESCRIPT_COMMENTLINE=2
val SCE_ESCRIPT_COMMENTDOC=3
val SCE_ESCRIPT_NUMBER=4
val SCE_ESCRIPT_WORD=5
val SCE_ESCRIPT_STRING=6
val SCE_ESCRIPT_OPERATOR=7
val SCE_ESCRIPT_IDENTIFIER=8
val SCE_ESCRIPT_BRACE=9
val SCE_ESCRIPT_WORD2=10
val SCE_ESCRIPT_WORD3=11
# Lexical states for SCLEX_PS
lex PS=SCLEX_PS SCE_PS_
val SCE_PS_DEFAULT=0
val SCE_PS_COMMENT=1
val SCE_PS_DSC_COMMENT=2
val SCE_PS_DSC_VALUE=3
val SCE_PS_NUMBER=4
val SCE_PS_NAME=5
val SCE_PS_KEYWORD=6
val SCE_PS_LITERAL=7
val SCE_PS_IMMEVAL=8
val SCE_PS_PAREN_ARRAY=9
val SCE_PS_PAREN_DICT=10
val SCE_PS_PAREN_PROC=11
val SCE_PS_TEXT=12
val SCE_PS_HEXSTRING=13
val SCE_PS_BASE85STRING=14
val SCE_PS_BADSTRINGCHAR=15
# Lexical states for SCLEX_NSIS
lex NSIS=SCLEX_NSIS SCE_NSIS_
val SCE_NSIS_DEFAULT=0
val SCE_NSIS_COMMENT=1
val SCE_NSIS_STRINGDQ=2
val SCE_NSIS_STRINGLQ=3
val SCE_NSIS_STRINGRQ=4
val SCE_NSIS_FUNCTION=5
val SCE_NSIS_VARIABLE=6
val SCE_NSIS_LABEL=7
val SCE_NSIS_USERDEFINED=8
val SCE_NSIS_SECTIONDEF=9
val SCE_NSIS_SUBSECTIONDEF=10
val SCE_NSIS_IFDEFINEDEF=11
val SCE_NSIS_MACRODEF=12
val SCE_NSIS_STRINGVAR=13
val SCE_NSIS_NUMBER=14
val SCE_NSIS_SECTIONGROUP=15
val SCE_NSIS_PAGEEX=16
val SCE_NSIS_FUNCTIONDEF=17
val SCE_NSIS_COMMENTBOX=18
# Lexical states for SCLEX_MMIXAL
lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_
val SCE_MMIXAL_LEADWS=0
val SCE_MMIXAL_COMMENT=1
val SCE_MMIXAL_LABEL=2
val SCE_MMIXAL_OPCODE=3
val SCE_MMIXAL_OPCODE_PRE=4
val SCE_MMIXAL_OPCODE_VALID=5
val SCE_MMIXAL_OPCODE_UNKNOWN=6
val SCE_MMIXAL_OPCODE_POST=7
val SCE_MMIXAL_OPERANDS=8
val SCE_MMIXAL_NUMBER=9
val SCE_MMIXAL_REF=10
val SCE_MMIXAL_CHAR=11
val SCE_MMIXAL_STRING=12
val SCE_MMIXAL_REGISTER=13
val SCE_MMIXAL_HEX=14
val SCE_MMIXAL_OPERATOR=15
val SCE_MMIXAL_SYMBOL=16
val SCE_MMIXAL_INCLUDE=17
# Lexical states for SCLEX_CLW
lex Clarion=SCLEX_CLW SCE_CLW_
val SCE_CLW_DEFAULT=0
val SCE_CLW_LABEL=1
val SCE_CLW_COMMENT=2
val SCE_CLW_STRING=3
val SCE_CLW_USER_IDENTIFIER=4
val SCE_CLW_INTEGER_CONSTANT=5
val SCE_CLW_REAL_CONSTANT=6
val SCE_CLW_PICTURE_STRING=7
val SCE_CLW_KEYWORD=8
val SCE_CLW_COMPILER_DIRECTIVE=9
val SCE_CLW_RUNTIME_EXPRESSIONS=10
val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11
val SCE_CLW_STRUCTURE_DATA_TYPE=12
val SCE_CLW_ATTRIBUTE=13
val SCE_CLW_STANDARD_EQUATE=14
val SCE_CLW_ERROR=15
val SCE_CLW_DEPRECATED=16
# Lexical states for SCLEX_LOT
lex LOT=SCLEX_LOT SCE_LOT_
val SCE_LOT_DEFAULT=0
val SCE_LOT_HEADER=1
val SCE_LOT_BREAK=2
val SCE_LOT_SET=3
val SCE_LOT_PASS=4
val SCE_LOT_FAIL=5
val SCE_LOT_ABORT=6
# Lexical states for SCLEX_YAML
lex YAML=SCLEX_YAML SCE_YAML_
val SCE_YAML_DEFAULT=0
val SCE_YAML_COMMENT=1
val SCE_YAML_IDENTIFIER=2
val SCE_YAML_KEYWORD=3
val SCE_YAML_NUMBER=4
val SCE_YAML_REFERENCE=5
val SCE_YAML_DOCUMENT=6
val SCE_YAML_TEXT=7
val SCE_YAML_ERROR=8
val SCE_YAML_OPERATOR=9
# Lexical states for SCLEX_TEX
lex TeX=SCLEX_TEX SCE_TEX_
val SCE_TEX_DEFAULT=0
val SCE_TEX_SPECIAL=1
val SCE_TEX_GROUP=2
val SCE_TEX_SYMBOL=3
val SCE_TEX_COMMAND=4
val SCE_TEX_TEXT=5
lex Metapost=SCLEX_METAPOST SCE_METAPOST_
val SCE_METAPOST_DEFAULT=0
val SCE_METAPOST_SPECIAL=1
val SCE_METAPOST_GROUP=2
val SCE_METAPOST_SYMBOL=3
val SCE_METAPOST_COMMAND=4
val SCE_METAPOST_TEXT=5
val SCE_METAPOST_EXTRA=6
# Lexical states for SCLEX_ERLANG
lex Erlang=SCLEX_ERLANG SCE_ERLANG_
val SCE_ERLANG_DEFAULT=0
val SCE_ERLANG_COMMENT=1
val SCE_ERLANG_VARIABLE=2
val SCE_ERLANG_NUMBER=3
val SCE_ERLANG_KEYWORD=4
val SCE_ERLANG_STRING=5
val SCE_ERLANG_OPERATOR=6
val SCE_ERLANG_ATOM=7
val SCE_ERLANG_FUNCTION_NAME=8
val SCE_ERLANG_CHARACTER=9
val SCE_ERLANG_MACRO=10
val SCE_ERLANG_RECORD=11
val SCE_ERLANG_PREPROC=12
val SCE_ERLANG_NODE_NAME=13
val SCE_ERLANG_COMMENT_FUNCTION=14
val SCE_ERLANG_COMMENT_MODULE=15
val SCE_ERLANG_COMMENT_DOC=16
val SCE_ERLANG_COMMENT_DOC_MACRO=17
val SCE_ERLANG_ATOM_QUOTED=18
val SCE_ERLANG_MACRO_QUOTED=19
val SCE_ERLANG_RECORD_QUOTED=20
val SCE_ERLANG_NODE_NAME_QUOTED=21
val SCE_ERLANG_BIFS=22
val SCE_ERLANG_MODULES=23
val SCE_ERLANG_MODULES_ATT=24
val SCE_ERLANG_UNKNOWN=31
# Lexical states for SCLEX_OCTAVE are identical to MatLab
lex Octave=SCLEX_OCTAVE SCE_MATLAB_
# Lexical states for SCLEX_MSSQL
lex MSSQL=SCLEX_MSSQL SCE_MSSQL_
val SCE_MSSQL_DEFAULT=0
val SCE_MSSQL_COMMENT=1
val SCE_MSSQL_LINE_COMMENT=2
val SCE_MSSQL_NUMBER=3
val SCE_MSSQL_STRING=4
val SCE_MSSQL_OPERATOR=5
val SCE_MSSQL_IDENTIFIER=6
val SCE_MSSQL_VARIABLE=7
val SCE_MSSQL_COLUMN_NAME=8
val SCE_MSSQL_STATEMENT=9
val SCE_MSSQL_DATATYPE=10
val SCE_MSSQL_SYSTABLE=11
val SCE_MSSQL_GLOBAL_VARIABLE=12
val SCE_MSSQL_FUNCTION=13
val SCE_MSSQL_STORED_PROCEDURE=14
val SCE_MSSQL_DEFAULT_PREF_DATATYPE=15
val SCE_MSSQL_COLUMN_NAME_2=16
# Lexical states for SCLEX_VERILOG
lex Verilog=SCLEX_VERILOG SCE_V_
val SCE_V_DEFAULT=0
val SCE_V_COMMENT=1
val SCE_V_COMMENTLINE=2
val SCE_V_COMMENTLINEBANG=3
val SCE_V_NUMBER=4
val SCE_V_WORD=5
val SCE_V_STRING=6
val SCE_V_WORD2=7
val SCE_V_WORD3=8
val SCE_V_PREPROCESSOR=9
val SCE_V_OPERATOR=10
val SCE_V_IDENTIFIER=11
val SCE_V_STRINGEOL=12
val SCE_V_USER=19
# Lexical states for SCLEX_KIX
lex Kix=SCLEX_KIX SCE_KIX_
val SCE_KIX_DEFAULT=0
val SCE_KIX_COMMENT=1
val SCE_KIX_STRING1=2
val SCE_KIX_STRING2=3
val SCE_KIX_NUMBER=4
val SCE_KIX_VAR=5
val SCE_KIX_MACRO=6
val SCE_KIX_KEYWORD=7
val SCE_KIX_FUNCTIONS=8
val SCE_KIX_OPERATOR=9
val SCE_KIX_IDENTIFIER=31
# Lexical states for SCLEX_GUI4CLI
lex Gui4Cli=SCLEX_GUI4CLI SCE_GC_
val SCE_GC_DEFAULT=0
val SCE_GC_COMMENTLINE=1
val SCE_GC_COMMENTBLOCK=2
val SCE_GC_GLOBAL=3
val SCE_GC_EVENT=4
val SCE_GC_ATTRIBUTE=5
val SCE_GC_CONTROL=6
val SCE_GC_COMMAND=7
val SCE_GC_STRING=8
val SCE_GC_OPERATOR=9
# Lexical states for SCLEX_SPECMAN
lex Specman=SCLEX_SPECMAN SCE_SN_
val SCE_SN_DEFAULT=0
val SCE_SN_CODE=1
val SCE_SN_COMMENTLINE=2
val SCE_SN_COMMENTLINEBANG=3
val SCE_SN_NUMBER=4
val SCE_SN_WORD=5
val SCE_SN_STRING=6
val SCE_SN_WORD2=7
val SCE_SN_WORD3=8
val SCE_SN_PREPROCESSOR=9
val SCE_SN_OPERATOR=10
val SCE_SN_IDENTIFIER=11
val SCE_SN_STRINGEOL=12
val SCE_SN_REGEXTAG=13
val SCE_SN_SIGNAL=14
val SCE_SN_USER=19
# Lexical states for SCLEX_AU3
lex Au3=SCLEX_AU3 SCE_AU3_
val SCE_AU3_DEFAULT=0
val SCE_AU3_COMMENT=1
val SCE_AU3_COMMENTBLOCK=2
val SCE_AU3_NUMBER=3
val SCE_AU3_FUNCTION=4
val SCE_AU3_KEYWORD=5
val SCE_AU3_MACRO=6
val SCE_AU3_STRING=7
val SCE_AU3_OPERATOR=8
val SCE_AU3_VARIABLE=9
val SCE_AU3_SENT=10
val SCE_AU3_PREPROCESSOR=11
val SCE_AU3_SPECIAL=12
val SCE_AU3_EXPAND=13
val SCE_AU3_COMOBJ=14
val SCE_AU3_UDF=15
# Lexical states for SCLEX_APDL
lex APDL=SCLEX_APDL SCE_APDL_
val SCE_APDL_DEFAULT=0
val SCE_APDL_COMMENT=1
val SCE_APDL_COMMENTBLOCK=2
val SCE_APDL_NUMBER=3
val SCE_APDL_STRING=4
val SCE_APDL_OPERATOR=5
val SCE_APDL_WORD=6
val SCE_APDL_PROCESSOR=7
val SCE_APDL_COMMAND=8
val SCE_APDL_SLASHCOMMAND=9
val SCE_APDL_STARCOMMAND=10
val SCE_APDL_ARGUMENT=11
val SCE_APDL_FUNCTION=12
# Lexical states for SCLEX_BASH
lex Bash=SCLEX_BASH SCE_SH_
val SCE_SH_DEFAULT=0
val SCE_SH_ERROR=1
val SCE_SH_COMMENTLINE=2
val SCE_SH_NUMBER=3
val SCE_SH_WORD=4
val SCE_SH_STRING=5
val SCE_SH_CHARACTER=6
val SCE_SH_OPERATOR=7
val SCE_SH_IDENTIFIER=8
val SCE_SH_SCALAR=9
val SCE_SH_PARAM=10
val SCE_SH_BACKTICKS=11
val SCE_SH_HERE_DELIM=12
val SCE_SH_HERE_Q=13
# Lexical states for SCLEX_ASN1
lex Asn1=SCLEX_ASN1 SCE_ASN1_
val SCE_ASN1_DEFAULT=0
val SCE_ASN1_COMMENT=1
val SCE_ASN1_IDENTIFIER=2
val SCE_ASN1_STRING=3
val SCE_ASN1_OID=4
val SCE_ASN1_SCALAR=5
val SCE_ASN1_KEYWORD=6
val SCE_ASN1_ATTRIBUTE=7
val SCE_ASN1_DESCRIPTOR=8
val SCE_ASN1_TYPE=9
val SCE_ASN1_OPERATOR=10
# Lexical states for SCLEX_VHDL
lex VHDL=SCLEX_VHDL SCE_VHDL_
val SCE_VHDL_DEFAULT=0
val SCE_VHDL_COMMENT=1
val SCE_VHDL_COMMENTLINEBANG=2
val SCE_VHDL_NUMBER=3
val SCE_VHDL_STRING=4
val SCE_VHDL_OPERATOR=5
val SCE_VHDL_IDENTIFIER=6
val SCE_VHDL_STRINGEOL=7
val SCE_VHDL_KEYWORD=8
val SCE_VHDL_STDOPERATOR=9
val SCE_VHDL_ATTRIBUTE=10
val SCE_VHDL_STDFUNCTION=11
val SCE_VHDL_STDPACKAGE=12
val SCE_VHDL_STDTYPE=13
val SCE_VHDL_USERWORD=14
# Lexical states for SCLEX_CAML
lex Caml=SCLEX_CAML SCE_CAML_
val SCE_CAML_DEFAULT=0
val SCE_CAML_IDENTIFIER=1
val SCE_CAML_TAGNAME=2
val SCE_CAML_KEYWORD=3
val SCE_CAML_KEYWORD2=4
val SCE_CAML_KEYWORD3=5
val SCE_CAML_LINENUM=6
val SCE_CAML_OPERATOR=7
val SCE_CAML_NUMBER=8
val SCE_CAML_CHAR=9
val SCE_CAML_WHITE=10
val SCE_CAML_STRING=11
val SCE_CAML_COMMENT=12
val SCE_CAML_COMMENT1=13
val SCE_CAML_COMMENT2=14
val SCE_CAML_COMMENT3=15
# Lexical states for SCLEX_HASKELL
lex Haskell=SCLEX_HASKELL SCE_HA_
val SCE_HA_DEFAULT=0
val SCE_HA_IDENTIFIER=1
val SCE_HA_KEYWORD=2
val SCE_HA_NUMBER=3
val SCE_HA_STRING=4
val SCE_HA_CHARACTER=5
val SCE_HA_CLASS=6
val SCE_HA_MODULE=7
val SCE_HA_CAPITAL=8
val SCE_HA_DATA=9
val SCE_HA_IMPORT=10
val SCE_HA_OPERATOR=11
val SCE_HA_INSTANCE=12
val SCE_HA_COMMENTLINE=13
val SCE_HA_COMMENTBLOCK=14
val SCE_HA_COMMENTBLOCK2=15
val SCE_HA_COMMENTBLOCK3=16
# Lexical states of SCLEX_TADS3
lex TADS3=SCLEX_TADS3 SCE_T3_
val SCE_T3_DEFAULT=0
val SCE_T3_X_DEFAULT=1
val SCE_T3_PREPROCESSOR=2
val SCE_T3_BLOCK_COMMENT=3
val SCE_T3_LINE_COMMENT=4
val SCE_T3_OPERATOR=5
val SCE_T3_KEYWORD=6
val SCE_T3_NUMBER=7
val SCE_T3_IDENTIFIER=8
val SCE_T3_S_STRING=9
val SCE_T3_D_STRING=10
val SCE_T3_X_STRING=11
val SCE_T3_LIB_DIRECTIVE=12
val SCE_T3_MSG_PARAM=13
val SCE_T3_HTML_TAG=14
val SCE_T3_HTML_DEFAULT=15
val SCE_T3_HTML_STRING=16
val SCE_T3_USER1=17
val SCE_T3_USER2=18
val SCE_T3_USER3=19
val SCE_T3_BRACE=20
# Lexical states for SCLEX_REBOL
lex Rebol=SCLEX_REBOL SCE_REBOL_
val SCE_REBOL_DEFAULT=0
val SCE_REBOL_COMMENTLINE=1
val SCE_REBOL_COMMENTBLOCK=2
val SCE_REBOL_PREFACE=3
val SCE_REBOL_OPERATOR=4
val SCE_REBOL_CHARACTER=5
val SCE_REBOL_QUOTEDSTRING=6
val SCE_REBOL_BRACEDSTRING=7
val SCE_REBOL_NUMBER=8
val SCE_REBOL_PAIR=9
val SCE_REBOL_TUPLE=10
val SCE_REBOL_BINARY=11
val SCE_REBOL_MONEY=12
val SCE_REBOL_ISSUE=13
val SCE_REBOL_TAG=14
val SCE_REBOL_FILE=15
val SCE_REBOL_EMAIL=16
val SCE_REBOL_URL=17
val SCE_REBOL_DATE=18
val SCE_REBOL_TIME=19
val SCE_REBOL_IDENTIFIER=20
val SCE_REBOL_WORD=21
val SCE_REBOL_WORD2=22
val SCE_REBOL_WORD3=23
val SCE_REBOL_WORD4=24
val SCE_REBOL_WORD5=25
val SCE_REBOL_WORD6=26
val SCE_REBOL_WORD7=27
val SCE_REBOL_WORD8=28
# Lexical states for SCLEX_SQL
lex SQL=SCLEX_SQL SCE_SQL_
val SCE_SQL_DEFAULT=0
val SCE_SQL_COMMENT=1
val SCE_SQL_COMMENTLINE=2
val SCE_SQL_COMMENTDOC=3
val SCE_SQL_NUMBER=4
val SCE_SQL_WORD=5
val SCE_SQL_STRING=6
val SCE_SQL_CHARACTER=7
val SCE_SQL_SQLPLUS=8
val SCE_SQL_SQLPLUS_PROMPT=9
val SCE_SQL_OPERATOR=10
val SCE_SQL_IDENTIFIER=11
val SCE_SQL_SQLPLUS_COMMENT=13
val SCE_SQL_COMMENTLINEDOC=15
val SCE_SQL_WORD2=16
val SCE_SQL_COMMENTDOCKEYWORD=17
val SCE_SQL_COMMENTDOCKEYWORDERROR=18
val SCE_SQL_USER1=19
val SCE_SQL_USER2=20
val SCE_SQL_USER3=21
val SCE_SQL_USER4=22
val SCE_SQL_QUOTEDIDENTIFIER=23
# Lexical states for SCLEX_SMALLTALK
lex Smalltalk=SCLEX_SMALLTALK SCE_ST_
val SCE_ST_DEFAULT=0
val SCE_ST_STRING=1
val SCE_ST_NUMBER=2
val SCE_ST_COMMENT=3
val SCE_ST_SYMBOL=4
val SCE_ST_BINARY=5
val SCE_ST_BOOL=6
val SCE_ST_SELF=7
val SCE_ST_SUPER=8
val SCE_ST_NIL=9
val SCE_ST_GLOBAL=10
val SCE_ST_RETURN=11
val SCE_ST_SPECIAL=12
val SCE_ST_KWSEND=13
val SCE_ST_ASSIGN=14
val SCE_ST_CHARACTER=15
val SCE_ST_SPEC_SEL=16
# Lexical states for SCLEX_FLAGSHIP (clipper)
lex FlagShip=SCLEX_FLAGSHIP SCE_FS_
val SCE_FS_DEFAULT=0
val SCE_FS_COMMENT=1
val SCE_FS_COMMENTLINE=2
val SCE_FS_COMMENTDOC=3
val SCE_FS_COMMENTLINEDOC=4
val SCE_FS_COMMENTDOCKEYWORD=5
val SCE_FS_COMMENTDOCKEYWORDERROR=6
val SCE_FS_KEYWORD=7
val SCE_FS_KEYWORD2=8
val SCE_FS_KEYWORD3=9
val SCE_FS_KEYWORD4=10
val SCE_FS_NUMBER=11
val SCE_FS_STRING=12
val SCE_FS_PREPROCESSOR=13
val SCE_FS_OPERATOR=14
val SCE_FS_IDENTIFIER=15
val SCE_FS_DATE=16
val SCE_FS_STRINGEOL=17
val SCE_FS_CONSTANT=18
val SCE_FS_WORDOPERATOR=19
val SCE_FS_DISABLEDCODE=20
val SCE_FS_DEFAULT_C=21
val SCE_FS_COMMENTDOC_C=22
val SCE_FS_COMMENTLINEDOC_C=23
val SCE_FS_KEYWORD_C=24
val SCE_FS_KEYWORD2_C=25
val SCE_FS_NUMBER_C=26
val SCE_FS_STRING_C=27
val SCE_FS_PREPROCESSOR_C=28
val SCE_FS_OPERATOR_C=29
val SCE_FS_IDENTIFIER_C=30
val SCE_FS_STRINGEOL_C=31
# Lexical states for SCLEX_CSOUND
lex Csound=SCLEX_CSOUND SCE_CSOUND_
val SCE_CSOUND_DEFAULT=0
val SCE_CSOUND_COMMENT=1
val SCE_CSOUND_NUMBER=2
val SCE_CSOUND_OPERATOR=3
val SCE_CSOUND_INSTR=4
val SCE_CSOUND_IDENTIFIER=5
val SCE_CSOUND_OPCODE=6
val SCE_CSOUND_HEADERSTMT=7
val SCE_CSOUND_USERKEYWORD=8
val SCE_CSOUND_COMMENTBLOCK=9
val SCE_CSOUND_PARAM=10
val SCE_CSOUND_ARATE_VAR=11
val SCE_CSOUND_KRATE_VAR=12
val SCE_CSOUND_IRATE_VAR=13
val SCE_CSOUND_GLOBAL_VAR=14
val SCE_CSOUND_STRINGEOL=15
# Lexical states for SCLEX_INNOSETUP
lex Inno=SCLEX_INNOSETUP SCE_INNO_
val SCE_INNO_DEFAULT=0
val SCE_INNO_COMMENT=1
val SCE_INNO_KEYWORD=2
val SCE_INNO_PARAMETER=3
val SCE_INNO_SECTION=4
val SCE_INNO_PREPROC=5
val SCE_INNO_INLINE_EXPANSION=6
val SCE_INNO_COMMENT_PASCAL=7
val SCE_INNO_KEYWORD_PASCAL=8
val SCE_INNO_KEYWORD_USER=9
val SCE_INNO_STRING_DOUBLE=10
val SCE_INNO_STRING_SINGLE=11
val SCE_INNO_IDENTIFIER=12
# Lexical states for SCLEX_OPAL
lex Opal=SCLEX_OPAL SCE_OPAL_
val SCE_OPAL_SPACE=0
val SCE_OPAL_COMMENT_BLOCK=1
val SCE_OPAL_COMMENT_LINE=2
val SCE_OPAL_INTEGER=3
val SCE_OPAL_KEYWORD=4
val SCE_OPAL_SORT=5
val SCE_OPAL_STRING=6
val SCE_OPAL_PAR=7
val SCE_OPAL_BOOL_CONST=8
val SCE_OPAL_DEFAULT=32
# Lexical states for SCLEX_SPICE
lex Spice=SCLEX_SPICE SCE_SPICE_
val SCE_SPICE_DEFAULT=0
val SCE_SPICE_IDENTIFIER=1
val SCE_SPICE_KEYWORD=2
val SCE_SPICE_KEYWORD2=3
val SCE_SPICE_KEYWORD3=4
val SCE_SPICE_NUMBER=5
val SCE_SPICE_DELIMITER=6
val SCE_SPICE_VALUE=7
val SCE_SPICE_COMMENTLINE=8
# Lexical states for SCLEX_CMAKE
lex CMAKE=SCLEX_CMAKE SCE_CMAKE_
val SCE_CMAKE_DEFAULT=0
val SCE_CMAKE_COMMENT=1
val SCE_CMAKE_STRINGDQ=2
val SCE_CMAKE_STRINGLQ=3
val SCE_CMAKE_STRINGRQ=4
val SCE_CMAKE_COMMANDS=5
val SCE_CMAKE_PARAMETERS=6
val SCE_CMAKE_VARIABLE=7
val SCE_CMAKE_USERDEFINED=8
val SCE_CMAKE_WHILEDEF=9
val SCE_CMAKE_FOREACHDEF=10
val SCE_CMAKE_IFDEFINEDEF=11
val SCE_CMAKE_MACRODEF=12
val SCE_CMAKE_STRINGVAR=13
val SCE_CMAKE_NUMBER=14
# Lexical states for SCLEX_GAP
lex Gap=SCLEX_GAP SCE_GAP_
val SCE_GAP_DEFAULT=0
val SCE_GAP_IDENTIFIER=1
val SCE_GAP_KEYWORD=2
val SCE_GAP_KEYWORD2=3
val SCE_GAP_KEYWORD3=4
val SCE_GAP_KEYWORD4=5
val SCE_GAP_STRING=6
val SCE_GAP_CHAR=7
val SCE_GAP_OPERATOR=8
val SCE_GAP_COMMENT=9
val SCE_GAP_NUMBER=10
val SCE_GAP_STRINGEOL=11
# Lexical state for SCLEX_PLM
lex PLM=SCLEX_PLM SCE_PLM_
val SCE_PLM_DEFAULT=0
val SCE_PLM_COMMENT=1
val SCE_PLM_STRING=2
val SCE_PLM_NUMBER=3
val SCE_PLM_IDENTIFIER=4
val SCE_PLM_OPERATOR=5
val SCE_PLM_CONTROL=6
val SCE_PLM_KEYWORD=7
# Lexical state for SCLEX_PROGRESS
lex Progress=SCLEX_PROGRESS SCE_4GL_
val SCE_4GL_DEFAULT=0
val SCE_4GL_NUMBER=1
val SCE_4GL_WORD=2
val SCE_4GL_STRING=3
val SCE_4GL_CHARACTER=4
val SCE_4GL_PREPROCESSOR=5
val SCE_4GL_OPERATOR=6
val SCE_4GL_IDENTIFIER=7
val SCE_4GL_BLOCK=8
val SCE_4GL_END=9
val SCE_4GL_COMMENT1=10
val SCE_4GL_COMMENT2=11
val SCE_4GL_COMMENT3=12
val SCE_4GL_COMMENT4=13
val SCE_4GL_COMMENT5=14
val SCE_4GL_COMMENT6=15
val SCE_4GL_DEFAULT_=16
val SCE_4GL_NUMBER_=17
val SCE_4GL_WORD_=18
val SCE_4GL_STRING_=19
val SCE_4GL_CHARACTER_=20
val SCE_4GL_PREPROCESSOR_=21
val SCE_4GL_OPERATOR_=22
val SCE_4GL_IDENTIFIER_=23
val SCE_4GL_BLOCK_=24
val SCE_4GL_END_=25
val SCE_4GL_COMMENT1_=26
val SCE_4GL_COMMENT2_=27
val SCE_4GL_COMMENT3_=28
val SCE_4GL_COMMENT4_=29
val SCE_4GL_COMMENT5_=30
val SCE_4GL_COMMENT6_=31
# Lexical states for SCLEX_ABAQUS
lex ABAQUS=SCLEX_ABAQUS SCE_ABAQUS_
val SCE_ABAQUS_DEFAULT=0
val SCE_ABAQUS_COMMENT=1
val SCE_ABAQUS_COMMENTBLOCK=2
val SCE_ABAQUS_NUMBER=3
val SCE_ABAQUS_STRING=4
val SCE_ABAQUS_OPERATOR=5
val SCE_ABAQUS_WORD=6
val SCE_ABAQUS_PROCESSOR=7
val SCE_ABAQUS_COMMAND=8
val SCE_ABAQUS_SLASHCOMMAND=9
val SCE_ABAQUS_STARCOMMAND=10
val SCE_ABAQUS_ARGUMENT=11
val SCE_ABAQUS_FUNCTION=12
# Lexical states for SCLEX_ASYMPTOTE
lex Asymptote=SCLEX_ASYMPTOTE SCE_ASY_
val SCE_ASY_DEFAULT=0
val SCE_ASY_COMMENT=1
val SCE_ASY_COMMENTLINE=2
val SCE_ASY_NUMBER=3
val SCE_ASY_WORD=4
val SCE_ASY_STRING=5
val SCE_ASY_CHARACTER=6
val SCE_ASY_OPERATOR=7
val SCE_ASY_IDENTIFIER=8
val SCE_ASY_STRINGEOL=9
val SCE_ASY_COMMENTLINEDOC=10
val SCE_ASY_WORD2=11
# Lexical states for SCLEX_R
lex R=SCLEX_R SCE_R_
val SCE_R_DEFAULT=0
val SCE_R_COMMENT=1
val SCE_R_KWORD=2
val SCE_R_BASEKWORD=3
val SCE_R_OTHERKWORD=4
val SCE_R_NUMBER=5
val SCE_R_STRING=6
val SCE_R_STRING2=7
val SCE_R_OPERATOR=8
val SCE_R_IDENTIFIER=9
val SCE_R_INFIX=10
val SCE_R_INFIXEOL=11
# Lexical state for SCLEX_MAGIKSF
lex MagikSF=SCLEX_MAGIKSF SCE_MAGIK_
val SCE_MAGIK_DEFAULT=0
val SCE_MAGIK_COMMENT=1
val SCE_MAGIK_HYPER_COMMENT=16
val SCE_MAGIK_STRING=2
val SCE_MAGIK_CHARACTER=3
val SCE_MAGIK_NUMBER=4
val SCE_MAGIK_IDENTIFIER=5
val SCE_MAGIK_OPERATOR=6
val SCE_MAGIK_FLOW=7
val SCE_MAGIK_CONTAINER=8
val SCE_MAGIK_BRACKET_BLOCK=9
val SCE_MAGIK_BRACE_BLOCK=10
val SCE_MAGIK_SQBRACKET_BLOCK=11
val SCE_MAGIK_UNKNOWN_KEYWORD=12
val SCE_MAGIK_KEYWORD=13
val SCE_MAGIK_PRAGMA=14
val SCE_MAGIK_SYMBOL=15
# Lexical state for SCLEX_POWERSHELL
lex PowerShell=SCLEX_POWERSHELL SCE_POWERSHELL_
val SCE_POWERSHELL_DEFAULT=0
val SCE_POWERSHELL_COMMENT=1
val SCE_POWERSHELL_STRING=2
val SCE_POWERSHELL_CHARACTER=3
val SCE_POWERSHELL_NUMBER=4
val SCE_POWERSHELL_VARIABLE=5
val SCE_POWERSHELL_OPERATOR=6
val SCE_POWERSHELL_IDENTIFIER=7
val SCE_POWERSHELL_KEYWORD=8
val SCE_POWERSHELL_CMDLET=9
val SCE_POWERSHELL_ALIAS=10
val SCE_POWERSHELL_FUNCTION=11
val SCE_POWERSHELL_USER1=12
val SCE_POWERSHELL_COMMENTSTREAM=13
# Lexical state for SCLEX_MYSQL
lex MySQL=SCLEX_MYSQL SCE_MYSQL_
val SCE_MYSQL_DEFAULT=0
val SCE_MYSQL_COMMENT=1
val SCE_MYSQL_COMMENTLINE=2
val SCE_MYSQL_VARIABLE=3
val SCE_MYSQL_SYSTEMVARIABLE=4
val SCE_MYSQL_KNOWNSYSTEMVARIABLE=5
val SCE_MYSQL_NUMBER=6
val SCE_MYSQL_MAJORKEYWORD=7
val SCE_MYSQL_KEYWORD=8
val SCE_MYSQL_DATABASEOBJECT=9
val SCE_MYSQL_PROCEDUREKEYWORD=10
val SCE_MYSQL_STRING=11
val SCE_MYSQL_SQSTRING=12
val SCE_MYSQL_DQSTRING=13
val SCE_MYSQL_OPERATOR=14
val SCE_MYSQL_FUNCTION=15
val SCE_MYSQL_IDENTIFIER=16
val SCE_MYSQL_QUOTEDIDENTIFIER=17
val SCE_MYSQL_USER1=18
val SCE_MYSQL_USER2=19
val SCE_MYSQL_USER3=20
val SCE_MYSQL_HIDDENCOMMAND=21
val SCE_MYSQL_PLACEHOLDER=22
# Lexical state for SCLEX_PO
lex Po=SCLEX_PO SCE_PO_
val SCE_PO_DEFAULT=0
val SCE_PO_COMMENT=1
val SCE_PO_MSGID=2
val SCE_PO_MSGID_TEXT=3
val SCE_PO_MSGSTR=4
val SCE_PO_MSGSTR_TEXT=5
val SCE_PO_MSGCTXT=6
val SCE_PO_MSGCTXT_TEXT=7
val SCE_PO_FUZZY=8
val SCE_PO_PROGRAMMER_COMMENT=9
val SCE_PO_REFERENCE=10
val SCE_PO_FLAGS=11
val SCE_PO_MSGID_TEXT_EOL=12
val SCE_PO_MSGSTR_TEXT_EOL=13
val SCE_PO_MSGCTXT_TEXT_EOL=14
val SCE_PO_ERROR=15
# Lexical states for SCLEX_PASCAL
lex Pascal=SCLEX_PASCAL SCE_PAS_
val SCE_PAS_DEFAULT=0
val SCE_PAS_IDENTIFIER=1
val SCE_PAS_COMMENT=2
val SCE_PAS_COMMENT2=3
val SCE_PAS_COMMENTLINE=4
val SCE_PAS_PREPROCESSOR=5
val SCE_PAS_PREPROCESSOR2=6
val SCE_PAS_NUMBER=7
val SCE_PAS_HEXNUMBER=8
val SCE_PAS_WORD=9
val SCE_PAS_STRING=10
val SCE_PAS_STRINGEOL=11
val SCE_PAS_CHARACTER=12
val SCE_PAS_OPERATOR=13
val SCE_PAS_ASM=14
# Lexical state for SCLEX_SORCUS
lex SORCUS=SCLEX_SORCUS SCE_SORCUS_
val SCE_SORCUS_DEFAULT=0
val SCE_SORCUS_COMMAND=1
val SCE_SORCUS_PARAMETER=2
val SCE_SORCUS_COMMENTLINE=3
val SCE_SORCUS_STRING=4
val SCE_SORCUS_STRINGEOL=5
val SCE_SORCUS_IDENTIFIER=6
val SCE_SORCUS_OPERATOR=7
val SCE_SORCUS_NUMBER=8
val SCE_SORCUS_CONSTANT=9
# Lexical state for SCLEX_POWERPRO
lex PowerPro=SCLEX_POWERPRO SCE_POWERPRO_
val SCE_POWERPRO_DEFAULT=0
val SCE_POWERPRO_COMMENTBLOCK=1
val SCE_POWERPRO_COMMENTLINE=2
val SCE_POWERPRO_NUMBER=3
val SCE_POWERPRO_WORD=4
val SCE_POWERPRO_WORD2=5
val SCE_POWERPRO_WORD3=6
val SCE_POWERPRO_WORD4=7
val SCE_POWERPRO_DOUBLEQUOTEDSTRING=8
val SCE_POWERPRO_SINGLEQUOTEDSTRING=9
val SCE_POWERPRO_LINECONTINUE=10
val SCE_POWERPRO_OPERATOR=11
val SCE_POWERPRO_IDENTIFIER=12
val SCE_POWERPRO_STRINGEOL=13
val SCE_POWERPRO_VERBATIM=14
val SCE_POWERPRO_ALTQUOTE=15
val SCE_POWERPRO_FUNCTION=16
# Lexical states for SCLEX_SML
lex SML=SCLEX_SML SCE_SML_
val SCE_SML_DEFAULT=0
val SCE_SML_IDENTIFIER=1
val SCE_SML_TAGNAME=2
val SCE_SML_KEYWORD=3
val SCE_SML_KEYWORD2=4
val SCE_SML_KEYWORD3=5
val SCE_SML_LINENUM=6
val SCE_SML_OPERATOR=7
val SCE_SML_NUMBER=8
val SCE_SML_CHAR=9
val SCE_SML_STRING=11
val SCE_SML_COMMENT=12
val SCE_SML_COMMENT1=13
val SCE_SML_COMMENT2=14
val SCE_SML_COMMENT3=15
# Lexical state for SCLEX_MARKDOWN
lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_
val SCE_MARKDOWN_DEFAULT=0
val SCE_MARKDOWN_LINE_BEGIN=1
val SCE_MARKDOWN_STRONG1=2
val SCE_MARKDOWN_STRONG2=3
val SCE_MARKDOWN_EM1=4
val SCE_MARKDOWN_EM2=5
val SCE_MARKDOWN_HEADER1=6
val SCE_MARKDOWN_HEADER2=7
val SCE_MARKDOWN_HEADER3=8
val SCE_MARKDOWN_HEADER4=9
val SCE_MARKDOWN_HEADER5=10
val SCE_MARKDOWN_HEADER6=11
val SCE_MARKDOWN_PRECHAR=12
val SCE_MARKDOWN_ULIST_ITEM=13
val SCE_MARKDOWN_OLIST_ITEM=14
val SCE_MARKDOWN_BLOCKQUOTE=15
val SCE_MARKDOWN_STRIKEOUT=16
val SCE_MARKDOWN_HRULE=17
val SCE_MARKDOWN_LINK=18
val SCE_MARKDOWN_CODE=19
val SCE_MARKDOWN_CODE2=20
val SCE_MARKDOWN_CODEBK=21
# Lexical state for SCLEX_TXT2TAGS
lex Txt2tags=SCLEX_TXT2TAGS SCE_TXT2TAGS_
val SCE_TXT2TAGS_DEFAULT=0
val SCE_TXT2TAGS_LINE_BEGIN=1
val SCE_TXT2TAGS_STRONG1=2
val SCE_TXT2TAGS_STRONG2=3
val SCE_TXT2TAGS_EM1=4
val SCE_TXT2TAGS_EM2=5
val SCE_TXT2TAGS_HEADER1=6
val SCE_TXT2TAGS_HEADER2=7
val SCE_TXT2TAGS_HEADER3=8
val SCE_TXT2TAGS_HEADER4=9
val SCE_TXT2TAGS_HEADER5=10
val SCE_TXT2TAGS_HEADER6=11
val SCE_TXT2TAGS_PRECHAR=12
val SCE_TXT2TAGS_ULIST_ITEM=13
val SCE_TXT2TAGS_OLIST_ITEM=14
val SCE_TXT2TAGS_BLOCKQUOTE=15
val SCE_TXT2TAGS_STRIKEOUT=16
val SCE_TXT2TAGS_HRULE=17
val SCE_TXT2TAGS_LINK=18
val SCE_TXT2TAGS_CODE=19
val SCE_TXT2TAGS_CODE2=20
val SCE_TXT2TAGS_CODEBK=21
val SCE_TXT2TAGS_COMMENT=22
val SCE_TXT2TAGS_OPTION=23
val SCE_TXT2TAGS_PREPROC=24
val SCE_TXT2TAGS_POSTPROC=25
# Lexical states for SCLEX_A68K
lex A68k=SCLEX_A68K SCE_A68K_
val SCE_A68K_DEFAULT=0
val SCE_A68K_COMMENT=1
val SCE_A68K_NUMBER_DEC=2
val SCE_A68K_NUMBER_BIN=3
val SCE_A68K_NUMBER_HEX=4
val SCE_A68K_STRING1=5
val SCE_A68K_OPERATOR=6
val SCE_A68K_CPUINSTRUCTION=7
val SCE_A68K_EXTINSTRUCTION=8
val SCE_A68K_REGISTER=9
val SCE_A68K_DIRECTIVE=10
val SCE_A68K_MACRO_ARG=11
val SCE_A68K_LABEL=12
val SCE_A68K_STRING2=13
val SCE_A68K_IDENTIFIER=14
val SCE_A68K_MACRO_DECLARATION=15
val SCE_A68K_COMMENT_WORD=16
val SCE_A68K_COMMENT_SPECIAL=17
val SCE_A68K_COMMENT_DOXYGEN=18
# Lexical states for SCLEX_MODULA
lex Modula=SCLEX_MODULA SCE_MODULA_
val SCE_MODULA_DEFAULT=0
val SCE_MODULA_COMMENT=1
val SCE_MODULA_DOXYCOMM=2
val SCE_MODULA_DOXYKEY=3
val SCE_MODULA_KEYWORD=4
val SCE_MODULA_RESERVED=5
val SCE_MODULA_NUMBER=6
val SCE_MODULA_BASENUM=7
val SCE_MODULA_FLOAT=8
val SCE_MODULA_STRING=9
val SCE_MODULA_STRSPEC=10
val SCE_MODULA_CHAR=11
val SCE_MODULA_CHARSPEC=12
val SCE_MODULA_PROC=13
val SCE_MODULA_PRAGMA=14
val SCE_MODULA_PRGKEY=15
val SCE_MODULA_OPERATOR=16
val SCE_MODULA_BADSTR=17
# Lexical states for SCLEX_COFFEESCRIPT
lex CoffeeScript=SCLEX_COFFEESCRIPT SCE_COFFEESCRIPT_
val SCE_COFFEESCRIPT_DEFAULT=0
val SCE_COFFEESCRIPT_COMMENT=1
val SCE_COFFEESCRIPT_COMMENTLINE=2
val SCE_COFFEESCRIPT_COMMENTDOC=3
val SCE_COFFEESCRIPT_NUMBER=4
val SCE_COFFEESCRIPT_WORD=5
val SCE_COFFEESCRIPT_STRING=6
val SCE_COFFEESCRIPT_CHARACTER=7
val SCE_COFFEESCRIPT_UUID=8
val SCE_COFFEESCRIPT_PREPROCESSOR=9
val SCE_COFFEESCRIPT_OPERATOR=10
val SCE_COFFEESCRIPT_IDENTIFIER=11
val SCE_COFFEESCRIPT_STRINGEOL=12
val SCE_COFFEESCRIPT_VERBATIM=13
val SCE_COFFEESCRIPT_REGEX=14
val SCE_COFFEESCRIPT_COMMENTLINEDOC=15
val SCE_COFFEESCRIPT_WORD2=16
val SCE_COFFEESCRIPT_COMMENTDOCKEYWORD=17
val SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR=18
val SCE_COFFEESCRIPT_GLOBALCLASS=19
val SCE_COFFEESCRIPT_STRINGRAW=20
val SCE_COFFEESCRIPT_TRIPLEVERBATIM=21
val SCE_COFFEESCRIPT_HASHQUOTEDSTRING=22
val SCE_COFFEESCRIPT_COMMENTBLOCK=22
val SCE_COFFEESCRIPT_VERBOSE_REGEX=23
val SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT=24
# Lexical states for SCLEX_AVS
lex AVS=SCLEX_AVS SCE_AVS_
val SCE_AVS_DEFAULT=0
val SCE_AVS_COMMENTBLOCK=1
val SCE_AVS_COMMENTBLOCKN=2
val SCE_AVS_COMMENTLINE=3
val SCE_AVS_NUMBER=4
val SCE_AVS_OPERATOR=5
val SCE_AVS_IDENTIFIER=6
val SCE_AVS_STRING=7
val SCE_AVS_TRIPLESTRING=8
val SCE_AVS_KEYWORD=9
val SCE_AVS_FILTER=10
val SCE_AVS_PLUGIN=11
val SCE_AVS_FUNCTION=12
val SCE_AVS_CLIPPROP=13
val SCE_AVS_USERDFN=14
# Lexical states for SCLEX_ECL
lex ECL=SCLEX_ECL SCE_ECL_
val SCE_ECL_DEFAULT=0
val SCE_ECL_COMMENT=1
val SCE_ECL_COMMENTLINE=2
val SCE_ECL_NUMBER=3
val SCE_ECL_STRING=4
val SCE_ECL_WORD0=5
val SCE_ECL_OPERATOR=6
val SCE_ECL_CHARACTER=7
val SCE_ECL_UUID=8
val SCE_ECL_PREPROCESSOR=9
val SCE_ECL_UNKNOWN=10
val SCE_ECL_IDENTIFIER=11
val SCE_ECL_STRINGEOL=12
val SCE_ECL_VERBATIM=13
val SCE_ECL_REGEX=14
val SCE_ECL_COMMENTLINEDOC=15
val SCE_ECL_WORD1=16
val SCE_ECL_COMMENTDOCKEYWORD=17
val SCE_ECL_COMMENTDOCKEYWORDERROR=18
val SCE_ECL_WORD2=19
val SCE_ECL_WORD3=20
val SCE_ECL_WORD4=21
val SCE_ECL_WORD5=22
val SCE_ECL_COMMENTDOC=23
val SCE_ECL_ADDED=24
val SCE_ECL_DELETED=25
val SCE_ECL_CHANGED=26
val SCE_ECL_MOVED=27
# Lexical states for SCLEX_OSCRIPT
lex OScript=SCLEX_OSCRIPT SCE_OSCRIPT_
val SCE_OSCRIPT_DEFAULT=0
val SCE_OSCRIPT_LINE_COMMENT=1
val SCE_OSCRIPT_BLOCK_COMMENT=2
val SCE_OSCRIPT_DOC_COMMENT=3
val SCE_OSCRIPT_PREPROCESSOR=4
val SCE_OSCRIPT_NUMBER=5
val SCE_OSCRIPT_SINGLEQUOTE_STRING=6
val SCE_OSCRIPT_DOUBLEQUOTE_STRING=7
val SCE_OSCRIPT_CONSTANT=8
val SCE_OSCRIPT_IDENTIFIER=9
val SCE_OSCRIPT_GLOBAL=10
val SCE_OSCRIPT_KEYWORD=11
val SCE_OSCRIPT_OPERATOR=12
val SCE_OSCRIPT_LABEL=13
val SCE_OSCRIPT_TYPE=14
val SCE_OSCRIPT_FUNCTION=15
val SCE_OSCRIPT_OBJECT=16
val SCE_OSCRIPT_PROPERTY=17
val SCE_OSCRIPT_METHOD=18
# Lexical states for SCLEX_VISUALPROLOG
lex VisualProlog=SCLEX_VISUALPROLOG SCE_VISUALPROLOG_
val SCE_VISUALPROLOG_DEFAULT=0
val SCE_VISUALPROLOG_KEY_MAJOR=1
val SCE_VISUALPROLOG_KEY_MINOR=2
val SCE_VISUALPROLOG_KEY_DIRECTIVE=3
val SCE_VISUALPROLOG_COMMENT_BLOCK=4
val SCE_VISUALPROLOG_COMMENT_LINE=5
val SCE_VISUALPROLOG_COMMENT_KEY=6
val SCE_VISUALPROLOG_COMMENT_KEY_ERROR=7
val SCE_VISUALPROLOG_IDENTIFIER=8
val SCE_VISUALPROLOG_VARIABLE=9
val SCE_VISUALPROLOG_ANONYMOUS=10
val SCE_VISUALPROLOG_NUMBER=11
val SCE_VISUALPROLOG_OPERATOR=12
val SCE_VISUALPROLOG_CHARACTER=13
val SCE_VISUALPROLOG_CHARACTER_TOO_MANY=14
val SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR=15
val SCE_VISUALPROLOG_STRING=16
val SCE_VISUALPROLOG_STRING_ESCAPE=17
val SCE_VISUALPROLOG_STRING_ESCAPE_ERROR=18
val SCE_VISUALPROLOG_STRING_EOL_OPEN=19
val SCE_VISUALPROLOG_STRING_VERBATIM=20
val SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL=21
val SCE_VISUALPROLOG_STRING_VERBATIM_EOL=22

# Events

evt void StyleNeeded=2000(int position)
evt void CharAdded=2001(int ch)
evt void SavePointReached=2002(void)
evt void SavePointLeft=2003(void)
evt void ModifyAttemptRO=2004(void)
# GTK+ Specific to work around focus and accelerator problems:
evt void Key=2005(int ch, int modifiers)
evt void DoubleClick=2006(int modifiers, int position, int line)
evt void UpdateUI=2007(int updated)
evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev, int token, int annotationLinesAdded)
evt void MacroRecord=2009(int message, int wParam, int lParam)
evt void MarginClick=2010(int modifiers, int position, int margin)
evt void NeedShown=2011(int position, int length)
evt void Painted=2013(void)
evt void UserListSelection=2014(int listType, string text, int position)
evt void URIDropped=2015(string text)
evt void DwellStart=2016(int position, int x, int y)
evt void DwellEnd=2017(int position, int x, int y)
evt void Zoom=2018(void)
evt void HotSpotClick=2019(int modifiers, int position)
evt void HotSpotDoubleClick=2020(int modifiers, int position)
evt void CallTipClick=2021(int position)
evt void AutoCSelection=2022(string text, int position)
evt void IndicatorClick=2023(int modifiers, int position)
evt void IndicatorRelease=2024(int modifiers, int position)
evt void AutoCCancelled=2025(void)
evt void AutoCCharDeleted=2026(void)
evt void HotSpotReleaseClick=2027(int modifiers, int position)

cat Provisional

# Line end types which may be used in addition to LF, CR, and CRLF
# SC_LINE_END_TYPE_UNICODE includes U+2028 Line Separator,
# U+2029 Paragraph Separator, and U+0085 Next Line
enu LineEndType=SC_LINE_END_TYPE_
val SC_LINE_END_TYPE_DEFAULT=0
val SC_LINE_END_TYPE_UNICODE=1

# Set the line end types that the application wants to use. May not be used if incompatible with lexer or encoding.
set void SetLineEndTypesAllowed=2656(int lineEndBitSet,)

# Get the line end types currently allowed.
get int GetLineEndTypesAllowed=2657(,)

# Get the line end types currently recognised. May be a subset of the allowed types due to lexer limitation.
get int GetLineEndTypesActive=2658(,)

# Bit set of LineEndType enumertion for which line ends beyond the standard
# LF, CR, and CRLF are supported by the lexer.
get int GetLineEndTypesSupported=4018(,)

# Allocate a set of sub styles for a particular base style, returning start of range
fun int AllocateSubStyles=4020(int styleBase, int numberStyles)

# The starting style number for the sub styles associated with a base style
get int GetSubStylesStart=4021(int styleBase,)

# The number of sub styles associated with a base style
get int GetSubStylesLength=4022(int styleBase,)

# Free allocated sub styles
fun void FreeSubStyles=4023(,)

# Set the identifiers that are shown in a particular style
set void SetIdentifiers=4024(int style, string identifiers)

# Where styles are duplicated by a feature such as active/inactive code
# return the distance between the two types.
get int DistanceToSecondaryStyles=4025(,)

# Get the set of base styles that can be extended with sub styles
get int GetSubStyleBases=4026(, stringresult styles)

cat Deprecated

# Deprecated in 2.21
# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+.
val SC_CP_DBCS=1

# Deprecated in 2.30

# In palette mode?
get bool GetUsePalette=2139(,)

# In palette mode, Scintilla uses the environment's palette calls to display
# more colours. This may lead to ugly displays.
set void SetUsePalette=2039(bool usePalette,)

Added include/ScintillaWidget.h.

















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/* Scintilla source code edit control */
/** @file ScintillaWidget.h
 ** Definition of Scintilla widget for GTK+.
 ** Only needed by GTK+ code but is harmless on other platforms.
 **/
/* Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed. */

#ifndef SCINTILLAWIDGET_H
#define SCINTILLAWIDGET_H

#if defined(GTK)

#ifdef __cplusplus
extern "C" {
#endif

#define SCINTILLA(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject)
#define SCINTILLA_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass)
#define IS_SCINTILLA(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, scintilla_get_type ())

typedef struct _ScintillaObject ScintillaObject;
typedef struct _ScintillaClass  ScintillaClass;

struct _ScintillaObject {
	GtkContainer cont;
	void *pscin;
};

struct _ScintillaClass {
	GtkContainerClass parent_class;

	void (* command) (ScintillaObject *ttt);
	void (* notify) (ScintillaObject *ttt);
};

GType		scintilla_get_type	(void);
GtkWidget*	scintilla_new		(void);
void		scintilla_set_id	(ScintillaObject *sci, uptr_t id);
sptr_t		scintilla_send_message	(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam);
void		scintilla_release_resources(void);

#define SCINTILLA_NOTIFY "sci-notify"

#ifdef __cplusplus
}
#endif

#elif defined(TK)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifdef __cplusplus
extern "C" {
#endif

#include <tcl.h>
#include <tk.h>

// a simple stack dumper
void _print_trace (bool on=false);
int _x_error_handler(Display *, XErrorEvent *);

typedef struct _ScintillaObject ScintillaObject;

// pick a start value safely above what the scintilla code already uses (see Scintilla.h)
enum {
   SCI_TKMSG_PAINT = 10000,
   SCI_TKMSG_DESTROY,
   SCI_TKMSG_DUMPSTYLES,
   SCI_TKMSG_ANNOTATIONINDENT,
   SCI_TKMSG_ANNOTATIONLENGTH,
   SCI_TKMSG_RESIZE
};

struct _ScintillaObject {
   _ScintillaObject() {
//      printf("HEY -- CTOR of ScintillaObject %p\n",(void *)this);
   }
   ~_ScintillaObject() {
//      printf("HEY -- DTOR of ScintillaObject %p\n",(void *)this);
   }
   Tcl_Interp *interp;
   Tk_Window   tkwin;
   ClientData  client; // this will hold the ref to the parent Tk widget

   // pointer to the platform-specific scintilla editor class object
	void *pscin;

   // this flag indicates if this is the main(client) window
   bool main;
};

// THESE ARE IMPLEMENTED IN ScintillaTK.cxx
ScintillaObject* scintilla_new(Tcl_Interp *, Tk_Window, ClientData);
sptr_t scintilla_send_message(ScintillaObject *sci, unsigned int iMessage, uptr_t wParam, sptr_t lParam);

#ifdef __cplusplus
}
#endif

#endif //if defined(TK)

#endif

Added lexers/LexA68k.cxx.





























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// Scintilla source code edit control
/** @file LexA68k.cxx
 ** Lexer for Assembler, just for the MASM syntax
 ** Written by Martial Demolins AKA Folco
 **/
// Copyright 2010 Martial Demolins <mdemolins(a)gmail.com>
// The License.txt file describes the conditions under which this software
// may be distributed.


#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


// Return values for GetOperatorType
#define NO_OPERATOR     0
#define OPERATOR_1CHAR  1
#define OPERATOR_2CHAR  2


/**
 *  IsIdentifierStart
 *
 *  Return true if the given char is a valid identifier first char
 */

static inline bool IsIdentifierStart (const int ch)
{
    return (isalpha(ch) || (ch == '_') || (ch == '\\'));
}


/**
 *  IsIdentifierChar
 *
 *  Return true if the given char is a valid identifier char
 */

static inline bool IsIdentifierChar (const int ch)
{
    return (isalnum(ch) || (ch == '_') || (ch == '@') || (ch == ':') || (ch == '.'));
}


/**
 *  GetOperatorType
 *
 *  Return:
 *  NO_OPERATOR     if char is not an operator
 *  OPERATOR_1CHAR  if the operator is one char long
 *  OPERATOR_2CHAR  if the operator is two chars long
 */

static inline int GetOperatorType (const int ch1, const int ch2)
{
    int OpType = NO_OPERATOR;

    if ((ch1 == '+') || (ch1 == '-') || (ch1 == '*') || (ch1 == '/') || (ch1 == '#') ||
        (ch1 == '(') || (ch1 == ')') || (ch1 == '~') || (ch1 == '&') || (ch1 == '|') || (ch1 == ','))
        OpType = OPERATOR_1CHAR;

    else if ((ch1 == ch2) && (ch1 == '<' || ch1 == '>'))
        OpType = OPERATOR_2CHAR;

    return OpType;
}


/**
 *  IsBin
 *
 *  Return true if the given char is 0 or 1
 */

static inline bool IsBin (const int ch)
{
    return (ch == '0') || (ch == '1');
}


/**
 *  IsDoxygenChar
 *
 *  Return true if the char may be part of a Doxygen keyword
 */

static inline bool IsDoxygenChar (const int ch)
{
    return isalpha(ch) || (ch == '$') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}');
}


/**
 *  ColouriseA68kDoc
 *
 *  Main function, which colourises a 68k source
 */

static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler)
{

    // Get references to keywords lists
    WordList &cpuInstruction = *keywordlists[0];
    WordList &registers = *keywordlists[1];
    WordList &directive = *keywordlists[2];
    WordList &extInstruction = *keywordlists[3];
    WordList &commentSpecial = *keywordlists[4];
    WordList &doxygenKeyword = *keywordlists[5];


    // Instanciate a context for our source
    StyleContext sc(startPos, length, initStyle, styler);


    /************************************************************
    *
    *   Parse the text
    *
    ************************************************************/

    for ( ; sc.More(); sc.Forward())
    {
        char Buffer[100];
        int OpType;

        // Reset style at beginning of line
        if (sc.atLineStart)
            sc.SetState(SCE_A68K_DEFAULT);


        /************************************************************
        *
        *   Handle current state if we are not in the "default style"
        *
        ************************************************************/

        if (sc.state != SCE_A68K_DEFAULT)
        {
            // Check if current style continue.
            // If this case, we loop because there is nothing else to do
            if (((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch))                                       // Decimal number
                || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch))                                      // Binary number
                || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch))                                   // Hexa number
                || ((sc.state == SCE_A68K_MACRO_ARG)  && isdigit(sc.ch))                                    // Arg of macro
                || ((sc.state == SCE_A68K_STRING1)    && (sc.ch != '\''))                                   // String single-quoted
                || ((sc.state == SCE_A68K_STRING2)    && (sc.ch != '\"'))                                   // String double-quoted
                || ((sc.state == SCE_A68K_MACRO_ARG)  && isdigit(sc.ch))                                    // Macro argument
                // Label. ' ' and '\t' are needed to handle macro declarations
                || ((sc.state == SCE_A68K_LABEL)      && (sc.ch != ':') && (sc.ch != ' ') && (sc.ch != '\t'))
                || ((sc.state == SCE_A68K_IDENTIFIER) && (sc.ch < 0x80) && IsIdentifierChar(sc.ch))         // Identifier
                || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && IsDoxygenChar(sc.ch))       // Doxygen keyword
                || ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && isalpha(sc.ch)))               // Comment current word
            {
                continue;
            }

            // Check if some states terminate at the current char:
            // we must include this char in the current style context
            else if (((sc.state == SCE_A68K_STRING1)    && (sc.ch < 0x80) && (sc.ch == '\''))       // String single-quoted
                     || ((sc.state == SCE_A68K_STRING2) && (sc.ch < 0x80) && (sc.ch == '\"'))       // String double-quoted
                     || ((sc.state == SCE_A68K_LABEL)   && (sc.ch < 0x80) && (sc.ch == ':')))       // Label
            {
                sc.ForwardSetState(SCE_A68K_DEFAULT);
            }

            // Check for special words or Doxygen keywords in comments
            else if (sc.state == SCE_A68K_COMMENT)
            {
                if (sc.ch == '\\') {
                    sc.SetState(SCE_A68K_COMMENT_DOXYGEN);
                }
                else if ((sc.ch < 0x80) && isalpha(sc.ch)) {
                    sc.SetState(SCE_A68K_COMMENT_WORD);
                }
                continue;
            }

            // Check for special words in comment
            else if ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && !isalpha(sc.ch))
            {
                sc.GetCurrent(Buffer, sizeof(Buffer));
                if (commentSpecial.InList(Buffer)) {
                    sc.ChangeState(SCE_A68K_COMMENT_SPECIAL);
                }
                else {
                    sc.ChangeState(SCE_A68K_COMMENT);
                }
                sc.SetState(SCE_A68K_COMMENT);
                continue;
            }

            // Check for Doxygen keywords
            else if ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && !IsDoxygenChar(sc.ch))
            {
                sc.GetCurrentLowered(Buffer, sizeof(Buffer));                           // Buffer the string of the current context
                if (!doxygenKeyword.InList(Buffer)) {
                    sc.ChangeState(SCE_A68K_COMMENT);
                }
                sc.SetState(SCE_A68K_COMMENT);
                continue;
            }

            // Check if we are in the case of a label which terminates without ':'
            // It should be a macro declaration, not a label
            else if ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && ((sc.ch == ' ') || (sc.ch == '\t')))
            {
                sc.ChangeState(SCE_A68K_MACRO_DECLARATION);
            }

            // Check if we are at the end of an identifier
            // In this case, colourise it if was a keyword.
            else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch))
            {
                sc.GetCurrentLowered(Buffer, sizeof(Buffer));                           // Buffer the string of the current context
                if (cpuInstruction.InList(Buffer)) {                                    // And check if it belongs to a keyword list
                    sc.ChangeState(SCE_A68K_CPUINSTRUCTION);
                }
                else if (extInstruction.InList(Buffer)) {
                    sc.ChangeState(SCE_A68K_EXTINSTRUCTION);
                }
                else if (registers.InList(Buffer)) {
                    sc.ChangeState(SCE_A68K_REGISTER);
                }
                else if (directive.InList(Buffer)) {
                    sc.ChangeState(SCE_A68K_DIRECTIVE);
                }
            }

            // All special contexts are now handled.Come back to default style
            sc.SetState(SCE_A68K_DEFAULT);
        }


        /************************************************************
        *
        *   Check if we must enter a new state
        *
        ************************************************************/

        // Label and macro identifiers start at the beginning of a line
        // We set both as a label, but if it wasn't one (no ':' at the end),
        // it will be changed as a macro identifier.
        if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) {
            sc.SetState(SCE_A68K_LABEL);
        }
        else if ((sc.ch < 0x80) && (sc.ch == ';')) {                            // Comment
            sc.SetState(SCE_A68K_COMMENT);
        }
        else if ((sc.ch < 0x80) && isdigit(sc.ch)) {                            // Decimal numbers haven't prefix
            sc.SetState(SCE_A68K_NUMBER_DEC);
        }
        else if ((sc.ch < 0x80) && (sc.ch == '%')) {                            // Binary numbers are prefixed with '%'
            sc.SetState(SCE_A68K_NUMBER_BIN);
        }
        else if ((sc.ch < 0x80) && (sc.ch == '$')) {                            // Hexadecimal numbers are prefixed with '$'
            sc.SetState(SCE_A68K_NUMBER_HEX);
        }
        else if ((sc.ch < 0x80) && (sc.ch == '\'')) {                           // String (single-quoted)
            sc.SetState(SCE_A68K_STRING1);
        }
        else if ((sc.ch < 0x80) && (sc.ch == '\"')) {                           // String (double-quoted)
            sc.SetState(SCE_A68K_STRING2);
        }
        else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) {   // Replacement symbols in macro
            sc.SetState(SCE_A68K_MACRO_ARG);
        }
        else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) {                  // An identifier: constant, label, etc...
            sc.SetState(SCE_A68K_IDENTIFIER);
        }
        else {
            if (sc.ch < 0x80) {
                OpType = GetOperatorType(sc.ch, sc.chNext);                     // Check if current char is an operator
                if (OpType != NO_OPERATOR) {
                    sc.SetState(SCE_A68K_OPERATOR);
                    if (OpType == OPERATOR_2CHAR) {                             // Check if the operator is 2 bytes long
                        sc.ForwardSetState(SCE_A68K_OPERATOR);                  // (>> or <<)
                    }
                }
            }
        }
    }                                                                           // End of for()
    sc.Complete();
}


// Names of the keyword lists

static const char * const a68kWordListDesc[] =
{
    "CPU instructions",
    "Registers",
    "Directives",
    "Extended instructions",
    "Comment special words",
    "Doxygen keywords",
    0
};

LexerModule lmA68k(SCLEX_A68K, ColouriseA68kDoc, "a68k", 0, a68kWordListDesc);

Added lexers/LexAPDL.cxx.







































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
// Scintilla source code edit control
/** @file LexAPDL.cxx
 ** Lexer for APDL. Based on the lexer for Assembler by The Black Horus.
 ** By Hadar Raz.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80 && (isalnum(ch) || ch == '_'));
}

static inline bool IsAnOperator(char ch) {
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
		ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
		ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
		ch == '$' || ch == ':' || ch == '%')
		return true;
	return false;
}

static void ColouriseAPDLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	int stringStart = ' ';

	WordList &processors = *keywordlists[0];
	WordList &commands = *keywordlists[1];
	WordList &slashcommands = *keywordlists[2];
	WordList &starcommands = *keywordlists[3];
	WordList &arguments = *keywordlists[4];
	WordList &functions = *keywordlists[5];

	// Do not leak onto next line
	initStyle = SCE_APDL_DEFAULT;
	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		// Determine if the current state should terminate.
		if (sc.state == SCE_APDL_NUMBER) {
			if (!(IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
				((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
				sc.SetState(SCE_APDL_DEFAULT);
			}
		} else if (sc.state == SCE_APDL_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_APDL_DEFAULT);
			}
		} else if (sc.state == SCE_APDL_COMMENTBLOCK) {
			if (sc.atLineEnd) {
				if (sc.ch == '\r') {
				sc.Forward();
				}
				sc.ForwardSetState(SCE_APDL_DEFAULT);
			}
		} else if (sc.state == SCE_APDL_STRING) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_APDL_DEFAULT);
			} else if ((sc.ch == '\'' && stringStart == '\'') || (sc.ch == '\"' && stringStart == '\"')) {
				sc.ForwardSetState(SCE_APDL_DEFAULT);
			}
		} else if (sc.state == SCE_APDL_WORD) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (processors.InList(s)) {
					sc.ChangeState(SCE_APDL_PROCESSOR);
				} else if (slashcommands.InList(s)) {
					sc.ChangeState(SCE_APDL_SLASHCOMMAND);
				} else if (starcommands.InList(s)) {
					sc.ChangeState(SCE_APDL_STARCOMMAND);
				} else if (commands.InList(s)) {
					sc.ChangeState(SCE_APDL_COMMAND);
				} else if (arguments.InList(s)) {
					sc.ChangeState(SCE_APDL_ARGUMENT);
				} else if (functions.InList(s)) {
					sc.ChangeState(SCE_APDL_FUNCTION);
				}
				sc.SetState(SCE_APDL_DEFAULT);
			}
		} else if (sc.state == SCE_APDL_OPERATOR) {
			if (!IsAnOperator(static_cast<char>(sc.ch))) {
			    sc.SetState(SCE_APDL_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_APDL_DEFAULT) {
			if (sc.ch == '!' && sc.chNext == '!') {
				sc.SetState(SCE_APDL_COMMENTBLOCK);
			} else if (sc.ch == '!') {
				sc.SetState(SCE_APDL_COMMENT);
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_APDL_NUMBER);
			} else if (sc.ch == '\'' || sc.ch == '\"') {
				sc.SetState(SCE_APDL_STRING);
				stringStart = sc.ch;
			} else if (IsAWordChar(sc.ch) || ((sc.ch == '*' || sc.ch == '/') && !isgraph(sc.chPrev))) {
				sc.SetState(SCE_APDL_WORD);
			} else if (IsAnOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_APDL_OPERATOR);
			}
		}
	}
	sc.Complete();
}

//------------------------------------------------------------------------------
// 06-27-07 Sergio Lucato
// - Included code folding for Ansys APDL lexer
// - Copyied from LexBasic.cxx and modified for APDL
//------------------------------------------------------------------------------

/* Bits:
 * 1  - whitespace
 * 2  - operator
 * 4  - identifier
 * 8  - decimal digit
 * 16 - hex digit
 * 32 - bin digit
 */
static int character_classification[128] =
{
    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  6,  2,  2,  2,  10, 6,
    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
};

static bool IsSpace(int c) {
	return c < 128 && (character_classification[c] & 1);
}

static bool IsIdentifier(int c) {
	return c < 128 && (character_classification[c] & 4);
}

static int LowerCase(int c)
{
	if (c >= 'A' && c <= 'Z')
		return 'a' + c - 'A';
	return c;
}

static int CheckAPDLFoldPoint(char const *token, int &level) {
	if (!strcmp(token, "*if") ||
		!strcmp(token, "*do") ||
		!strcmp(token, "*dowhile") ) {
		level |= SC_FOLDLEVELHEADERFLAG;
		return 1;
	}
	if (!strcmp(token, "*endif") ||
		!strcmp(token, "*enddo") ) {
		return -1;
	}
	return 0;
}

static void FoldAPDLDoc(unsigned int startPos, int length, int,
	WordList *[], Accessor &styler) {

	int line = styler.GetLine(startPos);
	int level = styler.LevelAt(line);
	int go = 0, done = 0;
	int endPos = startPos + length;
	char word[256];
	int wordlen = 0;
	int i;
    bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	// Scan for tokens at the start of the line (they may include
	// whitespace, for tokens like "End Function"
	for (i = startPos; i < endPos; i++) {
		int c = styler.SafeGetCharAt(i);
		if (!done && !go) {
			if (wordlen) { // are we scanning a token already?
				word[wordlen] = static_cast<char>(LowerCase(c));
				if (!IsIdentifier(c)) { // done with token
					word[wordlen] = '\0';
					go = CheckAPDLFoldPoint(word, level);
					if (!go) {
						// Treat any whitespace as single blank, for
						// things like "End   Function".
						if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
							word[wordlen] = ' ';
							if (wordlen < 255)
								wordlen++;
						}
						else // done with this line
							done = 1;
					}
				} else if (wordlen < 255) {
					wordlen++;
				}
			} else { // start scanning at first non-whitespace character
				if (!IsSpace(c)) {
					if (IsIdentifier(c)) {
						word[0] = static_cast<char>(LowerCase(c));
						wordlen = 1;
					} else // done with this line
						done = 1;
				}
			}
		}
		if (c == '\n') { // line end
			if (!done && wordlen == 0 && foldCompact) // line was only space
				level |= SC_FOLDLEVELWHITEFLAG;
			if (level != styler.LevelAt(line))
				styler.SetLevel(line, level);
			level += go;
			line++;
			// reset state
			wordlen = 0;
			level &= ~SC_FOLDLEVELHEADERFLAG;
			level &= ~SC_FOLDLEVELWHITEFLAG;
			go = 0;
			done = 0;
		}
	}
}

static const char * const apdlWordListDesc[] = {
    "processors",
    "commands",
    "slashommands",
    "starcommands",
    "arguments",
    "functions",
    0
};

LexerModule lmAPDL(SCLEX_APDL, ColouriseAPDLDoc, "apdl", FoldAPDLDoc, apdlWordListDesc);

Added lexers/LexASY.cxx.































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// Scintilla source code edit control
//Author: instanton (email: soft_share<at>126<dot>com)
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle,
		WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];

	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);

	int visibleChars = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			if (sc.state == SCE_ASY_STRING) {
				sc.SetState(SCE_ASY_STRING);
			}
			visibleChars = 0;
		}

		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
//				continuationLine = true;
				continue;
			}
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_ASY_OPERATOR:
				sc.SetState(SCE_ASY_DEFAULT);
				break;
			case SCE_ASY_NUMBER:
				if (!setWord.Contains(sc.ch)) {
					sc.SetState(SCE_ASY_DEFAULT);
				}
				break;
			case SCE_ASY_IDENTIFIER:
				if (!setWord.Contains(sc.ch) || (sc.ch == '.')) {
					char s[1000];
					sc.GetCurrentLowered(s, sizeof(s));
					if (keywords.InList(s)) {
						sc.ChangeState(SCE_ASY_WORD);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_ASY_WORD2);
					}
					sc.SetState(SCE_ASY_DEFAULT);
				}
				break;
			case SCE_ASY_COMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_ASY_DEFAULT);
				}
				break;
			case SCE_ASY_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_ASY_DEFAULT);
				}
				break;
			case SCE_ASY_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_ASY_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_ASY_DEFAULT);
				}
				break;
			case SCE_ASY_CHARACTER:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_ASY_STRINGEOL);
				} else 	if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_ASY_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_ASY_DEFAULT) {
			if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
				sc.SetState(SCE_ASY_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_ASY_COMMENT);
				sc.Forward();	//
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_ASY_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_ASY_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_ASY_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_ASY_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_ASY_OPERATOR);
			}
		}

	}
	sc.Complete();
}

static bool IsAsyCommentStyle(int style) {
	return style == SCE_ASY_COMMENT;
}


static inline bool isASYidentifier(int ch) {
	return
      ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ;
}

static int ParseASYWord(unsigned int pos, Accessor &styler, char *word)
{
  int length=0;
  char ch=styler.SafeGetCharAt(pos);
  *word=0;

  while(isASYidentifier(ch) && length<100){
          word[length]=ch;
          length++;
          ch=styler.SafeGetCharAt(pos+length);
  }
  word[length]=0;
  return length;
}

static bool IsASYDrawingLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;

	int startpos = pos;
	char buffer[100]="";

	while (startpos<eol_pos){
		char ch = styler[startpos];
		ParseASYWord(startpos,styler,buffer);
		bool drawcommands = strncmp(buffer,"draw",4)==0||
			strncmp(buffer,"pair",4)==0||strncmp(buffer,"label",5)==0;
		if (!drawcommands && ch!=' ') return false;
		else if (drawcommands) return true;
		startpos++;
	}
	return false;
}

static void FoldAsyDoc(unsigned int startPos, int length, int initStyle,
					   WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsAsyCommentStyle(style)) {
			if (!IsAsyCommentStyle(stylePrev) && (stylePrev != SCE_ASY_COMMENTLINEDOC)) {
				levelNext++;
			} else if (!IsAsyCommentStyle(styleNext) && (styleNext != SCE_ASY_COMMENTLINEDOC) && !atEOL) {
				levelNext--;
			}
		}
		if (style == SCE_ASY_OPERATOR) {
			if (ch == '{') {
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}

		if (atEOL && IsASYDrawingLine(lineCurrent, styler)){
			if (lineCurrent==0 && IsASYDrawingLine(lineCurrent + 1, styler))
				levelNext++;
			else if (lineCurrent!=0 && !IsASYDrawingLine(lineCurrent - 1, styler)
				&& IsASYDrawingLine(lineCurrent + 1, styler)
				)
				levelNext++;
			else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) &&
				!IsASYDrawingLine(lineCurrent+1, styler))
				levelNext--;
		}

		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!IsASpace(ch))
			visibleChars++;
	}
}

static const char * const asyWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            0,
        };

LexerModule lmASY(SCLEX_ASYMPTOTE, ColouriseAsyDoc, "asy", FoldAsyDoc, asyWordLists);

Added lexers/LexAU3.cxx.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
// Scintilla source code edit control
// @file LexAU3.cxx
// Lexer for AutoIt3  http://www.hiddensoft.com/autoit3
// by Jos van der Zande, jvdzande@yahoo.com
//
// Changes:
// March 28, 2004 - Added the standard Folding code
// April 21, 2004 - Added Preprosessor Table + Syntax Highlighting
//                  Fixed Number highlighting
//                  Changed default isoperator to IsAOperator to have a better match to AutoIt3
//                  Fixed "#comments_start" -> "#comments-start"
//                  Fixed "#comments_end" -> "#comments-end"
//                  Fixed Sendkeys in Strings when not terminated with }
//                  Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down}
// April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color.
//                  Added logic for #include <xyz.au3> to treat the <> as string
//                  Added underscore to IsAOperator.
// May 17, 2004   - Changed the folding logic from indent to keyword folding.
//                  Added Folding logic for blocks of single-commentlines or commentblock.
//                        triggered by: fold.comment=1
//                  Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1
//                  Added Special for #region - #endregion syntax highlight and folding.
// May 30, 2004   - Fixed issue with continuation lines on If statements.
// June 5, 2004   - Added comma to Operators for better readability.
//                  Added fold.compact support set with fold.compact=1
//                  Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1
//                        it will now only happen when fold.comment=2.
// Sep 5, 2004    - Added logic to handle colourizing words on the last line.
//                        Typed Characters now show as "default" till they match any table.
// Oct 10, 2004   - Added logic to show Comments in "Special" directives.
// Nov  1, 2004   - Added better testing for Numbers supporting x and e notation.
// Nov 28, 2004   - Added logic to handle continuation lines for syntax highlighting.
// Jan 10, 2005   - Added Abbreviations Keyword used for expansion
// Mar 24, 2005   - Updated Abbreviations Keywords to fix when followed by Operator.
// Apr 18, 2005   - Updated #CE/#Comment-End logic to take a linecomment ";" into account
//                - Added folding support for With...EndWith
//                - Added support for a DOT in variable names
//                - Fixed Underscore in CommentBlock
// May 23, 2005   - Fixed the SentKey lexing in case of a missing }
// Aug 11, 2005   - Fixed possible bug with s_save length > 100.
// Aug 23, 2005   - Added Switch/endswitch support to the folding logic.
// Sep 27, 2005   - Fixed the SentKey lexing logic in case of multiple sentkeys.
// Mar 12, 2006   - Fixed issue with <> coloring as String in stead of Operator in rare occasions.
// Apr  8, 2006   - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF)
// Mar  9, 2007   - Fixed bug with + following a String getting the wrong Color.
// Jun 20, 2007   - Fixed Commentblock issue when LF's are used as EOL.
// Jul 26, 2007   - Fixed #endregion undetected bug.
//
// Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
// Scintilla source code edit control

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsTypeCharacter(const int ch)
{
    return ch == '$';
}
static inline bool IsAWordChar(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.');
}

static inline bool IsAOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
	    ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' ||
	    ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' )
		return true;
	return false;
}

///////////////////////////////////////////////////////////////////////////////
// GetSendKey() filters the portion before and after a/multiple space(s)
// and return the first portion to be looked-up in the table
// also check if the second portion is valid... (up,down.on.off,toggle or a number)
///////////////////////////////////////////////////////////////////////////////

static int GetSendKey(const char *szLine, char *szKey)
{
	int		nFlag	= 0;
	int		nStartFound	= 0;
	int		nKeyPos	= 0;
	int		nSpecPos= 0;
	int		nSpecNum= 1;
	int		nPos	= 0;
	char	cTemp;
	char	szSpecial[100];

	// split the portion of the sendkey in the part before and after the spaces
	while ( ( (cTemp = szLine[nPos]) != '\0'))
	{
		// skip leading Ctrl/Shift/Alt state
		if (cTemp == '{') {
			nStartFound = 1;
		}
		//
		if (nStartFound == 1) {
			if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
			{
				nFlag = 1;
				// Add } to the end of the first bit for table lookup later.
				szKey[nKeyPos++] = '}';
			}
			else if (cTemp == ' ')
			{
				// skip other spaces
			}
			else if (nFlag == 0)
			{
				// save first portion into var till space or } is hit
				szKey[nKeyPos++] = cTemp;
			}
			else if ((nFlag == 1) && (cTemp != '}'))
			{
				// Save second portion into var...
				szSpecial[nSpecPos++] = cTemp;
				// check if Second portion is all numbers for repeat fuction
				if (isdigit(cTemp) == false) {nSpecNum = 0;}
			}
		}
		nPos++;									// skip to next char

	} // End While


	// Check if the second portion is either a number or one of these keywords
	szKey[nKeyPos] = '\0';
	szSpecial[nSpecPos] = '\0';
	if (strcmp(szSpecial,"down")== 0    || strcmp(szSpecial,"up")== 0  ||
		strcmp(szSpecial,"on")== 0      || strcmp(szSpecial,"off")== 0 ||
		strcmp(szSpecial,"toggle")== 0  || nSpecNum == 1 )
	{
		nFlag = 0;
	}
	else
	{
		nFlag = 1;
	}
	return nFlag;  // 1 is bad, 0 is good

} // GetSendKey()

//
// Routine to check the last "none comment" character on a line to see if its a continuation
//
static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
{
	int nsPos = styler.LineStart(szLine);
	int nePos = styler.LineStart(szLine+1) - 2;
	//int stylech = styler.StyleAt(nsPos);
	while (nsPos < nePos)
	{
		//stylech = styler.StyleAt(nePos);
		int stylech = styler.StyleAt(nsPos);
		if (!(stylech == SCE_AU3_COMMENT)) {
			char ch = styler.SafeGetCharAt(nePos);
			if (!isspacechar(ch)) {
				if (ch == '_')
					return true;
				else
					return false;
			}
		}
		nePos--; // skip to next char
	} // End While
	return false;
} // IsContinuationLine()

//
// syntax highlighting logic
static void ColouriseAU3Doc(unsigned int startPos,
							int length, int initStyle,
							WordList *keywordlists[],
							Accessor &styler) {

    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    WordList &keywords4 = *keywordlists[3];
    WordList &keywords5 = *keywordlists[4];
    WordList &keywords6 = *keywordlists[5];
    WordList &keywords7 = *keywordlists[6];
    WordList &keywords8 = *keywordlists[7];
	// find the first previous line without continuation character at the end
	int lineCurrent = styler.GetLine(startPos);
	int s_startPos = startPos;
	// When not inside a Block comment: find First line without _
	if (!(initStyle==SCE_AU3_COMMENTBLOCK)) {
		while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
			   (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent); // get start position
			initStyle =  0;                           // reset the start style to 0
		}
	}
	// Set the new length to include it from the start and set the start position
	length = length + s_startPos - startPos;      // correct the total length to process
    styler.StartAt(startPos);

    StyleContext sc(startPos, length, initStyle, styler);
	char si;     // string indicator "=1 '=2
	char ni;     // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3
	char ci;     // comment indicator 0=not linecomment(;)
	char s_save[100];
	si=0;
	ni=0;
	ci=0;
	//$$$
    for (; sc.More(); sc.Forward()) {
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));
		// **********************************************
		// save the total current word for eof processing
		if (IsAWordChar(sc.ch) || sc.ch == '}')
		{
			strcpy(s_save,s);
			int tp = static_cast<int>(strlen(s_save));
			if (tp < 99) {
				s_save[tp] = static_cast<char>(tolower(sc.ch));
				s_save[tp+1] = '\0';
			}
		}
		// **********************************************
		//
		switch (sc.state)
        {
            case SCE_AU3_COMMENTBLOCK:
            {
				//Reset at line end
				if (sc.atLineEnd) {
					ci=0;
					if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) {
						if (sc.atLineEnd)
							sc.SetState(SCE_AU3_DEFAULT);
						else
							sc.SetState(SCE_AU3_COMMENTBLOCK);
					}
					break;
				}
				//skip rest of line when a ; is encountered
				if (sc.chPrev == ';') {
					ci=2;
					sc.SetState(SCE_AU3_COMMENTBLOCK);
				}
				// skip rest of the line
				if (ci==2)
					break;
				// check when first character is detected on the line
				if (ci==0) {
					if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) {
						ci=1;
						sc.SetState(SCE_AU3_COMMENTBLOCK);
					}
					break;
				}
				if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) {
					if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0))
							sc.SetState(SCE_AU3_COMMENT);  // set to comment line for the rest of the line
					else
						ci=2;  // line doesn't begin with #CE so skip the rest of the line
				}
				break;
			}
            case SCE_AU3_COMMENT:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_OPERATOR:
            {
                // check if its a COMobject
				if (sc.chPrev == '.' && IsAWordChar(sc.ch)) {
					sc.SetState(SCE_AU3_COMOBJ);
				}
				else {
					sc.SetState(SCE_AU3_DEFAULT);
				}
                break;
            }
            case SCE_AU3_SPECIAL:
            {
                if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
				if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_KEYWORD:
            {
                if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0))))
                {
                    if (!IsTypeCharacter(sc.ch))
                    {
						if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 )
						{
							sc.ChangeState(SCE_AU3_COMMENTBLOCK);
							sc.SetState(SCE_AU3_COMMENTBLOCK);
							break;
						}
						else if (keywords.InList(s)) {
							sc.ChangeState(SCE_AU3_KEYWORD);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_AU3_FUNCTION);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_AU3_MACRO);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords5.InList(s)) {
							sc.ChangeState(SCE_AU3_PREPROCESSOR);
							sc.SetState(SCE_AU3_DEFAULT);
							if (strcmp(s, "#include")== 0)
							{
								si = 3;   // use to determine string start for #inlude <>
							}
						}
						else if (keywords6.InList(s)) {
							sc.ChangeState(SCE_AU3_SPECIAL);
							sc.SetState(SCE_AU3_SPECIAL);
						}
						else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) {
							sc.ChangeState(SCE_AU3_EXPAND);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords8.InList(s)) {
							sc.ChangeState(SCE_AU3_UDF);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (strcmp(s, "_") == 0) {
							sc.ChangeState(SCE_AU3_OPERATOR);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (!IsAWordChar(sc.ch)) {
							sc.ChangeState(SCE_AU3_DEFAULT);
							sc.SetState(SCE_AU3_DEFAULT);
						}
					}
				}
                if (sc.atLineEnd) {
					sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
			case SCE_AU3_NUMBER:
            {
				// Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3
				//
				// test for Hex notation
				if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0)
				{
					ni = 2;
					break;
				}
				// test for E notation
				if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1)
				{
					ni = 3;
					break;
				}
				//  Allow Hex characters inside hex numeric strings
				if ((ni == 2) &&
					(sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' ||
					 sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' ))
				{
					break;
				}
				// test for 1 dec point only
				if (sc.ch == '.')
				{
					if (ni==0)
					{
						ni=1;
					}
					else
					{
						ni=9;
					}
					break;
				}
				// end of numeric string ?
				if (!(IsADigit(sc.ch)))
				{
					if (ni==9)
					{
						sc.ChangeState(SCE_AU3_DEFAULT);
					}
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
			}
			case SCE_AU3_VARIABLE:
			{
				// Check if its a COMObject
				if (sc.ch == '.' && !IsADigit(sc.chNext)) {
					sc.SetState(SCE_AU3_OPERATOR);
				}
				else if (!IsAWordChar(sc.ch)) {
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
            }
			case SCE_AU3_COMOBJ:
			{
				if (!(IsAWordChar(sc.ch))) {
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
            }
            case SCE_AU3_STRING:
            {
				// check for " to end a double qouted string or
				// check for ' to end a single qouted string
	            if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>'))
				{
					sc.ForwardSetState(SCE_AU3_DEFAULT);
					si=0;
					break;
				}
                if (sc.atLineEnd)
				{
					si=0;
					// at line end and not found a continuation char then reset to default
					int lineCurrent = styler.GetLine(sc.currentPos);
					if (!IsContinuationLine(lineCurrent,styler))
					{
						sc.SetState(SCE_AU3_DEFAULT);
						break;
					}
				}
				// find Sendkeys in a STRING
				if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) {
					sc.SetState(SCE_AU3_SENT);}
				break;
            }

            case SCE_AU3_SENT:
            {
				// Send key string ended
				if (sc.chPrev == '}' && sc.ch != '}')
				{
					// set color to SENDKEY when valid sendkey .. else set back to regular string
					char sk[100];
					// split {111 222} and return {111} and check if 222 is valid.
					// if return code = 1 then invalid 222 so must be string
					if (GetSendKey(s,sk))
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					// if single char between {?} then its ok as sendkey for a single character
					else if (strlen(sk) == 3)
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					// if sendkey {111} is in table then ok as sendkey
					else if (keywords4.InList(sk))
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					else
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					sc.SetState(SCE_AU3_STRING);
				}
				else
				{
					// check if the start is a valid SendKey start
					int		nPos	= 0;
					int		nState	= 1;
					char	cTemp;
					while (!(nState == 2) && ((cTemp = s[nPos]) != '\0'))
					{
						if (cTemp == '{' && nState == 1)
						{
							nState = 2;
						}
						if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' ))
						{
							nState = 0;
						}
						nPos++;
					}
					//Verify characters infront of { ... if not assume  regular string
					if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) {
						sc.ChangeState(SCE_AU3_STRING);
						sc.SetState(SCE_AU3_STRING);
					}
					// If invalid character found then assume its a regular string
					if (nState == 0) {
						sc.ChangeState(SCE_AU3_STRING);
						sc.SetState(SCE_AU3_STRING);
					}
				}
				// check if next portion is again a sendkey
				if (sc.atLineEnd)
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.SetState(SCE_AU3_DEFAULT);
					si = 0;  // reset string indicator
				}
				//* check in next characters following a sentkey are again a sent key
				// Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{}
				if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) {
					sc.SetState(SCE_AU3_SENT);}
				// check to see if the string ended...
				// Sendkey string isn't complete but the string ended....
				if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
				break;
            }
        }  //switch (sc.state)

        // Determine if a new state should be entered:

		if (sc.state == SCE_AU3_DEFAULT)
        {
            if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
            else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
            else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);}
            else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
            //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include
            else if (sc.ch == '\"') {
				sc.SetState(SCE_AU3_STRING);
				si = 1;	}
            else if (sc.ch == '\'') {
				sc.SetState(SCE_AU3_STRING);
				si = 2;	}
            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
			{
				sc.SetState(SCE_AU3_NUMBER);
				ni = 0;
			}
            else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
            else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
			else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
        }
    }      //for (; sc.More(); sc.Forward())

	//*************************************
	// Colourize the last word correctly
	//*************************************
	if (sc.state == SCE_AU3_KEYWORD)
		{
		if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 )
		{
			sc.ChangeState(SCE_AU3_COMMENTBLOCK);
			sc.SetState(SCE_AU3_COMMENTBLOCK);
		}
		else if (keywords.InList(s_save)) {
			sc.ChangeState(SCE_AU3_KEYWORD);
			sc.SetState(SCE_AU3_KEYWORD);
		}
		else if (keywords2.InList(s_save)) {
			sc.ChangeState(SCE_AU3_FUNCTION);
			sc.SetState(SCE_AU3_FUNCTION);
		}
		else if (keywords3.InList(s_save)) {
			sc.ChangeState(SCE_AU3_MACRO);
			sc.SetState(SCE_AU3_MACRO);
		}
		else if (keywords5.InList(s_save)) {
			sc.ChangeState(SCE_AU3_PREPROCESSOR);
			sc.SetState(SCE_AU3_PREPROCESSOR);
		}
		else if (keywords6.InList(s_save)) {
			sc.ChangeState(SCE_AU3_SPECIAL);
			sc.SetState(SCE_AU3_SPECIAL);
		}
		else if (keywords7.InList(s_save) && sc.atLineEnd) {
			sc.ChangeState(SCE_AU3_EXPAND);
			sc.SetState(SCE_AU3_EXPAND);
		}
		else if (keywords8.InList(s_save)) {
			sc.ChangeState(SCE_AU3_UDF);
			sc.SetState(SCE_AU3_UDF);
		}
		else {
			sc.ChangeState(SCE_AU3_DEFAULT);
			sc.SetState(SCE_AU3_DEFAULT);
		}
	}
	if (sc.state == SCE_AU3_SENT)
    {
		// Send key string ended
		if (sc.chPrev == '}' && sc.ch != '}')
		{
			// set color to SENDKEY when valid sendkey .. else set back to regular string
			char sk[100];
			// split {111 222} and return {111} and check if 222 is valid.
			// if return code = 1 then invalid 222 so must be string
			if (GetSendKey(s_save,sk))
			{
				sc.ChangeState(SCE_AU3_STRING);
			}
			// if single char between {?} then its ok as sendkey for a single character
			else if (strlen(sk) == 3)
			{
				sc.ChangeState(SCE_AU3_SENT);
			}
			// if sendkey {111} is in table then ok as sendkey
			else if (keywords4.InList(sk))
			{
				sc.ChangeState(SCE_AU3_SENT);
			}
			else
			{
				sc.ChangeState(SCE_AU3_STRING);
			}
			sc.SetState(SCE_AU3_STRING);
		}
		// check if next portion is again a sendkey
		if (sc.atLineEnd)
		{
			sc.ChangeState(SCE_AU3_STRING);
			sc.SetState(SCE_AU3_DEFAULT);
		}
    }
	//*************************************
	sc.Complete();
}

//
static bool IsStreamCommentStyle(int style) {
	return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK;
}

//
// Routine to find first none space on the current line and return its Style
// needed for comment lines not starting on pos 1
static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
{
	int nsPos = styler.LineStart(szLine);
	int nePos = styler.LineStart(szLine+1) - 1;
	while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos)
	{
		nsPos++; // skip to next char

	} // End While
	return styler.StyleAt(nsPos);

} // GetStyleFirstWord()


//
static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
	int endPos = startPos + length;
	// get settings from the config files for folding comments and preprocessor lines
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	// vars for style of previous/current/next lines
	int style = GetStyleFirstWord(lineCurrent,styler);
	int stylePrev = 0;
	// find the first previous line without continuation character at the end
	while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
	       (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
		lineCurrent--;
		startPos = styler.LineStart(lineCurrent);
	}
	if (lineCurrent > 0) {
		stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
	}
	// vars for getting first word to check for keywords
	bool FirstWordStart = false;
	bool FirstWordEnd = false;
	char szKeyword[11]="";
	int	 szKeywordlen = 0;
	char szThen[5]="";
	int	 szThenlen = 0;
	bool ThenFoundLast = false;
	// var for indentlevel
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelNext = levelCurrent;
	//
	int	visibleChars = 0;
	char chNext = styler.SafeGetCharAt(startPos);
	char chPrev = ' ';
	//
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		if (IsAWordChar(ch)) {
			visibleChars++;
		}
		// get the syle for the current character neede to check in comment
		int stylech = styler.StyleAt(i);
		// get first word for the line for indent check max 9 characters
		if (FirstWordStart && (!(FirstWordEnd))) {
			if (!IsAWordChar(ch)) {
				FirstWordEnd = true;
				szKeyword[szKeywordlen] = '\0';
			}
			else {
				if (szKeywordlen < 10) {
				szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
				}
			}
		}
		// start the capture of the first word
		if (!(FirstWordStart)) {
			if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') {
				FirstWordStart = true;
				szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
			}
		}
		// only process this logic when not in comment section
		if (!(stylech == SCE_AU3_COMMENT)) {
			if (ThenFoundLast) {
				if (IsAWordChar(ch)) {
					ThenFoundLast = false;
				}
			}
			// find out if the word "then" is the last on a "if" line
			if (FirstWordEnd && strcmp(szKeyword,"if") == 0) {
				if (szThenlen == 4) {
					szThen[0] = szThen[1];
					szThen[1] = szThen[2];
					szThen[2] = szThen[3];
					szThen[3] = static_cast<char>(tolower(ch));
					if (strcmp(szThen,"then") == 0 ) {
						ThenFoundLast = true;
					}
				}
				else {
					szThen[szThenlen++] = static_cast<char>(tolower(ch));
					if (szThenlen == 5) {
						szThen[4] = '\0';
					}
				}
			}
		}
		// End of Line found so process the information
		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
			// **************************
			// Folding logic for Keywords
			// **************************
			// if a keyword is found on the current line and the line doesn't end with _ (continuation)
			//    and we are not inside a commentblock.
			if (szKeywordlen > 0 && (!(chPrev == '_')) &&
				((!(IsStreamCommentStyle(style)) || foldInComment)) ) {
				szKeyword[szKeywordlen] = '\0';
				// only fold "if" last keyword is "then"  (else its a one line if)
				if (strcmp(szKeyword,"if") == 0  && ThenFoundLast) {
						levelNext++;
				}
				// create new fold for these words
				if (strcmp(szKeyword,"do") == 0   || strcmp(szKeyword,"for") == 0 ||
					strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0||
					strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) {
						levelNext++;
				}
				// create double Fold for select&switch because Case will subtract one of the current level
				if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) {
						levelNext++;
						levelNext++;
				}
				// end the fold for these words before the current line
				if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 ||
					strcmp(szKeyword,"next") == 0    || strcmp(szKeyword,"until") == 0 ||
					strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){
						levelNext--;
						levelCurrent--;
				}
				// end the fold for these words before the current line and Start new fold
				if (strcmp(szKeyword,"case") == 0      || strcmp(szKeyword,"else") == 0 ||
					strcmp(szKeyword,"elseif") == 0 ) {
						levelCurrent--;
				}
				// end the double fold for this word before the current line
				if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) {
						levelNext--;
						levelNext--;
						levelCurrent--;
						levelCurrent--;
				}
				// end the fold for these words on the current line
				if (strcmp(szKeyword,"#endregion") == 0 ) {
						levelNext--;
				}
			}
			// Preprocessor and Comment folding
			int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
			// *************************************
			// Folding logic for preprocessor blocks
			// *************************************
			// process preprosessor line
			if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) {
				if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) {
				    levelNext++;
				}
				// fold till the last line for normal comment lines
				else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) {
					levelNext--;
				}
			}
			// *********************************
			// Folding logic for Comment blocks
			// *********************************
			if (foldComment && IsStreamCommentStyle(style)) {
				// Start of a comment block
				if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) {
				    levelNext++;
				}
				// fold till the last line for normal comment lines
				else if (IsStreamCommentStyle(stylePrev)
						&& !(styleNext == SCE_AU3_COMMENT)
						&& stylePrev == SCE_AU3_COMMENT
						&& style == SCE_AU3_COMMENT) {
					levelNext--;
				}
				// fold till the one but last line for Blockcomment lines
				else if (IsStreamCommentStyle(stylePrev)
						&& !(styleNext == SCE_AU3_COMMENTBLOCK)
						&& style == SCE_AU3_COMMENTBLOCK) {
					levelNext--;
					levelCurrent--;
				}
			}
			int levelUse = levelCurrent;
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			// reset values for the next line
			lineCurrent++;
			stylePrev = style;
			style = styleNext;
			levelCurrent = levelNext;
			visibleChars = 0;
			// if the last character is an Underscore then don't reset since the line continues on the next line.
			if (!(chPrev == '_')) {
				szKeywordlen = 0;
				szThenlen = 0;
				FirstWordStart = false;
				FirstWordEnd = false;
				ThenFoundLast = false;
			}
		}
		// save the last processed character
		if (!isspacechar(ch)) {
			chPrev = ch;
			visibleChars++;
		}
	}
}


//

static const char * const AU3WordLists[] = {
    "#autoit keywords",
    "#autoit functions",
    "#autoit macros",
    "#autoit Sent keys",
    "#autoit Pre-processors",
    "#autoit Special",
    "#autoit Expand",
    "#autoit UDF",
    0
};
LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);

Added lexers/LexAVE.cxx.















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// SciTE - Scintilla based Text Editor
/** @file LexAVE.cxx
 ** Lexer for Avenue.
 **
  ** Written by Alexey Yutkin <yutkin@geol.msu.ru>.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}
static inline bool IsEnumChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch)|| ch == '_');
}
static inline bool IsANumberChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' );
}

inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool isAveOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.'  )
		return true;
	return false;
}

static void ColouriseAveDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];

	// Do not leak onto next line
	if (initStyle == SCE_AVE_STRINGEOL) {
		initStyle = SCE_AVE_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			int currentLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(currentLine, 0);
		}
		if (sc.atLineStart && (sc.state == SCE_AVE_STRING)) {
			// Prevent SCE_AVE_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_AVE_STRING);
		}


		// Determine if the current state should terminate.
		if (sc.state == SCE_AVE_OPERATOR) {
			sc.SetState(SCE_AVE_DEFAULT);
		} else if (sc.state == SCE_AVE_NUMBER) {
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_ENUM) {
			if (!IsEnumChar(sc.ch)) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				//sc.GetCurrent(s, sizeof(s));
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_AVE_WORD6);
				}
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_AVE_DEFAULT);
			}
		} else if (sc.state == SCE_AVE_STRING) {
			 if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_AVE_STRINGEOL);
				sc.ForwardSetState(SCE_AVE_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_AVE_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_AVE_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_AVE_IDENTIFIER);
			} else if (sc.Match('\"')) {
				sc.SetState(SCE_AVE_STRING);
			} else if (sc.Match('\'')) {
				sc.SetState(SCE_AVE_COMMENT);
				sc.Forward();
			} else if (isAveOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_AVE_OPERATOR);
			} else if (sc.Match('#')) {
				sc.SetState(SCE_AVE_ENUM);
				sc.Forward();
			}
		}
	}
	sc.Complete();
}

static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = static_cast<char>(tolower(styler[startPos]));
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = static_cast<char>(tolower(chNext));
		chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_AVE_WORD) {
			if (ch == 't' || ch == 'f' || ch == 'w' || ch == 'e') {
				for (unsigned int j = 0; j < 6; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = static_cast<char>(tolower(styler[i + j]));
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
					// Normally "elseif" and "then" will be on the same line and will cancel
					// each other out.  // As implemented, this does not support fold.at.else.
					levelCurrent--;
				}
			}
		} else if (style == SCE_AVE_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmAVE(SCLEX_AVE, ColouriseAveDoc, "ave", FoldAveDoc);

Added lexers/LexAVS.cxx.











































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
// Scintilla source code edit control
/** @file LexAVS.cxx
 ** Lexer for AviSynth.
 **/
// Copyright 2012 by Bruno Barbieri <brunorex@gmail.com>
// Heavily based on LexPOV by Neil Hodgson
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ',');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
			(isdigit(ch) || ch == '.' || ch == '-' || ch == '+');
}

static void ColouriseAvsDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &filters = *keywordlists[1];
	WordList &plugins = *keywordlists[2];
	WordList &functions = *keywordlists[3];
	WordList &clipProperties = *keywordlists[4];
	WordList &userDefined = *keywordlists[5];

	int currentLine = styler.GetLine(startPos);
	// Initialize the block comment nesting level, if we are inside such a comment.
	int blockCommentLevel = 0;
	if (initStyle == SCE_AVS_COMMENTBLOCK || initStyle == SCE_AVS_COMMENTBLOCKN) {
		blockCommentLevel = styler.GetLineState(currentLine - 1);
	}

	// Do not leak onto next line
	if (initStyle == SCE_AVS_COMMENTLINE) {
		initStyle = SCE_AVS_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			if (sc.state == SCE_AVS_COMMENTBLOCK || sc.state == SCE_AVS_COMMENTBLOCKN) {
				// Inside a block comment, we set the line state
				styler.SetLineState(currentLine, blockCommentLevel);
			} else {
				// Reset the line state
				styler.SetLineState(currentLine, 0);
			}
		}
		
		// Determine if the current state should terminate.
		if (sc.state == SCE_AVS_OPERATOR) {
			sc.SetState(SCE_AVS_DEFAULT);
		} else if (sc.state == SCE_AVS_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-sign char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_AVS_DEFAULT);
			}
		} else if (sc.state == SCE_AVS_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));

				if (keywords.InList(s)) {
					sc.ChangeState(SCE_AVS_KEYWORD);
				} else if (filters.InList(s)) {
					sc.ChangeState(SCE_AVS_FILTER);
				} else if (plugins.InList(s)) {
					sc.ChangeState(SCE_AVS_PLUGIN);
				} else if (functions.InList(s)) {
					sc.ChangeState(SCE_AVS_FUNCTION);
				} else if (clipProperties.InList(s)) {
					sc.ChangeState(SCE_AVS_CLIPPROP);
				} else if (userDefined.InList(s)) {
					sc.ChangeState(SCE_AVS_USERDFN);
				}
				sc.SetState(SCE_AVS_DEFAULT);
			}
		} else if (sc.state == SCE_AVS_COMMENTBLOCK) {
			if (sc.Match('/', '*')) {
				blockCommentLevel++;
				sc.Forward();
			} else if (sc.Match('*', '/') && blockCommentLevel > 0) {
				blockCommentLevel--;
				sc.Forward();
				if (blockCommentLevel == 0) {
					sc.ForwardSetState(SCE_AVS_DEFAULT);
				}
			}
		} else if (sc.state == SCE_AVS_COMMENTBLOCKN) {
			if (sc.Match('[', '*')) {
				blockCommentLevel++;
				sc.Forward();
			} else if (sc.Match('*', ']') && blockCommentLevel > 0) {
				blockCommentLevel--;
				sc.Forward();
				if (blockCommentLevel == 0) {
					sc.ForwardSetState(SCE_AVS_DEFAULT);
				}
			}
		} else if (sc.state == SCE_AVS_COMMENTLINE) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_AVS_DEFAULT);
			}
		} else if (sc.state == SCE_AVS_STRING) {
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_AVS_DEFAULT);
			}
		} else if (sc.state == SCE_AVS_TRIPLESTRING) {
			if (sc.Match("\"\"\"")) {
				sc.Forward();
				sc.Forward();
				sc.ForwardSetState(SCE_AVS_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_AVS_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_AVS_NUMBER);
			} else 	if (IsADigit(sc.ch) || (sc.ch == ',' && IsADigit(sc.chNext))) {
				sc.Forward();
				sc.SetState(SCE_AVS_NUMBER);
			} else if (sc.Match('/', '*')) {
				blockCommentLevel = 1;
				sc.SetState(SCE_AVS_COMMENTBLOCK);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('[', '*')) {
				blockCommentLevel = 1;
				sc.SetState(SCE_AVS_COMMENTBLOCKN);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.ch == '#') {
				sc.SetState(SCE_AVS_COMMENTLINE);
			} else if (sc.ch == '\"') {
				if (sc.Match("\"\"\"")) {
					sc.SetState(SCE_AVS_TRIPLESTRING);
				} else {
					sc.SetState(SCE_AVS_STRING);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_AVS_OPERATOR);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_AVS_IDENTIFIER);
			}
		}
	}

	// End of file: complete any pending changeState
	if (sc.state == SCE_AVS_IDENTIFIER) {
		if (!IsAWordChar(sc.ch)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));

			if (keywords.InList(s)) {
				sc.ChangeState(SCE_AVS_KEYWORD);
			} else if (filters.InList(s)) {
				sc.ChangeState(SCE_AVS_FILTER);
			} else if (plugins.InList(s)) {
				sc.ChangeState(SCE_AVS_PLUGIN);
			} else if (functions.InList(s)) {
				sc.ChangeState(SCE_AVS_FUNCTION);
			} else if (clipProperties.InList(s)) {
				sc.ChangeState(SCE_AVS_CLIPPROP);
			} else if (userDefined.InList(s)) {
				sc.ChangeState(SCE_AVS_USERDFN);
			}
			sc.SetState(SCE_AVS_DEFAULT);
		}
	}

	sc.Complete();
}

static void FoldAvsDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *[],
	Accessor &styler) {

	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && style == SCE_AVS_COMMENTBLOCK) {
			if (stylePrev != SCE_AVS_COMMENTBLOCK) {
				levelCurrent++;
			} else if ((styleNext != SCE_AVS_COMMENTBLOCK) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}

		if (foldComment && style == SCE_AVS_COMMENTBLOCKN) {
			if (stylePrev != SCE_AVS_COMMENTBLOCKN) {
				levelCurrent++;
			} else if ((styleNext != SCE_AVS_COMMENTBLOCKN) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}

		if (style == SCE_AVS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const avsWordLists[] = {
	"Keywords",
	"Filters",
	"Plugins",
	"Functions",
	"Clip properties",
	"User defined functions",
	0,
};

LexerModule lmAVS(SCLEX_AVS, ColouriseAvsDoc, "avs", FoldAvsDoc, avsWordLists);

Added lexers/LexAbaqus.cxx.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
// Scintilla source code edit control
/** @file LexABAQUS.cxx
 ** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz.
 ** By Sergio Lucato.
 ** Sort of completely rewritten by Gertjan Kloosterman
 **/
// The License.txt file describes the conditions under which this software may be distributed.

// Code folding copyied and modified from LexBasic.cxx

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80 && (isalnum(ch) || (ch == '_')));
}

static inline bool IsAKeywordChar(const int ch) {
	return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' ')));
}

static inline bool IsASetChar(const int ch) {
	return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == '.') || (ch == '-')));
}

static inline bool IsAnOperator(char ch) {
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
		ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
		ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
		ch == '$' || ch == ':' || ch == '%')
		return true;
	return false;
}

static void ColouriseABAQUSDoc(unsigned int startPos, int length, int initStyle, WordList*[] /* *keywordlists[] */,
                            Accessor &styler) {
	enum localState { KW_LINE_KW, KW_LINE_COMMA, KW_LINE_PAR, KW_LINE_EQ, KW_LINE_VAL, \
					  DAT_LINE_VAL, DAT_LINE_COMMA,\
					  COMMENT_LINE,\
					  ST_ERROR, LINE_END } state ;

	// Do not leak onto next line
	state = LINE_END ;
	initStyle = SCE_ABAQUS_DEFAULT;
	StyleContext sc(startPos, length, initStyle, styler);

	// Things are actually quite simple
	// we have commentlines
	// keywordlines and datalines
	// On a data line there will only be colouring of numbers
	// a keyword line is constructed as
	// *word,[ paramname[=paramvalue]]*
	// if the line ends with a , the keyword line continues onto the new line

	for (; sc.More(); sc.Forward()) {
		switch ( state ) {
        case KW_LINE_KW :
            if ( sc.atLineEnd ) {
                // finished the line in keyword state, switch to LINE_END
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            } else if ( IsAKeywordChar(sc.ch) ) {
                // nothing changes
                state = KW_LINE_KW ;
            } else if ( sc.ch == ',' ) {
                // Well well we say a comma, arguments *MUST* follow
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = KW_LINE_COMMA ;
            } else {
                // Flag an error
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            // Done with processing
            break ;
        case KW_LINE_COMMA :
            // acomma on a keywordline was seen
            if ( IsAKeywordChar(sc.ch)) {
                sc.SetState(SCE_ABAQUS_ARGUMENT) ;
                state = KW_LINE_PAR ;
            } else if ( sc.atLineEnd || (sc.ch == ',') ) {
                // we remain in keyword mode
                state = KW_LINE_COMMA ;
            } else if ( sc.ch == ' ' ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = KW_LINE_COMMA ;
            } else {
                // Anything else constitutes an error
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case KW_LINE_PAR :
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            } else if ( IsAKeywordChar(sc.ch) || (sc.ch == '-') ) {
                // remain in this state
                state = KW_LINE_PAR ;
            } else if ( sc.ch == ',' ) {
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = KW_LINE_COMMA ;
            } else if ( sc.ch == '=' ) {
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = KW_LINE_EQ ;
            } else {
                // Anything else constitutes an error
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case KW_LINE_EQ :
            if ( sc.ch == ' ' ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                // remain in this state
                state = KW_LINE_EQ ;
            } else if ( IsADigit(sc.ch) || (sc.ch == '-') || (sc.ch == '.' && IsADigit(sc.chNext)) ) {
                sc.SetState(SCE_ABAQUS_NUMBER) ;
                state = KW_LINE_VAL ;
            } else if ( IsAKeywordChar(sc.ch) ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = KW_LINE_VAL ;
            } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
                sc.SetState(SCE_ABAQUS_STRING) ;
                state = KW_LINE_VAL ;
            } else {
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case KW_LINE_VAL :
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) {
                // nothing changes
                state = KW_LINE_VAL ;
            } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
                    ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) &&
                    (sc.state == SCE_ABAQUS_NUMBER)) {
                // remain in number mode
                state = KW_LINE_VAL ;
            } else if (sc.state == SCE_ABAQUS_STRING) {
                // accept everything until a closing quote
                if ( sc.ch == '\'' || sc.ch == '\"' ) {
                    sc.SetState(SCE_ABAQUS_DEFAULT) ;
                    state = KW_LINE_VAL ;
                }
            } else if ( sc.ch == ',' ) {
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = KW_LINE_COMMA ;
            } else {
                // anything else is an error
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case DAT_LINE_VAL :
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            } else if ( IsASetChar(sc.ch) && (sc.state == SCE_ABAQUS_DEFAULT) ) {
                // nothing changes
                state = DAT_LINE_VAL ;
            } else if (( (IsADigit(sc.ch) || sc.ch == '.' || (sc.ch == 'e' || sc.ch == 'E') ||
                    ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) &&
                    (sc.state == SCE_ABAQUS_NUMBER)) {
                // remain in number mode
                state = DAT_LINE_VAL ;
            } else if (sc.state == SCE_ABAQUS_STRING) {
                // accept everything until a closing quote
                if ( sc.ch == '\'' || sc.ch == '\"' ) {
                    sc.SetState(SCE_ABAQUS_DEFAULT) ;
                    state = DAT_LINE_VAL ;
                }
            } else if ( sc.ch == ',' ) {
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = DAT_LINE_COMMA ;
            } else {
                // anything else is an error
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case DAT_LINE_COMMA :
            // a comma on a data line was seen
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            } else if ( sc.ch == ' ' ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = DAT_LINE_COMMA ;
            } else if (sc.ch == ',')  {
                sc.SetState(SCE_ABAQUS_OPERATOR) ;
                state = DAT_LINE_COMMA ;
            } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) {
                sc.SetState(SCE_ABAQUS_NUMBER) ;
                state = DAT_LINE_VAL ;
            } else if ( IsAKeywordChar(sc.ch) ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = DAT_LINE_VAL ;
            } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
                sc.SetState(SCE_ABAQUS_STRING) ;
                state = DAT_LINE_VAL ;
            } else {
                sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                state = ST_ERROR ;
            }
            break ;
        case COMMENT_LINE :
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            }
            break ;
        case ST_ERROR :
            if ( sc.atLineEnd ) {
                sc.SetState(SCE_ABAQUS_DEFAULT) ;
                state = LINE_END ;
            }
            break ;
        case LINE_END :
            if ( sc.atLineEnd || sc.ch == ' ' ) {
                // nothing changes
                state = LINE_END ;
            } else if ( sc.ch == '*' ) {
                if ( sc.chNext == '*' ) {
                    state = COMMENT_LINE ;
                    sc.SetState(SCE_ABAQUS_COMMENT) ;
                } else {
                    state = KW_LINE_KW ;
                    sc.SetState(SCE_ABAQUS_STARCOMMAND) ;
                }
            } else {
                // it must be a data line, things are as if we are in DAT_LINE_COMMA
                if ( sc.ch == ',' ) {
                    sc.SetState(SCE_ABAQUS_OPERATOR) ;
                    state = DAT_LINE_COMMA ;
                } else if ( IsADigit(sc.ch) || (sc.ch == '-')|| (sc.ch == '.' && IsADigit(sc.chNext)) ) {
                    sc.SetState(SCE_ABAQUS_NUMBER) ;
                    state = DAT_LINE_VAL ;
                } else if ( IsAKeywordChar(sc.ch) ) {
                    sc.SetState(SCE_ABAQUS_DEFAULT) ;
                    state = DAT_LINE_VAL ;
                } else if ( (sc.ch == '\'') || (sc.ch == '\"') ) {
                    sc.SetState(SCE_ABAQUS_STRING) ;
                    state = DAT_LINE_VAL ;
                } else {
                    sc.SetState(SCE_ABAQUS_PROCESSOR) ;
                    state = ST_ERROR ;
                }
            }
            break ;
		  }
   }
   sc.Complete();
}

//------------------------------------------------------------------------------
// This copyied and modified from LexBasic.cxx
//------------------------------------------------------------------------------

/* Bits:
 * 1  - whitespace
 * 2  - operator
 * 4  - identifier
 * 8  - decimal digit
 * 16 - hex digit
 * 32 - bin digit
 */
static int character_classification[128] =
{
    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  6,  2,  2,  2,  10, 6,
    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
};

static bool IsSpace(int c) {
	return c < 128 && (character_classification[c] & 1);
}

static bool IsIdentifier(int c) {
	return c < 128 && (character_classification[c] & 4);
}

static int LowerCase(int c)
{
	if (c >= 'A' && c <= 'Z')
		return 'a' + c - 'A';
	return c;
}

static int LineEnd(int line, Accessor &styler)
{
    const int docLines = styler.GetLine(styler.Length() - 1);  // Available last line
    int eol_pos ;
    // if the line is the last line, the eol_pos is styler.Length()
    // eol will contain a new line, or a virtual new line
    if ( docLines == line )
        eol_pos = styler.Length() ;
    else
        eol_pos = styler.LineStart(line + 1) - 1;
    return eol_pos ;
}

static int LineStart(int line, Accessor &styler)
{
    return styler.LineStart(line) ;
}

// LineType
//
// bits determines the line type
// 1  : data line
// 2  : only whitespace
// 3  : data line with only whitespace
// 4  : keyword line
// 5  : block open keyword line
// 6  : block close keyword line
// 7  : keyword line in error
// 8  : comment line
static int LineType(int line, Accessor &styler) {
    int pos = LineStart(line, styler) ;
    int eol_pos = LineEnd(line, styler) ;

    int c ;
    char ch = ' ';

    int i = pos ;
    while ( i < eol_pos ) {
        c = styler.SafeGetCharAt(i);
        ch = static_cast<char>(LowerCase(c));
        // We can say something as soon as no whitespace
        // was encountered
        if ( !IsSpace(c) )
            break ;
        i++ ;
    }

    if ( i >= eol_pos ) {
        // This is a whitespace line, currently
        // classifies as data line
        return 3 ;
    }

    if ( ch != '*' ) {
        // This is a data line
        return 1 ;
    }

    if ( i == eol_pos - 1 ) {
        // Only a single *, error but make keyword line
        return 4+3 ;
    }

    // This means we can have a second character
    // if that is also a * this means a comment
    // otherwise it is a keyword.
    c = styler.SafeGetCharAt(i+1);
    ch = static_cast<char>(LowerCase(c));
    if ( ch == '*' ) {
        return 8 ;
    }

    // At this point we know this is a keyword line
    // the character at position i is a *
    // it is not a comment line
    char word[256] ;
    int  wlen = 0;

    word[wlen] = '*' ;
	wlen++ ;

    i++ ;
    while ( (i < eol_pos) && (wlen < 255) ) {
        c = styler.SafeGetCharAt(i);
        ch = static_cast<char>(LowerCase(c));

        if ( (!IsSpace(c)) && (!IsIdentifier(c)) )
            break ;

        if ( IsIdentifier(c) ) {
            word[wlen] = ch ;
			wlen++ ;
		}

        i++ ;
    }

    word[wlen] = 0 ;

    // Make a comparison
	if ( !strcmp(word, "*step") ||
         !strcmp(word, "*part") ||
         !strcmp(word, "*instance") ||
         !strcmp(word, "*assembly")) {
       return 4+1 ;
    }

	if ( !strcmp(word, "*endstep") ||
         !strcmp(word, "*endpart") ||
         !strcmp(word, "*endinstance") ||
         !strcmp(word, "*endassembly")) {
       return 4+2 ;
    }

    return 4 ;
}

static void SafeSetLevel(int line, int level, Accessor &styler)
{
    if ( line < 0 )
        return ;

    int mask = ((~SC_FOLDLEVELHEADERFLAG) | (~SC_FOLDLEVELWHITEFLAG));

    if ( (level & mask) < 0 )
        return ;

    if ( styler.LevelAt(line) != level )
        styler.SetLevel(line, level) ;
}

static void FoldABAQUSDoc(unsigned int startPos, int length, int,
WordList *[], Accessor &styler) {
    int startLine = styler.GetLine(startPos) ;
    int endLine   = styler.GetLine(startPos+length-1) ;

    // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
    // We want to deal with all the cases
    // To know the correct indentlevel, we need to look back to the
    // previous command line indentation level
	// order of formatting keyline datalines commentlines
    int beginData    = -1 ;
    int beginComment = -1 ;
    int prvKeyLine   = startLine ;
    int prvKeyLineTp =  0 ;

    // Scan until we find the previous keyword line
    // this will give us the level reference that we need
    while ( prvKeyLine > 0 ) {
        prvKeyLine-- ;
        prvKeyLineTp = LineType(prvKeyLine, styler) ;
        if ( prvKeyLineTp & 4 )
            break ;
    }

    // Determine the base line level of all lines following
    // the previous keyword
    // new keyword lines are placed on this level
    //if ( prvKeyLineTp & 4 ) {
    int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ;
    //}

    // uncomment line below if weird behaviour continues
    prvKeyLine = -1 ;

    // Now start scanning over the lines.
    for ( int line = startLine; line <= endLine; line++ ) {
        int lineType = LineType(line, styler) ;

        // Check for comment line
        if ( lineType == 8 ) {
            if ( beginComment < 0 ) {
                beginComment = line ;
			}
        }

        // Check for data line
        if ( (lineType == 1) || (lineType == 3) ) {
            if ( beginData < 0 ) {
                if ( beginComment >= 0 ) {
                    beginData = beginComment ;
                } else {
                    beginData = line ;
                }
            }
			beginComment = -1 ;
		}

        // Check for keywordline.
        // As soon as a keyword line is encountered, we can set the
        // levels of everything from the previous keyword line to this one
        if ( lineType & 4 ) {
            // this is a keyword, we can now place the previous keyword
            // all its data lines and the remainder

            // Write comments and data line
            if ( beginComment < 0 ) {
                beginComment = line ;
			}

            if ( beginData < 0 ) {
                beginData = beginComment ;
				if ( prvKeyLineTp != 5 )
					SafeSetLevel(prvKeyLine, level, styler) ;
				else
					SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
            } else {
                SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
            }

            int datLevel = level + 1 ;
			if ( !(prvKeyLineTp & 4) ) {
				datLevel = level ;
			}

            for ( int ll = beginData; ll < beginComment; ll++ )
                SafeSetLevel(ll, datLevel, styler) ;

            // The keyword we just found is going to be written at another level
            // if we have a type 5 and type 6
            if ( prvKeyLineTp == 5 ) {
                level += 1 ;
			}

            if ( prvKeyLineTp == 6 ) {
                level -= 1 ;
				if ( level < 0 ) {
					level = 0 ;
				}
            }

            for ( int lll = beginComment; lll < line; lll++ )
                SafeSetLevel(lll, level, styler) ;

            // wrap and reset
            beginComment = -1 ;
            beginData    = -1 ;
            prvKeyLine   = line ;
            prvKeyLineTp = lineType ;
        }

    }

    if ( beginComment < 0 ) {
        beginComment = endLine + 1 ;
    } else {
        // We need to find out whether this comment block is followed by
        // a data line or a keyword line
        const int docLines = styler.GetLine(styler.Length() - 1);

        for ( int line = endLine + 1; line <= docLines; line++ ) {
            int lineType = LineType(line, styler) ;

            if ( lineType != 8 ) {
				if ( !(lineType & 4) )  {
					beginComment = endLine + 1 ;
				}
                break ;
			}
        }
    }

    if ( beginData < 0 ) {
        beginData = beginComment ;
		if ( prvKeyLineTp != 5 )
			SafeSetLevel(prvKeyLine, level, styler) ;
		else
			SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
    } else {
        SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ;
    }

    int datLevel = level + 1 ;
	if ( !(prvKeyLineTp & 4) ) {
		datLevel = level ;
	}

    for ( int ll = beginData; ll < beginComment; ll++ )
        SafeSetLevel(ll, datLevel, styler) ;

	if ( prvKeyLineTp == 5 ) {
		level += 1 ;
	}

	if ( prvKeyLineTp == 6 ) {
		level -= 1 ;
	}
	for ( int m = beginComment; m <= endLine; m++ )
        SafeSetLevel(m, level, styler) ;
}

static const char * const abaqusWordListDesc[] = {
    "processors",
    "commands",
    "slashommands",
    "starcommands",
    "arguments",
    "functions",
    0
};

LexerModule lmAbaqus(SCLEX_ABAQUS, ColouriseABAQUSDoc, "abaqus", FoldABAQUSDoc, abaqusWordListDesc);

Added lexers/LexAda.cxx.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
// Scintilla source code edit control
/** @file LexAda.cxx
 ** Lexer for Ada 95
 **/
// Copyright 2002 by Sergey Koshcheyev <sergey.k@seznam.cz>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
 * Interface
 */

static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler);

static const char * const adaWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmAda(SCLEX_ADA, ColouriseDocument, "ada", NULL, adaWordListDesc);

/*
 * Implementation
 */

// Functions that have apostropheStartsAttribute as a parameter set it according to whether
// an apostrophe encountered after processing the current token will start an attribute or
// a character literal.
static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL);
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute);

static inline bool IsDelimiterCharacter(int ch);
static inline bool IsNumberStartCharacter(int ch);
static inline bool IsNumberCharacter(int ch);
static inline bool IsSeparatorOrDelimiterCharacter(int ch);
static bool IsValidIdentifier(const std::string& identifier);
static bool IsValidNumber(const std::string& number);
static inline bool IsWordStartCharacter(int ch);
static inline bool IsWordCharacter(int ch);

static void ColouriseCharacter(StyleContext& sc, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = true;

	sc.SetState(SCE_ADA_CHARACTER);

	// Skip the apostrophe and one more character (so that '' is shown as non-terminated and '''
	// is handled correctly)
	sc.Forward();
	sc.Forward();

	ColouriseContext(sc, '\'', SCE_ADA_CHARACTEREOL);
}

static void ColouriseContext(StyleContext& sc, char chEnd, int stateEOL) {
	while (!sc.atLineEnd && !sc.Match(chEnd)) {
		sc.Forward();
	}

	if (!sc.atLineEnd) {
		sc.ForwardSetState(SCE_ADA_DEFAULT);
	} else {
		sc.ChangeState(stateEOL);
	}
}

static void ColouriseComment(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
	// Apostrophe meaning is not changed, but the parameter is present for uniformity

	sc.SetState(SCE_ADA_COMMENTLINE);

	while (!sc.atLineEnd) {
		sc.Forward();
	}
}

static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = sc.Match (')');
	sc.SetState(SCE_ADA_DELIMITER);
	sc.ForwardSetState(SCE_ADA_DEFAULT);
}

static void ColouriseLabel(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = false;

	sc.SetState(SCE_ADA_LABEL);

	// Skip "<<"
	sc.Forward();
	sc.Forward();

	std::string identifier;

	while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
		identifier += static_cast<char>(tolower(sc.ch));
		sc.Forward();
	}

	// Skip ">>"
	if (sc.Match('>', '>')) {
		sc.Forward();
		sc.Forward();
	} else {
		sc.ChangeState(SCE_ADA_ILLEGAL);
	}

	// If the name is an invalid identifier or a keyword, then make it invalid label
	if (!IsValidIdentifier(identifier) || keywords.InList(identifier.c_str())) {
		sc.ChangeState(SCE_ADA_ILLEGAL);
	}

	sc.SetState(SCE_ADA_DEFAULT);

}

static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = true;

	std::string number;
	sc.SetState(SCE_ADA_NUMBER);

	// Get all characters up to a delimiter or a separator, including points, but excluding
	// double points (ranges).
	while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
		number += static_cast<char>(sc.ch);
		sc.Forward();
	}

	// Special case: exponent with sign
	if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
	        (sc.ch == '+' || sc.ch == '-')) {
		number += static_cast<char>(sc.ch);
		sc.Forward ();

		while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
			number += static_cast<char>(sc.ch);
			sc.Forward();
		}
	}

	if (!IsValidNumber(number)) {
		sc.ChangeState(SCE_ADA_ILLEGAL);
	}

	sc.SetState(SCE_ADA_DEFAULT);
}

static void ColouriseString(StyleContext& sc, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = true;

	sc.SetState(SCE_ADA_STRING);
	sc.Forward();

	ColouriseContext(sc, '"', SCE_ADA_STRINGEOL);
}

static void ColouriseWhiteSpace(StyleContext& sc, bool& /*apostropheStartsAttribute*/) {
	// Apostrophe meaning is not changed, but the parameter is present for uniformity
	sc.SetState(SCE_ADA_DEFAULT);
	sc.ForwardSetState(SCE_ADA_DEFAULT);
}

static void ColouriseWord(StyleContext& sc, WordList& keywords, bool& apostropheStartsAttribute) {
	apostropheStartsAttribute = true;
	sc.SetState(SCE_ADA_IDENTIFIER);

	std::string word;

	while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
		word += static_cast<char>(tolower(sc.ch));
		sc.Forward();
	}

	if (!IsValidIdentifier(word)) {
		sc.ChangeState(SCE_ADA_ILLEGAL);

	} else if (keywords.InList(word.c_str())) {
		sc.ChangeState(SCE_ADA_WORD);

		if (word != "all") {
			apostropheStartsAttribute = false;
		}
	}

	sc.SetState(SCE_ADA_DEFAULT);
}

//
// ColouriseDocument
//

static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler) {
	WordList &keywords = *keywordlists[0];

	StyleContext sc(startPos, length, initStyle, styler);

	int lineCurrent = styler.GetLine(startPos);
	bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;

	while (sc.More()) {
		if (sc.atLineEnd) {
			// Go to the next line
			sc.Forward();
			lineCurrent++;

			// Remember the line state for future incremental lexing
			styler.SetLineState(lineCurrent, apostropheStartsAttribute);

			// Don't continue any styles on the next line
			sc.SetState(SCE_ADA_DEFAULT);
		}

		// Comments
		if (sc.Match('-', '-')) {
			ColouriseComment(sc, apostropheStartsAttribute);

		// Strings
		} else if (sc.Match('"')) {
			ColouriseString(sc, apostropheStartsAttribute);

		// Characters
		} else if (sc.Match('\'') && !apostropheStartsAttribute) {
			ColouriseCharacter(sc, apostropheStartsAttribute);

		// Labels
		} else if (sc.Match('<', '<')) {
			ColouriseLabel(sc, keywords, apostropheStartsAttribute);

		// Whitespace
		} else if (IsASpace(sc.ch)) {
			ColouriseWhiteSpace(sc, apostropheStartsAttribute);

		// Delimiters
		} else if (IsDelimiterCharacter(sc.ch)) {
			ColouriseDelimiter(sc, apostropheStartsAttribute);

		// Numbers
		} else if (IsADigit(sc.ch) || sc.ch == '#') {
			ColouriseNumber(sc, apostropheStartsAttribute);

		// Keywords or identifiers
		} else {
			ColouriseWord(sc, keywords, apostropheStartsAttribute);
		}
	}

	sc.Complete();
}

static inline bool IsDelimiterCharacter(int ch) {
	switch (ch) {
	case '&':
	case '\'':
	case '(':
	case ')':
	case '*':
	case '+':
	case ',':
	case '-':
	case '.':
	case '/':
	case ':':
	case ';':
	case '<':
	case '=':
	case '>':
	case '|':
		return true;
	default:
		return false;
	}
}

static inline bool IsNumberCharacter(int ch) {
	return IsNumberStartCharacter(ch) ||
	       ch == '_' ||
	       ch == '.' ||
	       ch == '#' ||
	       (ch >= 'a' && ch <= 'f') ||
	       (ch >= 'A' && ch <= 'F');
}

static inline bool IsNumberStartCharacter(int ch) {
	return IsADigit(ch);
}

static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
	return IsASpace(ch) || IsDelimiterCharacter(ch);
}

static bool IsValidIdentifier(const std::string& identifier) {
	// First character can't be '_', so initialize the flag to true
	bool lastWasUnderscore = true;

	size_t length = identifier.length();

	// Zero-length identifiers are not valid (these can occur inside labels)
	if (length == 0) {
		return false;
	}

	// Check for valid character at the start
	if (!IsWordStartCharacter(identifier[0])) {
		return false;
	}

	// Check for only valid characters and no double underscores
	for (size_t i = 0; i < length; i++) {
		if (!IsWordCharacter(identifier[i]) ||
		        (identifier[i] == '_' && lastWasUnderscore)) {
			return false;
		}
		lastWasUnderscore = identifier[i] == '_';
	}

	// Check for underscore at the end
	if (lastWasUnderscore == true) {
		return false;
	}

	// All checks passed
	return true;
}

static bool IsValidNumber(const std::string& number) {
	size_t hashPos = number.find("#");
	bool seenDot = false;

	size_t i = 0;
	size_t length = number.length();

	if (length == 0)
		return false; // Just in case

	// Decimal number
	if (hashPos == std::string::npos) {
		bool canBeSpecial = false;

		for (; i < length; i++) {
			if (number[i] == '_') {
				if (!canBeSpecial) {
					return false;
				}
				canBeSpecial = false;
			} else if (number[i] == '.') {
				if (!canBeSpecial || seenDot) {
					return false;
				}
				canBeSpecial = false;
				seenDot = true;
			} else if (IsADigit(number[i])) {
				canBeSpecial = true;
			} else {
				break;
			}
		}

		if (!canBeSpecial)
			return false;
	} else {
		// Based number
		bool canBeSpecial = false;
		int base = 0;

		// Parse base
		for (; i < length; i++) {
			int ch = number[i];
			if (ch == '_') {
				if (!canBeSpecial)
					return false;
				canBeSpecial = false;
			} else if (IsADigit(ch)) {
				base = base * 10 + (ch - '0');
				if (base > 16)
					return false;
				canBeSpecial = true;
			} else if (ch == '#' && canBeSpecial) {
				break;
			} else {
				return false;
			}
		}

		if (base < 2)
			return false;
		if (i == length)
			return false;

		i++; // Skip over '#'

		// Parse number
		canBeSpecial = false;

		for (; i < length; i++) {
			int ch = tolower(number[i]);

			if (ch == '_') {
				if (!canBeSpecial) {
					return false;
				}
				canBeSpecial = false;

			} else if (ch == '.') {
				if (!canBeSpecial || seenDot) {
					return false;
				}
				canBeSpecial = false;
				seenDot = true;

			} else if (IsADigit(ch)) {
				if (ch - '0' >= base) {
					return false;
				}
				canBeSpecial = true;

			} else if (ch >= 'a' && ch <= 'f') {
				if (ch - 'a' + 10 >= base) {
					return false;
				}
				canBeSpecial = true;

			} else if (ch == '#' && canBeSpecial) {
				break;

			} else {
				return false;
			}
		}

		if (i == length) {
			return false;
		}

		i++;
	}

	// Exponent (optional)
	if (i < length) {
		if (number[i] != 'e' && number[i] != 'E')
			return false;

		i++; // Move past 'E'

		if (i == length) {
			return false;
		}

		if (number[i] == '+')
			i++;
		else if (number[i] == '-') {
			if (seenDot) {
				i++;
			} else {
				return false; // Integer literals should not have negative exponents
			}
		}

		if (i == length) {
			return false;
		}

		bool canBeSpecial = false;

		for (; i < length; i++) {
			if (number[i] == '_') {
				if (!canBeSpecial) {
					return false;
				}
				canBeSpecial = false;
			} else if (IsADigit(number[i])) {
				canBeSpecial = true;
			} else {
				return false;
			}
		}

		if (!canBeSpecial)
			return false;
	}

	// if i == length, number was parsed successfully.
	return i == length;
}

static inline bool IsWordCharacter(int ch) {
	return IsWordStartCharacter(ch) || IsADigit(ch);
}

static inline bool IsWordStartCharacter(int ch) {
	return (isascii(ch) && isalpha(ch)) || ch == '_';
}

Added lexers/LexAsm.cxx.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
// Scintilla source code edit control
/** @file LexAsm.cxx
 ** Lexer for Assembler, just for the MASM syntax
 ** Written by The Black Horus
 ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10
 ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring
 ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>
#include <map>
#include <set>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
		ch == '_' || ch == '?');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' ||
		ch == '%' || ch == '@' || ch == '$' || ch == '?');
}

static inline bool IsAsmOperator(const int ch) {
	if ((ch < 0x80) && (isalnum(ch)))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
		ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
		ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
		ch == '%' || ch == ':')
		return true;
	return false;
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK;
}

static inline int LowerCase(int c) {
	if (c >= 'A' && c <= 'Z')
		return 'a' + c - 'A';
	return c;
}

// An individual named option for use in an OptionSet

// Options used for LexerAsm
struct OptionsAsm {
	std::string delimiter;
	bool fold;
	bool foldSyntaxBased;
	bool foldCommentMultiline;
	bool foldCommentExplicit;
	std::string foldExplicitStart;
	std::string foldExplicitEnd;
	bool foldExplicitAnywhere;
	bool foldCompact;
	OptionsAsm() {
		delimiter = "";
		fold = false;
		foldSyntaxBased = true;
		foldCommentMultiline = false;
		foldCommentExplicit = false;
		foldExplicitStart = "";
		foldExplicitEnd   = "";
		foldExplicitAnywhere = false;
		foldCompact = true;
	}
};

static const char * const asmWordListDesc[] = {
	"CPU instructions",
	"FPU instructions",
	"Registers",
	"Directives",
	"Directive operands",
	"Extended instructions",
	"Directives4Foldstart",
	"Directives4Foldend",
	0
};

struct OptionSetAsm : public OptionSet<OptionsAsm> {
	OptionSetAsm() {
		DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter,
			"Character used for COMMENT directive's delimiter, replacing the standard \"~\".");

		DefineProperty("fold", &OptionsAsm::fold);

		DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased,
			"Set this property to 0 to disable syntax based folding.");

		DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline,
			"Set this property to 1 to enable folding multi-line comments.");

		DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit,
			"This option enables folding explicit fold points when using the Asm lexer. "
			"Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} "
			"at the end of a section that should fold.");

		DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart,
			"The string to use for explicit fold start points, replacing the standard ;{.");

		DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd,
			"The string to use for explicit fold end points, replacing the standard ;}.");

		DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere,
			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments.");

		DefineProperty("fold.compact", &OptionsAsm::foldCompact);

		DefineWordListSets(asmWordListDesc);
	}
};

class LexerAsm : public ILexer {
	WordList cpuInstruction;
	WordList mathInstruction;
	WordList registers;
	WordList directive;
	WordList directiveOperand;
	WordList extInstruction;
	WordList directives4foldstart;
	WordList directives4foldend;
	OptionsAsm options;
	OptionSetAsm osAsm;
public:
	LexerAsm() {
	}
	virtual ~LexerAsm() {
	}
	void SCI_METHOD Release() {
		delete this;
	}
	int SCI_METHOD Version() const {
		return lvOriginal;
	}
	const char * SCI_METHOD PropertyNames() {
		return osAsm.PropertyNames();
	}
	int SCI_METHOD PropertyType(const char *name) {
		return osAsm.PropertyType(name);
	}
	const char * SCI_METHOD DescribeProperty(const char *name) {
		return osAsm.DescribeProperty(name);
	}
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char * SCI_METHOD DescribeWordListSets() {
		return osAsm.DescribeWordListSets();
	}
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

	void * SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}

	static ILexer *LexerFactoryAsm() {
		return new LexerAsm();
	}
};

int SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) {
	if (osAsm.PropertySet(&options, key, val)) {
		return 0;
	}
	return -1;
}

int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &cpuInstruction;
		break;
	case 1:
		wordListN = &mathInstruction;
		break;
	case 2:
		wordListN = &registers;
		break;
	case 3:
		wordListN = &directive;
		break;
	case 4:
		wordListN = &directiveOperand;
		break;
	case 5:
		wordListN = &extInstruction;
		break;
	case 6:
		wordListN = &directives4foldstart;
		break;
	case 7:
		wordListN = &directives4foldend;
		break;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
		}
	}
	return firstModification;
}

void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);

	// Do not leak onto next line
	if (initStyle == SCE_ASM_STRINGEOL)
		initStyle = SCE_ASM_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward())
	{

		// Prevent SCE_ASM_STRINGEOL from leaking back to previous line
		if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) {
			sc.SetState(SCE_ASM_STRING);
		} else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) {
			sc.SetState(SCE_ASM_CHARACTER);
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_ASM_OPERATOR) {
			if (!IsAsmOperator(sc.ch)) {
			    sc.SetState(SCE_ASM_DEFAULT);
			}
		} else if (sc.state == SCE_ASM_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_ASM_DEFAULT);
			}
		} else if (sc.state == SCE_ASM_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) ) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				bool IsDirective = false;

				if (cpuInstruction.InList(s)) {
					sc.ChangeState(SCE_ASM_CPUINSTRUCTION);
				} else if (mathInstruction.InList(s)) {
					sc.ChangeState(SCE_ASM_MATHINSTRUCTION);
				} else if (registers.InList(s)) {
					sc.ChangeState(SCE_ASM_REGISTER);
				}  else if (directive.InList(s)) {
					sc.ChangeState(SCE_ASM_DIRECTIVE);
					IsDirective = true;
				} else if (directiveOperand.InList(s)) {
					sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND);
				} else if (extInstruction.InList(s)) {
					sc.ChangeState(SCE_ASM_EXTINSTRUCTION);
				}
				sc.SetState(SCE_ASM_DEFAULT);
				if (IsDirective && !strcmp(s, "comment")) {
					char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0];
					while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) {
						sc.ForwardSetState(SCE_ASM_DEFAULT);
					}
					if (sc.ch == delimiter) {
						sc.SetState(SCE_ASM_COMMENTDIRECTIVE);
					}
				}
			}
		} else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) {
			char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0];
			if (sc.ch == delimiter) {
				while (!sc.atLineEnd) {
					sc.Forward();
				}
				sc.SetState(SCE_ASM_DEFAULT);
			}
		} else if (sc.state == SCE_ASM_COMMENT ) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_ASM_DEFAULT);
			}
		} else if (sc.state == SCE_ASM_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_ASM_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_ASM_STRINGEOL);
				sc.ForwardSetState(SCE_ASM_DEFAULT);
			}
		} else if (sc.state == SCE_ASM_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_ASM_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_ASM_STRINGEOL);
				sc.ForwardSetState(SCE_ASM_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_ASM_DEFAULT) {
			if (sc.ch == ';'){
				sc.SetState(SCE_ASM_COMMENT);
			} else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) {
				sc.SetState(SCE_ASM_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_ASM_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_ASM_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_ASM_CHARACTER);
			} else if (IsAsmOperator(sc.ch)) {
				sc.SetState(SCE_ASM_OPERATOR);
			}
		}

	}
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "else".

void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {

	if (!options.fold)
		return;

	LexAccessor styler(pAccess);

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	char word[100];
	int wordlen = 0;
	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (options.foldCommentMultiline && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) {
			if (userDefinedFoldMarkers) {
				if (styler.Match(i, options.foldExplicitStart.c_str())) {
 					levelNext++;
				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
 					levelNext--;
 				}
			} else {
				if (ch == ';') {
					if (chNext == '{') {
						levelNext++;
					} else if (chNext == '}') {
						levelNext--;
					}
				}
 			}
 		}
		if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) {
			word[wordlen++] = static_cast<char>(LowerCase(ch));
			if (wordlen == 100) {                   // prevent overflow
				word[0] = '\0';
				wordlen = 1;
			}
			if (styleNext != SCE_ASM_DIRECTIVE) {   // reading directive ready
				word[wordlen] = '\0';
				wordlen = 0;
				if (directives4foldstart.InList(word)) {
					levelNext++;
				} else if (directives4foldend.InList(word)){
					levelNext--;
				}
			}
		}
		if (!IsASpace(ch))
			visibleChars++;
		if (atEOL || (i == endPos-1)) {
			int levelUse = levelCurrent;
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && options.foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
				// There is an empty line at end of file so give it same level and empty
				styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
			}
			visibleChars = 0;
		}
	}
}

LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc);

Added lexers/LexAsn1.cxx.

























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexAsn1.cxx
 ** Lexer for ASN.1
 **/
// Copyright 2004 by Herr Pfarrer rpfarrer <at> yahoo <dot> de
// Last Updated: 20/07/2004
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Some char test functions
static bool isAsn1Number(int ch)
{
	return (ch >= '0' && ch <= '9');
}

static bool isAsn1Letter(int ch)
{
	return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}

static bool isAsn1Char(int ch)
{
	return (ch == '-' ) || isAsn1Number(ch) || isAsn1Letter (ch);
}

//
//	Function determining the color of a given code portion
//	Based on a "state"
//
static void ColouriseAsn1Doc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[], Accessor &styler)
{
	// The keywords
	WordList &Keywords = *keywordLists[0];
	WordList &Attributes = *keywordLists[1];
	WordList &Descriptors = *keywordLists[2];
	WordList &Types = *keywordLists[3];

	// Parse the whole buffer character by character using StyleContext
	StyleContext sc(startPos, length, initStyle, styler);
	for (; sc.More(); sc.Forward())
	{
		// The state engine
		switch (sc.state)
		{
		case SCE_ASN1_DEFAULT:		// Plain characters
asn1_default:
			if (sc.ch == '-' && sc.chNext == '-')
				// A comment begins here
				sc.SetState(SCE_ASN1_COMMENT);
			else if (sc.ch == '"')
				// A string begins here
				sc.SetState(SCE_ASN1_STRING);
			else if (isAsn1Number (sc.ch))
				// A number starts here (identifier should start with a letter in ASN.1)
				sc.SetState(SCE_ASN1_SCALAR);
			else if (isAsn1Char (sc.ch))
				// An identifier starts here (identifier always start with a letter)
				sc.SetState(SCE_ASN1_IDENTIFIER);
			else if (sc.ch == ':')
				// A ::= operator starts here
				sc.SetState(SCE_ASN1_OPERATOR);
			break;
		case SCE_ASN1_COMMENT:		// A comment
			if (sc.ch == '\r' || sc.ch == '\n')
				// A comment ends here
				sc.SetState(SCE_ASN1_DEFAULT);
			break;
		case SCE_ASN1_IDENTIFIER:	// An identifier (keyword, attribute, descriptor or type)
			if (!isAsn1Char (sc.ch))
			{
				// The end of identifier is here: we can look for it in lists by now and change its state
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (Keywords.InList(s))
					// It's a keyword, change its state
					sc.ChangeState(SCE_ASN1_KEYWORD);
				else if (Attributes.InList(s))
					// It's an attribute, change its state
					sc.ChangeState(SCE_ASN1_ATTRIBUTE);
				else if (Descriptors.InList(s))
					// It's a descriptor, change its state
					sc.ChangeState(SCE_ASN1_DESCRIPTOR);
				else if (Types.InList(s))
					// It's a type, change its state
					sc.ChangeState(SCE_ASN1_TYPE);

				// Set to default now
				sc.SetState(SCE_ASN1_DEFAULT);
			}
			break;
		case SCE_ASN1_STRING:		// A string delimited by ""
			if (sc.ch == '"')
			{
				// A string ends here
				sc.ForwardSetState(SCE_ASN1_DEFAULT);

				// To correctly manage a char sticking to the string quote
				goto asn1_default;
			}
			break;
		case SCE_ASN1_SCALAR:		// A plain number
			if (!isAsn1Number (sc.ch))
				// A number ends here
				sc.SetState(SCE_ASN1_DEFAULT);
			break;
		case SCE_ASN1_OPERATOR:		// The affectation operator ::= and wath follows (eg: ::= { org 6 } OID or ::= 12 trap)
			if (sc.ch == '{')
			{
				// An OID definition starts here: enter the sub loop
				for (; sc.More(); sc.Forward())
				{
					if (isAsn1Number (sc.ch) && (!isAsn1Char (sc.chPrev) || isAsn1Number (sc.chPrev)))
						// The OID number is highlighted
						sc.SetState(SCE_ASN1_OID);
					else if (isAsn1Char (sc.ch))
						// The OID parent identifier is plain
						sc.SetState(SCE_ASN1_IDENTIFIER);
					else
						sc.SetState(SCE_ASN1_DEFAULT);

					if (sc.ch == '}')
						// Here ends the OID and the operator sub loop: go back to main loop
						break;
				}
			}
			else if (isAsn1Number (sc.ch))
			{
				// A trap number definition starts here: enter the sub loop
				for (; sc.More(); sc.Forward())
				{
					if (isAsn1Number (sc.ch))
						// The trap number is highlighted
						sc.SetState(SCE_ASN1_OID);
					else
					{
						// The number ends here: go back to main loop
						sc.SetState(SCE_ASN1_DEFAULT);
						break;
					}
				}
			}
			else if (sc.ch != ':' && sc.ch != '=' && sc.ch != ' ')
				// The operator doesn't imply an OID definition nor a trap, back to main loop
				goto asn1_default; // To be sure to handle actually the state change
			break;
		}
	}
	sc.Complete();
}

static void FoldAsn1Doc(unsigned int, int, int, WordList *[], Accessor &styler)
{
	// No folding enabled, no reason to continue...
	if( styler.GetPropertyInt("fold") == 0 )
		return;

	// No folding implemented: doesn't make sense for ASN.1
}

static const char * const asn1WordLists[] = {
	"Keywords",
	"Attributes",
	"Descriptors",
	"Types",
	0, };


LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);

Added lexers/LexBaan.cxx.









































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexBaan.cxx
 ** Lexer for Baan.
 ** Based heavily on LexCPP.cxx
 **/
// Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int  ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '$' || ch == ':');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColouriseBaanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	if (initStyle == SCE_BAAN_STRINGEOL)	// Does not leak onto next line
		initStyle = SCE_BAAN_DEFAULT;

	int visibleChars = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_BAAN_OPERATOR) {
			sc.SetState(SCE_BAAN_DEFAULT);
		} else if (sc.state == SCE_BAAN_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_BAAN_WORD2);
				}
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			} else {
				if (sc.atLineEnd && (sc.chNext != '^')) {
					sc.SetState(SCE_BAAN_DEFAULT);
				}
			}
		} else if (sc.state == SCE_BAAN_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_COMMENTDOC) {
			if (sc.MatchIgnoreCase("enddllusage")) {
				for (unsigned int i = 0; i < 10; i++){
					sc.Forward();
				}
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			}
		} else if (sc.state == SCE_BAAN_STRING) {
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_BAAN_DEFAULT);
			} else if ((sc.atLineEnd) && (sc.chNext != '^')) {
				sc.ChangeState(SCE_BAAN_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		}

		if (sc.state == SCE_BAAN_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_BAAN_NUMBER);
			} else if (sc.MatchIgnoreCase("dllusage")){
					sc.SetState(SCE_BAAN_COMMENTDOC);
					do {
						sc.Forward();
					} while ((!sc.atLineEnd) && sc.More());
			} else if (IsAWordStart(sc.ch)) {
					sc.SetState(SCE_BAAN_IDENTIFIER);
			} else if (sc.Match('|')){
					sc.SetState(SCE_BAAN_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_BAAN_STRING);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_BAAN_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while (IsASpace(sc.ch) && sc.More());
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_BAAN_OPERATOR);
			}
		}
		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldBaanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment &&
			(style == SCE_BAAN_COMMENT || style == SCE_BAAN_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_BAAN_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmBaan(SCLEX_BAAN, ColouriseBaanDoc, "baan", FoldBaanDoc);

Added lexers/LexBash.cxx.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
// Scintilla source code edit control
/** @file LexBash.cxx
 ** Lexer for Bash.
 **/
// Copyright 2004-2012 by Neil Hodgson <neilh@scintilla.org>
// Adapted from LexPerl by Kein-Hong Man 2004
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define HERE_DELIM_MAX			256

// define this if you want 'invalid octals' to be marked as errors
// usually, this is not a good idea, permissive lexing is better
#undef PEDANTIC_OCTAL

#define BASH_BASE_ERROR			65
#define BASH_BASE_DECIMAL		66
#define BASH_BASE_HEX			67
#ifdef PEDANTIC_OCTAL
#define BASH_BASE_OCTAL			68
#define	BASH_BASE_OCTAL_ERROR	69
#endif

// state constants for parts of a bash command segment
#define	BASH_CMD_BODY			0
#define BASH_CMD_START			1
#define BASH_CMD_WORD			2
#define BASH_CMD_TEST			3
#define BASH_CMD_ARITH			4
#define BASH_CMD_DELIM			5

// state constants for nested delimiter pairs, used by
// SCE_SH_STRING and SCE_SH_BACKTICKS processing
#define BASH_DELIM_LITERAL		0
#define BASH_DELIM_STRING		1
#define BASH_DELIM_CSTRING		2
#define BASH_DELIM_LSTRING		3
#define BASH_DELIM_COMMAND		4
#define BASH_DELIM_BACKTICK		5

#define BASH_DELIM_STACK_MAX	7

static inline int translateBashDigit(int ch) {
	if (ch >= '0' && ch <= '9') {
		return ch - '0';
	} else if (ch >= 'a' && ch <= 'z') {
		return ch - 'a' + 10;
	} else if (ch >= 'A' && ch <= 'Z') {
		return ch - 'A' + 36;
	} else if (ch == '@') {
		return 62;
	} else if (ch == '_') {
		return 63;
	}
	return BASH_BASE_ERROR;
}

static inline int getBashNumberBase(char *s) {
	int i = 0;
	int base = 0;
	while (*s) {
		base = base * 10 + (*s++ - '0');
		i++;
	}
	if (base > 64 || i > 2) {
		return BASH_BASE_ERROR;
	}
	return base;
}

static int opposite(int ch) {
	if (ch == '(') return ')';
	if (ch == '[') return ']';
	if (ch == '{') return '}';
	if (ch == '<') return '>';
	return ch;
}

static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
							 WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList cmdDelimiter, bashStruct, bashStruct_in;
	cmdDelimiter.Set("| || |& & && ; ;; ( ) { }");
	bashStruct.Set("if elif fi while until else then do done esac eval");
	bashStruct_in.Set("for case select");

	CharacterSet setWordStart(CharacterSet::setAlpha, "_");
	// note that [+-] are often parts of identifiers in shell scripts
	CharacterSet setWord(CharacterSet::setAlphaNum, "._+-");
	CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/<?!.~@");
	CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMACahGLNn");
	CharacterSet setParam(CharacterSet::setAlphaNum, "$_");
	CharacterSet setHereDoc(CharacterSet::setAlpha, "_\\-+!");
	CharacterSet setHereDoc2(CharacterSet::setAlphaNum, "_-+!");
	CharacterSet setLeftShift(CharacterSet::setDigits, "=$");

	class HereDocCls {	// Class to manage HERE document elements
	public:
		int State;		// 0: '<<' encountered
		// 1: collect the delimiter
		// 2: here doc text (lines after the delimiter)
		int Quote;		// the char after '<<'
		bool Quoted;		// true if Quote in ('\'','"','`')
		bool Indent;		// indented delimiter (for <<-)
		int DelimiterLength;	// strlen(Delimiter)
		char *Delimiter;	// the Delimiter, 256: sizeof PL_tokenbuf
		HereDocCls() {
			State = 0;
			Quote = 0;
			Quoted = false;
			Indent = 0;
			DelimiterLength = 0;
			Delimiter = new char[HERE_DELIM_MAX];
			Delimiter[0] = '\0';
		}
		void Append(int ch) {
			Delimiter[DelimiterLength++] = static_cast<char>(ch);
			Delimiter[DelimiterLength] = '\0';
		}
		~HereDocCls() {
			delete []Delimiter;
		}
	};
	HereDocCls HereDoc;

	class QuoteCls {	// Class to manage quote pairs (simplified vs LexPerl)
		public:
		int Count;
		int Up, Down;
		QuoteCls() {
			Count = 0;
			Up    = '\0';
			Down  = '\0';
		}
		void Open(int u) {
			Count++;
			Up    = u;
			Down  = opposite(Up);
		}
		void Start(int u) {
			Count = 0;
			Open(u);
		}
	};
	QuoteCls Quote;

	class QuoteStackCls {	// Class to manage quote pairs that nest
		public:
		int Count;
		int Up, Down;
		int Style;
		int Depth;			// levels pushed
		int *CountStack;
		int *UpStack;
		int *StyleStack;
		QuoteStackCls() {
			Count = 0;
			Up    = '\0';
			Down  = '\0';
			Style = 0;
			Depth = 0;
			CountStack = new int[BASH_DELIM_STACK_MAX];
			UpStack    = new int[BASH_DELIM_STACK_MAX];
			StyleStack = new int[BASH_DELIM_STACK_MAX];
		}
		void Start(int u, int s) {
			Count = 1;
			Up    = u;
			Down  = opposite(Up);
			Style = s;
		}
		void Push(int u, int s) {
			if (Depth >= BASH_DELIM_STACK_MAX)
				return;
			CountStack[Depth] = Count;
			UpStack   [Depth] = Up;
			StyleStack[Depth] = Style;
			Depth++;
			Count = 1;
			Up    = u;
			Down  = opposite(Up);
			Style = s;
		}
		void Pop(void) {
			if (Depth <= 0)
				return;
			Depth--;
			Count = CountStack[Depth];
			Up    = UpStack   [Depth];
			Style = StyleStack[Depth];
			Down  = opposite(Up);
		}
		~QuoteStackCls() {
			delete []CountStack;
			delete []UpStack;
			delete []StyleStack;
		}
	};
	QuoteStackCls QuoteStack;

	int numBase = 0;
	int digit;
	unsigned int endPos = startPos + length;
	int cmdState = BASH_CMD_START;
	int testExprType = 0;

	// Always backtracks to the start of a line that is not a continuation
	// of the previous line (i.e. start of a bash command segment)
	int ln = styler.GetLine(startPos);
	if (ln > 0 && startPos == static_cast<unsigned int>(styler.LineStart(ln)))
		ln--;
	for (;;) {
		startPos = styler.LineStart(ln);
		if (ln == 0 || styler.GetLineState(ln) == BASH_CMD_START)
			break;
		ln--;
	}
	initStyle = SCE_SH_DEFAULT;

	StyleContext sc(startPos, endPos - startPos, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// handle line continuation, updates per-line stored state
		if (sc.atLineStart) {
			ln = styler.GetLine(sc.currentPos);
			if (sc.state == SCE_SH_STRING
			 || sc.state == SCE_SH_BACKTICKS
			 || sc.state == SCE_SH_CHARACTER
			 || sc.state == SCE_SH_HERE_Q
			 || sc.state == SCE_SH_COMMENTLINE
			 || sc.state == SCE_SH_PARAM) {
				// force backtrack while retaining cmdState
				styler.SetLineState(ln, BASH_CMD_BODY);
			} else {
				if (ln > 0) {
					if ((sc.GetRelative(-3) == '\\' && sc.GetRelative(-2) == '\r' && sc.chPrev == '\n')
					 || sc.GetRelative(-2) == '\\') {	// handle '\' line continuation
						// retain last line's state
					} else
						cmdState = BASH_CMD_START;
				}
				styler.SetLineState(ln, cmdState);
			}
		}

		// controls change of cmdState at the end of a non-whitespace element
		// states BODY|TEST|ARITH persist until the end of a command segment
		// state WORD persist, but ends with 'in' or 'do' construct keywords
		int cmdStateNew = BASH_CMD_BODY;
		if (cmdState == BASH_CMD_TEST || cmdState == BASH_CMD_ARITH || cmdState == BASH_CMD_WORD)
			cmdStateNew = cmdState;
		int stylePrev = sc.state;

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_SH_OPERATOR:
				sc.SetState(SCE_SH_DEFAULT);
				if (cmdState == BASH_CMD_DELIM)		// if command delimiter, start new command
					cmdStateNew = BASH_CMD_START;
				else if (sc.chPrev == '\\')			// propagate command state if line continued
					cmdStateNew = cmdState;
				break;
			case SCE_SH_WORD:
				// "." never used in Bash variable names but used in file names
				if (!setWord.Contains(sc.ch)) {
					char s[500];
					char s2[10];
					sc.GetCurrent(s, sizeof(s));
					// allow keywords ending in a whitespace or command delimiter
					s2[0] = static_cast<char>(sc.ch);
					s2[1] = '\0';
					bool keywordEnds = IsASpace(sc.ch) || cmdDelimiter.InList(s2);
					// 'in' or 'do' may be construct keywords
					if (cmdState == BASH_CMD_WORD) {
						if (strcmp(s, "in") == 0 && keywordEnds)
							cmdStateNew = BASH_CMD_BODY;
						else if (strcmp(s, "do") == 0 && keywordEnds)
							cmdStateNew = BASH_CMD_START;
						else
							sc.ChangeState(SCE_SH_IDENTIFIER);
						sc.SetState(SCE_SH_DEFAULT);
						break;
					}
					// a 'test' keyword starts a test expression
					if (strcmp(s, "test") == 0) {
						if (cmdState == BASH_CMD_START && keywordEnds) {
							cmdStateNew = BASH_CMD_TEST;
							testExprType = 0;
						} else
							sc.ChangeState(SCE_SH_IDENTIFIER);
					}
					// detect bash construct keywords
					else if (bashStruct.InList(s)) {
						if (cmdState == BASH_CMD_START && keywordEnds)
							cmdStateNew = BASH_CMD_START;
						else
							sc.ChangeState(SCE_SH_IDENTIFIER);
					}
					// 'for'|'case'|'select' needs 'in'|'do' to be highlighted later
					else if (bashStruct_in.InList(s)) {
						if (cmdState == BASH_CMD_START && keywordEnds)
							cmdStateNew = BASH_CMD_WORD;
						else
							sc.ChangeState(SCE_SH_IDENTIFIER);
					}
					// disambiguate option items and file test operators
					else if (s[0] == '-') {
						if (cmdState != BASH_CMD_TEST)
							sc.ChangeState(SCE_SH_IDENTIFIER);
					}
					// disambiguate keywords and identifiers
					else if (cmdState != BASH_CMD_START
						  || !(keywords.InList(s) && keywordEnds)) {
						sc.ChangeState(SCE_SH_IDENTIFIER);
					}
					sc.SetState(SCE_SH_DEFAULT);
				}
				break;
			case SCE_SH_IDENTIFIER:
				if (sc.chPrev == '\\') {	// for escaped chars
					sc.ForwardSetState(SCE_SH_DEFAULT);
				} else if (!setWord.Contains(sc.ch)) {
					sc.SetState(SCE_SH_DEFAULT);
				}
				break;
			case SCE_SH_NUMBER:
				digit = translateBashDigit(sc.ch);
				if (numBase == BASH_BASE_DECIMAL) {
					if (sc.ch == '#') {
						char s[10];
						sc.GetCurrent(s, sizeof(s));
						numBase = getBashNumberBase(s);
						if (numBase != BASH_BASE_ERROR)
							break;
					} else if (IsADigit(sc.ch))
						break;
				} else if (numBase == BASH_BASE_HEX) {
					if (IsADigit(sc.ch, 16))
						break;
#ifdef PEDANTIC_OCTAL
				} else if (numBase == BASH_BASE_OCTAL ||
						   numBase == BASH_BASE_OCTAL_ERROR) {
					if (digit <= 7)
						break;
					if (digit <= 9) {
						numBase = BASH_BASE_OCTAL_ERROR;
						break;
					}
#endif
				} else if (numBase == BASH_BASE_ERROR) {
					if (digit <= 9)
						break;
				} else {	// DD#DDDD number style handling
					if (digit != BASH_BASE_ERROR) {
						if (numBase <= 36) {
							// case-insensitive if base<=36
							if (digit >= 36) digit -= 26;
						}
						if (digit < numBase)
							break;
						if (digit <= 9) {
							numBase = BASH_BASE_ERROR;
							break;
						}
					}
				}
				// fallthrough when number is at an end or error
				if (numBase == BASH_BASE_ERROR
#ifdef PEDANTIC_OCTAL
					|| numBase == BASH_BASE_OCTAL_ERROR
#endif
				) {
					sc.ChangeState(SCE_SH_ERROR);
				}
				sc.SetState(SCE_SH_DEFAULT);
				break;
			case SCE_SH_COMMENTLINE:
				if (sc.atLineEnd && sc.chPrev != '\\') {
					sc.SetState(SCE_SH_DEFAULT);
				}
				break;
			case SCE_SH_HERE_DELIM:
				// From Bash info:
				// ---------------
				// Specifier format is: <<[-]WORD
				// Optional '-' is for removal of leading tabs from here-doc.
				// Whitespace acceptable after <<[-] operator
				//
				if (HereDoc.State == 0) { // '<<' encountered
					HereDoc.Quote = sc.chNext;
					HereDoc.Quoted = false;
					HereDoc.DelimiterLength = 0;
					HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
					if (sc.chNext == '\'' || sc.chNext == '\"') {	// a quoted here-doc delimiter (' or ")
						sc.Forward();
						HereDoc.Quoted = true;
						HereDoc.State = 1;
					} else if (!HereDoc.Indent && sc.chNext == '-') {	// <<- indent case
						HereDoc.Indent = true;
					} else if (setHereDoc.Contains(sc.chNext)) {
						// an unquoted here-doc delimiter, no special handling
						// TODO check what exactly bash considers part of the delim
						HereDoc.State = 1;
					} else if (sc.chNext == '<') {	// HERE string <<<
						sc.Forward();
						sc.ForwardSetState(SCE_SH_DEFAULT);
					} else if (IsASpace(sc.chNext)) {
						// eat whitespace
					} else if (setLeftShift.Contains(sc.chNext)) {
						// left shift << or <<= operator cases
						sc.ChangeState(SCE_SH_OPERATOR);
						sc.ForwardSetState(SCE_SH_DEFAULT);
					} else {
						// symbols terminates; deprecated zero-length delimiter
						HereDoc.State = 1;
					}
				} else if (HereDoc.State == 1) { // collect the delimiter
					if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') {
						HereDoc.Append(sc.ch);
					} else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) {	// closing quote => end of delimiter
						sc.ForwardSetState(SCE_SH_DEFAULT);
					} else if (sc.ch == '\\') {
						// skip escape prefix
					} else if (!HereDoc.Quoted) {
						sc.SetState(SCE_SH_DEFAULT);
					}
					if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) {	// force blowup
						sc.SetState(SCE_SH_ERROR);
						HereDoc.State = 0;
					}
				}
				break;
			case SCE_SH_HERE_Q:
				// HereDoc.State == 2
				if (sc.atLineStart) {
					sc.SetState(SCE_SH_HERE_Q);
					int prefixws = 0;
					while (IsASpace(sc.ch) && !sc.atLineEnd) {	// whitespace prefix
						sc.Forward();
						prefixws++;
					}
					if (prefixws > 0)
						sc.SetState(SCE_SH_HERE_Q);
					while (!sc.atLineEnd) {
						sc.Forward();
					}
					char s[HERE_DELIM_MAX];
					sc.GetCurrent(s, sizeof(s));
					if (sc.LengthCurrent() == 0) {  // '' or "" delimiters
						if (prefixws == 0 && HereDoc.Quoted && HereDoc.DelimiterLength == 0)
							sc.SetState(SCE_SH_DEFAULT);
						break;
					}
					if (s[strlen(s) - 1] == '\r')
						s[strlen(s) - 1] = '\0';
					if (strcmp(HereDoc.Delimiter, s) == 0) {
						if ((prefixws == 0) ||	// indentation rule
							(prefixws > 0 && HereDoc.Indent)) {
							sc.SetState(SCE_SH_DEFAULT);
							break;
						}
					}
				}
				break;
			case SCE_SH_SCALAR:	// variable names
				if (!setParam.Contains(sc.ch)) {
					if (sc.LengthCurrent() == 1) {
						// Special variable: $(, $_ etc.
						sc.ForwardSetState(SCE_SH_DEFAULT);
					} else {
						sc.SetState(SCE_SH_DEFAULT);
					}
				}
				break;
			case SCE_SH_STRING:	// delimited styles, can nest
			case SCE_SH_BACKTICKS:
				if (sc.ch == '\\' && QuoteStack.Up != '\\') {
					if (QuoteStack.Style != BASH_DELIM_LITERAL)
						sc.Forward();
				} else if (sc.ch == QuoteStack.Down) {
					QuoteStack.Count--;
					if (QuoteStack.Count == 0) {
						if (QuoteStack.Depth > 0) {
							QuoteStack.Pop();
						} else
							sc.ForwardSetState(SCE_SH_DEFAULT);
					}
				} else if (sc.ch == QuoteStack.Up) {
					QuoteStack.Count++;
				} else {
					if (QuoteStack.Style == BASH_DELIM_STRING ||
						QuoteStack.Style == BASH_DELIM_LSTRING
					) {	// do nesting for "string", $"locale-string"
						if (sc.ch == '`') {
							QuoteStack.Push(sc.ch, BASH_DELIM_BACKTICK);
						} else if (sc.ch == '$' && sc.chNext == '(') {
							sc.Forward();
							QuoteStack.Push(sc.ch, BASH_DELIM_COMMAND);
						}
					} else if (QuoteStack.Style == BASH_DELIM_COMMAND ||
							   QuoteStack.Style == BASH_DELIM_BACKTICK
					) {	// do nesting for $(command), `command`
						if (sc.ch == '\'') {
							QuoteStack.Push(sc.ch, BASH_DELIM_LITERAL);
						} else if (sc.ch == '\"') {
							QuoteStack.Push(sc.ch, BASH_DELIM_STRING);
						} else if (sc.ch == '`') {
							QuoteStack.Push(sc.ch, BASH_DELIM_BACKTICK);
						} else if (sc.ch == '$') {
							if (sc.chNext == '\'') {
								sc.Forward();
								QuoteStack.Push(sc.ch, BASH_DELIM_CSTRING);
							} else if (sc.chNext == '\"') {
								sc.Forward();
								QuoteStack.Push(sc.ch, BASH_DELIM_LSTRING);
							} else if (sc.chNext == '(') {
								sc.Forward();
								QuoteStack.Push(sc.ch, BASH_DELIM_COMMAND);
							}
						}
					}
				}
				break;
			case SCE_SH_PARAM: // ${parameter}
				if (sc.ch == '\\' && Quote.Up != '\\') {
					sc.Forward();
				} else if (sc.ch == Quote.Down) {
					Quote.Count--;
					if (Quote.Count == 0) {
						sc.ForwardSetState(SCE_SH_DEFAULT);
					}
				} else if (sc.ch == Quote.Up) {
					Quote.Count++;
				}
				break;
			case SCE_SH_CHARACTER: // singly-quoted strings
				if (sc.ch == Quote.Down) {
					Quote.Count--;
					if (Quote.Count == 0) {
						sc.ForwardSetState(SCE_SH_DEFAULT);
					}
				}
				break;
		}

		// Must check end of HereDoc state 1 before default state is handled
		if (HereDoc.State == 1 && sc.atLineEnd) {
			// Begin of here-doc (the line after the here-doc delimiter):
			// Lexically, the here-doc starts from the next line after the >>, but the
			// first line of here-doc seem to follow the style of the last EOL sequence
			HereDoc.State = 2;
			if (HereDoc.Quoted) {
				if (sc.state == SCE_SH_HERE_DELIM) {
					// Missing quote at end of string! We are stricter than bash.
					// Colour here-doc anyway while marking this bit as an error.
					sc.ChangeState(SCE_SH_ERROR);
				}
				// HereDoc.Quote always == '\''
				sc.SetState(SCE_SH_HERE_Q);
			} else if (HereDoc.DelimiterLength == 0) {
				// no delimiter, illegal (but '' and "" are legal)
				sc.ChangeState(SCE_SH_ERROR);
				sc.SetState(SCE_SH_DEFAULT);
			} else {
				sc.SetState(SCE_SH_HERE_Q);
			}
		}

		// update cmdState about the current command segment
		if (stylePrev != SCE_SH_DEFAULT && sc.state == SCE_SH_DEFAULT) {
			cmdState = cmdStateNew;
		}
		// Determine if a new state should be entered.
		if (sc.state == SCE_SH_DEFAULT) {
			if (sc.ch == '\\') {
				// Bash can escape any non-newline as a literal
				sc.SetState(SCE_SH_IDENTIFIER);
				if (sc.chNext == '\r' || sc.chNext == '\n')
					sc.SetState(SCE_SH_OPERATOR);
			} else if (IsADigit(sc.ch)) {
				sc.SetState(SCE_SH_NUMBER);
				numBase = BASH_BASE_DECIMAL;
				if (sc.ch == '0') {	// hex,octal
					if (sc.chNext == 'x' || sc.chNext == 'X') {
						numBase = BASH_BASE_HEX;
						sc.Forward();
					} else if (IsADigit(sc.chNext)) {
#ifdef PEDANTIC_OCTAL
						numBase = BASH_BASE_OCTAL;
#else
						numBase = BASH_BASE_HEX;
#endif
					}
				}
			} else if (setWordStart.Contains(sc.ch)) {
				sc.SetState(SCE_SH_WORD);
			} else if (sc.ch == '#') {
				sc.SetState(SCE_SH_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_SH_STRING);
				QuoteStack.Start(sc.ch, BASH_DELIM_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_SH_CHARACTER);
				Quote.Start(sc.ch);
			} else if (sc.ch == '`') {
				sc.SetState(SCE_SH_BACKTICKS);
				QuoteStack.Start(sc.ch, BASH_DELIM_BACKTICK);
			} else if (sc.ch == '$') {
				if (sc.Match("$((")) {
					sc.SetState(SCE_SH_OPERATOR);	// handle '((' later
					continue;
				}
				sc.SetState(SCE_SH_SCALAR);
				sc.Forward();
				if (sc.ch == '{') {
					sc.ChangeState(SCE_SH_PARAM);
					Quote.Start(sc.ch);
				} else if (sc.ch == '\'') {
					sc.ChangeState(SCE_SH_STRING);
					QuoteStack.Start(sc.ch, BASH_DELIM_CSTRING);
				} else if (sc.ch == '"') {
					sc.ChangeState(SCE_SH_STRING);
					QuoteStack.Start(sc.ch, BASH_DELIM_LSTRING);
				} else if (sc.ch == '(') {
					sc.ChangeState(SCE_SH_BACKTICKS);
					QuoteStack.Start(sc.ch, BASH_DELIM_COMMAND);
				} else if (sc.ch == '`') {	// $` seen in a configure script, valid?
					sc.ChangeState(SCE_SH_BACKTICKS);
					QuoteStack.Start(sc.ch, BASH_DELIM_BACKTICK);
				} else {
					continue;	// scalar has no delimiter pair
				}
			} else if (sc.Match('<', '<')) {
				sc.SetState(SCE_SH_HERE_DELIM);
				HereDoc.State = 0;
				HereDoc.Indent = false;
			} else if (sc.ch == '-'	&&	// one-char file test operators
					   setSingleCharOp.Contains(sc.chNext) &&
					   !setWord.Contains(sc.GetRelative(2)) &&
					   IsASpace(sc.chPrev)) {
				sc.SetState(SCE_SH_WORD);
				sc.Forward();
			} else if (setBashOperator.Contains(sc.ch)) {
				char s[10];
				bool isCmdDelim = false;
				sc.SetState(SCE_SH_OPERATOR);
				// handle opening delimiters for test/arithmetic expressions - ((,[[,[
				if (cmdState == BASH_CMD_START
				 || cmdState == BASH_CMD_BODY) {
					if (sc.Match('(', '(')) {
						cmdState = BASH_CMD_ARITH;
						sc.Forward();
					} else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) {
						cmdState = BASH_CMD_TEST;
						testExprType = 1;
						sc.Forward();
					} else if (sc.ch == '[' && IsASpace(sc.chNext)) {
						cmdState = BASH_CMD_TEST;
						testExprType = 2;
					}
				}
				// special state -- for ((x;y;z)) in ... looping
				if (cmdState == BASH_CMD_WORD && sc.Match('(', '(')) {
					cmdState = BASH_CMD_ARITH;
					sc.Forward();
					continue;
				}
				// handle command delimiters in command START|BODY|WORD state, also TEST if 'test'
				if (cmdState == BASH_CMD_START
				 || cmdState == BASH_CMD_BODY
				 || cmdState == BASH_CMD_WORD
				 || (cmdState == BASH_CMD_TEST && testExprType == 0)) {
					s[0] = static_cast<char>(sc.ch);
					if (setBashOperator.Contains(sc.chNext)) {
						s[1] = static_cast<char>(sc.chNext);
						s[2] = '\0';
						isCmdDelim = cmdDelimiter.InList(s);
						if (isCmdDelim)
							sc.Forward();
					}
					if (!isCmdDelim) {
						s[1] = '\0';
						isCmdDelim = cmdDelimiter.InList(s);
					}
					if (isCmdDelim) {
						cmdState = BASH_CMD_DELIM;
						continue;
					}
				}
				// handle closing delimiters for test/arithmetic expressions - )),]],]
				if (cmdState == BASH_CMD_ARITH && sc.Match(')', ')')) {
					cmdState = BASH_CMD_BODY;
					sc.Forward();
				} else if (cmdState == BASH_CMD_TEST && IsASpace(sc.chPrev)) {
					if (sc.Match(']', ']') && testExprType == 1) {
						sc.Forward();
						cmdState = BASH_CMD_BODY;
					} else if (sc.ch == ']' && testExprType == 2) {
						cmdState = BASH_CMD_BODY;
					}
				}
			}
		}// sc.state
	}
	sc.Complete();
	if (sc.state == SCE_SH_HERE_Q) {
		styler.ChangeLexerState(sc.currentPos, styler.Length());
	}
	sc.Complete();
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		if (ch == '#')
			return true;
		else if (ch != ' ' && ch != '\t')
			return false;
	}
	return false;
}

static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
						Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		// Comment folding
		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
		{
			if (!IsCommentLine(lineCurrent - 1, styler)
				&& IsCommentLine(lineCurrent + 1, styler))
				levelCurrent++;
			else if (IsCommentLine(lineCurrent - 1, styler)
					 && !IsCommentLine(lineCurrent + 1, styler))
				levelCurrent--;
		}
		if (style == SCE_SH_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		// Here Document folding
		if (style == SCE_SH_HERE_DELIM) {
			if (ch == '<' && chNext == '<') {
				levelCurrent++;
			}
		} else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_SH_DEFAULT) {
			levelCurrent--;
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const bashWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc);

Added lexers/LexBasic.cxx.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
// Scintilla source code edit control
/** @file LexBasic.cxx
 ** Lexer for BlitzBasic and PureBasic.
 ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics
// and derivatives. Once they diverge enough, might want to split it into multiple
// lexers for more code clearity.
//
// Mail me (elias <at> users <dot> sf <dot> net) for any bugs.

// Folding only works for simple things like functions or types.

// You may want to have a look at my ctags lexer as well, if you additionally to coloring
// and folding need to extract things like label tags in your editor.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>
#include <map>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/* Bits:
 * 1  - whitespace
 * 2  - operator
 * 4  - identifier
 * 8  - decimal digit
 * 16 - hex digit
 * 32 - bin digit
 */
static int character_classification[128] =
{
    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  10, 2,
    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
};

static bool IsSpace(int c) {
	return c < 128 && (character_classification[c] & 1);
}

static bool IsOperator(int c) {
	return c < 128 && (character_classification[c] & 2);
}

static bool IsIdentifier(int c) {
	return c < 128 && (character_classification[c] & 4);
}

static bool IsDigit(int c) {
	return c < 128 && (character_classification[c] & 8);
}

static bool IsHexDigit(int c) {
	return c < 128 && (character_classification[c] & 16);
}

static bool IsBinDigit(int c) {
	return c < 128 && (character_classification[c] & 32);
}

static int LowerCase(int c)
{
	if (c >= 'A' && c <= 'Z')
		return 'a' + c - 'A';
	return c;
}

static int CheckBlitzFoldPoint(char const *token, int &level) {
	if (!strcmp(token, "function") ||
		!strcmp(token, "type")) {
		level |= SC_FOLDLEVELHEADERFLAG;
		return 1;
	}
	if (!strcmp(token, "end function") ||
		!strcmp(token, "end type")) {
		return -1;
	}
	return 0;
}

static int CheckPureFoldPoint(char const *token, int &level) {
	if (!strcmp(token, "procedure") ||
		!strcmp(token, "enumeration") ||
		!strcmp(token, "interface") ||
		!strcmp(token, "structure")) {
		level |= SC_FOLDLEVELHEADERFLAG;
		return 1;
	}
	if (!strcmp(token, "endprocedure") ||
		!strcmp(token, "endenumeration") ||
		!strcmp(token, "endinterface") ||
		!strcmp(token, "endstructure")) {
		return -1;
	}
	return 0;
}

static int CheckFreeFoldPoint(char const *token, int &level) {
	if (!strcmp(token, "function") ||
		!strcmp(token, "sub") ||
		!strcmp(token, "type")) {
		level |= SC_FOLDLEVELHEADERFLAG;
		return 1;
	}
	if (!strcmp(token, "end function") ||
		!strcmp(token, "end sub") ||
		!strcmp(token, "end type")) {
		return -1;
	}
	return 0;
}

// An individual named option for use in an OptionSet

// Options used for LexerBasic
struct OptionsBasic {
	bool fold;
	bool foldSyntaxBased;
	bool foldCommentExplicit;
	std::string foldExplicitStart;
	std::string foldExplicitEnd;
	bool foldExplicitAnywhere;
	bool foldCompact;
	OptionsBasic() {
		fold = false;
		foldSyntaxBased = true;
		foldCommentExplicit = false;
		foldExplicitStart = "";
		foldExplicitEnd   = "";
		foldExplicitAnywhere = false;
		foldCompact = true;
	}
};

static const char * const blitzbasicWordListDesc[] = {
	"BlitzBasic Keywords",
	"user1",
	"user2",
	"user3",
	0
};

static const char * const purebasicWordListDesc[] = {
	"PureBasic Keywords",
	"PureBasic PreProcessor Keywords",
	"user defined 1",
	"user defined 2",
	0
};

static const char * const freebasicWordListDesc[] = {
	"FreeBasic Keywords",
	"FreeBasic PreProcessor Keywords",
	"user defined 1",
	"user defined 2",
	0
};

struct OptionSetBasic : public OptionSet<OptionsBasic> {
	OptionSetBasic(const char * const wordListDescriptions[]) {
		DefineProperty("fold", &OptionsBasic::fold);

		DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased,
			"Set this property to 0 to disable syntax based folding.");

		DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit,
			"This option enables folding explicit fold points when using the Basic lexer. "
			"Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start "
			"and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded.");

		DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart,
			"The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB).");

		DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd,
			"The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB).");

		DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere,
			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments.");

		DefineProperty("fold.compact", &OptionsBasic::foldCompact);

		DefineWordListSets(wordListDescriptions);
	}
};

class LexerBasic : public ILexer {
	char comment_char;
	int (*CheckFoldPoint)(char const *, int &);
	WordList keywordlists[4];
	OptionsBasic options;
	OptionSetBasic osBasic;
public:
	LexerBasic(char comment_char_, int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) :
	           comment_char(comment_char_),
	           CheckFoldPoint(CheckFoldPoint_),
	           osBasic(wordListDescriptions) {
	}
	virtual ~LexerBasic() {
	}
	void SCI_METHOD Release() {
		delete this;
	}
	int SCI_METHOD Version() const {
		return lvOriginal;
	}
	const char * SCI_METHOD PropertyNames() {
		return osBasic.PropertyNames();
	}
	int SCI_METHOD PropertyType(const char *name) {
		return osBasic.PropertyType(name);
	}
	const char * SCI_METHOD DescribeProperty(const char *name) {
		return osBasic.DescribeProperty(name);
	}
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char * SCI_METHOD DescribeWordListSets() {
		return osBasic.DescribeWordListSets();
	}
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

	void * SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}
	static ILexer *LexerFactoryBlitzBasic() {
		return new LexerBasic(';', CheckBlitzFoldPoint, blitzbasicWordListDesc);
	}
	static ILexer *LexerFactoryPureBasic() {
		return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc);
	}
	static ILexer *LexerFactoryFreeBasic() {
		return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc );
	}
};

int SCI_METHOD LexerBasic::PropertySet(const char *key, const char *val) {
	if (osBasic.PropertySet(&options, key, val)) {
		return 0;
	}
	return -1;
}

int SCI_METHOD LexerBasic::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &keywordlists[0];
		break;
	case 1:
		wordListN = &keywordlists[1];
		break;
	case 2:
		wordListN = &keywordlists[2];
		break;
	case 3:
		wordListN = &keywordlists[3];
		break;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
		}
	}
	return firstModification;
}

void SCI_METHOD LexerBasic::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);

	bool wasfirst = true, isfirst = true; // true if first token in a line
	styler.StartAt(startPos);

	StyleContext sc(startPos, length, initStyle, styler);

	// Can't use sc.More() here else we miss the last character
	for (; ; sc.Forward()) {
		if (sc.state == SCE_B_IDENTIFIER) {
			if (!IsIdentifier(sc.ch)) {
				// Labels
				if (wasfirst && sc.Match(':')) {
					sc.ChangeState(SCE_B_LABEL);
					sc.ForwardSetState(SCE_B_DEFAULT);
				} else {
					char s[100];
					int kstates[4] = {
						SCE_B_KEYWORD,
						SCE_B_KEYWORD2,
						SCE_B_KEYWORD3,
						SCE_B_KEYWORD4,
					};
					sc.GetCurrentLowered(s, sizeof(s));
					for (int i = 0; i < 4; i++) {
						if (keywordlists[i].InList(s)) {
							sc.ChangeState(kstates[i]);
						}
					}
					// Types, must set them as operator else they will be
					// matched as number/constant
					if (sc.Match('.') || sc.Match('$') || sc.Match('%') ||
						sc.Match('#')) {
						sc.SetState(SCE_B_OPERATOR);
					} else {
						sc.SetState(SCE_B_DEFAULT);
					}
				}
			}
		} else if (sc.state == SCE_B_OPERATOR) {
			if (!IsOperator(sc.ch) || sc.Match('#'))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_LABEL) {
			if (!IsIdentifier(sc.ch))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_CONSTANT) {
			if (!IsIdentifier(sc.ch))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_NUMBER) {
			if (!IsDigit(sc.ch))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_HEXNUMBER) {
			if (!IsHexDigit(sc.ch))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_BINNUMBER) {
			if (!IsBinDigit(sc.ch))
				sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_STRING) {
			if (sc.ch == '"') {
				sc.ForwardSetState(SCE_B_DEFAULT);
			}
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_B_ERROR);
				sc.SetState(SCE_B_DEFAULT);
			}
		} else if (sc.state == SCE_B_COMMENT || sc.state == SCE_B_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_B_DEFAULT);
			}
		}

		if (sc.atLineStart)
			isfirst = true;

		if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) {
			if (isfirst && sc.Match('.')) {
				sc.SetState(SCE_B_LABEL);
			} else if (isfirst && sc.Match('#')) {
				wasfirst = isfirst;
				sc.SetState(SCE_B_IDENTIFIER);
			} else if (sc.Match(comment_char)) {
				// Hack to make deprecated QBASIC '$Include show
				// up in freebasic with SCE_B_PREPROCESSOR.
				if (comment_char == '\'' && sc.Match(comment_char, '$'))
					sc.SetState(SCE_B_PREPROCESSOR);
				else
					sc.SetState(SCE_B_COMMENT);
			} else if (sc.Match('"')) {
				sc.SetState(SCE_B_STRING);
			} else if (IsDigit(sc.ch)) {
				sc.SetState(SCE_B_NUMBER);
			} else if (sc.Match('$')) {
				sc.SetState(SCE_B_HEXNUMBER);
			} else if (sc.Match('%')) {
				sc.SetState(SCE_B_BINNUMBER);
			} else if (sc.Match('#')) {
				sc.SetState(SCE_B_CONSTANT);
			} else if (IsOperator(sc.ch)) {
				sc.SetState(SCE_B_OPERATOR);
			} else if (IsIdentifier(sc.ch)) {
				wasfirst = isfirst;
				sc.SetState(SCE_B_IDENTIFIER);
			} else if (!IsSpace(sc.ch)) {
				sc.SetState(SCE_B_ERROR);
			}
		}

		if (!IsSpace(sc.ch))
			isfirst = false;

		if (!sc.More())
			break;
	}
	sc.Complete();
}


void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) {

	if (!options.fold)
		return;

	LexAccessor styler(pAccess);

	int line = styler.GetLine(startPos);
	int level = styler.LevelAt(line);
	int go = 0, done = 0;
	int endPos = startPos + length;
	char word[256];
	int wordlen = 0;
	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
	int cNext = styler[startPos];

	// Scan for tokens at the start of the line (they may include
	// whitespace, for tokens like "End Function"
	for (int i = startPos; i < endPos; i++) {
		int c = cNext;
		cNext = styler.SafeGetCharAt(i + 1);
		bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n');
		if (options.foldSyntaxBased && !done && !go) {
			if (wordlen) { // are we scanning a token already?
				word[wordlen] = static_cast<char>(LowerCase(c));
				if (!IsIdentifier(c)) { // done with token
					word[wordlen] = '\0';
					go = CheckFoldPoint(word, level);
					if (!go) {
						// Treat any whitespace as single blank, for
						// things like "End   Function".
						if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
							word[wordlen] = ' ';
							if (wordlen < 255)
								wordlen++;
						}
						else // done with this line
							done = 1;
					}
				} else if (wordlen < 255) {
					wordlen++;
				}
			} else { // start scanning at first non-whitespace character
				if (!IsSpace(c)) {
					if (IsIdentifier(c)) {
						word[0] = static_cast<char>(LowerCase(c));
						wordlen = 1;
					} else // done with this line
						done = 1;
				}
			}
		}
		if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) {
			if (userDefinedFoldMarkers) {
				if (styler.Match(i, options.foldExplicitStart.c_str())) {
 					level |= SC_FOLDLEVELHEADERFLAG;
					go = 1;
				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
 					go = -1;
 				}
			} else {
				if (c == comment_char) {
					if (cNext == '{') {
						level |= SC_FOLDLEVELHEADERFLAG;
						go = 1;
					} else if (cNext == '}') {
						go = -1;
					}
				}
 			}
 		}
		if (atEOL) { // line end
			if (!done && wordlen == 0 && options.foldCompact) // line was only space
				level |= SC_FOLDLEVELWHITEFLAG;
			if (level != styler.LevelAt(line))
				styler.SetLevel(line, level);
			level += go;
			line++;
			// reset state
			wordlen = 0;
			level &= ~SC_FOLDLEVELHEADERFLAG;
			level &= ~SC_FOLDLEVELWHITEFLAG;
			go = 0;
			done = 0;
		}
	}
}

LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, LexerBasic::LexerFactoryBlitzBasic, "blitzbasic", blitzbasicWordListDesc);

LexerModule lmPureBasic(SCLEX_PUREBASIC, LexerBasic::LexerFactoryPureBasic, "purebasic", purebasicWordListDesc);

LexerModule lmFreeBasic(SCLEX_FREEBASIC, LexerBasic::LexerFactoryFreeBasic, "freebasic", freebasicWordListDesc);

Added lexers/LexBullant.cxx.



















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// SciTE - Scintilla based Text Editor
// LexBullant.cxx - lexer for Bullant

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	s[0] = '\0';
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		s[i + 1] = '\0';
	}
	int lev= 0;
	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.')){
		chAttr = SCE_C_NUMBER;
	}
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;
			if (strcmp(s, "end") == 0)
				lev = -1;
			else if (strcmp(s, "method") == 0 ||
				strcmp(s, "case") == 0 ||
				strcmp(s, "class") == 0 ||
				strcmp(s, "debug") == 0 ||
				strcmp(s, "test") == 0 ||
				strcmp(s, "if") == 0 ||
				strcmp(s, "lock") == 0 ||
				strcmp(s, "transaction") == 0 ||
				strcmp(s, "trap") == 0 ||
				strcmp(s, "until") == 0 ||
				strcmp(s, "while") == 0)
				lev = 1;
		}
	}
	styler.ColourTo(end, chAttr);
	return lev;
}

static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {
	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold") != 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;

	int state = initStyle;
	if (state == SCE_C_STRINGEOL)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	styler.StartSegment(startPos);
	int endFoundThisLine = 0;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			endFoundThisLine = 0;
			if (state == SCE_C_STRINGEOL) {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;
				styler.SetLevel(lineCurrent, lev);
				lineCurrent++;
				levelPrev = levelCurrent;
			}
			visibleChars = 0;

/*			int indentBlock = GetLineIndentation(lineCurrent);
			if (blockChange==1){
				lineCurrent++;
				int pos=SetLineIndentation(lineCurrent, indentBlock + indentSize);
			} else if (blockChange==-1) {
				indentBlock -= indentSize;
				if (indentBlock < 0)
					indentBlock = 0;
				SetLineIndentation(lineCurrent, indentBlock);
				lineCurrent++;
			}
			blockChange=0;
*/		}
		if (!(isascii(ch) && isspace(ch)))
			visibleChars++;

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (iswordstart(ch)) {
				styler.ColourTo(i-1, state);
					state = SCE_C_IDENTIFIER;
			} else if (ch == '@' && chNext == 'o') {
				if ((styler.SafeGetCharAt(i+2) =='f') && (styler.SafeGetCharAt(i+3) == 'f')) {
					styler.ColourTo(i-1, state);
					state = SCE_C_COMMENT;
				}
			} else if (ch == '#') {
				styler.ColourTo(i-1, state);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i-1, state);
				state = SCE_C_CHARACTER;
			} else if (isoperator(ch)) {
				styler.ColourTo(i-1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!iswordchar(ch)) {
				int levelChange = classifyWordBullant(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				chNext = styler.SafeGetCharAt(i + 1);
				if (ch == '#') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_C_STRING;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
				}
				if (endFoundThisLine == 0)
					levelCurrent+=levelChange;
				if (levelChange == -1)
					endFoundThisLine=1;
			}
		} else if (state == SCE_C_COMMENT) {
			if (ch == '@' && chNext == 'o') {
				if (styler.SafeGetCharAt(i+2) == 'n') {
					styler.ColourTo(i+2, state);
					state = SCE_C_DEFAULT;
					i+=2;
				}
			}
		} else if (state == SCE_C_COMMENTLINE) {
			if (ch == '\r' || ch == '\n') {
				endFoundThisLine = 0;
				styler.ColourTo(i-1, state);
				state = SCE_C_DEFAULT;
			}
		} else if (state == SCE_C_STRING) {
			if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (ch == '\"') {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			} else if (chNext == '\r' || chNext == '\n') {
				endFoundThisLine = 0;
				styler.ColourTo(i-1, SCE_C_STRINGEOL);
				state = SCE_C_STRINGEOL;
			}
		} else if (state == SCE_C_CHARACTER) {
			if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
				endFoundThisLine = 0;
				styler.ColourTo(i-1, SCE_C_STRINGEOL);
				state = SCE_C_STRINGEOL;
			} else if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (ch == '\'') {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
		}
		chPrev = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);

	}
}

static const char * const bullantWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmBullant(SCLEX_BULLANT, ColouriseBullantDoc, "bullant", 0, bullantWordListDesc);

Added lexers/LexCLW.cxx.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
// Scintilla source code edit control
/** @file LexClw.cxx
 ** Lexer for Clarion.
 ** 2004/12/17 Updated Lexer
 **/
// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Is an end of line character
inline bool IsEOL(const int ch) {

	return(ch == '\n');
}

// Convert character to uppercase
static char CharacterUpper(char chChar) {

	if (chChar < 'a' || chChar > 'z') {
		return(chChar);
	}
	else {
		return(static_cast<char>(chChar - 'a' + 'A'));
	}
}

// Convert string to uppercase
static void StringUpper(char *szString) {

	while (*szString) {
		*szString = CharacterUpper(*szString);
		szString++;
	}
}

// Is a label start character
inline bool IsALabelStart(const int iChar) {

	return(isalpha(iChar) || iChar == '_');
}

// Is a label character
inline bool IsALabelCharacter(const int iChar) {

	return(isalnum(iChar) || iChar == '_' || iChar == ':');
}

// Is the character is a ! and the the next character is not a !
inline bool IsACommentStart(const int iChar) {

	return(iChar == '!');
}

// Is the character a Clarion hex character (ABCDEF)
inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {

	// Case insensitive.
	if (!bCaseSensitive) {
		if (strchr("ABCDEFabcdef", iChar) != NULL) {
			return(true);
		}
	}
	// Case sensitive
	else {
		if (strchr("ABCDEF", iChar) != NULL) {
			return(true);
		}
	}
	return(false);
}

// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {

	// Case insensitive.
	if (!bCaseSensitive) {
		// If character is a numeric base character
		if (strchr("BOHboh", iChar) != NULL) {
			return(true);
		}
	}
	// Case sensitive
	else {
		// If character is a numeric base character
		if (strchr("BOH", iChar) != NULL) {
			return(true);
		}
	}
	return(false);
}

// Set the correct numeric constant state
inline bool SetNumericConstantState(StyleContext &scDoc) {

	int iPoints = 0;			// Point counter
	char cNumericString[512];	// Numeric string buffer

	// Buffer the current numberic string
	scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
	// Loop through the string until end of string (NULL termination)
	for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
		// Depending on the character
		switch (cNumericString[iIndex]) {
			// Is a . (point)
			case '.' :
				// Increment point counter
				iPoints++;
				break;
			default :
				break;
		}
	}
	// If points found (can be more than one for improper formatted number
	if (iPoints > 0) {
		return(true);
	}
	// Else no points found
	else {
		return(false);
	}
}

// Get the next word in uppercase from the current position (keyword lookahead)
inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) {

	unsigned int iIndex = 0;		// Buffer Index

	// Loop through the remaining string from the current position
	for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) {
		// Get the character from the buffer using the offset
		char cCharacter = styler[iOffset];
		if (IsEOL(cCharacter)) {
			break;
		}
		// If the character is alphabet character
		if (isalpha(cCharacter)) {
			// Add UPPERCASE character to the word buffer
			cWord[iIndex++] = CharacterUpper(cCharacter);
		}
	}
	// Add null termination
	cWord[iIndex] = '\0';
	// If no word was found
	if (iIndex == 0) {
		// Return failure
		return(false);
	}
	// Else word was found
	else {
		// Return success
		return(true);
	}
}

// Clarion Language Colouring Procedure
static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {

	int iParenthesesLevel = 0;		// Parenthese Level
	int iColumn1Label = false;		// Label starts in Column 1

	WordList &wlClarionKeywords = *wlKeywords[0];			// Clarion Keywords
	WordList &wlCompilerDirectives = *wlKeywords[1];		// Compiler Directives
	WordList &wlRuntimeExpressions = *wlKeywords[2];		// Runtime Expressions
	WordList &wlBuiltInProcsFuncs = *wlKeywords[3];			// Builtin Procedures and Functions
	WordList &wlStructsDataTypes = *wlKeywords[4];			// Structures and Data Types
	WordList &wlAttributes = *wlKeywords[5];				// Procedure Attributes
	WordList &wlStandardEquates = *wlKeywords[6];			// Standard Equates
	WordList &wlLabelReservedWords = *wlKeywords[7];		// Clarion Reserved Keywords (Labels)
	WordList &wlProcLabelReservedWords = *wlKeywords[8];	// Clarion Reserved Keywords (Procedure Labels)

	const char wlProcReservedKeywordList[] =
	"PROCEDURE FUNCTION";
	WordList wlProcReservedKeywords;
	wlProcReservedKeywords.Set(wlProcReservedKeywordList);

	const char wlCompilerKeywordList[] =
	"COMPILE OMIT";
	WordList wlCompilerKeywords;
	wlCompilerKeywords.Set(wlCompilerKeywordList);

	const char wlLegacyStatementsList[] =
	"BOF EOF FUNCTION POINTER SHARE";
	WordList wlLegacyStatements;
	wlLegacyStatements.Set(wlLegacyStatementsList);

	StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);

	// lex source code
    for (; scDoc.More(); scDoc.Forward())
	{
		//
		// Determine if the current state should terminate.
		//

		// Label State Handling
		if (scDoc.state == SCE_CLW_LABEL) {
			// If the character is not a valid label
			if (!IsALabelCharacter(scDoc.ch)) {
				// If the character is a . (dot syntax)
				if (scDoc.ch == '.') {
					// Turn off column 1 label flag as label now cannot be reserved work
					iColumn1Label = false;
					// Uncolour the . (dot) to default state, move forward one character,
					// and change back to the label state.
					scDoc.SetState(SCE_CLW_DEFAULT);
					scDoc.Forward();
					scDoc.SetState(SCE_CLW_LABEL);
				}
				// Else check label
				else {
					char cLabel[512];		// Label buffer
					// Buffer the current label string
					scDoc.GetCurrent(cLabel,sizeof(cLabel));
					// If case insensitive, convert string to UPPERCASE to match passed keywords.
					if (!bCaseSensitive) {
						StringUpper(cLabel);
					}
					// Else if UPPERCASE label string is in the Clarion compiler keyword list
					if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
						// change the label to error state
						scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
					}
					// Else if UPPERCASE label string is in the Clarion reserved keyword list
					else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
						// change the label to error state
						scDoc.ChangeState(SCE_CLW_ERROR);
					}
					// Else if UPPERCASE label string is
					else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
						char cWord[512];	// Word buffer
						// Get the next word from the current position
						if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
							// If the next word is a procedure reserved word
							if (wlProcReservedKeywords.InList(cWord)) {
								// Change the label to error state
								scDoc.ChangeState(SCE_CLW_ERROR);
							}
						}
					}
					// Else if label string is in the compiler directive keyword list
					else if (wlCompilerDirectives.InList(cLabel)) {
						// change the state to compiler directive state
						scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
					}
					// Terminate the label state and set to default state
					scDoc.SetState(SCE_CLW_DEFAULT);
				}
			}
		}
		// Keyword State Handling
		else if (scDoc.state == SCE_CLW_KEYWORD) {
			// If character is : (colon)
			if (scDoc.ch == ':') {
				char cEquate[512];		// Equate buffer
				// Move forward to include : (colon) in buffer
				scDoc.Forward();
				// Buffer the equate string
				scDoc.GetCurrent(cEquate,sizeof(cEquate));
				// If case insensitive, convert string to UPPERCASE to match passed keywords.
				if (!bCaseSensitive) {
					StringUpper(cEquate);
				}
				// If statement string is in the equate list
				if (wlStandardEquates.InList(cEquate)) {
					// Change to equate state
					scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
				}
			}
			// If the character is not a valid label character
			else if (!IsALabelCharacter(scDoc.ch)) {
				char cStatement[512];		// Statement buffer
				// Buffer the statement string
				scDoc.GetCurrent(cStatement,sizeof(cStatement));
				// If case insensitive, convert string to UPPERCASE to match passed keywords.
				if (!bCaseSensitive) {
					StringUpper(cStatement);
				}
				// If statement string is in the Clarion keyword list
				if (wlClarionKeywords.InList(cStatement)) {
					// Change the statement string to the Clarion keyword state
					scDoc.ChangeState(SCE_CLW_KEYWORD);
				}
				// Else if statement string is in the compiler directive keyword list
				else if (wlCompilerDirectives.InList(cStatement)) {
					// Change the statement string to the compiler directive state
					scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
				}
				// Else if statement string is in the runtime expressions keyword list
				else if (wlRuntimeExpressions.InList(cStatement)) {
					// Change the statement string to the runtime expressions state
					scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
				}
				// Else if statement string is in the builtin procedures and functions keyword list
				else if (wlBuiltInProcsFuncs.InList(cStatement)) {
					// Change the statement string to the builtin procedures and functions state
					scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
				}
				// Else if statement string is in the tructures and data types keyword list
				else if (wlStructsDataTypes.InList(cStatement)) {
					// Change the statement string to the structures and data types state
					scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
				}
				// Else if statement string is in the procedure attribute keyword list
				else if (wlAttributes.InList(cStatement)) {
					// Change the statement string to the procedure attribute state
					scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
				}
				// Else if statement string is in the standard equate keyword list
				else if (wlStandardEquates.InList(cStatement)) {
					// Change the statement string to the standard equate state
					scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
				}
				// Else if statement string is in the deprecated or legacy keyword list
				else if (wlLegacyStatements.InList(cStatement)) {
					// Change the statement string to the standard equate state
					scDoc.ChangeState(SCE_CLW_DEPRECATED);
				}
				// Else the statement string doesn't match any work list
				else {
					// Change the statement string to the default state
					scDoc.ChangeState(SCE_CLW_DEFAULT);
				}
				// Terminate the keyword state and set to default state
				scDoc.SetState(SCE_CLW_DEFAULT);
			}
		}
		// String State Handling
		else if (scDoc.state == SCE_CLW_STRING) {
			// If the character is an ' (single quote)
			if (scDoc.ch == '\'') {
				// Set the state to default and move forward colouring
				// the ' (single quote) as default state
				// terminating the string state
				scDoc.SetState(SCE_CLW_DEFAULT);
				scDoc.Forward();
			}
			// If the next character is an ' (single quote)
			if (scDoc.chNext == '\'') {
				// Move forward one character and set to default state
				// colouring the next ' (single quote) as default state
				// terminating the string state
				scDoc.ForwardSetState(SCE_CLW_DEFAULT);
				scDoc.Forward();
			}
		}
		// Picture String State Handling
		else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
			// If the character is an ( (open parenthese)
			if (scDoc.ch == '(') {
				// Increment the parenthese level
				iParenthesesLevel++;
			}
			// Else if the character is a ) (close parenthese)
			else if (scDoc.ch == ')') {
				// If the parenthese level is set to zero
				// parentheses matched
				if (!iParenthesesLevel) {
					scDoc.SetState(SCE_CLW_DEFAULT);
				}
				// Else parenthese level is greater than zero
				// still looking for matching parentheses
				else {
					// Decrement the parenthese level
					iParenthesesLevel--;
				}
			}
		}
		// Standard Equate State Handling
		else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
			if (!isalnum(scDoc.ch)) {
				scDoc.SetState(SCE_CLW_DEFAULT);
			}
		}
		// Integer Constant State Handling
		else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
			// If the character is not a digit (0-9)
			// or character is not a hexidecimal character (A-F)
			// or character is not a . (point)
			// or character is not a numberic base character (B,O,H)
			if (!(isdigit(scDoc.ch)
			|| IsAHexCharacter(scDoc.ch, bCaseSensitive)
			|| scDoc.ch == '.'
			|| IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
				// If the number was a real
				if (SetNumericConstantState(scDoc)) {
					// Colour the matched string to the real constant state
					scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
				}
				// Else the number was an integer
				else {
					// Colour the matched string to an integer constant state
					scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
				}
				// Terminate the integer constant state and set to default state
				scDoc.SetState(SCE_CLW_DEFAULT);
			}
		}

		//
		// Determine if a new state should be entered.
		//

		// Beginning of Line Handling
		if (scDoc.atLineStart) {
			// Reset the column 1 label flag
			iColumn1Label = false;
			// If column 1 character is a label start character
			if (IsALabelStart(scDoc.ch)) {
				// Label character is found in column 1
				// so set column 1 label flag and clear last column 1 label
				iColumn1Label = true;
				// Set the state to label
				scDoc.SetState(SCE_CLW_LABEL);
			}
			// else if character is a space or tab
			else if (IsASpace(scDoc.ch)){
				// Set to default state
				scDoc.SetState(SCE_CLW_DEFAULT);
			}
			// else if comment start (!) or is an * (asterisk)
			else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
				// then set the state to comment.
				scDoc.SetState(SCE_CLW_COMMENT);
			}
			// else the character is a ? (question mark)
			else if (scDoc.ch == '?') {
				// Change to the compiler directive state, move forward,
				// colouring the ? (question mark), change back to default state.
				scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
				scDoc.Forward();
				scDoc.SetState(SCE_CLW_DEFAULT);
			}
			// else an invalid character in column 1
			else {
				// Set to error state
				scDoc.SetState(SCE_CLW_ERROR);
			}
		}
		// End of Line Handling
		else if (scDoc.atLineEnd) {
			// Reset to the default state at the end of each line.
			scDoc.SetState(SCE_CLW_DEFAULT);
		}
		// Default Handling
		else {
			// If in default state
			if (scDoc.state == SCE_CLW_DEFAULT) {
				// If is a letter could be a possible statement
				if (isalpha(scDoc.ch)) {
					// Set the state to Clarion Keyword and verify later
					scDoc.SetState(SCE_CLW_KEYWORD);
				}
				// else is a number
				else if (isdigit(scDoc.ch)) {
					// Set the state to Integer Constant and verify later
					scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
				}
				// else if the start of a comment or a | (line continuation)
				else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
					// then set the state to comment.
					scDoc.SetState(SCE_CLW_COMMENT);
				}
				// else if the character is a ' (single quote)
				else if (scDoc.ch == '\'') {
					// If the character is also a ' (single quote)
					// Embedded Apostrophe
					if (scDoc.chNext == '\'') {
						// Move forward colouring it as default state
						scDoc.ForwardSetState(SCE_CLW_DEFAULT);
					}
					else {
						// move to the next character and then set the state to comment.
						scDoc.ForwardSetState(SCE_CLW_STRING);
					}
				}
				// else the character is an @ (ampersand)
				else if (scDoc.ch == '@') {
					// Case insensitive.
					if (!bCaseSensitive) {
						// If character is a valid picture token character
						if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
							// Set to the picture string state
							scDoc.SetState(SCE_CLW_PICTURE_STRING);
						}
					}
					// Case sensitive
					else {
						// If character is a valid picture token character
						if (strchr("DEKNPST", scDoc.chNext) != NULL) {
							// Set the picture string state
							scDoc.SetState(SCE_CLW_PICTURE_STRING);
						}
					}
				}
			}
		}
	}
	// lexing complete
	scDoc.Complete();
}

// Clarion Language Case Sensitive Colouring Procedure
static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {

	ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
}

// Clarion Language Case Insensitive Colouring Procedure
static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {

	ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
}

// Fill Buffer

static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) {

	unsigned int uiPos = 0;

	while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
		szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
		uiPos++;
	}
	szBuffer[uiPos] = '\0';
}

// Classify Clarion Fold Point

static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {

	if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
		if (strcmp(szString, "PROCEDURE") == 0) {
	//		iLevel = SC_FOLDLEVELBASE + 1;
		}
		else if (strcmp(szString, "MAP") == 0 ||
			strcmp(szString,"ACCEPT") == 0 ||
			strcmp(szString,"BEGIN") == 0 ||
			strcmp(szString,"CASE") == 0 ||
			strcmp(szString,"EXECUTE") == 0 ||
			strcmp(szString,"IF") == 0 ||
			strcmp(szString,"ITEMIZE") == 0 ||
			strcmp(szString,"INTERFACE") == 0 ||
			strcmp(szString,"JOIN") == 0 ||
			strcmp(szString,"LOOP") == 0 ||
			strcmp(szString,"MODULE") == 0 ||
			strcmp(szString,"RECORD") == 0) {
			iLevel++;
		}
		else if (strcmp(szString, "APPLICATION") == 0 ||
			strcmp(szString, "CLASS") == 0 ||
			strcmp(szString, "DETAIL") == 0 ||
			strcmp(szString, "FILE") == 0 ||
			strcmp(szString, "FOOTER") == 0 ||
			strcmp(szString, "FORM") == 0 ||
			strcmp(szString, "GROUP") == 0 ||
			strcmp(szString, "HEADER") == 0 ||
			strcmp(szString, "INTERFACE") == 0 ||
			strcmp(szString, "MENU") == 0 ||
			strcmp(szString, "MENUBAR") == 0 ||
			strcmp(szString, "OLE") == 0 ||
			strcmp(szString, "OPTION") == 0 ||
			strcmp(szString, "QUEUE") == 0 ||
			strcmp(szString, "REPORT") == 0 ||
			strcmp(szString, "SHEET") == 0 ||
			strcmp(szString, "TAB") == 0 ||
			strcmp(szString, "TOOLBAR") == 0 ||
			strcmp(szString, "VIEW") == 0 ||
			strcmp(szString, "WINDOW") == 0) {
			iLevel++;
		}
		else if (strcmp(szString, "END") == 0 ||
			strcmp(szString, "UNTIL") == 0 ||
			strcmp(szString, "WHILE") == 0) {
			iLevel--;
		}
	}
	return(iLevel);
}

// Clarion Language Folding Procedure
static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) {

	unsigned int uiEndPos = uiStartPos + iLength;
	int iLineCurrent = accStyler.GetLine(uiStartPos);
	int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int iLevelCurrent = iLevelPrev;
	char chNext = accStyler[uiStartPos];
	int iStyle = iInitStyle;
	int iStyleNext = accStyler.StyleAt(uiStartPos);
	int iVisibleChars = 0;
	int iLastStart = 0;

	for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {

		char chChar = chNext;
		chNext = accStyler.SafeGetCharAt(uiPos + 1);
		int iStylePrev = iStyle;
		iStyle = iStyleNext;
		iStyleNext = accStyler.StyleAt(uiPos + 1);
		bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');

		if (iStylePrev == SCE_CLW_DEFAULT) {
			if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
				// Store last word start point.
				iLastStart = uiPos;
			}
		}

		if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
			if(iswordchar(chChar) && !iswordchar(chNext)) {
				char chBuffer[100];
				FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
				iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
			//	if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
			//		accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
			//		iLevelPrev = SC_FOLDLEVELBASE;
			//	}
			}
		}

		if (bEOL) {
			int iLevel = iLevelPrev;
			if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
				iLevel |= SC_FOLDLEVELHEADERFLAG;
			if (iLevel != accStyler.LevelAt(iLineCurrent)) {
				accStyler.SetLevel(iLineCurrent,iLevel);
			}
			iLineCurrent++;
			iLevelPrev = iLevelCurrent;
			iVisibleChars = 0;
		}

		if (!isspacechar(chChar))
			iVisibleChars++;
	}

	// Fill in the real level of the next line, keeping the current flags
	// as they will be filled in later.
	int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
}

// Word List Descriptions
static const char * const rgWordListDescriptions[] = {
	"Clarion Keywords",
	"Compiler Directives",
	"Built-in Procedures and Functions",
	"Runtime Expressions",
	"Structure and Data Types",
	"Attributes",
	"Standard Equates",
	"Reserved Words (Labels)",
	"Reserved Words (Procedure Labels)",
	0,
};

// Case Sensitive Clarion Language Lexer
LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);

// Case Insensitive Clarion Language Lexer
LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);

Added lexers/LexCOBOL.cxx.























































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
// Scintilla source code edit control
/** @file LexCOBOL.cxx
 ** Lexer for COBOL
 ** Based on LexPascal.cxx
 ** Written by Laurent le Tynevez
 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
 ** Updated by Rod Falck, Aug 2006 Converted to COBOL
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define IN_DIVISION 0x01
#define IN_DECLARATIVES 0x02
#define IN_SECTION 0x04
#define IN_PARAGRAPH 0x08
#define IN_FLAGS 0xF
#define NOT_HEADER 0x10

inline bool isCOBOLoperator(char ch)
    {
    return isoperator(ch);
    }

inline bool isCOBOLwordchar(char ch)
    {
    return isascii(ch) && (isalnum(ch) || ch == '-');

    }

inline bool isCOBOLwordstart(char ch)
    {
    return isascii(ch) && isalnum(ch);
    }

static int CountBits(int nBits)
	{
	int count = 0;
	for (int i = 0; i < 32; ++i)
		{
		count += nBits & 1;
		nBits >>= 1;
		}
	return count;
	}

static void getRange(unsigned int start,
        unsigned int end,
        Accessor &styler,
        char *s,
        unsigned int len) {
    unsigned int i = 0;
    while ((i < end - start + 1) && (i < len-1)) {
        s[i] = static_cast<char>(tolower(styler[start + i]));
        i++;
    }
    s[i] = '\0';
}

static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr) {
    styler.ColourTo(end, attr);
}


static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, int nContainment, bool *bAarea) {
    int ret = 0;

    WordList& a_keywords = *keywordlists[0];
    WordList& b_keywords = *keywordlists[1];
    WordList& c_keywords = *keywordlists[2];

    char s[100];
    getRange(start, end, styler, s, sizeof(s));

    char chAttr = SCE_C_IDENTIFIER;
    if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) {
        chAttr = SCE_C_NUMBER;
		char *p = s + 1;
		while (*p) {
			if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) {
				chAttr = SCE_C_IDENTIFIER;
			    break;
			}
			++p;
		}
    }
    else {
        if (a_keywords.InList(s)) {
            chAttr = SCE_C_WORD;
        }
        else if (b_keywords.InList(s)) {
            chAttr = SCE_C_WORD2;
        }
        else if (c_keywords.InList(s)) {
            chAttr = SCE_C_UUID;
        }
    }
    if (*bAarea) {
        if (strcmp(s, "division") == 0) {
            ret = IN_DIVISION;
			// we've determined the containment, anything else is just ignored for those purposes
			*bAarea = false;
		} else if (strcmp(s, "declaratives") == 0) {
            ret = IN_DIVISION | IN_DECLARATIVES;
			if (nContainment & IN_DECLARATIVES)
				ret |= NOT_HEADER | IN_SECTION;
			// we've determined the containment, anything else is just ignored for those purposes
			*bAarea = false;
		} else if (strcmp(s, "section") == 0) {
            ret = (nContainment &~ IN_PARAGRAPH) | IN_SECTION;
			// we've determined the containment, anything else is just ignored for those purposes
			*bAarea = false;
		} else if (strcmp(s, "end") == 0 && (nContainment & IN_DECLARATIVES)) {
            ret = IN_DIVISION | IN_DECLARATIVES | IN_SECTION | NOT_HEADER;
		} else {
			ret = nContainment | IN_PARAGRAPH;
        }
    }
    ColourTo(styler, end, chAttr);
    return ret;
}

static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
    Accessor &styler) {

    styler.StartAt(startPos);

    int state = initStyle;
    if (state == SCE_C_CHARACTER)   // Does not leak onto next line
        state = SCE_C_DEFAULT;
    char chPrev = ' ';
    char chNext = styler[startPos];
    unsigned int lengthDoc = startPos + length;

    int nContainment;

    int currentLine = styler.GetLine(startPos);
    if (currentLine > 0) {
        styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
        nContainment = styler.GetLineState(currentLine);
		nContainment &= ~NOT_HEADER;
    } else {
        styler.SetLineState(currentLine, 0);
        nContainment = 0;
    }

    styler.StartSegment(startPos);
    bool bNewLine = true;
    bool bAarea = !isspacechar(chNext);
	int column = 0;
    for (unsigned int i = startPos; i < lengthDoc; i++) {
        char ch = chNext;

        chNext = styler.SafeGetCharAt(i + 1);

		++column;

        if (bNewLine) {
			column = 0;
        }
		if (column <= 1 && !bAarea) {
			bAarea = !isspacechar(ch);
			}
        bool bSetNewLine = false;
        if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
            // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
            // Avoid triggering two times on Dos/Win
            // End of line
            if (state == SCE_C_CHARACTER) {
                ColourTo(styler, i, state);
                state = SCE_C_DEFAULT;
            }
            styler.SetLineState(currentLine, nContainment);
            currentLine++;
            bSetNewLine = true;
			if (nContainment & NOT_HEADER)
				nContainment &= ~(NOT_HEADER | IN_DECLARATIVES | IN_SECTION);
        }

        if (styler.IsLeadByte(ch)) {
            chNext = styler.SafeGetCharAt(i + 2);
            chPrev = ' ';
            i += 1;
            continue;
        }

        if (state == SCE_C_DEFAULT) {
            if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) {
                ColourTo(styler, i-1, state);
                state = SCE_C_IDENTIFIER;
            } else if (column == 6 && ch == '*') {
            // Cobol comment line: asterisk in column 7.
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTLINE;
            } else if (ch == '*' && chNext == '>') {
            // Cobol inline comment: asterisk, followed by greater than.
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTLINE;
            } else if (column == 0 && ch == '*' && chNext != '*') {
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTLINE;
            } else if (column == 0 && ch == '/' && chNext != '*') {
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTLINE;
            } else if (column == 0 && ch == '*' && chNext == '*') {
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTDOC;
            } else if (column == 0 && ch == '/' && chNext == '*') {
                ColourTo(styler, i-1, state);
                state = SCE_C_COMMENTDOC;
            } else if (ch == '"') {
                ColourTo(styler, i-1, state);
                state = SCE_C_STRING;
            } else if (ch == '\'') {
                ColourTo(styler, i-1, state);
                state = SCE_C_CHARACTER;
            } else if (ch == '?' && column == 0) {
                ColourTo(styler, i-1, state);
                state = SCE_C_PREPROCESSOR;
            } else if (isCOBOLoperator(ch)) {
                ColourTo(styler, i-1, state);
                ColourTo(styler, i, SCE_C_OPERATOR);
            }
        } else if (state == SCE_C_IDENTIFIER) {
            if (!isCOBOLwordchar(ch)) {
                int lStateChange = classifyWordCOBOL(styler.GetStartSegment(), i - 1, keywordlists, styler, nContainment, &bAarea);

                if(lStateChange != 0) {
                    styler.SetLineState(currentLine, lStateChange);
                    nContainment = lStateChange;
                }

                state = SCE_C_DEFAULT;
                chNext = styler.SafeGetCharAt(i + 1);
                if (ch == '"') {
                    state = SCE_C_STRING;
                } else if (ch == '\'') {
                    state = SCE_C_CHARACTER;
                } else if (isCOBOLoperator(ch)) {
                    ColourTo(styler, i, SCE_C_OPERATOR);
                }
            }
        } else {
            if (state == SCE_C_PREPROCESSOR) {
                if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
                    ColourTo(styler, i-1, state);
                    state = SCE_C_DEFAULT;
                }
            } else if (state == SCE_C_COMMENT) {
                if (ch == '\r' || ch == '\n') {
                    ColourTo(styler, i, state);
                    state = SCE_C_DEFAULT;
                }
            } else if (state == SCE_C_COMMENTDOC) {
                if (ch == '\r' || ch == '\n') {
                    if (((i > styler.GetStartSegment() + 2) || (
                        (initStyle == SCE_C_COMMENTDOC) &&
                        (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
                            ColourTo(styler, i, state);
                            state = SCE_C_DEFAULT;
                    }
                }
            } else if (state == SCE_C_COMMENTLINE) {
                if (ch == '\r' || ch == '\n') {
                    ColourTo(styler, i-1, state);
                    state = SCE_C_DEFAULT;
                }
            } else if (state == SCE_C_STRING) {
                if (ch == '"') {
                    ColourTo(styler, i, state);
                    state = SCE_C_DEFAULT;
                }
            } else if (state == SCE_C_CHARACTER) {
                if (ch == '\'') {
                    ColourTo(styler, i, state);
                    state = SCE_C_DEFAULT;
                }
            }
        }
        chPrev = ch;
        bNewLine = bSetNewLine;
		if (bNewLine)
			{
			bAarea = false;
			}
    }
    ColourTo(styler, lengthDoc - 1, state);
}

static void FoldCOBOLDoc(unsigned int startPos, int length, int, WordList *[],
                            Accessor &styler) {
    bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
    unsigned int endPos = startPos + length;
    int visibleChars = 0;
    int lineCurrent = styler.GetLine(startPos);
    int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK : 0xFFF;
    char chNext = styler[startPos];

    bool bNewLine = true;
    bool bAarea = !isspacechar(chNext);
	int column = 0;
	bool bComment = false;
    for (unsigned int i = startPos; i < endPos; i++) {
        char ch = chNext;
        chNext = styler.SafeGetCharAt(i + 1);
		++column;

        if (bNewLine) {
			column = 0;
			bComment = (ch == '*' || ch == '/' || ch == '?');
        }
		if (column <= 1 && !bAarea) {
			bAarea = !isspacechar(ch);
			}
        bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
        if (atEOL) {
			int nContainment = styler.GetLineState(lineCurrent);
            int lev = CountBits(nContainment & IN_FLAGS) | SC_FOLDLEVELBASE;
			if (bAarea && !bComment)
				--lev;
            if (visibleChars == 0 && foldCompact)
                lev |= SC_FOLDLEVELWHITEFLAG;
            if ((bAarea) && (visibleChars > 0) && !(nContainment & NOT_HEADER) && !bComment)
                lev |= SC_FOLDLEVELHEADERFLAG;
            if (lev != styler.LevelAt(lineCurrent)) {
                styler.SetLevel(lineCurrent, lev);
            }
			if ((lev & SC_FOLDLEVELNUMBERMASK) <= (levelPrev & SC_FOLDLEVELNUMBERMASK)) {
				// this level is at the same level or less than the previous line
				// therefore these is nothing for the previous header to collapse, so remove the header
				styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
			}
            levelPrev = lev;
            visibleChars = 0;
			bAarea = false;
            bNewLine = true;
            lineCurrent++;
        } else {
            bNewLine = false;
        }


        if (!isspacechar(ch))
            visibleChars++;
    }

    // Fill in the real level of the next line, keeping the current flags as they will be filled in later
    int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
    styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const COBOLWordListDesc[] = {
    "A Keywords",
    "B Keywords",
    "Extended Keywords",
    0
};

LexerModule lmCOBOL(SCLEX_COBOL, ColouriseCOBOLDoc, "COBOL", FoldCOBOLDoc, COBOLWordListDesc);

Added lexers/LexCPP.cxx.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
// Scintilla source code edit control
/** @file LexCPP.cxx
 ** Lexer for C++, C, Java, and JavaScript.
 ** Further folding features and configuration properties added by "Udo Lechner" <dlchnr(at)gmx(dot)net>
 **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include <string>
#include <vector>
#include <map>
#include <algorithm>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "SparseState.h"
#include "SubStyles.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool IsSpaceEquiv(int state) {
	return (state <= SCE_C_COMMENTDOC) ||
		// including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE
		(state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) ||
		(state == SCE_C_COMMENTDOCKEYWORDERROR);
}

// Preconditions: sc.currentPos points to a character after '+' or '-'.
// The test for pos reaching 0 should be redundant,
// and is in only for safety measures.
// Limitation: this code will give the incorrect answer for code like
// a = b+++/ptn/...
// Putting a space between the '++' post-inc operator and the '+' binary op
// fixes this, and is highly recommended for readability anyway.
static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) {
	int pos = (int) sc.currentPos;
	while (--pos > 0) {
		char ch = styler[pos];
		if (ch == '+' || ch == '-') {
			return styler[pos - 1] == ch;
		}
	}
	return false;
}

static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) {
	// Don't look at styles, so no need to flush.
	int pos = (int) sc.currentPos;
	int currentLine = styler.GetLine(pos);
	int lineStartPos = styler.LineStart(currentLine);
	char ch;
	while (--pos > lineStartPos) {
		ch = styler.SafeGetCharAt(pos);
		if (ch != ' ' && ch != '\t') {
			break;
		}
	}
	const char *retBack = "nruter";
	const char *s = retBack;
	while (*s
		&& pos >= lineStartPos
		&& styler.SafeGetCharAt(pos) == *s) {
		s++;
		pos--;
	}
	return !*s;
}

static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) {
	std::string restOfLine;
	int i =0;
	char ch = styler.SafeGetCharAt(start, '\n');
	int endLine = styler.LineEnd(styler.GetLine(start));
	while (((start+i) < endLine) && (ch != '\r')) {
		char chNext = styler.SafeGetCharAt(start + i + 1, '\n');
		if (ch == '/' && (chNext == '/' || chNext == '*'))
			break;
		if (allowSpace || (ch != ' '))
			restOfLine += ch;
		i++;
		ch = chNext;
	}
	return restOfLine;
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_C_COMMENT ||
		style == SCE_C_COMMENTDOC ||
		style == SCE_C_COMMENTDOCKEYWORD ||
		style == SCE_C_COMMENTDOCKEYWORDERROR;
}

static std::vector<std::string> Tokenize(const std::string &s) {
	// Break into space separated tokens
	std::string word;
	std::vector<std::string> tokens;
	for (const char *cp = s.c_str(); *cp; cp++) {
		if ((*cp == ' ') || (*cp == '\t')) {
			if (!word.empty()) {
				tokens.push_back(word);
				word = "";
			}
		} else {
			word += *cp;
		}
	}
	if (!word.empty()) {
		tokens.push_back(word);
	}
	return tokens;
}

struct PPDefinition {
	int line;
	std::string key;
	std::string value;
	bool isUndef;
	PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false) :
		line(line_), key(key_), value(value_), isUndef(isUndef_) {
	}
};

class LinePPState {
	int state;
	int ifTaken;
	int level;
	bool ValidLevel() const {
		return level >= 0 && level < 32;
	}
	int maskLevel() const {
		return 1 << level;
	}
public:
	LinePPState() : state(0), ifTaken(0), level(-1) {
	}
	bool IsInactive() const {
		return state != 0;
	}
	bool CurrentIfTaken() {
		return (ifTaken & maskLevel()) != 0;
	}
	void StartSection(bool on) {
		level++;
		if (ValidLevel()) {
			if (on) {
				state &= ~maskLevel();
				ifTaken |= maskLevel();
			} else {
				state |= maskLevel();
				ifTaken &= ~maskLevel();
			}
		}
	}
	void EndSection() {
		if (ValidLevel()) {
			state &= ~maskLevel();
			ifTaken &= ~maskLevel();
		}
		level--;
	}
	void InvertCurrentLevel() {
		if (ValidLevel()) {
			state ^= maskLevel();
			ifTaken |= maskLevel();
		}
	}
};

// Hold the preprocessor state for each line seen.
// Currently one entry per line but could become sparse with just one entry per preprocessor line.
class PPStates {
	std::vector<LinePPState> vlls;
public:
	LinePPState ForLine(int line) {
		if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) {
			return vlls[line];
		} else {
			return LinePPState();
		}
	}
	void Add(int line, LinePPState lls) {
		vlls.resize(line+1);
		vlls[line] = lls;
	}
};

// An individual named option for use in an OptionSet

// Options used for LexerCPP
struct OptionsCPP {
	bool stylingWithinPreprocessor;
	bool identifiersAllowDollars;
	bool trackPreprocessor;
	bool updatePreprocessor;
	bool triplequotedStrings;
	bool hashquotedStrings;
	bool fold;
	bool foldSyntaxBased;
	bool foldComment;
	bool foldCommentMultiline;
	bool foldCommentExplicit;
	std::string foldExplicitStart;
	std::string foldExplicitEnd;
	bool foldExplicitAnywhere;
	bool foldPreprocessor;
	bool foldCompact;
	bool foldAtElse;
	OptionsCPP() {
		stylingWithinPreprocessor = false;
		identifiersAllowDollars = true;
		trackPreprocessor = true;
		updatePreprocessor = true;
		triplequotedStrings = false;
		hashquotedStrings = false;
		fold = false;
		foldSyntaxBased = true;
		foldComment = false;
		foldCommentMultiline = true;
		foldCommentExplicit = true;
		foldExplicitStart = "";
		foldExplicitEnd = "";
		foldExplicitAnywhere = false;
		foldPreprocessor = false;
		foldCompact = false;
		foldAtElse = false;
	}
};

static const char *const cppWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "Documentation comment keywords",
            "Global classes and typedefs",
            "Preprocessor definitions",
            0,
};

struct OptionSetCPP : public OptionSet<OptionsCPP> {
	OptionSetCPP() {
		DefineProperty("styling.within.preprocessor", &OptionsCPP::stylingWithinPreprocessor,
			"For C++ code, determines whether all preprocessor code is styled in the "
			"preprocessor style (0, the default) or only from the initial # to the end "
			"of the command word(1).");

		DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars,
			"Set to 0 to disallow the '$' character in identifiers with the cpp lexer.");

		DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor,
			"Set to 1 to interpret #if/#else/#endif to grey out code that is not active.");

		DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor,
			"Set to 1 to update preprocessor definitions when #define found.");

		DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings,
			"Set to 1 to enable highlighting of triple-quoted strings.");

		DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings,
			"Set to 1 to enable highlighting of hash-quoted strings.");

		DefineProperty("fold", &OptionsCPP::fold);

		DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased,
			"Set this property to 0 to disable syntax based folding.");

		DefineProperty("fold.comment", &OptionsCPP::foldComment,
			"This option enables folding multi-line comments and explicit fold points when using the C++ lexer. "
			"Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} "
			"at the end of a section that should fold.");

		DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline,
			"Set this property to 0 to disable folding multi-line comments when fold.comment=1.");

		DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit,
			"Set this property to 0 to disable folding explicit fold points when fold.comment=1.");

		DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart,
			"The string to use for explicit fold start points, replacing the standard //{.");

		DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd,
			"The string to use for explicit fold end points, replacing the standard //}.");

		DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere,
			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments.");

		DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor,
			"This option enables folding preprocessor directives when using the C++ lexer. "
			"Includes C#'s explicit #region and #endregion folding directives.");

		DefineProperty("fold.compact", &OptionsCPP::foldCompact);

		DefineProperty("fold.at.else", &OptionsCPP::foldAtElse,
			"This option enables C++ folding on a \"} else {\" line of an if statement.");

		DefineWordListSets(cppWordLists);
	}
};

static const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0};

class LexerCPP : public ILexerWithSubStyles {
	bool caseSensitive;
	CharacterSet setWord;
	CharacterSet setNegationOp;
	CharacterSet setArithmethicOp;
	CharacterSet setRelOp;
	CharacterSet setLogicalOp;
	PPStates vlls;
	std::vector<PPDefinition> ppDefineHistory;
	WordList keywords;
	WordList keywords2;
	WordList keywords3;
	WordList keywords4;
	WordList ppDefinitions;
	std::map<std::string, std::string> preprocessorDefinitionsStart;
	OptionsCPP options;
	OptionSetCPP osCPP;
	SparseState<std::string> rawStringTerminators;
	enum { activeFlag = 0x40 };
	enum { ssIdentifier, ssDocKeyword };
	SubStyles subStyles;
public:
	LexerCPP(bool caseSensitive_) :
		caseSensitive(caseSensitive_),
		setWord(CharacterSet::setAlphaNum, "._", 0x80, true),
		setNegationOp(CharacterSet::setNone, "!"),
		setArithmethicOp(CharacterSet::setNone, "+-/*%"),
		setRelOp(CharacterSet::setNone, "=!<>"),
		setLogicalOp(CharacterSet::setNone, "|&"),
		subStyles(styleSubable, 0x80, 0x40, activeFlag) {
	}
	virtual ~LexerCPP() {
	}
	void SCI_METHOD Release() {
		delete this;
	}
	int SCI_METHOD Version() const {
		return lvSubStyles;
	}
	const char * SCI_METHOD PropertyNames() {
		return osCPP.PropertyNames();
	}
	int SCI_METHOD PropertyType(const char *name) {
		return osCPP.PropertyType(name);
	}
	const char * SCI_METHOD DescribeProperty(const char *name) {
		return osCPP.DescribeProperty(name);
	}
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char * SCI_METHOD DescribeWordListSets() {
		return osCPP.DescribeWordListSets();
	}
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

	void * SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}

	int SCI_METHOD LineEndTypesSupported() {
		return SC_LINE_END_TYPE_UNICODE;
	};

	int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
		return subStyles.Allocate(styleBase, numberStyles);
	}
	int SCI_METHOD SubStylesStart(int styleBase) {
		return subStyles.Start(styleBase);
	}
	int SCI_METHOD SubStylesLength(int styleBase) {
		return subStyles.Length(styleBase);
	}
	void SCI_METHOD FreeSubStyles() {
		subStyles.Free();
	}
	void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
		subStyles.SetIdentifiers(style, identifiers);
	}
	int SCI_METHOD DistanceToSecondaryStyles() {
		return activeFlag;
	}
	const char * SCI_METHOD GetSubStyleBases() {
		return styleSubable;
	}

	static ILexer *LexerFactoryCPP() {
		return new LexerCPP(true);
	}
	static ILexer *LexerFactoryCPPInsensitive() {
		return new LexerCPP(false);
	}
	static int MaskActive(int style) {
		return style & ~activeFlag;
	}
	void EvaluateTokens(std::vector<std::string> &tokens);
	bool EvaluateExpression(const std::string &expr, const std::map<std::string, std::string> &preprocessorDefinitions);
};

int SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) {
	if (osCPP.PropertySet(&options, key, val)) {
		if (strcmp(key, "lexer.cpp.allow.dollars") == 0) {
			setWord = CharacterSet(CharacterSet::setAlphaNum, "._", 0x80, true);
			if (options.identifiersAllowDollars) {
				setWord.Add('$');
			}
		}
		return 0;
	}
	return -1;
}

int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &keywords;
		break;
	case 1:
		wordListN = &keywords2;
		break;
	case 2:
		wordListN = &keywords3;
		break;
	case 3:
		wordListN = &keywords4;
		break;
	case 4:
		wordListN = &ppDefinitions;
		break;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
			if (n == 4) {
				// Rebuild preprocessorDefinitions
				preprocessorDefinitionsStart.clear();
				for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) {
					char *cpDefinition = ppDefinitions.words[nDefinition];
					char *cpEquals = strchr(cpDefinition, '=');
					if (cpEquals) {
						std::string name(cpDefinition, cpEquals - cpDefinition);
						std::string val(cpEquals+1);
						preprocessorDefinitionsStart[name] = val;
					} else {
						std::string name(cpDefinition);
						std::string val("1");
						preprocessorDefinitionsStart[name] = val;
					}
				}
			}
		}
	}
	return firstModification;
}

// Functor used to truncate history
struct After {
	int line;
	After(int line_) : line(line_) {}
	bool operator()(PPDefinition &p) const {
		return p.line > line;
	}
};

void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);

	CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
	CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");

	CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");

	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);

	CharacterSet setInvalidRawFirst(CharacterSet::setNone, " )\\\t\v\f\n");

	if (options.identifiersAllowDollars) {
		setWordStart.Add('$');
	}

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;
	int styleBeforeDCKeyword = SCE_C_DEFAULT;
	bool continuationLine = false;
	bool isIncludePreprocessor = false;
	bool isStringInPreprocessor = false;
	bool inRERange = false;

	int lineCurrent = styler.GetLine(startPos);
	if ((MaskActive(initStyle) == SCE_C_PREPROCESSOR) ||
      (MaskActive(initStyle) == SCE_C_COMMENTLINE) ||
      (MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) {
		// Set continuationLine if last character of previous line is '\'
		if (lineCurrent > 0) {
			int endLinePrevious = styler.LineEnd(lineCurrent - 1);
			if (endLinePrevious > 0) {
				continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
			}
		}
	}

	// look back to set chPrevNonWhite properly for better regex colouring
	if (startPos > 0) {
		int back = startPos;
		while (--back && IsSpaceEquiv(MaskActive(styler.StyleAt(back))))
			;
		if (MaskActive(styler.StyleAt(back)) == SCE_C_OPERATOR) {
			chPrevNonWhite = styler.SafeGetCharAt(back);
		}
	}

	StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(0xff));
	LinePPState preproc = vlls.ForLine(lineCurrent);

	bool definitionsChanged = false;

	// Truncate ppDefineHistory before current line

	if (!options.updatePreprocessor)
		ppDefineHistory.clear();

	std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(lineCurrent-1));
	if (itInvalid != ppDefineHistory.end()) {
		ppDefineHistory.erase(itInvalid, ppDefineHistory.end());
		definitionsChanged = true;
	}

	std::map<std::string, std::string> preprocessorDefinitions = preprocessorDefinitionsStart;
	for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
		if (itDef->isUndef)
			preprocessorDefinitions.erase(itDef->key);
		else
			preprocessorDefinitions[itDef->key] = itDef->value;
	}

	std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
	SparseState<std::string> rawSTNew(lineCurrent);

	int activitySet = preproc.IsInactive() ? activeFlag : 0;

	const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
	const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);

	int lineEndNext = styler.LineEnd(lineCurrent);

	for (; sc.More();) {

		if (sc.atLineStart) {
			// Using MaskActive() is not needed in the following statement.
			// Inside inactive preprocessor declaration, state will be reset anyway at the end of this block.
			if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) {
				// Prevent SCE_C_STRINGEOL from leaking back to previous line which
				// ends with a line continuation by locking in the state upto this position.
				sc.SetState(sc.state);
			}
			if ((MaskActive(sc.state) == SCE_C_PREPROCESSOR) && (!continuationLine)) {
				sc.SetState(SCE_C_DEFAULT|activitySet);
			}
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
			lastWordWasUUID = false;
			isIncludePreprocessor = false;
			inRERange = false;
			if (preproc.IsInactive()) {
				activitySet = activeFlag;
				sc.SetState(sc.state | activitySet);
			}
		}

		if (sc.atLineEnd) {
			lineCurrent++;
			lineEndNext = styler.LineEnd(lineCurrent);
			vlls.Add(lineCurrent, preproc);
			if (rawStringTerminator != "") {
				rawSTNew.Set(lineCurrent-1, rawStringTerminator);
			}
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) {
				lineCurrent++;
				lineEndNext = styler.LineEnd(lineCurrent);
				vlls.Add(lineCurrent, preproc);
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					// Even in UTF-8, \r and \n are separate
					sc.Forward();
				}
				continuationLine = true;
				sc.Forward();
				continue;
			}
		}

		const bool atLineEndBeforeSwitch = sc.atLineEnd;

		// Determine if the current state should terminate.
		switch (MaskActive(sc.state)) {
			case SCE_C_OPERATOR:
				sc.SetState(SCE_C_DEFAULT|activitySet);
				break;
			case SCE_C_NUMBER:
				// We accept almost anything because of hex. and number suffixes
				if (!(setWord.Contains(sc.ch)
				   || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E' ||
				                                          sc.chPrev == 'p' || sc.chPrev == 'P')))) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_IDENTIFIER:
				if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) {
					char s[1000];
					if (caseSensitive) {
						sc.GetCurrent(s, sizeof(s));
					} else {
						sc.GetCurrentLowered(s, sizeof(s));
					}
					if (keywords.InList(s)) {
						lastWordWasUUID = strcmp(s, "uuid") == 0;
						sc.ChangeState(SCE_C_WORD|activitySet);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_C_WORD2|activitySet);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_C_GLOBALCLASS|activitySet);
					} else {
						int subStyle = classifierIdentifiers.ValueFor(s);
						if (subStyle >= 0) {
							sc.ChangeState(subStyle|activitySet);
						}
					}
					const bool literalString = sc.ch == '\"';
					if (literalString || sc.ch == '\'') {
						size_t lenS = strlen(s);
						const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext);
						if (raw)
							s[lenS--] = '\0';
						bool valid =
							(lenS == 0) ||
							((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) ||
							((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8'));
						if (valid) {
							if (literalString)
								sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet);
							else
								sc.ChangeState(SCE_C_CHARACTER|activitySet);
						}
					}
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_PREPROCESSOR: 	
				if (options.stylingWithinPreprocessor) {
					if (IsASpace(sc.ch)) {
						sc.SetState(SCE_C_DEFAULT|activitySet);
					}
				} else if (isStringInPreprocessor && (sc.Match('>') || sc.Match('\"'))) {
					isStringInPreprocessor = false;
				} else if (!isStringInPreprocessor) {
					if ((isIncludePreprocessor && sc.Match('<')) || sc.Match('\"')) {
						isStringInPreprocessor = true;
					} else if (sc.Match('/', '*')) {
						sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet);
						sc.Forward();	// Eat the *
					} else if (sc.Match('/', '/')) {
						sc.SetState(SCE_C_DEFAULT|activitySet);
					}
				}
				break;
			case SCE_C_PREPROCESSORCOMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet);
					continue;	// Without advancing in case of '\'.
				}
				break;
			case SCE_C_COMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_COMMENTDOC:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_C_COMMENTDOC;
						sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet);
					}
				}
				break;
			case SCE_C_COMMENTLINE:
				if (sc.atLineStart && !continuationLine) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_COMMENTLINEDOC:
				if (sc.atLineStart && !continuationLine) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC;
						sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet);
					}
				}
				break;
			case SCE_C_COMMENTDOCKEYWORD:
				if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				} else if (!setDoxygen.Contains(sc.ch)) {
					char s[100];
					if (caseSensitive) {
						sc.GetCurrent(s, sizeof(s));
					} else {
						sc.GetCurrentLowered(s, sizeof(s));
					}
					if (!IsASpace(sc.ch)) {
						sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
					} else if (!keywords3.InList(s + 1)) {
						int subStyleCDKW = classifierDocKeyWords.ValueFor(s+1);
						if (subStyleCDKW >= 0) {
							sc.ChangeState(subStyleCDKW|activitySet);
						} else {
							sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
						}
					}
					sc.SetState(styleBeforeDCKeyword|activitySet);
				}
				break;
			case SCE_C_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_C_STRINGEOL|activitySet);
				} else if (isIncludePreprocessor) {
					if (sc.ch == '>') {
						sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
						isIncludePreprocessor = false;
					}
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_HASHQUOTEDSTRING:
				if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_STRINGRAW:
				if (sc.Match(rawStringTerminator.c_str())) {
					for (size_t termPos=rawStringTerminator.size(); termPos; termPos--)
						sc.Forward();
					sc.SetState(SCE_C_DEFAULT|activitySet);
					rawStringTerminator = "";
				}
				break;
			case SCE_C_CHARACTER:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_C_STRINGEOL|activitySet);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_REGEX:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				} else if (! inRERange && sc.ch == '/') {
					sc.Forward();
					while ((sc.ch < 0x80) && islower(sc.ch))
						sc.Forward();    // gobble regex flags
					sc.SetState(SCE_C_DEFAULT|activitySet);
				} else if (sc.ch == '\\' && (static_cast<int>(sc.currentPos+1) < lineEndNext)) {
					// Gobble up the escaped character
					sc.Forward();
				} else if (sc.ch == '[') {
					inRERange = true;
				} else if (sc.ch == ']') {
					inRERange = false;
				}
				break;
			case SCE_C_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_VERBATIM:
				if (sc.ch == '\"') {
					if (sc.chNext == '\"') {
						sc.Forward();
					} else {
						sc.ForwardSetState(SCE_C_DEFAULT|activitySet);
					}
				}
				break;
			case SCE_C_TRIPLEVERBATIM:
				if (sc.Match("\"\"\"")) {
					while (sc.Match('"')) {
						sc.Forward();
					}
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
				break;
			case SCE_C_UUID:
				if (sc.atLineEnd || sc.ch == ')') {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				}
		}

		if (sc.atLineEnd && !atLineEndBeforeSwitch) {
			// State exit processing consumed characters up to end of line.
			lineCurrent++;
			lineEndNext = styler.LineEnd(lineCurrent);
			vlls.Add(lineCurrent, preproc);
		}

		// Determine if a new state should be entered.
		if (MaskActive(sc.state) == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM|activitySet);
				sc.Forward();
			} else if (options.triplequotedStrings && sc.Match("\"\"\"")) {
				sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet);
				sc.Forward(2);
			} else if (options.hashquotedStrings && sc.Match('#', '\"')) {
				sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID|activitySet);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER|activitySet);
				}
			} else if (!sc.atLineEnd && (setWordStart.Contains(sc.ch) || (sc.ch == '@'))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID|activitySet);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER|activitySet);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTDOC|activitySet);
				} else {
					sc.SetState(SCE_C_COMMENT|activitySet);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
					// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTLINEDOC|activitySet);
				else
					sc.SetState(SCE_C_COMMENTLINE|activitySet);
			} else if (sc.ch == '/'
				   && (setOKBeforeRE.Contains(chPrevNonWhite)
				       || followsReturnKeyword(sc, styler))
				   && (!setCouldBePostOp.Contains(chPrevNonWhite)
				       || !FollowsPostfixOperator(sc, styler))) {
				sc.SetState(SCE_C_REGEX|activitySet);	// JavaScript's RegEx
				inRERange = false;
			} else if (sc.ch == '\"') {
				if (sc.chPrev == 'R') {
					styler.Flush();
					if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) {
						sc.SetState(SCE_C_STRINGRAW|activitySet);
						rawStringTerminator = ")";
						for (int termPos = sc.currentPos + 1;; termPos++) {
							char chTerminator = styler.SafeGetCharAt(termPos, '(');
							if (chTerminator == '(')
								break;
							rawStringTerminator += chTerminator;
						}
						rawStringTerminator += '\"';
					} else {
						sc.SetState(SCE_C_STRING|activitySet);
					}
				} else {
					sc.SetState(SCE_C_STRING|activitySet);
				}
				isIncludePreprocessor = false;	// ensure that '>' won't end the string
			} else if (isIncludePreprocessor && sc.ch == '<') {
				sc.SetState(SCE_C_STRING|activitySet);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER|activitySet);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_C_PREPROCESSOR|activitySet);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT|activitySet);
				} else if (sc.Match("include")) {
					isIncludePreprocessor = true;
				} else {
					if (options.trackPreprocessor) {
						if (sc.Match("ifdef") || sc.Match("ifndef")) {
							bool isIfDef = sc.Match("ifdef");
							int i = isIfDef ? 5 : 6;
							std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false);
							bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
							preproc.StartSection(isIfDef == foundDef);
						} else if (sc.Match("if")) {
							std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true);
							bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
							preproc.StartSection(ifGood);
						} else if (sc.Match("else")) {
							if (!preproc.CurrentIfTaken()) {
								preproc.InvertCurrentLevel();
								activitySet = preproc.IsInactive() ? activeFlag : 0;
								if (!activitySet)
									sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
							} else if (!preproc.IsInactive()) {
								preproc.InvertCurrentLevel();
								activitySet = preproc.IsInactive() ? activeFlag : 0;
								if (!activitySet)
									sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
							}
						} else if (sc.Match("elif")) {
							// Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif
							if (!preproc.CurrentIfTaken()) {
								// Similar to #if
								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true);
								bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
								if (ifGood) {
									preproc.InvertCurrentLevel();
									activitySet = preproc.IsInactive() ? activeFlag : 0;
									if (!activitySet)
										sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
								}
							} else if (!preproc.IsInactive()) {
								preproc.InvertCurrentLevel();
								activitySet = preproc.IsInactive() ? activeFlag : 0;
								if (!activitySet)
									sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
							}
						} else if (sc.Match("endif")) {
							preproc.EndSection();
							activitySet = preproc.IsInactive() ? activeFlag : 0;
							sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
						} else if (sc.Match("define")) {
							if (options.updatePreprocessor && !preproc.IsInactive()) {
								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
								if (restOfLine.find(")") == std::string::npos) {	// Don't handle macros with arguments
									std::vector<std::string> tokens = Tokenize(restOfLine);
									std::string key;
									std::string value("1");
									if (tokens.size() >= 1) {
										key = tokens[0];
										if (tokens.size() >= 2) {
											value = tokens[1];
										}
										preprocessorDefinitions[key] = value;
										ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value));
										definitionsChanged = true;
									}
								}
							}
						} else if (sc.Match("undef")) {
							if (options.updatePreprocessor && !preproc.IsInactive()) {
								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true);
								std::vector<std::string> tokens = Tokenize(restOfLine);
								std::string key;
								if (tokens.size() >= 1) {
									key = tokens[0];
									preprocessorDefinitions.erase(key);
									ppDefineHistory.push_back(PPDefinition(lineCurrent, key, "", true));
									definitionsChanged = true;
								}
							}
						}
					}
				}
			} else if (isoperator(sc.ch)) {
				sc.SetState(SCE_C_OPERATOR|activitySet);
			}
		}

		if (!IsASpace(sc.ch) && !IsSpaceEquiv(MaskActive(sc.state))) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
		continuationLine = false;
		sc.Forward();
	}
	const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent);
	if (definitionsChanged || rawStringsChanged)
		styler.ChangeLexerState(startPos, startPos + length);
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".

void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {

	if (!options.fold)
		return;

	LexAccessor styler(pAccess);

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	bool inLineComment = false;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	unsigned int lineStartNext = styler.LineStart(lineCurrent+1);
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = MaskActive(styler.StyleAt(startPos));
	int style = MaskActive(initStyle);
	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = MaskActive(styler.StyleAt(i + 1));
		bool atEOL = i == (lineStartNext-1);
		if ((style == SCE_C_COMMENTLINE) || (style == SCE_C_COMMENTLINEDOC))
			inLineComment = true;
		if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style) && !inLineComment) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) {
			if (userDefinedFoldMarkers) {
				if (styler.Match(i, options.foldExplicitStart.c_str())) {
					levelNext++;
				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
					levelNext--;
				}
			} else {
				if ((ch == '/') && (chNext == '/')) {
					char chNext2 = styler.SafeGetCharAt(i + 2);
					if (chNext2 == '{') {
						levelNext++;
					} else if (chNext2 == '}') {
						levelNext--;
					}
				}
			}
		}
		if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
			if (ch == '#') {
				unsigned int j = i + 1;
				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "region") || styler.Match(j, "if")) {
					levelNext++;
				} else if (styler.Match(j, "end")) {
					levelNext--;
				}
			}
		}
		if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}
		if (!IsASpace(ch))
			visibleChars++;
		if (atEOL || (i == endPos-1)) {
			int levelUse = levelCurrent;
			if (options.foldSyntaxBased && options.foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && options.foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			lineStartNext = styler.LineStart(lineCurrent+1);
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
				// There is an empty line at end of file so give it same level and empty
				styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
			}
			visibleChars = 0;
			inLineComment = false;
		}
	}
}

void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens) {

	// Evaluate defined() statements to either 0 or 1
	for (size_t i=0; (i+2)<tokens.size();) {
		if ((tokens[i] == "defined") && (tokens[i+1] == "(")) {
			const char *val = "0";
			if (tokens[i+2] == ")") {
				// defined()
				tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 3);
			} else if (((i+3)<tokens.size()) && (tokens[i+3] == ")")) {
				// defined(<int>)
				tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4);
				val = "1";
			}
			tokens[i] = val;
		} else {
			i++;
		}
	}

	// Find bracketed subexpressions and recurse on them
	std::vector<std::string>::iterator itBracket = std::find(tokens.begin(), tokens.end(), "(");
	std::vector<std::string>::iterator itEndBracket = std::find(tokens.begin(), tokens.end(), ")");
	while ((itBracket != tokens.end()) && (itEndBracket != tokens.end()) && (itEndBracket > itBracket)) {
		std::vector<std::string> inBracket(itBracket + 1, itEndBracket);
		EvaluateTokens(inBracket);

		// The insertion is done before the removal because there were failures with the opposite approach
		tokens.insert(itBracket, inBracket.begin(), inBracket.end());
		itBracket = std::find(tokens.begin(), tokens.end(), "(");
		itEndBracket = std::find(tokens.begin(), tokens.end(), ")");
		tokens.erase(itBracket, itEndBracket + 1);

		itBracket = std::find(tokens.begin(), tokens.end(), "(");
		itEndBracket = std::find(tokens.begin(), tokens.end(), ")");
	}

	// Evaluate logical negations
	for (size_t j=0; (j+1)<tokens.size();) {
		if (setNegationOp.Contains(tokens[j][0])) {
			int isTrue = atoi(tokens[j+1].c_str());
			if (tokens[j] == "!")
				isTrue = !isTrue;
			std::vector<std::string>::iterator itInsert =
				tokens.erase(tokens.begin() + j, tokens.begin() + j + 2);
			tokens.insert(itInsert, isTrue ? "1" : "0");
		} else {
			j++;
		}
	}

	// Evaluate expressions in precedence order
	enum precedence { precArithmetic, precRelative, precLogical };
	for (int prec=precArithmetic; prec <= precLogical; prec++) {
		// Looking at 3 tokens at a time so end at 2 before end
		for (size_t k=0; (k+2)<tokens.size();) {
			char chOp = tokens[k+1][0];
			if (
				((prec==precArithmetic) && setArithmethicOp.Contains(chOp)) ||
				((prec==precRelative) && setRelOp.Contains(chOp)) ||
				((prec==precLogical) && setLogicalOp.Contains(chOp))
				) {
				int valA = atoi(tokens[k].c_str());
				int valB = atoi(tokens[k+2].c_str());
				int result = 0;
				if (tokens[k+1] == "+")
					result = valA + valB;
				else if (tokens[k+1] == "-")
					result = valA - valB;
				else if (tokens[k+1] == "*")
					result = valA * valB;
				else if (tokens[k+1] == "/")
					result = valA / (valB ? valB : 1);
				else if (tokens[k+1] == "%")
					result = valA % (valB ? valB : 1);
				else if (tokens[k+1] == "<")
					result = valA < valB;
				else if (tokens[k+1] == "<=")
					result = valA <= valB;
				else if (tokens[k+1] == ">")
					result = valA > valB;
				else if (tokens[k+1] == ">=")
					result = valA >= valB;
				else if (tokens[k+1] == "==")
					result = valA == valB;
				else if (tokens[k+1] == "!=")
					result = valA != valB;
				else if (tokens[k+1] == "||")
					result = valA || valB;
				else if (tokens[k+1] == "&&")
					result = valA && valB;
				char sResult[30];
				sprintf(sResult, "%d", result);
				std::vector<std::string>::iterator itInsert =
					tokens.erase(tokens.begin() + k, tokens.begin() + k + 3);
				tokens.insert(itInsert, sResult);
			} else {
				k++;
			}
		}
	}
}

bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map<std::string, std::string> &preprocessorDefinitions) {
	// Break into tokens, replacing with definitions
	std::string word;
	std::vector<std::string> tokens;
	const char *cp = expr.c_str();
	for (;;) {
		if (setWord.Contains(static_cast<unsigned char>(*cp))) {
			word += *cp;
		} else {
			std::map<std::string, std::string>::const_iterator it = preprocessorDefinitions.find(word);
			if (it != preprocessorDefinitions.end()) {
				tokens.push_back(it->second);
			} else if (!word.empty() && ((word[0] >= '0' && word[0] <= '9') || (word == "defined"))) {
				tokens.push_back(word);
			}
			word = "";
			if (!*cp) {
				break;
			}
			if ((*cp != ' ') && (*cp != '\t')) {
				std::string op(cp, 1);
				if (setRelOp.Contains(static_cast<unsigned char>(*cp))) {
					if (setRelOp.Contains(static_cast<unsigned char>(cp[1]))) {
						op += cp[1];
						cp++;
					}
				} else if (setLogicalOp.Contains(static_cast<unsigned char>(*cp))) {
					if (setLogicalOp.Contains(static_cast<unsigned char>(cp[1]))) {
						op += cp[1];
						cp++;
					}
				}
				tokens.push_back(op);
			}
		}
		cp++;
	}

	EvaluateTokens(tokens);

	// "0" or "" -> false else true
	bool isFalse = tokens.empty() ||
		((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0"));
	return !isFalse;
}

LexerModule lmCPP(SCLEX_CPP, LexerCPP::LexerFactoryCPP, "cpp", cppWordLists);
LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, LexerCPP::LexerFactoryCPPInsensitive, "cppnocase", cppWordLists);

Added lexers/LexCSS.cxx.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
// Scintilla source code edit control
/** @file LexCSS.cxx
 ** Lexer for Cascading Style Sheets
 ** Written by Jakub Vrna
 ** Improved by Philippe Lhoste (CSS2)
 ** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ )
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// TODO: handle SCSS nested properties like font: { weight: bold; size: 1em; }
// TODO: handle SCSS interpolation: #{}
// TODO: add features for Less if somebody feels like contributing; http://lesscss.org/
// TODO: refactor this monster so that the next poor slob can read it!

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


static inline bool IsAWordChar(const unsigned int ch) {
	/* FIXME:
	 * The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars.
	 * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee
	 * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher
	 */
	return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_';
}

inline bool IsCssOperator(const int ch) {
	if (!((ch < 0x80) && isalnum(ch)) &&
		(ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
		 ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
		 /* CSS2 */
		 ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' ||
		 ch == '[' || ch == ']' || ch == '(' || ch == ')')) {
		return true;
	}
	return false;
}

// look behind (from start of document to our start position) to determine current nesting level
inline int NestingLevelLookBehind(unsigned int startPos, Accessor &styler) {
	int ch;
	int nestingLevel = 0;

	for (unsigned int i = 0; i < startPos; i++) {
		ch = styler.SafeGetCharAt(i);
		if (ch == '{')
			nestingLevel++;
		else if (ch == '}')
			nestingLevel--;
	}

	return nestingLevel;
}

static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
	WordList &css1Props = *keywordlists[0];
	WordList &pseudoClasses = *keywordlists[1];
	WordList &css2Props = *keywordlists[2];
	WordList &css3Props = *keywordlists[3];
	WordList &pseudoElements = *keywordlists[4];
	WordList &exProps = *keywordlists[5];
	WordList &exPseudoClasses = *keywordlists[6];
	WordList &exPseudoElements = *keywordlists[7];

	StyleContext sc(startPos, length, initStyle, styler);

	int lastState = -1; // before operator
	int lastStateC = -1; // before comment
	int lastStateS = -1; // before single-quoted/double-quoted string
	int lastStateVar = -1; // before variable (SCSS)
	int lastStateVal = -1; // before value (SCSS)
	int op = ' '; // last operator
	int opPrev = ' '; // last operator
	bool insideParentheses = false; // true if currently in a CSS url() or similar construct

	// property lexer.css.scss.language
	//	Set to 1 for Sassy CSS (.scss)
	bool isScssDocument = styler.GetPropertyInt("lexer.css.scss.language") != 0;

	// property lexer.css.less.language
	// Set to 1 for Less CSS (.less)
	bool isLessDocument = styler.GetPropertyInt("lexer.css.less.language") != 0;

	// property lexer.css.hss.language
	// Set to 1 for HSS (.hss)
	bool isHssDocument = styler.GetPropertyInt("lexer.css.hss.language") != 0;

	// SCSS/LESS/HSS have the concept of variable
	bool hasVariables = isScssDocument || isLessDocument || isHssDocument;
	char varPrefix = 0;
	if (hasVariables)
		varPrefix = isLessDocument ? '@' : '$';

	// SCSS/LESS/HSS support single-line comments
	typedef enum _CommentModes { eCommentBlock = 0, eCommentLine = 1} CommentMode;
	CommentMode comment_mode = eCommentBlock;
	bool hasSingleLineComments = isScssDocument || isLessDocument || isHssDocument;

	// must keep track of nesting level in document types that support it (SCSS/LESS/HSS)
	bool hasNesting = false;
	int nestingLevel = 0;
	if (isScssDocument || isLessDocument || isHssDocument) {
		hasNesting = true;
		nestingLevel = NestingLevelLookBehind(startPos, styler);
	}

	// "the loop"
	for (; sc.More(); sc.Forward()) {
		if (sc.state == SCE_CSS_COMMENT && ((comment_mode == eCommentBlock && sc.Match('*', '/')) || (comment_mode == eCommentLine && sc.atLineEnd))) {
			if (lastStateC == -1) {
				// backtrack to get last state:
				// comments are like whitespace, so we must return to the previous state
				unsigned int i = startPos;
				for (; i > 0; i--) {
					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
						if (lastStateC == SCE_CSS_OPERATOR) {
							op = styler.SafeGetCharAt(i-1);
							opPrev = styler.SafeGetCharAt(i-2);
							while (--i) {
								lastState = styler.StyleAt(i-1);
								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
									break;
							}
							if (i == 0)
								lastState = SCE_CSS_DEFAULT;
						}
						break;
					}
				}
				if (i == 0)
					lastStateC = SCE_CSS_DEFAULT;
			}
			if (comment_mode == eCommentBlock) {
				sc.Forward();
				sc.ForwardSetState(lastStateC);
			} else /* eCommentLine */ {
				sc.SetState(lastStateC);
			}
		}

		if (sc.state == SCE_CSS_COMMENT)
			continue;

		if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
			if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
				continue;
			unsigned int i = sc.currentPos;
			while (i && styler[i-1] == '\\')
				i--;
			if ((sc.currentPos - i) % 2 == 1)
				continue;
			sc.ForwardSetState(lastStateS);
		}

		if (sc.state == SCE_CSS_OPERATOR) {
			if (op == ' ') {
				unsigned int i = startPos;
				op = styler.SafeGetCharAt(i-1);
				opPrev = styler.SafeGetCharAt(i-2);
				while (--i) {
					lastState = styler.StyleAt(i-1);
					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
						break;
				}
			}
			switch (op) {
			case '@':
				if (lastState == SCE_CSS_DEFAULT || hasNesting)
					sc.SetState(SCE_CSS_DIRECTIVE);
				break;
			case '>':
			case '+':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
					lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case '[':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
					lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_ATTRIBUTE);
				break;
			case ']':
				if (lastState == SCE_CSS_ATTRIBUTE)
					sc.SetState(SCE_CSS_TAG);
				break;
			case '{':
				nestingLevel++;
				switch (lastState) {
				case SCE_CSS_MEDIA:
					sc.SetState(SCE_CSS_DEFAULT);
					break;
				case SCE_CSS_TAG:
				case SCE_CSS_DIRECTIVE:
					sc.SetState(SCE_CSS_IDENTIFIER);
					break;
				}
				break;
			case '}':
				if (--nestingLevel < 0)
					nestingLevel = 0;
				switch (lastState) {
				case SCE_CSS_DEFAULT:
				case SCE_CSS_VALUE:
				case SCE_CSS_IMPORTANT:
				case SCE_CSS_IDENTIFIER:
				case SCE_CSS_IDENTIFIER2:
				case SCE_CSS_IDENTIFIER3:
					if (hasNesting)
						sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT);
					else
						sc.SetState(SCE_CSS_DEFAULT);
					break;
				}
				break;
			case '(':
				if (lastState == SCE_CSS_PSEUDOCLASS)
					sc.SetState(SCE_CSS_TAG);
				else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)
					sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS);
				break;
			case ')':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
					lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
					lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT)
					sc.SetState(SCE_CSS_TAG);
				break;
			case ':':
				switch (lastState) {
				case SCE_CSS_TAG:
				case SCE_CSS_DEFAULT:
				case SCE_CSS_CLASS:
				case SCE_CSS_ID:
				case SCE_CSS_PSEUDOCLASS:
				case SCE_CSS_EXTENDED_PSEUDOCLASS:
				case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				case SCE_CSS_PSEUDOELEMENT:
				case SCE_CSS_EXTENDED_PSEUDOELEMENT:
					sc.SetState(SCE_CSS_PSEUDOCLASS);
					break;
				case SCE_CSS_IDENTIFIER:
				case SCE_CSS_IDENTIFIER2:
				case SCE_CSS_IDENTIFIER3:
				case SCE_CSS_EXTENDED_IDENTIFIER:
				case SCE_CSS_UNKNOWN_IDENTIFIER:
				case SCE_CSS_VARIABLE:
					sc.SetState(SCE_CSS_VALUE);
					lastStateVal = lastState;
					break;
				}
				break;
			case '.':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
					lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_CLASS);
				break;
			case '#':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
					lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_ID);
				break;
			case ',':
			case '|':
			case '~':
				if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ';':
				switch (lastState) {
				case SCE_CSS_DIRECTIVE:
					if (hasNesting) {
						sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT);
					} else {
						sc.SetState(SCE_CSS_DEFAULT);
					}
					break;
				case SCE_CSS_VALUE:
				case SCE_CSS_IMPORTANT:
					// data URLs can have semicolons; simplistically check for wrapping parentheses and move along
					if (insideParentheses) {
						sc.SetState(lastState);
					} else {
						if (lastStateVal == SCE_CSS_VARIABLE) {
							sc.SetState(SCE_CSS_DEFAULT);
						} else {
							sc.SetState(SCE_CSS_IDENTIFIER);
						}
					}
					break;
				case SCE_CSS_VARIABLE:
					if (lastStateVar == SCE_CSS_VALUE) {
						// data URLs can have semicolons; simplistically check for wrapping parentheses and move along
						if (insideParentheses) {
							sc.SetState(SCE_CSS_VALUE);
						} else {
							sc.SetState(SCE_CSS_IDENTIFIER);
						}
					} else {
						sc.SetState(SCE_CSS_DEFAULT);
					}
					break;
				}
				break;
			case '!':
				if (lastState == SCE_CSS_VALUE)
					sc.SetState(SCE_CSS_IMPORTANT);
				break;
			}
		}

		if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) {
			sc.SetState(SCE_CSS_TAG);
			continue;
		}

		// check for inside parentheses (whether part of an "operator" or not)
		if (sc.ch == '(')
			insideParentheses = true;
		else if (sc.ch == ')')
			insideParentheses = false;

		// SCSS special modes
		if (hasVariables) {
			// variable name
			if (sc.ch == varPrefix) {
				switch (sc.state) {
				case SCE_CSS_DEFAULT:
					if (isLessDocument) // give priority to pseudo elements
						break;
				case SCE_CSS_VALUE:
					lastStateVar = sc.state;
					sc.SetState(SCE_CSS_VARIABLE);
					continue;
				}
			}
			if (sc.state == SCE_CSS_VARIABLE) {
				if (IsAWordChar(sc.ch)) {
					// still looking at the variable name
					continue;
				}
				if (lastStateVar == SCE_CSS_VALUE) {
					// not looking at the variable name any more, and it was part of a value
					sc.SetState(SCE_CSS_VALUE);
				}
			}

			// nested rule parent selector
			if (sc.ch == '&') {
				switch (sc.state) {
				case SCE_CSS_DEFAULT:
				case SCE_CSS_IDENTIFIER:
					sc.SetState(SCE_CSS_TAG);
					continue;
				}
			}
		}

		// nesting rules that apply to SCSS and Less
		if (hasNesting) {
			// check for nested rule selector
			if (sc.state == SCE_CSS_IDENTIFIER && (IsAWordChar(sc.ch) || sc.ch == ':' || sc.ch == '.' || sc.ch == '#')) {
				// look ahead to see whether { comes before next ; and }
				unsigned int endPos = startPos + length;
				int ch;

				for (unsigned int i = sc.currentPos; i < endPos; i++) {
					ch = styler.SafeGetCharAt(i);
					if (ch == ';' || ch == '}')
						break;
					if (ch == '{') {
						sc.SetState(SCE_CSS_DEFAULT);
						continue;
					}
				}
			}

		}

		if (IsAWordChar(sc.ch)) {
			if (sc.state == SCE_CSS_DEFAULT)
				sc.SetState(SCE_CSS_TAG);
			continue;
		}

		if (IsAWordChar(sc.chPrev) && (
			sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 ||
			sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER ||
			sc.state == SCE_CSS_UNKNOWN_IDENTIFIER ||
			sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
			sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
			sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
			sc.state == SCE_CSS_IMPORTANT ||
			sc.state == SCE_CSS_DIRECTIVE
		)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			char *s2 = s;
			while (*s2 && !IsAWordChar(*s2))
				s2++;
			switch (sc.state) {
			case SCE_CSS_IDENTIFIER:
			case SCE_CSS_IDENTIFIER2:
			case SCE_CSS_IDENTIFIER3:
			case SCE_CSS_EXTENDED_IDENTIFIER:
			case SCE_CSS_UNKNOWN_IDENTIFIER:
				if (css1Props.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER);
				else if (css2Props.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER2);
				else if (css3Props.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER3);
				else if (exProps.InList(s2))
					sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER);
				else
					sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
				break;
			case SCE_CSS_PSEUDOCLASS:
			case SCE_CSS_PSEUDOELEMENT:
			case SCE_CSS_EXTENDED_PSEUDOCLASS:
			case SCE_CSS_EXTENDED_PSEUDOELEMENT:
			case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOCLASS);
				else if (opPrev == ':' && pseudoElements.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOELEMENT);
				else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS);
				else if (opPrev == ':' && exPseudoElements.InList(s2))
					sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT);
				else
					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
				break;
			case SCE_CSS_IMPORTANT:
				if (strcmp(s2, "important") != 0)
					sc.ChangeState(SCE_CSS_VALUE);
				break;
			case SCE_CSS_DIRECTIVE:
				if (op == '@' && strcmp(s2, "media") == 0)
					sc.ChangeState(SCE_CSS_MEDIA);
				break;
			}
		}

		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (
			sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID ||
			(sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */
				sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
				sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
				sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
			))
		))
			sc.SetState(SCE_CSS_TAG);

		if (sc.Match('/', '*')) {
			lastStateC = sc.state;
			comment_mode = eCommentBlock;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if (hasSingleLineComments && sc.Match('/', '/') && !insideParentheses) {
			// note that we've had to treat ([...]// as the start of a URL not a comment, e.g. url(http://example.com), url(//example.com)
			lastStateC = sc.state;
			comment_mode = eCommentLine;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE)
			&& (sc.ch == '\"' || sc.ch == '\'')) {
			lastStateS = sc.state;
			sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
		} else if (IsCssOperator(sc.ch)
			&& (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
			&& ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{')
		) {
			if (sc.state != SCE_CSS_OPERATOR)
				lastState = sc.state;
			sc.SetState(SCE_CSS_OPERATOR);
			op = sc.ch;
			opPrev = sc.chPrev;
		}
	}

	sc.Complete();
}

static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment) {
			if (!inComment && (style == SCE_CSS_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_CSS_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_CSS_COMMENT);
		}
		if (style == SCE_CSS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const cssWordListDesc[] = {
	"CSS1 Properties",
	"Pseudo-classes",
	"CSS2 Properties",
	"CSS3 Properties",
	"Pseudo-elements",
	"Browser-Specific CSS Properties",
	"Browser-Specific Pseudo-classes",
	"Browser-Specific Pseudo-elements",
	0
};

LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);

Added lexers/LexCaml.cxx.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
// Scintilla source code edit control
/** @file LexCaml.cxx
 ** Lexer for Objective Caml.
 **/
// Copyright 2005-2009 by Robert Roessler <robertr@rftp.com>
// The License.txt file describes the conditions under which this software may be distributed.
/*	Release History
	20050204 Initial release.
	20050205 Quick compiler standards/"cleanliness" adjustment.
	20050206 Added cast for IsLeadByte().
	20050209 Changes to "external" build support.
	20050306 Fix for 1st-char-in-doc "corner" case.
	20050502 Fix for [harmless] one-past-the-end coloring.
	20050515 Refined numeric token recognition logic.
	20051125 Added 2nd "optional" keywords class.
	20051129 Support "magic" (read-only) comments for RCaml.
	20051204 Swtich to using StyleContext infrastructure.
	20090629 Add full Standard ML '97 support.
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

//	Since the Microsoft __iscsym[f] funcs are not ANSI...
inline int  iscaml(int c) {return isalnum(c) || c == '_';}
inline int iscamlf(int c) {return isalpha(c) || c == '_';}

static const int baseT[24] = {
	0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* A - L */
	0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16	/* M - X */
};

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#ifdef BUILD_AS_EXTERNAL_LEXER
/*
	(actually seems to work!)
*/
#include <string>
#include "WindowAccessor.h"
#include "ExternalLexer.h"

#undef EXT_LEXER_DECL
#define EXT_LEXER_DECL __declspec( dllexport ) __stdcall

#if PLAT_WIN
#include <windows.h>
#endif

static void ColouriseCamlDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler);

static void FoldCamlDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler);

static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length,
	int initStyle, char *words[], WindowID window, char *props);

static const char* LexerName = "caml";

#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) {
	char buffer[2000];
	va_list pArguments;
	va_start(pArguments, format);
	vsprintf(buffer,format,pArguments);
	va_end(pArguments);
	Platform::DebugDisplay(buffer);
}
#else
void Platform::DebugPrintf(const char *, ...) {
}
#endif

bool Platform::IsDBCSLeadByte(int codePage, char ch) {
	return ::IsDBCSLeadByteEx(codePage, ch) != 0;
}

long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
	return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam, lParam);
}

long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
	return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam,
		reinterpret_cast<LPARAM>(lParam));
}

void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length,
	int initStyle, char *words[], WindowID window, char *props)
{
	// below useless evaluation(s) to supress "not used" warnings
	lexer;
	// build expected data structures and do the Fold
	InternalLexOrFold(1, startPos, length, initStyle, words, window, props);

}

int EXT_LEXER_DECL GetLexerCount()
{
	return 1;	// just us [Objective] Caml lexers here!
}

void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
{
	// below useless evaluation(s) to supress "not used" warnings
	Index;
	// return as much of our lexer name as will fit (what's up with Index?)
	if (buflength > 0) {
		buflength--;
		int n = strlen(LexerName);
		if (n > buflength)
			n = buflength;
		memcpy(name, LexerName, n), name[n] = '\0';
	}
}

void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length,
	int initStyle, char *words[], WindowID window, char *props)
{
	// below useless evaluation(s) to supress "not used" warnings
	lexer;
	// build expected data structures and do the Lex
	InternalLexOrFold(0, startPos, length, initStyle, words, window, props);
}

static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length,
	int initStyle, char *words[], WindowID window, char *props)
{
	// create and initialize a WindowAccessor (including contained PropSet)
	PropSetSimple ps;
	ps.SetMultiple(props);
	WindowAccessor wa(window, ps);
	// create and initialize WordList(s)
	int nWL = 0;
	for (; words[nWL]; nWL++) ;	// count # of WordList PTRs needed
	WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs
	int i = 0;
	for (; i < nWL; i++) {
		wl[i] = new WordList();	// (works or THROWS bad_alloc EXCEPTION)
		wl[i]->Set(words[i]);
	}
	wl[i] = 0;
	// call our "internal" folder/lexer (... then do Flush!)
	if (foldOrLex)
		FoldCamlDoc(startPos, length, initStyle, wl, wa);
	else
		ColouriseCamlDoc(startPos, length, initStyle, wl, wa);
	wa.Flush();
	// clean up before leaving
	for (i = nWL - 1; i >= 0; i--)
		delete wl[i];
	delete [] wl;
}

static
#endif	/* BUILD_AS_EXTERNAL_LEXER */

void ColouriseCamlDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	// initialize styler
	StyleContext sc(startPos, length, initStyle, styler);

	int chBase = 0, chToken = 0, chLit = 0;
	WordList& keywords  = *keywordlists[0];
	WordList& keywords2 = *keywordlists[1];
	WordList& keywords3 = *keywordlists[2];
	const bool isSML = keywords.InList("andalso");
	const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);

	// set up [initial] state info (terminating states that shouldn't "bleed")
	const int state_ = sc.state & 0x0f;
	if (state_ <= SCE_CAML_CHAR
		|| (isSML && state_ == SCE_CAML_STRING))
		sc.state = SCE_CAML_DEFAULT;
	int nesting = (state_ >= SCE_CAML_COMMENT)? (state_ - SCE_CAML_COMMENT): 0;

	// foreach char in range...
	while (sc.More()) {
		// set up [per-char] state info
		int state2 = -1;				// (ASSUME no state change)
		int chColor = sc.currentPos - 1;// (ASSUME standard coloring range)
		bool advance = true;			// (ASSUME scanner "eats" 1 char)

		// step state machine
		switch (sc.state & 0x0f) {
		case SCE_CAML_DEFAULT:
			chToken = sc.currentPos;	// save [possible] token start (JIC)
			// it's wide open; what do we have?
			if (iscamlf(sc.ch))
				state2 = SCE_CAML_IDENTIFIER;
			else if (!isSML && sc.Match('`') && iscamlf(sc.chNext))
				state2 = SCE_CAML_TAGNAME;
			else if (!isSML && sc.Match('#') && isdigit(sc.chNext))
				state2 = SCE_CAML_LINENUM;
			else if (isdigit(sc.ch)) {
				// it's a number, assume base 10
				state2 = SCE_CAML_NUMBER, chBase = 10;
				if (sc.Match('0')) {
					// there MAY be a base specified...
					const char* baseC = "bBoOxX";
					if (isSML) {
						if (sc.chNext == 'w')
							sc.Forward();	// (consume SML "word" indicator)
						baseC = "x";
					}
					// ... change to specified base AS REQUIRED
					if (strchr(baseC, sc.chNext))
						chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward();
				}
			} else if (!isSML && sc.Match('\''))	// (Caml char literal?)
				state2 = SCE_CAML_CHAR, chLit = 0;
			else if (isSML && sc.Match('#', '"'))	// (SML char literal?)
				state2 = SCE_CAML_CHAR, sc.Forward();
			else if (sc.Match('"'))
				state2 = SCE_CAML_STRING;
			else if (sc.Match('(', '*'))
				state2 = SCE_CAML_COMMENT, sc.Forward(), sc.ch = ' '; // (*)...
			else if (strchr("!?~"			/* Caml "prefix-symbol" */
					"=<>@^|&+-*/$%"			/* Caml "infix-symbol" */
					"()[]{};,:.#", sc.ch)	// Caml "bracket" or ;,:.#
											// SML "extra" ident chars
				|| (isSML && (sc.Match('\\') || sc.Match('`'))))
				state2 = SCE_CAML_OPERATOR;
			break;

		case SCE_CAML_IDENTIFIER:
			// [try to] interpret as [additional] identifier char
			if (!(iscaml(sc.ch) || sc.Match('\''))) {
				const int n = sc.currentPos - chToken;
				if (n < 24) {
					// length is believable as keyword, [re-]construct token
					char t[24];
					for (int i = -n; i < 0; i++)
						t[n + i] = static_cast<char>(sc.GetRelative(i));
					t[n] = '\0';
					// special-case "_" token as KEYWORD
					if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
						sc.ChangeState(SCE_CAML_KEYWORD);
					else if (keywords2.InList(t))
						sc.ChangeState(SCE_CAML_KEYWORD2);
					else if (keywords3.InList(t))
						sc.ChangeState(SCE_CAML_KEYWORD3);
				}
				state2 = SCE_CAML_DEFAULT, advance = false;
			}
			break;

		case SCE_CAML_TAGNAME:
			// [try to] interpret as [additional] tagname char
			if (!(iscaml(sc.ch) || sc.Match('\'')))
				state2 = SCE_CAML_DEFAULT, advance = false;
			break;

		/*case SCE_CAML_KEYWORD:
		case SCE_CAML_KEYWORD2:
		case SCE_CAML_KEYWORD3:
			// [try to] interpret as [additional] keyword char
			if (!iscaml(ch))
				state2 = SCE_CAML_DEFAULT, advance = false;
			break;*/

		case SCE_CAML_LINENUM:
			// [try to] interpret as [additional] linenum directive char
			if (!isdigit(sc.ch))
				state2 = SCE_CAML_DEFAULT, advance = false;
			break;

		case SCE_CAML_OPERATOR: {
			// [try to] interpret as [additional] operator char
			const char* o = 0;
			if (iscaml(sc.ch) || isspace(sc.ch)			// ident or whitespace
				|| (o = strchr(")]};,\'\"#", sc.ch),o)	// "termination" chars
				|| (!isSML && sc.Match('`'))			// Caml extra term char
				|| (!strchr("!$%&*+-./:<=>?@^|~", sc.ch)// "operator" chars
														// SML extra ident chars
					&& !(isSML && (sc.Match('\\') || sc.Match('`'))))) {
				// check for INCLUSIVE termination
				if (o && strchr(")]};,", sc.ch)) {
					if ((sc.Match(')') && sc.chPrev == '(')
						|| (sc.Match(']') && sc.chPrev == '['))
						// special-case "()" and "[]" tokens as KEYWORDS
						sc.ChangeState(SCE_CAML_KEYWORD);
					chColor++;
				} else
					advance = false;
				state2 = SCE_CAML_DEFAULT;
			}
			break;
		}

		case SCE_CAML_NUMBER:
			// [try to] interpret as [additional] numeric literal char
			if ((!isSML && sc.Match('_')) || IsADigit(sc.ch, chBase))
				break;
			// how about an integer suffix?
			if (!isSML && (sc.Match('l') || sc.Match('L') || sc.Match('n'))
				&& (sc.chPrev == '_' || IsADigit(sc.chPrev, chBase)))
				break;
			// or a floating-point literal?
			if (chBase == 10) {
				// with a decimal point?
				if (sc.Match('.')
					&& ((!isSML && sc.chPrev == '_')
						|| IsADigit(sc.chPrev, chBase)))
					break;
				// with an exponent? (I)
				if ((sc.Match('e') || sc.Match('E'))
					&& ((!isSML && (sc.chPrev == '.' || sc.chPrev == '_'))
						|| IsADigit(sc.chPrev, chBase)))
					break;
				// with an exponent? (II)
				if (((!isSML && (sc.Match('+') || sc.Match('-')))
						|| (isSML && sc.Match('~')))
					&& (sc.chPrev == 'e' || sc.chPrev == 'E'))
					break;
			}
			// it looks like we have run out of number
			state2 = SCE_CAML_DEFAULT, advance = false;
			break;

		case SCE_CAML_CHAR:
			if (!isSML) {
				// [try to] interpret as [additional] char literal char
				if (sc.Match('\\')) {
					chLit = 1;	// (definitely IS a char literal)
					if (sc.chPrev == '\\')
						sc.ch = ' ';	// (...\\')
				// should we be terminating - one way or another?
				} else if ((sc.Match('\'') && sc.chPrev != '\\')
					|| sc.atLineEnd) {
					state2 = SCE_CAML_DEFAULT;
					if (sc.Match('\''))
						chColor++;
					else
						sc.ChangeState(SCE_CAML_IDENTIFIER);
				// ... maybe a char literal, maybe not
				} else if (chLit < 1 && sc.currentPos - chToken >= 2)
					sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false;
				break;
			}/* else
				// fall through for SML char literal (handle like string) */

		case SCE_CAML_STRING:
			// [try to] interpret as [additional] [SML char/] string literal char
			if (isSML && sc.Match('\\') && sc.chPrev != '\\' && isspace(sc.chNext))
				state2 = SCE_CAML_WHITE;
			else if (sc.Match('\\') && sc.chPrev == '\\')
				sc.ch = ' ';	// (...\\")
			// should we be terminating - one way or another?
			else if ((sc.Match('"') && sc.chPrev != '\\')
				|| (isSML && sc.atLineEnd)) {
				state2 = SCE_CAML_DEFAULT;
				if (sc.Match('"'))
					chColor++;
			}
			break;

		case SCE_CAML_WHITE:
			// [try to] interpret as [additional] SML embedded whitespace char
			if (sc.Match('\\')) {
				// style this puppy NOW...
				state2 = SCE_CAML_STRING, sc.ch = ' ' /* (...\") */, chColor++,
					styler.ColourTo(chColor, SCE_CAML_WHITE), styler.Flush();
				// ... then backtrack to determine original SML literal type
				int p = chColor - 2;
				for (; p >= 0 && styler.StyleAt(p) == SCE_CAML_WHITE; p--) ;
				if (p >= 0)
					state2 = static_cast<int>(styler.StyleAt(p));
				// take care of state change NOW
				sc.ChangeState(state2), state2 = -1;
			}
			break;

		case SCE_CAML_COMMENT:
		case SCE_CAML_COMMENT1:
		case SCE_CAML_COMMENT2:
		case SCE_CAML_COMMENT3:
			// we're IN a comment - does this start a NESTED comment?
			if (sc.Match('(', '*'))
				state2 = sc.state + 1, chToken = sc.currentPos,
					sc.Forward(), sc.ch = ' ' /* (*)... */, nesting++;
			// [try to] interpret as [additional] comment char
			else if (sc.Match(')') && sc.chPrev == '*') {
				if (nesting)
					state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
				else
					state2 = SCE_CAML_DEFAULT;
				chColor++;
			// enable "magic" (read-only) comment AS REQUIRED
			} else if (useMagic && sc.currentPos - chToken == 4
				&& sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
				sc.state |= 0x10;	// (switch to read-only comment style)
			break;
		}

		// handle state change and char coloring AS REQUIRED
		if (state2 >= 0)
			styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
		// move to next char UNLESS re-scanning current char
		if (advance)
			sc.Forward();
	}

	// do any required terminal char coloring (JIC)
	sc.Complete();
}

#ifdef BUILD_AS_EXTERNAL_LEXER
static
#endif	/* BUILD_AS_EXTERNAL_LEXER */
void FoldCamlDoc(
	unsigned int, int,
	int,
	WordList *[],
	Accessor &)
{
}

static const char * const camlWordListDesc[] = {
	"Keywords",		// primary Objective Caml keywords
	"Keywords2",	// "optional" keywords (typically from Pervasives)
	"Keywords3",	// "optional" keywords (typically typenames)
	0
};

#ifndef BUILD_AS_EXTERNAL_LEXER
LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc);
#endif	/* BUILD_AS_EXTERNAL_LEXER */

Added lexers/LexCmake.cxx.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
// Scintilla source code edit control
/** @file LexCmake.cxx
 ** Lexer for Cmake
 **/
// Copyright 2007 by Cristian Adam <cristian [dot] adam [at] gmx [dot] net>
// based on the NSIS lexer
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool isCmakeNumber(char ch)
{
    return(ch >= '0' && ch <= '9');
}

static bool isCmakeChar(char ch)
{
    return(ch == '.' ) || (ch == '_' ) || isCmakeNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}

static bool isCmakeLetter(char ch)
{
    return(ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}

static bool CmakeNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
{
    int nNextLine = -1;
    for ( unsigned int i = start; i < end; i++ ) {
        char cNext = styler.SafeGetCharAt( i );
        if ( cNext == '\n' ) {
            nNextLine = i+1;
            break;
        }
    }

    if ( nNextLine == -1 ) // We never foudn the next line...
        return false;

    for ( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ ) {
        char cNext = styler.SafeGetCharAt( firstChar );
        if ( cNext == ' ' )
            continue;
        if ( cNext == '\t' )
            continue;
        if ( styler.Match(firstChar, "ELSE")  || styler.Match(firstChar, "else"))
            return true;
        break;
    }

    return false;
}

static int calculateFoldCmake(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse)
{
    // If the word is too long, it is not what we are looking for
    if ( end - start > 20 )
        return foldlevel;

    int newFoldlevel = foldlevel;

    char s[20]; // The key word we are looking for has atmost 13 characters
    for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) {
        s[i] = static_cast<char>( styler[ start + i ] );
        s[i + 1] = '\0';
    }

    if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0
         || CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0
         || CompareCaseInsensitive(s, "ELSEIF") == 0 )
        newFoldlevel++;
    else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0
              || CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0)
        newFoldlevel--;
    else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 )
        newFoldlevel++;
    else if ( bElse && CompareCaseInsensitive(s, "ELSE") == 0 )
        newFoldlevel++;

    return newFoldlevel;
}

static int classifyWordCmake(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
{
    char word[100] = {0};
    char lowercaseWord[100] = {0};

    WordList &Commands = *keywordLists[0];
    WordList &Parameters = *keywordLists[1];
    WordList &UserDefined = *keywordLists[2];

    for (unsigned int i = 0; i < end - start + 1 && i < 99; i++) {
        word[i] = static_cast<char>( styler[ start + i ] );
        lowercaseWord[i] = static_cast<char>(tolower(word[i]));
    }

    // Check for special words...
    if ( CompareCaseInsensitive(word, "MACRO") == 0 || CompareCaseInsensitive(word, "ENDMACRO") == 0 )
        return SCE_CMAKE_MACRODEF;

    if ( CompareCaseInsensitive(word, "IF") == 0 ||  CompareCaseInsensitive(word, "ENDIF") == 0 )
        return SCE_CMAKE_IFDEFINEDEF;

    if ( CompareCaseInsensitive(word, "ELSEIF") == 0  || CompareCaseInsensitive(word, "ELSE") == 0 )
        return SCE_CMAKE_IFDEFINEDEF;

    if ( CompareCaseInsensitive(word, "WHILE") == 0 || CompareCaseInsensitive(word, "ENDWHILE") == 0)
        return SCE_CMAKE_WHILEDEF;

    if ( CompareCaseInsensitive(word, "FOREACH") == 0 || CompareCaseInsensitive(word, "ENDFOREACH") == 0)
        return SCE_CMAKE_FOREACHDEF;

    if ( Commands.InList(lowercaseWord) )
        return SCE_CMAKE_COMMANDS;

    if ( Parameters.InList(word) )
        return SCE_CMAKE_PARAMETERS;


    if ( UserDefined.InList(word) )
        return SCE_CMAKE_USERDEFINED;

    if ( strlen(word) > 3 ) {
        if ( word[1] == '{' && word[strlen(word)-1] == '}' )
            return SCE_CMAKE_VARIABLE;
    }

    // To check for numbers
    if ( isCmakeNumber( word[0] ) ) {
        bool bHasSimpleCmakeNumber = true;
        for (unsigned int j = 1; j < end - start + 1 && j < 99; j++) {
            if ( !isCmakeNumber( word[j] ) ) {
                bHasSimpleCmakeNumber = false;
                break;
            }
        }

        if ( bHasSimpleCmakeNumber )
            return SCE_CMAKE_NUMBER;
    }

    return SCE_CMAKE_DEFAULT;
}

static void ColouriseCmakeDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
{
    int state = SCE_CMAKE_DEFAULT;
    if ( startPos > 0 )
        state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox

    styler.StartAt( startPos );
    styler.GetLine( startPos );

    unsigned int nLengthDoc = startPos + length;
    styler.StartSegment( startPos );

    char cCurrChar;
    bool bVarInString = false;
    bool bClassicVarInString = false;

    unsigned int i;
    for ( i = startPos; i < nLengthDoc; i++ ) {
        cCurrChar = styler.SafeGetCharAt( i );
        char cNextChar = styler.SafeGetCharAt(i+1);

        switch (state) {
        case SCE_CMAKE_DEFAULT:
            if ( cCurrChar == '#' ) { // we have a comment line
                styler.ColourTo(i-1, state );
                state = SCE_CMAKE_COMMENT;
                break;
            }
            if ( cCurrChar == '"' ) {
                styler.ColourTo(i-1, state );
                state = SCE_CMAKE_STRINGDQ;
                bVarInString = false;
                bClassicVarInString = false;
                break;
            }
            if ( cCurrChar == '\'' ) {
                styler.ColourTo(i-1, state );
                state = SCE_CMAKE_STRINGRQ;
                bVarInString = false;
                bClassicVarInString = false;
                break;
            }
            if ( cCurrChar == '`' ) {
                styler.ColourTo(i-1, state );
                state = SCE_CMAKE_STRINGLQ;
                bVarInString = false;
                bClassicVarInString = false;
                break;
            }

            // CMake Variable
            if ( cCurrChar == '$' || isCmakeChar(cCurrChar)) {
                styler.ColourTo(i-1,state);
                state = SCE_CMAKE_VARIABLE;

                // If it is a number, we must check and set style here first...
                if ( isCmakeNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
                    styler.ColourTo( i, SCE_CMAKE_NUMBER);

                break;
            }

            break;
        case SCE_CMAKE_COMMENT:
            if ( cNextChar == '\n' || cNextChar == '\r' ) {
                // Special case:
                if ( cCurrChar == '\\' ) {
                    styler.ColourTo(i-2,state);
                    styler.ColourTo(i,SCE_CMAKE_DEFAULT);
                }
                else {
                    styler.ColourTo(i,state);
                    state = SCE_CMAKE_DEFAULT;
                }
            }
            break;
        case SCE_CMAKE_STRINGDQ:
        case SCE_CMAKE_STRINGLQ:
        case SCE_CMAKE_STRINGRQ:

            if ( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
                break; // Ignore the next character, even if it is a quote of some sort

            if ( cCurrChar == '"' && state == SCE_CMAKE_STRINGDQ ) {
                styler.ColourTo(i,state);
                state = SCE_CMAKE_DEFAULT;
                break;
            }

            if ( cCurrChar == '`' && state == SCE_CMAKE_STRINGLQ ) {
                styler.ColourTo(i,state);
                state = SCE_CMAKE_DEFAULT;
                break;
            }

            if ( cCurrChar == '\'' && state == SCE_CMAKE_STRINGRQ ) {
                styler.ColourTo(i,state);
                state = SCE_CMAKE_DEFAULT;
                break;
            }

            if ( cNextChar == '\r' || cNextChar == '\n' ) {
                int nCurLine = styler.GetLine(i+1);
                int nBack = i;
                // We need to check if the previous line has a \ in it...
                bool bNextLine = false;

                while ( nBack > 0 ) {
                    if ( styler.GetLine(nBack) != nCurLine )
                        break;

                    char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here

                    if ( cTemp == '\\' ) {
                        bNextLine = true;
                        break;
                    }
                    if ( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
                        break;

                    nBack--;
                }

                if ( bNextLine ) {
                    styler.ColourTo(i+1,state);
                }
                if ( bNextLine == false ) {
                    styler.ColourTo(i,state);
                    state = SCE_CMAKE_DEFAULT;
                }
            }
            break;

        case SCE_CMAKE_VARIABLE:

            // CMake Variable:
            if ( cCurrChar == '$' )
                state = SCE_CMAKE_DEFAULT;
            else if ( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
                state = SCE_CMAKE_DEFAULT;
            else if ( (isCmakeChar(cCurrChar) && !isCmakeChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' ) {
                state = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler );
                styler.ColourTo( i, state);
                state = SCE_CMAKE_DEFAULT;
            }
            else if ( !isCmakeChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' ) {
                if ( classifyWordCmake( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_CMAKE_NUMBER )
                    styler.ColourTo( i-1, SCE_CMAKE_NUMBER );

                state = SCE_CMAKE_DEFAULT;

                if ( cCurrChar == '"' ) {
                    state = SCE_CMAKE_STRINGDQ;
                    bVarInString = false;
                    bClassicVarInString = false;
                }
                else if ( cCurrChar == '`' ) {
                    state = SCE_CMAKE_STRINGLQ;
                    bVarInString = false;
                    bClassicVarInString = false;
                }
                else if ( cCurrChar == '\'' ) {
                    state = SCE_CMAKE_STRINGRQ;
                    bVarInString = false;
                    bClassicVarInString = false;
                }
                else if ( cCurrChar == '#' ) {
                    state = SCE_CMAKE_COMMENT;
                }
            }
            break;
        }

        if ( state == SCE_CMAKE_COMMENT) {
            styler.ColourTo(i,state);
        }
        else if ( state == SCE_CMAKE_STRINGDQ || state == SCE_CMAKE_STRINGLQ || state == SCE_CMAKE_STRINGRQ ) {
            bool bIngoreNextDollarSign = false;

            if ( bVarInString && cCurrChar == '$' ) {
                bVarInString = false;
                bIngoreNextDollarSign = true;
            }
            else if ( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) ) {
                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
                bVarInString = false;
                bIngoreNextDollarSign = false;
            }

            else if ( bVarInString && !isCmakeChar(cNextChar) ) {
                int nWordState = classifyWordCmake( styler.GetStartSegment(), i, keywordLists, styler);
                if ( nWordState == SCE_CMAKE_VARIABLE )
                    styler.ColourTo( i, SCE_CMAKE_STRINGVAR);
                bVarInString = false;
            }
            // Covers "${TEST}..."
            else if ( bClassicVarInString && cNextChar == '}' ) {
                styler.ColourTo( i+1, SCE_CMAKE_STRINGVAR);
                bClassicVarInString = false;
            }

            // Start of var in string
            if ( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' ) {
                styler.ColourTo( i-1, state);
                bClassicVarInString = true;
                bVarInString = false;
            }
            else if ( !bIngoreNextDollarSign && cCurrChar == '$' ) {
                styler.ColourTo( i-1, state);
                bVarInString = true;
                bClassicVarInString = false;
            }
        }
    }

    // Colourise remaining document
    styler.ColourTo(nLengthDoc-1,state);
}

static void FoldCmakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
    // No folding enabled, no reason to continue...
    if ( styler.GetPropertyInt("fold") == 0 )
        return;

    bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;

    int lineCurrent = styler.GetLine(startPos);
    unsigned int safeStartPos = styler.LineStart( lineCurrent );

    bool bArg1 = true;
    int nWordStart = -1;

    int levelCurrent = SC_FOLDLEVELBASE;
    if (lineCurrent > 0)
        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
    int levelNext = levelCurrent;

    for (unsigned int i = safeStartPos; i < startPos + length; i++) {
        char chCurr = styler.SafeGetCharAt(i);

        if ( bArg1 ) {
            if ( nWordStart == -1 && (isCmakeLetter(chCurr)) ) {
                nWordStart = i;
            }
            else if ( isCmakeLetter(chCurr) == false && nWordStart > -1 ) {
                int newLevel = calculateFoldCmake( nWordStart, i-1, levelNext, styler, foldAtElse);

                if ( newLevel == levelNext ) {
                    if ( foldAtElse ) {
                        if ( CmakeNextLineHasElse(i, startPos + length, styler) )
                            levelNext--;
                    }
                }
                else
                    levelNext = newLevel;
                bArg1 = false;
            }
        }

        if ( chCurr == '\n' ) {
            if ( bArg1 && foldAtElse) {
                if ( CmakeNextLineHasElse(i, startPos + length, styler) )
                    levelNext--;
            }

            // If we are on a new line...
            int levelUse = levelCurrent;
            int lev = levelUse | levelNext << 16;
            if (levelUse < levelNext )
                lev |= SC_FOLDLEVELHEADERFLAG;
            if (lev != styler.LevelAt(lineCurrent))
                styler.SetLevel(lineCurrent, lev);

            lineCurrent++;
            levelCurrent = levelNext;
            bArg1 = true; // New line, lets look at first argument again
            nWordStart = -1;
        }
    }

    int levelUse = levelCurrent;
    int lev = levelUse | levelNext << 16;
    if (levelUse < levelNext)
        lev |= SC_FOLDLEVELHEADERFLAG;
    if (lev != styler.LevelAt(lineCurrent))
        styler.SetLevel(lineCurrent, lev);
}

static const char * const cmakeWordLists[] = {
    "Commands",
    "Parameters",
    "UserDefined",
    0,
    0,};

LexerModule lmCmake(SCLEX_CMAKE, ColouriseCmakeDoc, "cmake", FoldCmakeDoc, cmakeWordLists);

Added lexers/LexCoffeeScript.cxx.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
// Scintilla source code edit control
/** @file LexCoffeeScript.cxx
 ** Lexer for CoffeeScript.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// Based on the Scintilla C++ Lexer
// Written by Eric Promislow <ericp@activestate.com> in 2011 for the Komodo IDE
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "Platform.h"
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool IsSpaceEquiv(int state) {
	return (state <= SCE_C_COMMENTDOC
	    // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE
	    || state == SCE_C_COMMENTLINEDOC
	    || state == SCE_C_COMMENTDOCKEYWORD
	    || state == SCE_C_COMMENTDOCKEYWORDERROR
	    || state == SCE_COFFEESCRIPT_COMMENTBLOCK
	    || state == SCE_COFFEESCRIPT_VERBOSE_REGEX
	    || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT
	    || state == SCE_C_WORD
	    || state == SCE_C_REGEX);
}

// Preconditions: sc.currentPos points to a character after '+' or '-'.
// The test for pos reaching 0 should be redundant,
// and is in only for safety measures.
// Limitation: this code will give the incorrect answer for code like
// a = b+++/ptn/...
// Putting a space between the '++' post-inc operator and the '+' binary op
// fixes this, and is highly recommended for readability anyway.
static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) {
	int pos = (int) sc.currentPos;
	while (--pos > 0) {
		char ch = styler[pos];
		if (ch == '+' || ch == '-') {
			return styler[pos - 1] == ch;
		}
	}
	return false;
}

static bool followsReturnKeyword(StyleContext &sc, Accessor &styler) {
    // Don't look at styles, so no need to flush.
	int pos = (int) sc.currentPos;
	int currentLine = styler.GetLine(pos);
	int lineStartPos = styler.LineStart(currentLine);
	char ch;
	while (--pos > lineStartPos) {
		ch = styler.SafeGetCharAt(pos);
		if (ch != ' ' && ch != '\t') {
			break;
		}
	}
	const char *retBack = "nruter";
	const char *s = retBack;
	while (*s
	       && pos >= lineStartPos
	       && styler.SafeGetCharAt(pos) == *s) {
		s++;
		pos--;
	}
	return !*s;
}

static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// property styling.within.preprocessor
	//	For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default)
	//	or only from the initial # to the end of the command word(1).
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
	CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");

	CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");

	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);

	// property lexer.cpp.allow.dollars
	//	Set to 0 to disallow the '$' character in identifiers with the cpp lexer.
	if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) {
		setWordStart.Add('$');
		setWord.Add('$');
	}

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;
	int styleBeforeDCKeyword = SCE_C_DEFAULT;
	bool continuationLine = false;
	bool isIncludePreprocessor = false;

	if (initStyle == SCE_C_PREPROCESSOR) {
		// Set continuationLine if last character of previous line is '\'
		int lineCurrent = styler.GetLine(startPos);
		if (lineCurrent > 0) {
			int chBack = styler.SafeGetCharAt(startPos-1, 0);
			int chBack2 = styler.SafeGetCharAt(startPos-2, 0);
			int lineEndChar = '!';
			if (chBack2 == '\r' && chBack == '\n') {
				lineEndChar = styler.SafeGetCharAt(startPos-3, 0);
			} else if (chBack == '\n' || chBack == '\r') {
				lineEndChar = chBack2;
			}
			continuationLine = lineEndChar == '\\';
		}
	}

	// look back to set chPrevNonWhite properly for better regex colouring
	int endPos = startPos + length;
	if (startPos > 0) {
		unsigned int back = startPos;
		styler.Flush();
		while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back)))
			;
		if (styler.StyleAt(back) == SCE_C_OPERATOR) {
			chPrevNonWhite = styler.SafeGetCharAt(back);
		}
		if (startPos != back) {
			initStyle = styler.StyleAt(back);
		}
		startPos = back;
	}

	StyleContext sc(startPos, endPos - startPos, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
			lastWordWasUUID = false;
			isIncludePreprocessor = false;
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continuationLine = true;
				continue;
			}
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_C_OPERATOR:
				sc.SetState(SCE_C_DEFAULT);
				break;
			case SCE_C_NUMBER:
				// We accept almost anything because of hex. and number suffixes
				if (!setWord.Contains(sc.ch)) {
					sc.SetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_IDENTIFIER:
				if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) {
					char s[1000];
					sc.GetCurrent(s, sizeof(s));
					if (keywords.InList(s)) {
						lastWordWasUUID = strcmp(s, "uuid") == 0;
						sc.ChangeState(SCE_C_WORD);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_C_WORD2);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_C_GLOBALCLASS);
					}
					sc.SetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_PREPROCESSOR:
				if (sc.atLineStart && !continuationLine) {
					sc.SetState(SCE_C_DEFAULT);
				} else if (stylingWithinPreprocessor) {
					if (IsASpace(sc.ch)) {
						sc.SetState(SCE_C_DEFAULT);
					}
				} else {
					if (sc.Match('/', '*') || sc.Match('/', '/')) {
						sc.SetState(SCE_C_DEFAULT);
					}
				}
				break;
			case SCE_C_COMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_COMMENTDOC:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_C_COMMENTDOC;
						sc.SetState(SCE_C_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_C_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_COMMENTLINEDOC:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC;
						sc.SetState(SCE_C_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_C_COMMENTDOCKEYWORD:
				if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT);
				} else if (!setDoxygen.Contains(sc.ch)) {
					char s[100];
					sc.GetCurrent(s, sizeof(s));
					if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
						sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
					}
					sc.SetState(styleBeforeDCKeyword);
				}
				break;
			case SCE_C_STRING:
				if (isIncludePreprocessor) {
					if (sc.ch == '>') {
						sc.ForwardSetState(SCE_C_DEFAULT);
						isIncludePreprocessor = false;
					}
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_CHARACTER:
				if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_REGEX:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT);
				} else if (sc.ch == '/') {
					sc.Forward();
					while ((sc.ch < 0x80) && islower(sc.ch))
						sc.Forward();    // gobble regex flags
					sc.SetState(SCE_C_DEFAULT);
				} else if (sc.ch == '\\') {
					// Gobble up the quoted character
					if (sc.chNext == '\\' || sc.chNext == '/') {
						sc.Forward();
					}
				}
				break;
			case SCE_C_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_C_VERBATIM:
				if (sc.ch == '\"') {
					if (sc.chNext == '\"') {
						sc.Forward();
					} else {
						sc.ForwardSetState(SCE_C_DEFAULT);
					}
				}
				break;
			case SCE_C_UUID:
				if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
					sc.SetState(SCE_C_DEFAULT);
				}
				break;
			case SCE_COFFEESCRIPT_COMMENTBLOCK:
				if (sc.Match("###")) {
					sc.ChangeState(SCE_C_COMMENT);
					sc.Forward();
					sc.Forward();
					sc.ForwardSetState(SCE_C_DEFAULT);
				} else if (sc.ch == '\\') {
					sc.Forward();
				}
				break;
			case SCE_COFFEESCRIPT_VERBOSE_REGEX:
				if (sc.Match("///")) {
					sc.Forward();
					sc.Forward();
					sc.ChangeState(SCE_C_REGEX);
					sc.ForwardSetState(SCE_C_DEFAULT);
				} else if (sc.Match('#')) {
					sc.ChangeState(SCE_C_REGEX);
					sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT);
				} else if (sc.ch == '\\') {
					sc.Forward();
				}
				break;
			case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT:
				if (sc.atLineStart) {
					sc.ChangeState(SCE_C_COMMENT);
					sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX);
				}
				break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER);
				}
			} else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTDOC);
				} else {
					sc.SetState(SCE_C_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match("///")) {
				sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX);
			} else if (sc.ch == '/'
				   && (setOKBeforeRE.Contains(chPrevNonWhite)
				       || followsReturnKeyword(sc, styler))
				   && (!setCouldBePostOp.Contains(chPrevNonWhite)
				       || !FollowsPostfixOperator(sc, styler))) {
				sc.SetState(SCE_C_REGEX);	// JavaScript's RegEx
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_C_STRING);
				isIncludePreprocessor = false;	// ensure that '>' won't end the string
			} else if (isIncludePreprocessor && sc.ch == '<') {
				sc.SetState(SCE_C_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER);
			} else if (sc.ch == '#') {
                if (sc.Match("###")) {
                    sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK);
                } else {
                    sc.SetState(SCE_C_COMMENTLINE);
                }
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_C_OPERATOR);
			}
		}

		if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
		continuationLine = false;
	}
    // Change temporary coffeescript states into standard C ones.
    switch (sc.state) {
        case SCE_COFFEESCRIPT_COMMENTBLOCK:
            sc.ChangeState(SCE_C_COMMENT);
            break;
        case SCE_COFFEESCRIPT_VERBOSE_REGEX:
            sc.ChangeState(SCE_C_REGEX);
            break;
        case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT:
            sc.ChangeState(SCE_C_COMMENTLINE);
            break;
    }
	sc.Complete();
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		if (ch == '#')
			return true;
        else if (ch == '/'
                 && i < eol_pos - 1
                 && styler[i + 1] == '*')
			return true;
		else if (ch != ' ' && ch != '\t')
			return false;
	}
	return false;
}

static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int,
				WordList *[], Accessor &styler) {
	// A simplified version of FoldPyDoc
	const int maxPos = startPos + length;
	const int maxLines = styler.GetLine(maxPos - 1);             // Requested last line
	const int docLines = styler.GetLine(styler.Length() - 1);  // Available last line

	// property fold.coffeescript.comment
	const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0;

	const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;

	// Backtrack to previous non-blank line so we can determine indent level
	// for any white space lines
	// and so we can fix any preceding fold level (which is why we go back
	// at least one line in all cases)
	int spaceFlags = 0;
	int lineCurrent = styler.GetLine(startPos);
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
	while (lineCurrent > 0) {
		lineCurrent--;
		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)
		    && !IsCommentLine(lineCurrent, styler))
			break;
	}
	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;

	// Set up initial loop state
	int prevComment = 0;
	if (lineCurrent >= 1)
		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);

	// Process all characters to end of requested range
	// or comment that hangs over the end of the range.  Cap processing in all cases
	// to end of document (in case of comment at end).
	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) {

		// Gather info
		int lev = indentCurrent;
		int lineNext = lineCurrent + 1;
		int indentNext = indentCurrent;
		if (lineNext <= docLines) {
			// Information about next line is only available if not at end of document
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
		}
		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
		                           IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
		const int comment_continue = (comment && prevComment);
		if (!comment)
			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
		if (indentNext & SC_FOLDLEVELWHITEFLAG)
			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;

		if (comment_start) {
			// Place fold point at start of a block of comments
			lev |= SC_FOLDLEVELHEADERFLAG;
		} else if (comment_continue) {
			// Add level to rest of lines in the block
			lev = lev + 1;
		}

		// Skip past any blank lines for next indent level info; we skip also
		// comments (all comments, not just those starting in column 0)
		// which effectively folds them into surrounding code rather
		// than screwing up folding.

		while ((lineNext < docLines) &&
		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {

			lineNext++;
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
		}

		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
		const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);

		// Now set all the indent levels on the lines we skipped
		// Do this from end to start.  Once we encounter one line
		// which is indented more than the line after the end of
		// the comment-block, use the level of the block before

		int skipLine = lineNext;
		int skipLevel = levelAfterComments;

		while (--skipLine > lineCurrent) {
			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);

			if (foldCompact) {
				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
					skipLevel = levelBeforeComments;

				int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;

				styler.SetLevel(skipLine, skipLevel | whiteFlag);
			} else {
				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments &&
					!(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
					!IsCommentLine(skipLine, styler))
					skipLevel = levelBeforeComments;

				styler.SetLevel(skipLine, skipLevel);
			}
		}

		// Set fold header on non-comment line
		if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
				lev |= SC_FOLDLEVELHEADERFLAG;
		}

		// Keep track of block comment state of previous line
		prevComment = comment_start || comment_continue;

		// Set fold level for this line and move to next line
		styler.SetLevel(lineCurrent, lev);
		indentCurrent = indentNext;
		lineCurrent = lineNext;
	}
}

static const char *const csWordLists[] = {
            "Keywords",
            0,
};

LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists);

Added lexers/LexConf.cxx.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexConf.cxx
 ** Lexer for Apache Configuration Files.
 **
 ** First working version contributed by Ahmad Zawawi <ahmad.zawawi@gmail.com> on October 28, 2000.
 ** i created this lexer because i needed something pretty when dealing
 ** when Apache Configuration files...
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
{
	int state = SCE_CONF_DEFAULT;
	char chNext = styler[startPos];
	int lengthDoc = startPos + length;
	// create a buffer large enough to take the largest chunk...
	char *buffer = new char[length];
	int bufferCount = 0;

	// this assumes that we have 2 keyword list in conf.properties
	WordList &directives = *keywordLists[0];
	WordList &params = *keywordLists[1];

	// go through all provided text segment
	// using the hand-written state machine shown below
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	for (int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i++;
			continue;
		}
		switch(state) {
			case SCE_CONF_DEFAULT:
				if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
					// whitespace is simply ignored here...
					styler.ColourTo(i,SCE_CONF_DEFAULT);
					break;
				} else if( ch == '#' ) {
					// signals the start of a comment...
					state = SCE_CONF_COMMENT;
					styler.ColourTo(i,SCE_CONF_COMMENT);
				} else if( ch == '.' /*|| ch == '/'*/) {
					// signals the start of a file...
					state = SCE_CONF_EXTENSION;
					styler.ColourTo(i,SCE_CONF_EXTENSION);
				} else if( ch == '"') {
					state = SCE_CONF_STRING;
					styler.ColourTo(i,SCE_CONF_STRING);
				} else if( isascii(ch) && ispunct(ch) ) {
					// signals an operator...
					// no state jump necessary for this
					// simple case...
					styler.ColourTo(i,SCE_CONF_OPERATOR);
				} else if( isascii(ch) && isalpha(ch) ) {
					// signals the start of an identifier
					bufferCount = 0;
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
					state = SCE_CONF_IDENTIFIER;
				} else if( isascii(ch) && isdigit(ch) ) {
					// signals the start of a number
					bufferCount = 0;
					buffer[bufferCount++] = ch;
					//styler.ColourTo(i,SCE_CONF_NUMBER);
					state = SCE_CONF_NUMBER;
				} else {
					// style it the default style..
					styler.ColourTo(i,SCE_CONF_DEFAULT);
				}
				break;

			case SCE_CONF_COMMENT:
				// if we find a newline here,
				// we simply go to default state
				// else continue to work on it...
				if( ch == '\n' || ch == '\r' ) {
					state = SCE_CONF_DEFAULT;
				} else {
					styler.ColourTo(i,SCE_CONF_COMMENT);
				}
				break;

			case SCE_CONF_EXTENSION:
				// if we find a non-alphanumeric char,
				// we simply go to default state
				// else we're still dealing with an extension...
				if( (isascii(ch) && isalnum(ch)) || (ch == '_') ||
					(ch == '-') || (ch == '$') ||
					(ch == '/') || (ch == '.') || (ch == '*') )
				{
					styler.ColourTo(i,SCE_CONF_EXTENSION);
				} else {
					state = SCE_CONF_DEFAULT;
					chNext = styler[i--];
				}
				break;

			case SCE_CONF_STRING:
				// if we find the end of a string char, we simply go to default state
				// else we're still dealing with an string...
				if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) {
					state = SCE_CONF_DEFAULT;
				}
				styler.ColourTo(i,SCE_CONF_STRING);
				break;

			case SCE_CONF_IDENTIFIER:
				// stay  in CONF_IDENTIFIER state until we find a non-alphanumeric
				if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) {
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
				} else {
					state = SCE_CONF_DEFAULT;
					buffer[bufferCount] = '\0';

					// check if the buffer contains a keyword, and highlight it if it is a keyword...
					if(directives.InList(buffer)) {
						styler.ColourTo(i-1,SCE_CONF_DIRECTIVE );
					} else if(params.InList(buffer)) {
						styler.ColourTo(i-1,SCE_CONF_PARAMETER );
					} else if(strchr(buffer,'/') || strchr(buffer,'.')) {
						styler.ColourTo(i-1,SCE_CONF_EXTENSION);
					} else {
						styler.ColourTo(i-1,SCE_CONF_DEFAULT);
					}

					// push back the faulty character
					chNext = styler[i--];

				}
				break;

			case SCE_CONF_NUMBER:
				// stay  in CONF_NUMBER state until we find a non-numeric
				if( (isascii(ch) && isdigit(ch)) || ch == '.') {
					buffer[bufferCount++] = ch;
				} else {
					state = SCE_CONF_DEFAULT;
					buffer[bufferCount] = '\0';

					// Colourize here...
					if( strchr(buffer,'.') ) {
						// it is an IP address...
						styler.ColourTo(i-1,SCE_CONF_IP);
					} else {
						// normal number
						styler.ColourTo(i-1,SCE_CONF_NUMBER);
					}

					// push back a character
					chNext = styler[i--];
				}
				break;

		}
	}
	delete []buffer;
}

static const char * const confWordListDesc[] = {
	"Directives",
	"Parameters",
	0
};

LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc);

Added lexers/LexCrontab.cxx.





































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexCrontab.cxx
 ** Lexer to use with extended crontab files used by a powerful
 ** Windows scheduler/event monitor/automation manager nnCron.
 ** (http://nemtsev.eserv.ru/)
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordList
*keywordLists[], Accessor &styler)
{
	int state = SCE_NNCRONTAB_DEFAULT;
	char chNext = styler[startPos];
	int lengthDoc = startPos + length;
	// create a buffer large enough to take the largest chunk...
	char *buffer = new char[length];
	int bufferCount = 0;
	// used when highliting environment variables inside quoted string:
	bool insideString = false;

	// this assumes that we have 3 keyword list in conf.properties
	WordList &section = *keywordLists[0];
	WordList &keyword = *keywordLists[1];
	WordList &modifier = *keywordLists[2];

	// go through all provided text segment
	// using the hand-written state machine shown below
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	for (int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i++;
			continue;
		}
		switch(state) {
			case SCE_NNCRONTAB_DEFAULT:
				if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
					// whitespace is simply ignored here...
					styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
					break;
				} else if( ch == '#' && styler.SafeGetCharAt(i+1) == '(') {
					// signals the start of a task...
					state = SCE_NNCRONTAB_TASK;
					styler.ColourTo(i,SCE_NNCRONTAB_TASK);
				}
				  else if( ch == '\\' && (styler.SafeGetCharAt(i+1) == ' ' ||
										 styler.SafeGetCharAt(i+1) == '\t')) {
					// signals the start of an extended comment...
					state = SCE_NNCRONTAB_COMMENT;
					styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
				} else if( ch == '#' ) {
					// signals the start of a plain comment...
					state = SCE_NNCRONTAB_COMMENT;
					styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
				} else if( ch == ')' && styler.SafeGetCharAt(i+1) == '#') {
					// signals the end of a task...
					state = SCE_NNCRONTAB_TASK;
					styler.ColourTo(i,SCE_NNCRONTAB_TASK);
				} else if( ch == '"') {
					state = SCE_NNCRONTAB_STRING;
					styler.ColourTo(i,SCE_NNCRONTAB_STRING);
				} else if( ch == '%') {
					// signals environment variables
					state = SCE_NNCRONTAB_ENVIRONMENT;
					styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
				} else if( ch == '<' && styler.SafeGetCharAt(i+1) == '%') {
					// signals environment variables
					state = SCE_NNCRONTAB_ENVIRONMENT;
					styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
				} else if( ch == '*' ) {
					// signals an asterisk
					// no state jump necessary for this simple case...
					styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK);
				} else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) {
					// signals the start of an identifier
					bufferCount = 0;
					buffer[bufferCount++] = ch;
					state = SCE_NNCRONTAB_IDENTIFIER;
				} else if( isascii(ch) && isdigit(ch) ) {
					// signals the start of a number
					bufferCount = 0;
					buffer[bufferCount++] = ch;
					state = SCE_NNCRONTAB_NUMBER;
				} else {
					// style it the default style..
					styler.ColourTo(i,SCE_NNCRONTAB_DEFAULT);
				}
				break;

			case SCE_NNCRONTAB_COMMENT:
				// if we find a newline here,
				// we simply go to default state
				// else continue to work on it...
				if( ch == '\n' || ch == '\r' ) {
					state = SCE_NNCRONTAB_DEFAULT;
				} else {
					styler.ColourTo(i,SCE_NNCRONTAB_COMMENT);
				}
				break;

			case SCE_NNCRONTAB_TASK:
				// if we find a newline here,
				// we simply go to default state
				// else continue to work on it...
				if( ch == '\n' || ch == '\r' ) {
					state = SCE_NNCRONTAB_DEFAULT;
				} else {
					styler.ColourTo(i,SCE_NNCRONTAB_TASK);
				}
				break;

			case SCE_NNCRONTAB_STRING:
				if( ch == '%' ) {
					state = SCE_NNCRONTAB_ENVIRONMENT;
					insideString = true;
					styler.ColourTo(i-1,SCE_NNCRONTAB_STRING);
					break;
				}
				// if we find the end of a string char, we simply go to default state
				// else we're still dealing with an string...
				if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') ||
					(ch == '\n') || (ch == '\r') ) {
					state = SCE_NNCRONTAB_DEFAULT;
				}
				styler.ColourTo(i,SCE_NNCRONTAB_STRING);
				break;

			case SCE_NNCRONTAB_ENVIRONMENT:
				// if we find the end of a string char, we simply go to default state
				// else we're still dealing with an string...
				if( ch == '%' && insideString ) {
					state = SCE_NNCRONTAB_STRING;
					insideString = false;
					break;
				}
				if( (ch == '%' && styler.SafeGetCharAt(i-1)!='\\')
					|| (ch == '\n') || (ch == '\r') || (ch == '>') ) {
					state = SCE_NNCRONTAB_DEFAULT;
					styler.ColourTo(i,SCE_NNCRONTAB_ENVIRONMENT);
					break;
				}
				styler.ColourTo(i+1,SCE_NNCRONTAB_ENVIRONMENT);
				break;

			case SCE_NNCRONTAB_IDENTIFIER:
				// stay  in CONF_IDENTIFIER state until we find a non-alphanumeric
				if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') ||
					(ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') ||
					(ch == '@') ) {
					buffer[bufferCount++] = ch;
				} else {
					state = SCE_NNCRONTAB_DEFAULT;
					buffer[bufferCount] = '\0';

					// check if the buffer contains a keyword,
					// and highlight it if it is a keyword...
					if(section.InList(buffer)) {
						styler.ColourTo(i,SCE_NNCRONTAB_SECTION );
					} else if(keyword.InList(buffer)) {
						styler.ColourTo(i-1,SCE_NNCRONTAB_KEYWORD );
					} // else if(strchr(buffer,'/') || strchr(buffer,'.')) {
					//	styler.ColourTo(i-1,SCE_NNCRONTAB_EXTENSION);
					// }
					  else if(modifier.InList(buffer)) {
						styler.ColourTo(i-1,SCE_NNCRONTAB_MODIFIER );
					  }	else {
						styler.ColourTo(i-1,SCE_NNCRONTAB_DEFAULT);
					}
					// push back the faulty character
					chNext = styler[i--];
				}
				break;

			case SCE_NNCRONTAB_NUMBER:
				// stay  in CONF_NUMBER state until we find a non-numeric
				if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) {
					buffer[bufferCount++] = ch;
				} else {
					state = SCE_NNCRONTAB_DEFAULT;
					buffer[bufferCount] = '\0';
					// Colourize here... (normal number)
					styler.ColourTo(i-1,SCE_NNCRONTAB_NUMBER);
					// push back a character
					chNext = styler[i--];
				}
				break;
		}
	}
	delete []buffer;
}

static const char * const cronWordListDesc[] = {
	"Section keywords and Forth words",
	"nnCrontab keywords",
	"Modifiers",
	0
};

LexerModule lmNncrontab(SCLEX_NNCRONTAB, ColouriseNncrontabDoc, "nncrontab", 0, cronWordListDesc);

Added lexers/LexCsound.cxx.













































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexCsound.cxx
 ** Lexer for Csound (Orchestra & Score)
 ** Written by Georg Ritter - <ritterfuture A T gmail D O T com>
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
		ch == '_' || ch == '?');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' ||
		ch == '%' || ch == '@' || ch == '$' || ch == '?');
}

static inline bool IsCsoundOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
		ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
		ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
		ch == '%' || ch == ':')
		return true;
	return false;
}

static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
				Accessor &styler) {

	WordList &opcode = *keywordlists[0];
	WordList &headerStmt = *keywordlists[1];
	WordList &otherKeyword = *keywordlists[2];

	// Do not leak onto next line
	if (initStyle == SCE_CSOUND_STRINGEOL)
		initStyle = SCE_CSOUND_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward())
	{
		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_CSOUND_OPERATOR) {
			if (!IsCsoundOperator(static_cast<char>(sc.ch))) {
			    sc.SetState(SCE_CSOUND_DEFAULT);
			}
		}else if (sc.state == SCE_CSOUND_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_CSOUND_DEFAULT);
			}
		} else if (sc.state == SCE_CSOUND_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) ) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));

				if (opcode.InList(s)) {
					sc.ChangeState(SCE_CSOUND_OPCODE);
				} else if (headerStmt.InList(s)) {
					sc.ChangeState(SCE_CSOUND_HEADERSTMT);
				} else if (otherKeyword.InList(s)) {
					sc.ChangeState(SCE_CSOUND_USERKEYWORD);
				} else if (s[0] == 'p') {
					sc.ChangeState(SCE_CSOUND_PARAM);
				} else if (s[0] == 'a') {
					sc.ChangeState(SCE_CSOUND_ARATE_VAR);
				} else if (s[0] == 'k') {
					sc.ChangeState(SCE_CSOUND_KRATE_VAR);
				} else if (s[0] == 'i') { // covers both i-rate variables and i-statements
					sc.ChangeState(SCE_CSOUND_IRATE_VAR);
				} else if (s[0] == 'g') {
					sc.ChangeState(SCE_CSOUND_GLOBAL_VAR);
				}
				sc.SetState(SCE_CSOUND_DEFAULT);
			}
		}
		else if (sc.state == SCE_CSOUND_COMMENT ) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_CSOUND_DEFAULT);
			}
		}
		else if ((sc.state == SCE_CSOUND_ARATE_VAR) ||
			(sc.state == SCE_CSOUND_KRATE_VAR) ||
		(sc.state == SCE_CSOUND_IRATE_VAR)) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_CSOUND_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_CSOUND_DEFAULT) {
			if (sc.ch == ';'){
				sc.SetState(SCE_CSOUND_COMMENT);
			} else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
				sc.SetState(SCE_CSOUND_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_CSOUND_IDENTIFIER);
			} else if (IsCsoundOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_CSOUND_OPERATOR);
			} else if (sc.ch == 'p') {
				sc.SetState(SCE_CSOUND_PARAM);
			} else if (sc.ch == 'a') {
				sc.SetState(SCE_CSOUND_ARATE_VAR);
			} else if (sc.ch == 'k') {
				sc.SetState(SCE_CSOUND_KRATE_VAR);
			} else if (sc.ch == 'i') { // covers both i-rate variables and i-statements
				sc.SetState(SCE_CSOUND_IRATE_VAR);
			} else if (sc.ch == 'g') {
				sc.SetState(SCE_CSOUND_GLOBAL_VAR);
			}
		}
	}
	sc.Complete();
}

static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[],
		Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int stylePrev = 0;
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) {
			char s[20];
			unsigned int j = 0;
			while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) {
				s[j] = styler[i + j];
				j++;
			}
			s[j] = '\0';

			if (strcmp(s, "instr") == 0)
				levelCurrent++;
			if (strcmp(s, "endin") == 0)
				levelCurrent--;
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
		stylePrev = style;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}


static const char * const csoundWordListDesc[] = {
	"Opcodes",
	"Header Statements",
	"User keywords",
	0
};

LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc);

Added lexers/LexD.cxx.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
/** @file LexD.cxx
 ** Lexer for D.
 **
 ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com>
 ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net>
 **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>
#include <map>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/* Nested comments require keeping the value of the nesting level for every
   position in the document.  But since scintilla always styles line by line,
   we only need to store one value per line. The non-negative number indicates
   nesting level at the end of the line.
*/

// Underscore, letter, digit and universal alphas from C99 Appendix D.

static bool IsWordStart(int ch) {
	return (isascii(ch) && (isalpha(ch) || ch == '_')) || !isascii(ch);
}

static bool IsWord(int ch) {
	return (isascii(ch) && (isalnum(ch) || ch == '_')) || !isascii(ch);
}

static bool IsDoxygen(int ch) {
	if (isascii(ch) && islower(ch))
		return true;
	if (ch == '$' || ch == '@' || ch == '\\' ||
		ch == '&' || ch == '#' || ch == '<' || ch == '>' ||
		ch == '{' || ch == '}' || ch == '[' || ch == ']')
		return true;
	return false;
}

static bool IsStringSuffix(int ch) {
	return ch == 'c' || ch == 'w' || ch == 'd';
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_D_COMMENT ||
		style == SCE_D_COMMENTDOC ||
		style == SCE_D_COMMENTDOCKEYWORD ||
		style == SCE_D_COMMENTDOCKEYWORDERROR;
}

// An individual named option for use in an OptionSet

// Options used for LexerD
struct OptionsD {
	bool fold;
	bool foldSyntaxBased;
	bool foldComment;
	bool foldCommentMultiline;
	bool foldCommentExplicit;
	std::string foldExplicitStart;
	std::string foldExplicitEnd;
	bool foldExplicitAnywhere;
	bool foldCompact;
	int  foldAtElseInt;
	bool foldAtElse;
	OptionsD() {
		fold = false;
		foldSyntaxBased = true;
		foldComment = false;
		foldCommentMultiline = true;
		foldCommentExplicit = true;
		foldExplicitStart = "";
		foldExplicitEnd   = "";
		foldExplicitAnywhere = false;
		foldCompact = true;
		foldAtElseInt = -1;
		foldAtElse = false;
	}
};

static const char * const dWordLists[] = {
			"Primary keywords and identifiers",
			"Secondary keywords and identifiers",
			"Documentation comment keywords",
			"Type definitions and aliases",
			"Keywords 5",
			"Keywords 6",
			"Keywords 7",
			0,
		};

struct OptionSetD : public OptionSet<OptionsD> {
	OptionSetD() {
		DefineProperty("fold", &OptionsD::fold);

		DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased,
			"Set this property to 0 to disable syntax based folding.");

		DefineProperty("fold.comment", &OptionsD::foldComment);

		DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline,
			"Set this property to 0 to disable folding multi-line comments when fold.comment=1.");

		DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit,
			"Set this property to 0 to disable folding explicit fold points when fold.comment=1.");

		DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart,
			"The string to use for explicit fold start points, replacing the standard //{.");

		DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd,
			"The string to use for explicit fold end points, replacing the standard //}.");

		DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere,
			"Set this property to 1 to enable explicit fold points anywhere, not just in line comments.");

		DefineProperty("fold.compact", &OptionsD::foldCompact);

		DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt,
			"This option enables D folding on a \"} else {\" line of an if statement.");

		DefineProperty("fold.at.else", &OptionsD::foldAtElse);

		DefineWordListSets(dWordLists);
	}
};

class LexerD : public ILexer {
	bool caseSensitive;
	WordList keywords;
	WordList keywords2;
	WordList keywords3;
	WordList keywords4;
	WordList keywords5;
	WordList keywords6;
	WordList keywords7;
	OptionsD options;
	OptionSetD osD;
public:
	LexerD(bool caseSensitive_) :
		caseSensitive(caseSensitive_) {
	}
	virtual ~LexerD() {
	}
	void SCI_METHOD Release() {
		delete this;
	}
	int SCI_METHOD Version() const {
		return lvOriginal;
	}
	const char * SCI_METHOD PropertyNames() {
		return osD.PropertyNames();
	}
	int SCI_METHOD PropertyType(const char *name) {
		return osD.PropertyType(name);
	}
	const char * SCI_METHOD DescribeProperty(const char *name) {
		return osD.DescribeProperty(name);
	}
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char * SCI_METHOD DescribeWordListSets() {
		return osD.DescribeWordListSets();
	}
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

	void * SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}

	static ILexer *LexerFactoryD() {
		return new LexerD(true);
	}
	static ILexer *LexerFactoryDInsensitive() {
		return new LexerD(false);
	}
};

int SCI_METHOD LexerD::PropertySet(const char *key, const char *val) {
	if (osD.PropertySet(&options, key, val)) {
		return 0;
	}
	return -1;
}

int SCI_METHOD LexerD::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &keywords;
		break;
	case 1:
		wordListN = &keywords2;
		break;
	case 2:
		wordListN = &keywords3;
		break;
	case 3:
		wordListN = &keywords4;
		break;
	case 4:
		wordListN = &keywords5;
		break;
	case 5:
		wordListN = &keywords6;
		break;
	case 6:
		wordListN = &keywords7;
		break;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
		}
	}
	return firstModification;
}

void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);

	int styleBeforeDCKeyword = SCE_D_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	int curLine = styler.GetLine(startPos);
	int curNcLevel = curLine > 0? styler.GetLineState(curLine-1): 0;
	bool numFloat = false; // Float literals have '+' and '-' signs
	bool numHex = false;

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			curLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(curLine, curNcLevel);
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_D_OPERATOR:
				sc.SetState(SCE_D_DEFAULT);
				break;
			case SCE_D_NUMBER:
				// We accept almost anything because of hex. and number suffixes
				if (isascii(sc.ch) && (isalnum(sc.ch) || sc.ch == '_')) {
					continue;
				} else if (sc.ch == '.' && sc.chNext != '.' && !numFloat) {
					// Don't parse 0..2 as number.
					numFloat=true;
					continue;
				} else if ( ( sc.ch == '-' || sc.ch == '+' ) && (		/*sign and*/
					( !numHex && ( sc.chPrev == 'e' || sc.chPrev == 'E' ) ) || /*decimal or*/
					( sc.chPrev == 'p' || sc.chPrev == 'P' ) ) ) {		/*hex*/
					// Parse exponent sign in float literals: 2e+10 0x2e+10
					continue;
				} else {
					sc.SetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_IDENTIFIER:
				if (!IsWord(sc.ch)) {
					char s[1000];
					if (caseSensitive) {
						sc.GetCurrent(s, sizeof(s));
					} else {
						sc.GetCurrentLowered(s, sizeof(s));
					}
					if (keywords.InList(s)) {
						sc.ChangeState(SCE_D_WORD);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_D_WORD2);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_D_TYPEDEF);
					} else if (keywords5.InList(s)) {
						sc.ChangeState(SCE_D_WORD5);
					} else if (keywords6.InList(s)) {
						sc.ChangeState(SCE_D_WORD6);
					} else if (keywords7.InList(s)) {
						sc.ChangeState(SCE_D_WORD7);
					}
					sc.SetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_COMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_COMMENTDOC:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_D_COMMENTDOC;
						sc.SetState(SCE_D_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_D_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_COMMENTLINEDOC:
				if (sc.atLineStart) {
					sc.SetState(SCE_D_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_D_COMMENTLINEDOC;
						sc.SetState(SCE_D_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_D_COMMENTDOCKEYWORD:
				if ((styleBeforeDCKeyword == SCE_D_COMMENTDOC) && sc.Match('*', '/')) {
					sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
					sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				} else if (!IsDoxygen(sc.ch)) {
					char s[100];
					if (caseSensitive) {
						sc.GetCurrent(s, sizeof(s));
					} else {
						sc.GetCurrentLowered(s, sizeof(s));
					}
					if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
						sc.ChangeState(SCE_D_COMMENTDOCKEYWORDERROR);
					}
					sc.SetState(styleBeforeDCKeyword);
				}
				break;
			case SCE_D_COMMENTNESTED:
				if (sc.Match('+', '/')) {
					if (curNcLevel > 0)
						curNcLevel -= 1;
					curLine = styler.GetLine(sc.currentPos);
					styler.SetLineState(curLine, curNcLevel);
					sc.Forward();
					if (curNcLevel == 0) {
						sc.ForwardSetState(SCE_D_DEFAULT);
					}
				} else if (sc.Match('/','+')) {
					curNcLevel += 1;
					curLine = styler.GetLine(sc.currentPos);
					styler.SetLineState(curLine, curNcLevel);
					sc.Forward();
				}
				break;
			case SCE_D_STRING:
				if (sc.ch == '\\') {
					if (sc.chNext == '"' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '"') {
					if(IsStringSuffix(sc.chNext))
						sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_CHARACTER:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_D_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					// Char has no suffixes
					sc.ForwardSetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_STRINGB:
				if (sc.ch == '`') {
					if(IsStringSuffix(sc.chNext))
						sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				}
				break;
			case SCE_D_STRINGR:
				if (sc.ch == '"') {
					if(IsStringSuffix(sc.chNext))
						sc.Forward();
					sc.ForwardSetState(SCE_D_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_D_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_D_NUMBER);
				numFloat = sc.ch == '.';
				// Remember hex literal
				numHex = sc.ch == '0' && ( sc.chNext == 'x' || sc.chNext == 'X' );
			} else if ( (sc.ch == 'r' || sc.ch == 'x' || sc.ch == 'q')
				&& sc.chNext == '"' ) {
				// Limited support for hex and delimited strings: parse as r""
				sc.SetState(SCE_D_STRINGR);
				sc.Forward();
			} else if (IsWordStart(sc.ch) || sc.ch == '$') {
				sc.SetState(SCE_D_IDENTIFIER);
			} else if (sc.Match('/','+')) {
				curNcLevel += 1;
				curLine = styler.GetLine(sc.currentPos);
				styler.SetLineState(curLine, curNcLevel);
				sc.SetState(SCE_D_COMMENTNESTED);
				sc.Forward();
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {   // Support of Qt/Doxygen doc. style
					sc.SetState(SCE_D_COMMENTDOC);
				} else {
					sc.SetState(SCE_D_COMMENT);
				}
				sc.Forward();   // Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
					// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_D_COMMENTLINEDOC);
				else
					sc.SetState(SCE_D_COMMENTLINE);
			} else if (sc.ch == '"') {
				sc.SetState(SCE_D_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_D_CHARACTER);
			} else if (sc.ch == '`') {
				sc.SetState(SCE_D_STRINGB);
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_D_OPERATOR);
				if (sc.ch == '.' && sc.chNext == '.') sc.Forward(); // Range operator
			}
		}
	}
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".

void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {

	if (!options.fold)
		return;

	LexAccessor styler(pAccess);

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse;
	const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) {
			if (userDefinedFoldMarkers) {
				if (styler.Match(i, options.foldExplicitStart.c_str())) {
 					levelNext++;
				} else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
 					levelNext--;
 				}
			} else {
				if ((ch == '/') && (chNext == '/')) {
					char chNext2 = styler.SafeGetCharAt(i + 2);
					if (chNext2 == '{') {
						levelNext++;
					} else if (chNext2 == '}') {
						levelNext--;
					}
				}
 			}
 		}
		if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}
		if (atEOL || (i == endPos-1)) {
			if (options.foldComment && options.foldCommentMultiline) {  // Handle nested comments
				int nc;
				nc =  styler.GetLineState(lineCurrent);
				nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0;
				levelNext += nc;
			}
			int levelUse = levelCurrent;
			if (options.foldSyntaxBased && foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && options.foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!IsASpace(ch))
			visibleChars++;
	}
}

LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists);

Added lexers/LexECL.cxx.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
// Scintilla source code edit control
/** @file LexECL.cxx
 ** Lexer for ECL.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#ifdef __BORLANDC__
// Borland C++ displays warnings in vector header without this
#pragma option -w-ccc -w-rch
#endif

#include <string>
#include <vector>
#include <map>
#include <algorithm>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#define SET_LOWER "abcdefghijklmnopqrstuvwxyz"
#define SET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define SET_DIGITS "0123456789"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool IsSpaceEquiv(int state) {
	return (state <= SCE_ECL_COMMENTDOC) ||
		// including SCE_ECL_DEFAULT, SCE_ECL_COMMENT, SCE_ECL_COMMENTLINE
		(state == SCE_ECL_COMMENTLINEDOC) || (state == SCE_ECL_COMMENTDOCKEYWORD) ||
		(state == SCE_ECL_COMMENTDOCKEYWORDERROR);
}

static void ColouriseEclDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {
	WordList &keywords0 = *keywordlists[0];
	WordList &keywords1 = *keywordlists[1];
	WordList &keywords2 = *keywordlists[2];
	WordList &keywords3 = *keywordlists[3]; //Value Types
	WordList &keywords4 = *keywordlists[4];
	WordList &keywords5 = *keywordlists[5];
	WordList &keywords6 = *keywordlists[6];	//Javadoc Tags
	WordList cplusplus;
	cplusplus.Set("beginc endc");

	bool stylingWithinPreprocessor = false;

	CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,");
	CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]");
	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
	CharacterSet setQualified(CharacterSet::setNone, "uUxX");

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;
	int styleBeforeDCKeyword = SCE_ECL_DEFAULT;
	bool continuationLine = false;

	if (initStyle == SCE_ECL_PREPROCESSOR) {
		// Set continuationLine if last character of previous line is '\'
		int lineCurrent = styler.GetLine(startPos);
		if (lineCurrent > 0) {
			int chBack = styler.SafeGetCharAt(startPos-1, 0);
			int chBack2 = styler.SafeGetCharAt(startPos-2, 0);
			int lineEndChar = '!';
			if (chBack2 == '\r' && chBack == '\n') {
				lineEndChar = styler.SafeGetCharAt(startPos-3, 0);
			} else if (chBack == '\n' || chBack == '\r') {
				lineEndChar = chBack2;
			}
			continuationLine = lineEndChar == '\\';
		}
	}

	// look back to set chPrevNonWhite properly for better regex colouring
	if (startPos > 0) {
		int back = startPos;
		while (--back && IsSpaceEquiv(styler.StyleAt(back)))
			;
		if (styler.StyleAt(back) == SCE_ECL_OPERATOR) {
			chPrevNonWhite = styler.SafeGetCharAt(back);
		}
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineStart) {
			if (sc.state == SCE_ECL_STRING) {
				// Prevent SCE_ECL_STRINGEOL from leaking back to previous line which
				// ends with a line continuation by locking in the state upto this position.
				sc.SetState(SCE_ECL_STRING);
			}
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
			lastWordWasUUID = false;
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continuationLine = true;
				continue;
			}
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_ECL_ADDED:
			case SCE_ECL_DELETED:
			case SCE_ECL_CHANGED:
			case SCE_ECL_MOVED:
			if (sc.atLineStart)
					sc.SetState(SCE_ECL_DEFAULT);
				break;
			case SCE_ECL_OPERATOR:
				sc.SetState(SCE_ECL_DEFAULT);
				break;
			case SCE_ECL_NUMBER:
				// We accept almost anything because of hex. and number suffixes
				if (!setWord.Contains(sc.ch)) {
					sc.SetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_IDENTIFIER:
				if (!setWord.Contains(sc.ch) || (sc.ch == '.')) {
					char s[1000];
					sc.GetCurrentLowered(s, sizeof(s));
					if (keywords0.InList(s)) {
						lastWordWasUUID = strcmp(s, "uuid") == 0;
						sc.ChangeState(SCE_ECL_WORD0);
					} else if (keywords1.InList(s)) {
						sc.ChangeState(SCE_ECL_WORD1);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_ECL_WORD2);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_ECL_WORD4);
					} else if (keywords5.InList(s)) {
						sc.ChangeState(SCE_ECL_WORD5);
					}
					else	//Data types are of from KEYWORD## 
					{
						int i = static_cast<int>(strlen(s)) - 1;
						while(i >= 0 && (isdigit(s[i]) || s[i] == '_'))
							--i;

						char s2[1000];
						strncpy(s2, s, i + 1);
						s2[i + 1] = 0;
						if (keywords3.InList(s2)) {
							sc.ChangeState(SCE_ECL_WORD3);
						} 
					}
					sc.SetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_PREPROCESSOR:
				if (sc.atLineStart && !continuationLine) {
					sc.SetState(SCE_ECL_DEFAULT);
				} else if (stylingWithinPreprocessor) {
					if (IsASpace(sc.ch)) {
						sc.SetState(SCE_ECL_DEFAULT);
					}
				} else {
					if (sc.Match('/', '*') || sc.Match('/', '/')) {
						sc.SetState(SCE_ECL_DEFAULT);
					}
				}
				break;
			case SCE_ECL_COMMENT:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_COMMENTDOC:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_ECL_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_ECL_COMMENTDOC;
						sc.SetState(SCE_ECL_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_ECL_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_COMMENTLINEDOC:
				if (sc.atLineStart) {
					sc.SetState(SCE_ECL_DEFAULT);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = SCE_ECL_COMMENTLINEDOC;
						sc.SetState(SCE_ECL_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_ECL_COMMENTDOCKEYWORD:
				if ((styleBeforeDCKeyword == SCE_ECL_COMMENTDOC) && sc.Match('*', '/')) {
					sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR);
					sc.Forward();
					sc.ForwardSetState(SCE_ECL_DEFAULT);
				} else if (!setDoxygen.Contains(sc.ch)) {
					char s[1000];
					sc.GetCurrentLowered(s, sizeof(s));
					if (!IsASpace(sc.ch) || !keywords6.InList(s+1)) {
						sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR);
					}
					sc.SetState(styleBeforeDCKeyword);
				}
				break;
			case SCE_ECL_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_ECL_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_CHARACTER:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_ECL_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_REGEX:
				if (sc.atLineStart) {
					sc.SetState(SCE_ECL_DEFAULT);
				} else if (sc.ch == '/') {
					sc.Forward();
					while ((sc.ch < 0x80) && islower(sc.ch))
						sc.Forward();    // gobble regex flags
					sc.SetState(SCE_ECL_DEFAULT);
				} else if (sc.ch == '\\') {
					// Gobble up the quoted character
					if (sc.chNext == '\\' || sc.chNext == '/') {
						sc.Forward();
					}
				}
				break;
			case SCE_ECL_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_ECL_DEFAULT);
				}
				break;
			case SCE_ECL_VERBATIM:
				if (sc.ch == '\"') {
					if (sc.chNext == '\"') {
						sc.Forward();
					} else {
						sc.ForwardSetState(SCE_ECL_DEFAULT);
					}
				}
				break;
			case SCE_ECL_UUID:
				if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
					sc.SetState(SCE_ECL_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered.
		int lineCurrent = styler.GetLine(sc.currentPos);
		int lineState = styler.GetLineState(lineCurrent);
		if (sc.state == SCE_ECL_DEFAULT) {
			if (lineState) {
				sc.SetState(lineState);
			}
			else if (sc.Match('@', '\"')) {
				sc.SetState(SCE_ECL_VERBATIM);
				sc.Forward();
			} else if (setQualified.Contains(sc.ch) && sc.chNext == '\'') {
				sc.SetState(SCE_ECL_CHARACTER);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_ECL_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_ECL_NUMBER);
				}
			} else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_ECL_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_ECL_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_ECL_COMMENTDOC);
				} else {
					sc.SetState(SCE_ECL_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!"))
					// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_ECL_COMMENTLINEDOC);
				else
					sc.SetState(SCE_ECL_COMMENTLINE);
			} else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) {
				sc.SetState(SCE_ECL_REGEX);	// JavaScript's RegEx
//			} else if (sc.ch == '\"') {
//				sc.SetState(SCE_ECL_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_ECL_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_ECL_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_ECL_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_ECL_OPERATOR);
			}
		}

		if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
		continuationLine = false;
	}
	sc.Complete();

}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_ECL_COMMENT ||
		style == SCE_ECL_COMMENTDOC ||
		style == SCE_ECL_COMMENTDOCKEYWORD ||
		style == SCE_ECL_COMMENTDOCKEYWORDERROR;
}

bool MatchNoCase(Accessor & styler, unsigned int & pos, const char *s) {
	int i=0;
	for (; *s; i++) {
		char compare_char = tolower(*s);
		char styler_char = tolower(styler.SafeGetCharAt(pos+i));
		if (compare_char != styler_char) 
			return false;
		s++;
	}
	pos+=i-1;
	return true;
}


// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldEclDoc(unsigned int startPos, int length, int initStyle, 
					   WordList *[], Accessor &styler) {
	bool foldComment = true;
	bool foldPreprocessor = true;
	bool foldCompact = true;
	bool foldAtElse = true;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_ECL_COMMENTLINEDOC)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_ECL_COMMENTLINEDOC) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (foldComment && (style == SCE_ECL_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelNext++;
				} else if (chNext2 == '}') {
					levelNext--;
				}
			}
		}
		if (foldPreprocessor && (style == SCE_ECL_PREPROCESSOR)) {
			if (ch == '#') {
				unsigned int j = i + 1;
				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (MatchNoCase(styler, j, "region") || MatchNoCase(styler, j, "if")) {
					levelNext++;
				} else if (MatchNoCase(styler, j, "endregion") || MatchNoCase(styler, j, "end")) {
					levelNext--;
				}
			}
		}
		if (style == SCE_ECL_OPERATOR) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}
		if (style == SCE_ECL_WORD2) {
			if (MatchNoCase(styler, i, "record") || MatchNoCase(styler, i, "transform") || MatchNoCase(styler, i, "type") || MatchNoCase(styler, i, "function") || 
				MatchNoCase(styler, i, "module") || MatchNoCase(styler, i, "service") || MatchNoCase(styler, i, "interface") || MatchNoCase(styler, i, "ifblock") ||
				MatchNoCase(styler, i, "macro") || MatchNoCase(styler, i, "beginc++")) {
				levelNext++;
			} else if (MatchNoCase(styler, i, "endmacro") || MatchNoCase(styler, i, "endc++") || MatchNoCase(styler, i, "end")) {
				levelNext--;
			}
		}
		if (atEOL || (i == endPos-1)) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
				// There is an empty line at end of file so give it same level and empty
				styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
			}
			visibleChars = 0;
		}
		if (!IsASpace(ch))
			visibleChars++;
	}
}

static const char * const EclWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmECL(
   SCLEX_ECL,
   ColouriseEclDoc,
   "ecl",
   FoldEclDoc,
   EclWordListDesc);

Added lexers/LexEScript.cxx.









































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
// Scintilla source code edit control
/** @file LexESCRIPT.cxx
 ** Lexer for ESCRIPT
 **/
// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com)

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}



static void ColouriseESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];

	// Do not leak onto next line
	/*if (initStyle == SCE_ESCRIPT_STRINGEOL)
		initStyle = SCE_ESCRIPT_DEFAULT;*/

	StyleContext sc(startPos, length, initStyle, styler);

	bool caseSensitive = styler.GetPropertyInt("escript.case.sensitive", 0) != 0;

	for (; sc.More(); sc.Forward()) {

		/*if (sc.atLineStart && (sc.state == SCE_ESCRIPT_STRING)) {
			// Prevent SCE_ESCRIPT_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_ESCRIPT_STRING);
		}*/

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_ESCRIPT_OPERATOR || sc.state == SCE_ESCRIPT_BRACE) {
			sc.SetState(SCE_ESCRIPT_DEFAULT);
		} else if (sc.state == SCE_ESCRIPT_NUMBER) {
			if (!IsADigit(sc.ch) || sc.ch != '.') {
				sc.SetState(SCE_ESCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_ESCRIPT_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				if (caseSensitive) {
					sc.GetCurrent(s, sizeof(s));
				} else {
					sc.GetCurrentLowered(s, sizeof(s));
				}

//				sc.GetCurrentLowered(s, sizeof(s));

                                if (keywords.InList(s)) {
					sc.ChangeState(SCE_ESCRIPT_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_ESCRIPT_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_ESCRIPT_WORD3);
                                        // sc.state = SCE_ESCRIPT_IDENTIFIER;
				}
				sc.SetState(SCE_ESCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_ESCRIPT_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_ESCRIPT_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_ESCRIPT_COMMENTLINE) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_ESCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_ESCRIPT_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_ESCRIPT_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_ESCRIPT_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_ESCRIPT_NUMBER);
			} else if (IsAWordStart(sc.ch) || (sc.ch == '#')) {
				sc.SetState(SCE_ESCRIPT_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_ESCRIPT_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_ESCRIPT_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_ESCRIPT_STRING);
				//} else if (isoperator(static_cast<char>(sc.ch))) {
			} else if (sc.ch == '+' || sc.ch == '-' || sc.ch == '*' || sc.ch == '/' || sc.ch == '=' || sc.ch == '<' || sc.ch == '>' || sc.ch == '&' || sc.ch == '|' || sc.ch == '!' || sc.ch == '?' || sc.ch == ':') {
				sc.SetState(SCE_ESCRIPT_OPERATOR);
			} else if (sc.ch == '{' || sc.ch == '}') {
				sc.SetState(SCE_ESCRIPT_BRACE);
			}
		}

	}
	sc.Complete();
}


static int classifyFoldPointESCRIPT(const char* s, const char* prevWord) {
	int lev = 0;
	if (strcmp(prevWord, "end") == 0) return lev;
	if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0)
		return -1;

        if (strcmp(s, "for") == 0 || strcmp(s, "foreach") == 0
	    || strcmp(s, "program") == 0 || strcmp(s, "function") == 0
	    || strcmp(s, "while") == 0 || strcmp(s, "case") == 0
	    || strcmp(s, "if") == 0 ) {
		lev = 1;
	} else if ( strcmp(s, "endfor") == 0 || strcmp(s, "endforeach") == 0
	    || strcmp(s, "endprogram") == 0 || strcmp(s, "endfunction") == 0
	    || strcmp(s, "endwhile") == 0 || strcmp(s, "endcase") == 0
	    || strcmp(s, "endif") == 0 ) {
		lev = -1;
	}

	return lev;
}


static bool IsStreamCommentStyle(int style) {
	return style == SCE_ESCRIPT_COMMENT ||
	       style == SCE_ESCRIPT_COMMENTDOC ||
	       style == SCE_ESCRIPT_COMMENTLINE;
}

static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
	//~ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	// Do not know how to fold the comment at the moment.
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
        bool foldComment = true;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	int lastStart = 0;
	char prevWord[32] = "";

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');


		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}

		if (foldComment && (style == SCE_ESCRIPT_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelCurrent++;
				} else if (chNext2 == '}') {
					levelCurrent--;
				}
			}
		}

		if (stylePrev == SCE_ESCRIPT_DEFAULT && style == SCE_ESCRIPT_WORD3)
		{
			// Store last word start point.
			lastStart = i;
		}

		if (style == SCE_ESCRIPT_WORD3) {
			if(iswordchar(ch) && !iswordchar(chNext)) {
				char s[32];
				unsigned int j;
				for(j = 0; ( j < 31 ) && ( j < i-lastStart+1 ); j++) {
					s[j] = static_cast<char>(tolower(styler[lastStart + j]));
				}
				s[j] = '\0';
				levelCurrent += classifyFoldPointESCRIPT(s, prevWord);
				strcpy(prevWord, s);
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
			strcpy(prevWord, "");
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}



static const char * const ESCRIPTWordLists[] = {
	"Primary keywords and identifiers",
	"Intrinsic functions",
	"Extended and user defined functions",
	0,
};

LexerModule lmESCRIPT(SCLEX_ESCRIPT, ColouriseESCRIPTDoc, "escript", FoldESCRIPTDoc, ESCRIPTWordLists);

Added lexers/LexEiffel.cxx.



































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexEiffel.cxx
 ** Lexer for Eiffel.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool isEiffelOperator(unsigned int ch) {
	// '.' left out as it is used to make up numbers
	return ch == '*' || ch == '/' || ch == '\\' || ch == '-' || ch == '+' ||
	        ch == '(' || ch == ')' || ch == '=' ||
	        ch == '{' || ch == '}' || ch == '~' ||
	        ch == '[' || ch == ']' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' ||
	        ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '!' || ch == '@' || ch == '?';
}

static inline bool IsAWordChar(unsigned int  ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(unsigned int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColouriseEiffelDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_EIFFEL_STRINGEOL) {
			if (sc.ch != '\r' && sc.ch != '\n') {
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		} else if (sc.state == SCE_EIFFEL_OPERATOR) {
			sc.SetState(SCE_EIFFEL_DEFAULT);
		} else if (sc.state == SCE_EIFFEL_WORD) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (!keywords.InList(s)) {
					sc.ChangeState(SCE_EIFFEL_IDENTIFIER);
				}
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		} else if (sc.state == SCE_EIFFEL_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		} else if (sc.state == SCE_EIFFEL_COMMENTLINE) {
			if (sc.ch == '\r' || sc.ch == '\n') {
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		} else if (sc.state == SCE_EIFFEL_STRING) {
			if (sc.ch == '%') {
				sc.Forward();
			} else if (sc.ch == '\"') {
				sc.Forward();
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		} else if (sc.state == SCE_EIFFEL_CHARACTER) {
			if (sc.ch == '\r' || sc.ch == '\n') {
				sc.SetState(SCE_EIFFEL_STRINGEOL);
			} else if (sc.ch == '%') {
				sc.Forward();
			} else if (sc.ch == '\'') {
				sc.Forward();
				sc.SetState(SCE_EIFFEL_DEFAULT);
			}
		}

		if (sc.state == SCE_EIFFEL_DEFAULT) {
			if (sc.ch == '-' && sc.chNext == '-') {
				sc.SetState(SCE_EIFFEL_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_EIFFEL_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_EIFFEL_CHARACTER);
			} else if (IsADigit(sc.ch) || (sc.ch == '.')) {
				sc.SetState(SCE_EIFFEL_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_EIFFEL_WORD);
			} else if (isEiffelOperator(sc.ch)) {
				sc.SetState(SCE_EIFFEL_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static bool IsEiffelComment(Accessor &styler, int pos, int len) {
	return len>1 && styler[pos]=='-' && styler[pos+1]=='-';
}

static void FoldEiffelDocIndent(unsigned int startPos, int length, int,
						   WordList *[], Accessor &styler) {
	int lengthDoc = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsEiffelComment);
	char chNext = styler[startPos];
	for (int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsEiffelComment);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					// Line after is blank so check the next - maybe should continue further?
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsEiffelComment);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}
}

static void FoldEiffelDocKeyWords(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int stylePrev = 0;
	int styleNext = styler.StyleAt(startPos);
	// lastDeferred should be determined by looking back to last keyword in case
	// the "deferred" is on a line before "class"
	bool lastDeferred = false;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if ((stylePrev != SCE_EIFFEL_WORD) && (style == SCE_EIFFEL_WORD)) {
			char s[20];
			unsigned int j = 0;
			while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) {
				s[j] = styler[i + j];
				j++;
			}
			s[j] = '\0';

			if (
				(strcmp(s, "check") == 0) ||
				(strcmp(s, "debug") == 0) ||
				(strcmp(s, "deferred") == 0) ||
				(strcmp(s, "do") == 0) ||
				(strcmp(s, "from") == 0) ||
				(strcmp(s, "if") == 0) ||
				(strcmp(s, "inspect") == 0) ||
				(strcmp(s, "once") == 0)
			)
				levelCurrent++;
			if (!lastDeferred && (strcmp(s, "class") == 0))
				levelCurrent++;
			if (strcmp(s, "end") == 0)
				levelCurrent--;
			lastDeferred = strcmp(s, "deferred") == 0;
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
		stylePrev = style;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const eiffelWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmEiffel(SCLEX_EIFFEL, ColouriseEiffelDoc, "eiffel", FoldEiffelDocIndent, eiffelWordListDesc);
LexerModule lmEiffelkw(SCLEX_EIFFELKW, ColouriseEiffelDoc, "eiffelkw", FoldEiffelDocKeyWords, eiffelWordListDesc);

Added lexers/LexErlang.cxx.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
// Scintilla source code edit control
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
/** @file LexErlang.cxx
 ** Lexer for Erlang.
 ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com)
 ** Originally wrote by Peter-Henry Mander,
 ** based on Matlab lexer by Jos Fonseca.
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static int is_radix(int radix, int ch) {
	int digit;

	if (36 < radix || 2 > radix)
		return 0;

	if (isdigit(ch)) {
		digit = ch - '0';
	} else if (isalnum(ch)) {
		digit = toupper(ch) - 'A' + 10;
	} else {
		return 0;
	}

	return (digit < radix);
}

typedef enum {
	STATE_NULL,
	COMMENT,
	COMMENT_FUNCTION,
	COMMENT_MODULE,
	COMMENT_DOC,
	COMMENT_DOC_MACRO,
	ATOM_UNQUOTED,
	ATOM_QUOTED,
	NODE_NAME_UNQUOTED,
	NODE_NAME_QUOTED,
	MACRO_START,
	MACRO_UNQUOTED,
	MACRO_QUOTED,
	RECORD_START,
	RECORD_UNQUOTED,
	RECORD_QUOTED,
	NUMERAL_START,
	NUMERAL_BASE_VALUE,
	NUMERAL_FLOAT,
	NUMERAL_EXPONENT,
	PREPROCESSOR
} atom_parse_state_t;

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (ch != ' ') && (isalnum(ch) || ch == '_');
}

static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle,
								WordList *keywordlists[], Accessor &styler) {

	StyleContext sc(startPos, length, initStyle, styler);
	WordList &reservedWords = *keywordlists[0];
	WordList &erlangBIFs = *keywordlists[1];
	WordList &erlangPreproc = *keywordlists[2];
	WordList &erlangModulesAtt = *keywordlists[3];
	WordList &erlangDoc = *keywordlists[4];
	WordList &erlangDocMacro = *keywordlists[5];
	int radix_digits = 0;
	int exponent_digits = 0;
	atom_parse_state_t parse_state = STATE_NULL;
	atom_parse_state_t old_parse_state = STATE_NULL;
	bool to_late_to_comment = false;
	char cur[100];
	int old_style = SCE_ERLANG_DEFAULT;

	styler.StartAt(startPos);

	for (; sc.More(); sc.Forward()) {
		int style = SCE_ERLANG_DEFAULT;
		if (STATE_NULL != parse_state) {

			switch (parse_state) {

				case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break;

			/* COMMENTS ------------------------------------------------------*/
				case COMMENT : {
					if (sc.ch != '%') {
						to_late_to_comment = true;
					} else if (!to_late_to_comment && sc.ch == '%') {
						// Switch to comment level 2 (Function)
						sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION);
						old_style = SCE_ERLANG_COMMENT_FUNCTION;
						parse_state = COMMENT_FUNCTION;
						sc.Forward();
					}
				}
				// V--- Falling through!
				case COMMENT_FUNCTION : {
					if (sc.ch != '%') {
						to_late_to_comment = true;
					} else if (!to_late_to_comment && sc.ch == '%') {
						// Switch to comment level 3 (Module)
						sc.ChangeState(SCE_ERLANG_COMMENT_MODULE);
						old_style = SCE_ERLANG_COMMENT_MODULE;
						parse_state = COMMENT_MODULE;
						sc.Forward();
					}
				}
				// V--- Falling through!
				case COMMENT_MODULE : {
					if (parse_state != COMMENT) {
						// Search for comment documentation
						if (sc.chNext == '@') {
							old_parse_state = parse_state;
							parse_state = ('{' == sc.ch)
											? COMMENT_DOC_MACRO
											: COMMENT_DOC;
							sc.ForwardSetState(sc.state);
						}
					}

					// All comments types fall here.
					if (sc.atLineEnd) {
						to_late_to_comment = false;
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case COMMENT_DOC :
				// V--- Falling through!
				case COMMENT_DOC_MACRO : {

					if (!isalnum(sc.ch)) {
						// Try to match documentation comment
						sc.GetCurrent(cur, sizeof(cur));

						if (parse_state == COMMENT_DOC_MACRO
							&& erlangDocMacro.InList(cur)) {
								sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO);
								while (sc.ch != '}' && !sc.atLineEnd)
									sc.Forward();
						} else if (erlangDoc.InList(cur)) {
							sc.ChangeState(SCE_ERLANG_COMMENT_DOC);
						} else {
							sc.ChangeState(old_style);
						}

						// Switch back to old state
						sc.SetState(old_style);
						parse_state = old_parse_state;
					}

					if (sc.atLineEnd) {
						to_late_to_comment = false;
						sc.ChangeState(old_style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Atoms ---------------------------------------------------------*/
				case ATOM_UNQUOTED : {
					if ('@' == sc.ch){
						parse_state = NODE_NAME_UNQUOTED;
					} else if (sc.ch == ':') {
						// Searching for module name
						if (sc.chNext == ' ') {
							// error
							sc.ChangeState(SCE_ERLANG_UNKNOWN);
							parse_state = STATE_NULL;
						} else {
							sc.Forward();
							if (isalnum(sc.ch))  {
								sc.GetCurrent(cur, sizeof(cur));
								sc.ChangeState(SCE_ERLANG_MODULES);
								sc.SetState(SCE_ERLANG_MODULES);
							}
						}
					} else if (!IsAWordChar(sc.ch)) {

						sc.GetCurrent(cur, sizeof(cur));
						if (reservedWords.InList(cur)) {
							style = SCE_ERLANG_KEYWORD;
						} else if (erlangBIFs.InList(cur)
									&& strcmp(cur,"erlang:")){
							style = SCE_ERLANG_BIFS;
						} else if (sc.ch == '(' || '/' == sc.ch){
							style = SCE_ERLANG_FUNCTION_NAME;
						} else {
							style = SCE_ERLANG_ATOM;
						}

						sc.ChangeState(style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}

				} break;

				case ATOM_QUOTED : {
					if ( '@' == sc.ch ){
						parse_state = NODE_NAME_QUOTED;
					} else if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_ATOM);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Node names ----------------------------------------------------*/
				case NODE_NAME_UNQUOTED : {
					if ('@' == sc.ch) {
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_NODE_NAME);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case NODE_NAME_QUOTED : {
					if ('@' == sc.ch) {
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Records -------------------------------------------------------*/
				case RECORD_START : {
					if ('\'' == sc.ch) {
						parse_state = RECORD_QUOTED;
					} else if (isalpha(sc.ch) && islower(sc.ch)) {
						parse_state = RECORD_UNQUOTED;
					} else { // error
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case RECORD_UNQUOTED : {
					if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_RECORD);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case RECORD_QUOTED : {
					if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_RECORD_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Macros --------------------------------------------------------*/
				case MACRO_START : {
					if ('\'' == sc.ch) {
						parse_state = MACRO_QUOTED;
					} else if (isalpha(sc.ch)) {
						parse_state = MACRO_UNQUOTED;
					} else { // error
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case MACRO_UNQUOTED : {
					if (!IsAWordChar(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_MACRO);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

				case MACRO_QUOTED : {
					if ('\'' == sc.ch && '\\' != sc.chPrev) {
						sc.ChangeState(SCE_ERLANG_MACRO_QUOTED);
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Numerics ------------------------------------------------------*/
			/* Simple integer */
				case NUMERAL_START : {
					if (isdigit(sc.ch)) {
						radix_digits *= 10;
						radix_digits += sc.ch - '0'; // Assuming ASCII here!
					} else if ('#' == sc.ch) {
						if (2 > radix_digits || 36 < radix_digits) {
							sc.SetState(SCE_ERLANG_DEFAULT);
							parse_state = STATE_NULL;
						} else {
							parse_state = NUMERAL_BASE_VALUE;
						}
					} else if ('.' == sc.ch && isdigit(sc.chNext)) {
						radix_digits = 0;
						parse_state = NUMERAL_FLOAT;
					} else if ('e' == sc.ch || 'E' == sc.ch) {
						exponent_digits = 0;
						parse_state = NUMERAL_EXPONENT;
					} else {
						radix_digits = 0;
						sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Integer in other base than 10 (x#yyy) */
				case NUMERAL_BASE_VALUE : {
					if (!is_radix(radix_digits,sc.ch)) {
						radix_digits = 0;

						if (!isalnum(sc.ch))
							sc.ChangeState(SCE_ERLANG_NUMBER);

						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Float (x.yyy) */
				case NUMERAL_FLOAT : {
					if ('e' == sc.ch || 'E' == sc.ch) {
						exponent_digits = 0;
						parse_state = NUMERAL_EXPONENT;
					} else if (!isdigit(sc.ch)) {
						sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			/* Exponent, either integer or float (xEyy, x.yyEzzz) */
				case NUMERAL_EXPONENT : {
					if (('-' == sc.ch || '+' == sc.ch)
							&& (isdigit(sc.chNext))) {
						sc.Forward();
					} else if (!isdigit(sc.ch)) {
						if (0 < exponent_digits)
							sc.ChangeState(SCE_ERLANG_NUMBER);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					} else {
						++exponent_digits;
					}
				} break;

			/* -------------------------------------------------------------- */
			/* Preprocessor --------------------------------------------------*/
				case PREPROCESSOR : {
					if (!IsAWordChar(sc.ch)) {

						sc.GetCurrent(cur, sizeof(cur));
						if (erlangPreproc.InList(cur)) {
							style = SCE_ERLANG_PREPROC;
						} else if (erlangModulesAtt.InList(cur)) {
							style = SCE_ERLANG_MODULES_ATT;
						}

						sc.ChangeState(style);
						sc.SetState(SCE_ERLANG_DEFAULT);
						parse_state = STATE_NULL;
					}
				} break;

			}

		} /* End of : STATE_NULL != parse_state */
		else
		{
			switch (sc.state) {
				case SCE_ERLANG_VARIABLE : {
					if (!IsAWordChar(sc.ch))
						sc.SetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_STRING : {
					 if (sc.ch == '\"' && sc.chPrev != '\\')
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_COMMENT : {
					 if (sc.atLineEnd)
						sc.SetState(SCE_ERLANG_DEFAULT);
				} break;
				case SCE_ERLANG_CHARACTER : {
					if (sc.chPrev == '\\') {
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
					} else if (sc.ch != '\\') {
						sc.ForwardSetState(SCE_ERLANG_DEFAULT);
					}
				} break;
				case SCE_ERLANG_OPERATOR : {
					if (sc.chPrev == '.') {
						if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\'
							|| sc.ch == '^') {
							sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						} else if (sc.ch == '\'') {
							sc.ForwardSetState(SCE_ERLANG_DEFAULT);
						} else {
							sc.SetState(SCE_ERLANG_DEFAULT);
						}
					} else {
						sc.SetState(SCE_ERLANG_DEFAULT);
					}
				} break;
			}
		}

		if (sc.state == SCE_ERLANG_DEFAULT) {
			bool no_new_state = false;

			switch (sc.ch) {
				case '\"' : sc.SetState(SCE_ERLANG_STRING); break;
				case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break;
				case '%' : {
					parse_state = COMMENT;
					sc.SetState(SCE_ERLANG_COMMENT);
				} break;
				case '#' : {
					parse_state = RECORD_START;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '?' : {
					parse_state = MACRO_START;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '\'' : {
					parse_state = ATOM_QUOTED;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} break;
				case '+' :
				case '-' : {
					if (IsADigit(sc.chNext)) {
						parse_state = NUMERAL_START;
						radix_digits = 0;
						sc.SetState(SCE_ERLANG_UNKNOWN);
					} else if (sc.ch != '+') {
						parse_state = PREPROCESSOR;
						sc.SetState(SCE_ERLANG_UNKNOWN);
					}
				} break;
				default : no_new_state = true;
			}

			if (no_new_state) {
				if (isdigit(sc.ch)) {
					parse_state = NUMERAL_START;
					radix_digits = sc.ch - '0';
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} else if (isupper(sc.ch) || '_' == sc.ch) {
					sc.SetState(SCE_ERLANG_VARIABLE);
				} else if (isalpha(sc.ch)) {
					parse_state = ATOM_UNQUOTED;
					sc.SetState(SCE_ERLANG_UNKNOWN);
				} else if (isoperator(static_cast<char>(sc.ch))
							|| sc.ch == '\\') {
					sc.SetState(SCE_ERLANG_OPERATOR);
				}
			}
		}

	}
	sc.Complete();
}

static int ClassifyErlangFoldPoint(
	Accessor &styler,
	int styleNext,
	int keyword_start
) {
	int lev = 0;
	if (styler.Match(keyword_start,"case")
		|| (
			styler.Match(keyword_start,"fun")
			&& (SCE_ERLANG_FUNCTION_NAME != styleNext)
			)
		|| styler.Match(keyword_start,"if")
		|| styler.Match(keyword_start,"query")
		|| styler.Match(keyword_start,"receive")
	) {
		++lev;
	} else if (styler.Match(keyword_start,"end")) {
		--lev;
	}

	return lev;
}

static void FoldErlangDoc(
	unsigned int startPos, int length, int initStyle,
	WordList** /*keywordlists*/, Accessor &styler
) {
	unsigned int endPos = startPos + length;
	int currentLine = styler.GetLine(startPos);
	int lev;
	int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK;
	int currentLevel = previousLevel;
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	int stylePrev;
	int keyword_start = 0;
	char ch;
	char chNext = styler.SafeGetCharAt(startPos);
	bool atEOL;

	for (unsigned int i = startPos; i < endPos; i++) {
		ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		// Get styles
		stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n');

		if (stylePrev != SCE_ERLANG_KEYWORD
			&& style == SCE_ERLANG_KEYWORD) {
			keyword_start = i;
		}

		// Fold on keywords
		if (stylePrev == SCE_ERLANG_KEYWORD
			&& style != SCE_ERLANG_KEYWORD
			&& style != SCE_ERLANG_ATOM
		) {
			currentLevel += ClassifyErlangFoldPoint(styler,
													styleNext,
													keyword_start);
		}

		// Fold on comments
		if (style == SCE_ERLANG_COMMENT
			|| style == SCE_ERLANG_COMMENT_MODULE
			|| style == SCE_ERLANG_COMMENT_FUNCTION) {

			if (ch == '%' && chNext == '{') {
				currentLevel++;
			} else if (ch == '%' && chNext == '}') {
				currentLevel--;
			}
		}

		// Fold on braces
		if (style == SCE_ERLANG_OPERATOR) {
			if (ch == '{' || ch == '(' || ch == '[') {
				currentLevel++;
			} else if (ch == '}' || ch == ')' || ch == ']') {
				currentLevel--;
			}
		}


		if (atEOL) {
			lev = previousLevel;

			if (currentLevel > previousLevel)
				lev |= SC_FOLDLEVELHEADERFLAG;

			if (lev != styler.LevelAt(currentLine))
				styler.SetLevel(currentLine, lev);

			currentLine++;
			previousLevel = currentLevel;
		}

	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	styler.SetLevel(currentLine,
					previousLevel
					| (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK));
}

static const char * const erlangWordListDesc[] = {
	"Erlang Reserved words",
	"Erlang BIFs",
	"Erlang Preprocessor",
	"Erlang Module Attributes",
	"Erlang Documentation",
	"Erlang Documentation Macro",
	0
};

LexerModule lmErlang(
	SCLEX_ERLANG,
	ColouriseErlangDoc,
	"erlang",
	FoldErlangDoc,
	erlangWordListDesc);

Added lexers/LexFlagship.cxx.





































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
// Scintilla source code edit control
/** @file LexFlagShip.cxx
 ** Lexer for Harbour and FlagShip.
 ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.)
 **/
// Copyright 2005 by Randy Butler
// Copyright 2010 by Xavi <jarabal/at/gmail.com> (Harbour)
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Extended to accept accented characters
static inline bool IsAWordChar(int ch)
{
	return ch >= 0x80 ||
				(isalnum(ch) || ch == '_');
}

static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,
                                 WordList *keywordlists[], Accessor &styler)
{

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];

	// property lexer.flagship.styling.within.preprocessor
	//	For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the
	//	initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code.
	bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0;

	CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");

	int visibleChars = 0;
	int closeStringChar = 0;
	int styleBeforeDCKeyword = SCE_FS_DEFAULT;
	bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_FS_OPERATOR:
			case SCE_FS_OPERATOR_C:
			case SCE_FS_WORDOPERATOR:
				sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				break;
			case SCE_FS_IDENTIFIER:
			case SCE_FS_IDENTIFIER_C:
				if (!IsAWordChar(sc.ch)) {
					char s[64];
					sc.GetCurrentLowered(s, sizeof(s));
					if (keywords.InList(s)) {
						sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C);
					} else if (bEnableCode && keywords3.InList(s)) {
						sc.ChangeState(SCE_FS_KEYWORD3);
					} else if (bEnableCode && keywords4.InList(s)) {
						sc.ChangeState(SCE_FS_KEYWORD4);
					}// Else, it is really an identifier...
					sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				}
				break;
			case SCE_FS_NUMBER:
				if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
					sc.SetState(SCE_FS_DEFAULT);
				}
				break;
			case SCE_FS_NUMBER_C:
				if (!IsAWordChar(sc.ch) && sc.ch != '.') {
					sc.SetState(SCE_FS_DEFAULT_C);
				}
				break;
			case SCE_FS_CONSTANT:
				if (!IsAWordChar(sc.ch)) {
					sc.SetState(SCE_FS_DEFAULT);
				}
				break;
			case SCE_FS_STRING:
			case SCE_FS_STRING_C:
				if (sc.ch == closeStringChar) {
					sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				} else if (sc.atLineEnd) {
					sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C);
				}
				break;
			case SCE_FS_STRINGEOL:
			case SCE_FS_STRINGEOL_C:
				if (sc.atLineStart) {
					sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				}
				break;
			case SCE_FS_COMMENTDOC:
			case SCE_FS_COMMENTDOC_C:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C;
						sc.SetState(SCE_FS_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_FS_COMMENT:
			case SCE_FS_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_FS_DEFAULT);
				}
				break;
			case SCE_FS_COMMENTLINEDOC:
			case SCE_FS_COMMENTLINEDOC_C:
				if (sc.atLineStart) {
					sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				} else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
					// Verify that we have the conditions to mark a comment-doc-keyword
					if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
						styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C;
						sc.SetState(SCE_FS_COMMENTDOCKEYWORD);
					}
				}
				break;
			case SCE_FS_COMMENTDOCKEYWORD:
				if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) &&
						sc.Match('*', '/')) {
					sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR);
					sc.Forward();
					sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				} else if (!setDoxygen.Contains(sc.ch)) {
					char s[64];
					sc.GetCurrentLowered(s, sizeof(s));
					if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) {
						sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR);
					}
					sc.SetState(styleBeforeDCKeyword);
				}
				break;
			case SCE_FS_PREPROCESSOR:
			case SCE_FS_PREPROCESSOR_C:
				if (sc.atLineEnd) {
					if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) {
						sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
					}
				} else if (stylingWithinPreprocessor) {
					if (IsASpaceOrTab(sc.ch)) {
						sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
					}
				} else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) {
					sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				}
				break;
			case SCE_FS_DISABLEDCODE:
				if (sc.ch == '#' && visibleChars == 0) {
					sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C);
					do {	// Skip whitespace between # and preprocessor word
						sc.Forward();
					} while (IsASpaceOrTab(sc.ch) && sc.More());
					if (sc.MatchIgnoreCase("pragma")) {
						sc.Forward(6);
						do {	// Skip more whitespace until keyword
							sc.Forward();
						} while (IsASpaceOrTab(sc.ch) && sc.More());
						if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) {
							bEnableCode = true;
							sc.SetState(SCE_FS_DISABLEDCODE);
							sc.Forward(sc.ch == '_' ? 8 : 6);
							sc.ForwardSetState(SCE_FS_DEFAULT);
						} else {
							sc.ChangeState(SCE_FS_DISABLEDCODE);
						}
					} else {
						sc.ChangeState(SCE_FS_DISABLEDCODE);
					}
				}
				break;
			case SCE_FS_DATE:
				if (sc.ch == '}') {
					sc.ForwardSetState(SCE_FS_DEFAULT);
				} else if (sc.atLineEnd) {
					sc.ChangeState(SCE_FS_STRINGEOL);
				}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) {
			if (bEnableCode &&
					(sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) {
				sc.SetState(SCE_FS_WORDOPERATOR);
				sc.Forward(4);
			} else if (bEnableCode && sc.MatchIgnoreCase(".or.")) {
				sc.SetState(SCE_FS_WORDOPERATOR);
				sc.Forward(3);
			} else if (bEnableCode &&
					(sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") ||
					(!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) {
				sc.SetState(SCE_FS_CONSTANT);
				sc.Forward(2);
			} else if (sc.Match('/', '*')) {
				sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C);
				sc.Forward();
			} else if (bEnableCode && sc.Match('&', '&')) {
				sc.SetState(SCE_FS_COMMENTLINE);
				sc.Forward();
			} else if (sc.Match('/', '/')) {
				sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C);
				sc.Forward();
			} else if (bEnableCode && sc.ch == '*' && visibleChars == 0) {
				sc.SetState(SCE_FS_COMMENT);
			} else if (sc.ch == '\"' || sc.ch == '\'') {
				sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C);
				closeStringChar = sc.ch;
			} else if (closeStringChar == '>' && sc.ch == '<') {
				sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C);
			} else if (sc.ch == '#' && visibleChars == 0) {
				sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C);
				do {	// Skip whitespace between # and preprocessor word
					sc.Forward();
				} while (IsASpaceOrTab(sc.ch) && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C);
				} else if (sc.MatchIgnoreCase("include")) {
					if (stylingWithinPreprocessor) {
						closeStringChar = '>';
					}
				} else if (sc.MatchIgnoreCase("pragma")) {
					sc.Forward(6);
					do {	// Skip more whitespace until keyword
						sc.Forward();
					} while (IsASpaceOrTab(sc.ch) && sc.More());
					if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) {
						bEnableCode = false;
						if (stylingWithinPreprocessor) {
							sc.SetState(SCE_FS_DISABLEDCODE);
							sc.Forward(8);
							sc.ForwardSetState(SCE_FS_DEFAULT_C);
						} else {
							sc.SetState(SCE_FS_DISABLEDCODE);
						}
					} else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) {
						bEnableCode = true;
						sc.SetState(SCE_FS_DISABLEDCODE);
						sc.Forward(sc.ch == '_' ? 8 : 6);
						sc.ForwardSetState(SCE_FS_DEFAULT);
					}
				}
			} else if (bEnableCode && sc.ch == '{') {
				int p = 0;
				int chSeek;
				unsigned int endPos(startPos + length);
				do {	// Skip whitespace
					chSeek = sc.GetRelative(++p);
				} while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos));
				if (chSeek == '^') {
					sc.SetState(SCE_FS_DATE);
				} else {
					sc.SetState(SCE_FS_OPERATOR);
				}
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C);
			} else if (IsAWordChar(sc.ch)) {
				sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C);
			} else if (isoperator(static_cast<char>(sc.ch)) || (bEnableCode && sc.ch == '@')) {
				sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C);
			}
		}

		if (sc.atLineEnd) {
			visibleChars = 0;
			closeStringChar = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldFlagShipDoc(unsigned int startPos, int length, int,
									WordList *[], Accessor &styler)
{

	int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0 && lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
	char chNext = styler[startPos];
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}
}

static const char * const FSWordListDesc[] = {
	"Keywords Commands",
	"Std Library Functions",
	"Procedure, return, exit",
	"Class (oop)",
	"Doxygen keywords",
	0
};

LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);

Added lexers/LexForth.cxx.







































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexForth.cxx
 ** Lexer for FORTH
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
		ch == '_' || ch == '?' || ch == '"' || ch == '@' ||
		ch == '!' || ch == '[' || ch == ']' || ch == '/' ||
		ch == '+' || ch == '-' || ch == '*' || ch == '<' ||
		ch == '>' || ch == '=' || ch == ';' || ch == '(' ||
		ch == ')' );
}

static inline bool IsAWordStart(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
}

static inline bool IsANumChar(int ch) {
	return (ch < 0x80) && (isxdigit(ch) || ch == '.' || ch == 'e' || ch == 'E' );
}

static inline bool IsASpaceChar(int ch) {
	return (ch < 0x80) && isspace(ch);
}

static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, WordList *keywordLists[],
                            Accessor &styler) {

    WordList &control = *keywordLists[0];
    WordList &keyword = *keywordLists[1];
    WordList &defword = *keywordLists[2];
    WordList &preword1 = *keywordLists[3];
    WordList &preword2 = *keywordLists[4];
    WordList &strings = *keywordLists[5];

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward())
	{
		// Determine if the current state should terminate.
		if (sc.state == SCE_FORTH_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_FORTH_DEFAULT);
			}
		}else if (sc.state == SCE_FORTH_COMMENT_ML) {
			if (sc.ch == ')') {
				sc.ForwardSetState(SCE_FORTH_DEFAULT);
			}
		}else if (sc.state == SCE_FORTH_IDENTIFIER || sc.state == SCE_FORTH_NUMBER) {
			// handle numbers here too, because what we thought was a number might
			// turn out to be a keyword e.g. 2DUP
			if (IsASpaceChar(sc.ch) ) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				int newState = sc.state == SCE_FORTH_NUMBER ? SCE_FORTH_NUMBER : SCE_FORTH_DEFAULT;
				if (control.InList(s)) {
					sc.ChangeState(SCE_FORTH_CONTROL);
				} else if (keyword.InList(s)) {
					sc.ChangeState(SCE_FORTH_KEYWORD);
				} else if (defword.InList(s)) {
					sc.ChangeState(SCE_FORTH_DEFWORD);
				}  else if (preword1.InList(s)) {
					sc.ChangeState(SCE_FORTH_PREWORD1);
				} else if (preword2.InList(s)) {
					sc.ChangeState(SCE_FORTH_PREWORD2);
				} else if (strings.InList(s)) {
					sc.ChangeState(SCE_FORTH_STRING);
					newState = SCE_FORTH_STRING;
				}
				sc.SetState(newState);
			}
			if (sc.state == SCE_FORTH_NUMBER) {
				if (IsASpaceChar(sc.ch)) {
					sc.SetState(SCE_FORTH_DEFAULT);
				} else if (!IsANumChar(sc.ch)) {
					sc.ChangeState(SCE_FORTH_IDENTIFIER);
				}
			}
		}else if (sc.state == SCE_FORTH_STRING) {
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_FORTH_DEFAULT);
			}
		}else if (sc.state == SCE_FORTH_LOCALE) {
			if (sc.ch == '}') {
				sc.ForwardSetState(SCE_FORTH_DEFAULT);
			}
		}else if (sc.state == SCE_FORTH_DEFWORD) {
			if (IsASpaceChar(sc.ch)) {
				sc.SetState(SCE_FORTH_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_FORTH_DEFAULT) {
			if (sc.ch == '\\'){
				sc.SetState(SCE_FORTH_COMMENT);
			} else if (sc.ch == '(' &&
					(sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
					(sc.atLineEnd   || IsASpaceChar(sc.chNext))) {
				sc.SetState(SCE_FORTH_COMMENT_ML);
			} else if (	(sc.ch == '$' && (isascii(sc.chNext) && isxdigit(sc.chNext))) ) {
				// number starting with $ is a hex number
				sc.SetState(SCE_FORTH_NUMBER);
				while(sc.More() && isascii(sc.chNext) && isxdigit(sc.chNext))
					sc.Forward();
			} else if ( (sc.ch == '%' && (isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))) ) {
				// number starting with % is binary
				sc.SetState(SCE_FORTH_NUMBER);
				while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1'))
					sc.Forward();
			} else if (	isascii(sc.ch) &&
						(isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) )
					){
				sc.SetState(SCE_FORTH_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_FORTH_IDENTIFIER);
			} else if (sc.ch == '{') {
				sc.SetState(SCE_FORTH_LOCALE);
			} else if (sc.ch == ':' && isascii(sc.chNext) && isspace(sc.chNext)) {
				// highlight word definitions e.g.  : GCD ( n n -- n ) ..... ;
				//                                  ^ ^^^
				sc.SetState(SCE_FORTH_DEFWORD);
				while(sc.More() && isascii(sc.chNext) && isspace(sc.chNext))
					sc.Forward();
			} else if (sc.ch == ';' &&
					(sc.atLineStart || IsASpaceChar(sc.chPrev)) &&
					(sc.atLineEnd   || IsASpaceChar(sc.chNext))	) {
				// mark the ';' that ends a word
				sc.SetState(SCE_FORTH_DEFWORD);
				sc.ForwardSetState(SCE_FORTH_DEFAULT);
			}
		}

	}
	sc.Complete();
}

static void FoldForthDoc(unsigned int, int, int, WordList *[],
						Accessor &) {
}

static const char * const forthWordLists[] = {
			"control keywords",
			"keywords",
			"definition words",
			"prewords with one argument",
			"prewords with two arguments",
			"string definition keywords",
			0,
		};

LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists);


Added lexers/LexFortran.cxx.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
// Scintilla source code edit control
/** @file LexFortran.cxx
 ** Lexer for Fortran.
 ** Writen by Chuan-jian Shen, Last changed Sep. 2003
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
/***************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
/***************************************/
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
/***************************************/

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/***********************************************/
static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '%');
}
/**********************************************/
static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch));
}
/***************************************/
inline bool IsABlank(unsigned int ch) {
    return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ;
}
/***************************************/
inline bool IsALineEnd(char ch) {
    return ((ch == '\n') || (ch == '\r')) ;
}
/***************************************/
unsigned int GetContinuedPos(unsigned int pos, Accessor &styler) {
	while (!IsALineEnd(styler.SafeGetCharAt(pos++))) continue;
	if (styler.SafeGetCharAt(pos) == '\n') pos++;
	while (IsABlank(styler.SafeGetCharAt(pos++))) continue;
	char chCur = styler.SafeGetCharAt(pos);
	if (chCur == '&') {
		while (IsABlank(styler.SafeGetCharAt(++pos))) continue;
		return pos;
	} else {
		return pos;
	}
}
/***************************************/
static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle,
			WordList *keywordlists[], Accessor &styler, bool isFixFormat) {
	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	/***************************************/
	int posLineStart = 0, numNonBlank = 0, prevState = 0;
	int endPos = startPos + length;
	/***************************************/
	// backtrack to the nearest keyword
	while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_F_WORD)) {
		startPos--;
	}
	startPos = styler.LineStart(styler.GetLine(startPos));
	initStyle = styler.StyleAt(startPos - 1);
	StyleContext sc(startPos, endPos-startPos, initStyle, styler);
	/***************************************/
	for (; sc.More(); sc.Forward()) {
		// remember the start position of the line
		if (sc.atLineStart) {
			posLineStart = sc.currentPos;
			numNonBlank = 0;
			sc.SetState(SCE_F_DEFAULT);
		}
		if (!IsASpaceOrTab(sc.ch)) numNonBlank ++;
		/***********************************************/
		// Handle the fix format generically
		int toLineStart = sc.currentPos - posLineStart;
		if (isFixFormat && (toLineStart < 6 || toLineStart >= 72)) {
			if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') {
                if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") ||
                    sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") ||
                    sc.MatchIgnoreCase("cms$")  || sc.MatchIgnoreCase("*ms$")  || sc.MatchIgnoreCase("!ms$")  ||
                    sc.chNext == '$') {
                    sc.SetState(SCE_F_PREPROCESSOR);
				} else {
					sc.SetState(SCE_F_COMMENT);
				}

				while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end
			} else if (toLineStart >= 72) {
				sc.SetState(SCE_F_COMMENT);
				while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end
			} else if (toLineStart < 5) {
				if (IsADigit(sc.ch))
					sc.SetState(SCE_F_LABEL);
				else
					sc.SetState(SCE_F_DEFAULT);
			} else if (toLineStart == 5) {
				//if (!IsASpace(sc.ch) && sc.ch != '0') {
				if (sc.ch != '\r' && sc.ch != '\n') {
					sc.SetState(SCE_F_CONTINUATION);
                    if (!IsASpace(sc.ch) && sc.ch != '0')
                        sc.ForwardSetState(prevState);
				} else
					sc.SetState(SCE_F_DEFAULT);
			}
			continue;
		}
		/***************************************/
		// Hanndle preprocessor directives
		if (sc.ch == '#' && numNonBlank == 1)
		{
            sc.SetState(SCE_F_PREPROCESSOR);
            while (!sc.atLineEnd && sc.More())
                sc.Forward(); // Until line end
		}
		/***************************************/
		// Handle line continuation generically.
		if (!isFixFormat && sc.ch == '&' && sc.state != SCE_F_COMMENT) {
			char chTemp = ' ';
			int j = 1;
			while (IsABlank(chTemp) && j<132) {
				chTemp = static_cast<char>(sc.GetRelative(j));
				j++;
			}
			if (chTemp == '!') {
				sc.SetState(SCE_F_CONTINUATION);
				if (sc.chNext == '!') sc.ForwardSetState(SCE_F_COMMENT);
			} else if (chTemp == '\r' || chTemp == '\n') {
				int currentState = sc.state;
				sc.SetState(SCE_F_CONTINUATION);
				sc.ForwardSetState(SCE_F_DEFAULT);
				while (IsASpace(sc.ch) && sc.More()) sc.Forward();
				if (sc.ch == '&') {
					sc.SetState(SCE_F_CONTINUATION);
					sc.Forward();
				}
				sc.SetState(currentState);
			}
		}
		/***************************************/
		// Determine if the current state should terminate.
		if (sc.state == SCE_F_OPERATOR) {
			sc.SetState(SCE_F_DEFAULT);
		} else if (sc.state == SCE_F_NUMBER) {
			if (!(IsAWordChar(sc.ch) || sc.ch=='\'' || sc.ch=='\"' || sc.ch=='.')) {
				sc.SetState(SCE_F_DEFAULT);
			}
		} else if (sc.state == SCE_F_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '%')) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_F_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_F_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_F_WORD3);
				}
				sc.SetState(SCE_F_DEFAULT);
			}
		} else if (sc.state == SCE_F_COMMENT || sc.state == SCE_F_PREPROCESSOR) {
			if (sc.ch == '\r' || sc.ch == '\n') {
				sc.SetState(SCE_F_DEFAULT);
			}
		} else if (sc.state == SCE_F_STRING1) {
			prevState = sc.state;
			if (sc.ch == '\'') {
				if (sc.chNext == '\'') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_F_DEFAULT);
					prevState = SCE_F_DEFAULT;
				}
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_F_STRINGEOL);
				sc.ForwardSetState(SCE_F_DEFAULT);
			}
		} else if (sc.state == SCE_F_STRING2) {
			prevState = sc.state;
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_F_STRINGEOL);
				sc.ForwardSetState(SCE_F_DEFAULT);
			} else if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_F_DEFAULT);
					prevState = SCE_F_DEFAULT;
				}
			}
		} else if (sc.state == SCE_F_OPERATOR2) {
			if (sc.ch == '.') {
				sc.ForwardSetState(SCE_F_DEFAULT);
			}
		} else if (sc.state == SCE_F_CONTINUATION) {
			sc.SetState(SCE_F_DEFAULT);
		} else if (sc.state == SCE_F_LABEL) {
			if (!IsADigit(sc.ch)) {
				sc.SetState(SCE_F_DEFAULT);
			} else {
				if (isFixFormat && sc.currentPos-posLineStart > 4)
					sc.SetState(SCE_F_DEFAULT);
				else if (numNonBlank > 5)
					sc.SetState(SCE_F_DEFAULT);
			}
		}
		/***************************************/
		// Determine if a new state should be entered.
		if (sc.state == SCE_F_DEFAULT) {
			if (sc.ch == '!') {
                if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") ||
                    sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') {
					sc.SetState(SCE_F_PREPROCESSOR);
				} else {
					sc.SetState(SCE_F_COMMENT);
				}
			} else if ((!isFixFormat) && IsADigit(sc.ch) && numNonBlank == 1) {
				sc.SetState(SCE_F_LABEL);
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_F_NUMBER);
			} else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' ||
					    tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) {
				sc.SetState(SCE_F_NUMBER);
				sc.Forward();
			} else if (sc.ch == '.' && isalpha(sc.chNext)) {
				sc.SetState(SCE_F_OPERATOR2);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_F_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_F_STRING2);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_F_STRING1);
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_F_OPERATOR);
			}
		}
	}
	sc.Complete();
}
/***************************************/
// To determine the folding level depending on keywords
static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) {
	int lev = 0;
	if ((strcmp(prevWord, "else") == 0 && strcmp(s, "if") == 0) || strcmp(s, "elseif") == 0)
		return -1;
	if (strcmp(s, "associate") == 0 || strcmp(s, "block") == 0
	    || strcmp(s, "blockdata") == 0 || strcmp(s, "select") == 0
	    || strcmp(s, "do") == 0 || strcmp(s, "enum") ==0
	    || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0
		|| strcmp(s, "module") == 0 || strcmp(s, "program") == 0
		|| strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0
		|| (strcmp(s, "type") == 0 && chNextNonBlank != '(')
        || strcmp(s, "critical") == 0){
			if (strcmp(prevWord, "end") == 0)
				lev = 0;
			else
				lev = 1;
	} else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=')
		|| strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0
		|| strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0
		|| strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0
		|| strcmp(s, "endif") == 0 || strcmp(s, "endforall") == 0
		|| strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0
		|| strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0
		|| strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0
		|| strcmp(s, "endwhere") == 0 || strcmp(s, "endcritical") == 0
		|| (strcmp(s, "procedure") == 0 && strcmp(prevWord, "module") == 0) ) { // Take care of the "module procedure" statement
			lev = -1;
	} else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if
			lev = 0;
	} else if (strcmp(prevWord, "type") == 0 && strcmp(s, "is") == 0){ // type is
                        lev = -1;
        }
	return lev;
}
// Folding the code
static void FoldFortranDoc(unsigned int startPos, int length, int initStyle,
						   Accessor &styler, bool isFixFormat) {
	//
	// bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	// Do not know how to fold the comment at the moment.
	//
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	char chNextNonBlank;
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	/***************************************/
	int lastStart = 0;
	char prevWord[32] = "";
	char Label[6] = "";
	// Variables for do label folding.
	static int doLabels[100];
	static int posLabel=-1;
	/***************************************/
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		chNextNonBlank = chNext;
		unsigned int j=i+1;
		while(IsABlank(chNextNonBlank) && j<endPos) {
			j ++ ;
			chNextNonBlank = styler.SafeGetCharAt(j);
		}
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		//
		if (((isFixFormat && stylePrev == SCE_F_CONTINUATION) || stylePrev == SCE_F_DEFAULT || stylePrev == SCE_F_OPERATOR) && (style == SCE_F_WORD || style == SCE_F_LABEL)) {
			// Store last word and label start point.
			lastStart = i;
		}
		/***************************************/
		if (style == SCE_F_WORD) {
			if(iswordchar(ch) && !iswordchar(chNext)) {
				char s[32];
				unsigned int k;
				for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) {
					s[k] = static_cast<char>(tolower(styler[lastStart+k]));
				}
				s[k] = '\0';
				// Handle the forall and where statement and structure.
				if (strcmp(s, "forall") == 0 || strcmp(s, "where") == 0) {
					if (strcmp(prevWord, "end") != 0) {
						j = i + 1;
						char chBrace = '(', chSeek = ')', ch1 = styler.SafeGetCharAt(j);
						// Find the position of the first (
						while (ch1 != chBrace && j<endPos) {
							j++;
							ch1 = styler.SafeGetCharAt(j);
						}
						char styBrace = styler.StyleAt(j);
						int depth = 1;
						char chAtPos;
						char styAtPos;
						while (j<endPos) {
							j++;
							chAtPos = styler.SafeGetCharAt(j);
							styAtPos = styler.StyleAt(j);
							if (styAtPos == styBrace) {
								if (chAtPos == chBrace) depth++;
								if (chAtPos == chSeek) depth--;
								if (depth == 0) break;
							}
						}
						while (j<endPos) {
							j++;
							chAtPos = styler.SafeGetCharAt(j);
							styAtPos = styler.StyleAt(j);
							if (styAtPos == SCE_F_COMMENT || IsABlank(chAtPos)) continue;
							if (isFixFormat) {
								if (!IsALineEnd(chAtPos)) {
									break;
								} else {
									if (lineCurrent < styler.GetLine(styler.Length()-1)) {
										j = styler.LineStart(lineCurrent+1);
										if (styler.StyleAt(j+5) == SCE_F_CONTINUATION) {
											j += 5;
											continue;
										} else {
											levelCurrent++;
											break;
										}
									}
								}
							} else {
								if (chAtPos == '&' && styler.StyleAt(j) == SCE_F_CONTINUATION) {
									j = GetContinuedPos(j+1, styler);
									continue;
								} else if (IsALineEnd(chAtPos)) {
									levelCurrent ++;
									break;
								} else {
									break;
								}
							}
						}
					}
				} else {
					levelCurrent += classifyFoldPointFortran(s, prevWord, chNextNonBlank);
					// Store the do Labels into array
					if (strcmp(s, "do") == 0 && IsADigit(chNextNonBlank)) {
						unsigned int k = 0;
						for (i=j; (i<j+5 && i<endPos); i++) {
							ch = styler.SafeGetCharAt(i);
							if (IsADigit(ch))
								Label[k++] = ch;
							else
								break;
						}
						Label[k] = '\0';
						posLabel ++;
						doLabels[posLabel] = atoi(Label);
					}
				}
				strcpy(prevWord, s);
			}
		} else if (style == SCE_F_LABEL) {
			if(IsADigit(ch) && !IsADigit(chNext)) {
				for(j = 0; ( j < 5 ) && ( j < i-lastStart+1 ); j++) {
					ch = styler.SafeGetCharAt(lastStart + j);
					if (IsADigit(ch) && styler.StyleAt(lastStart+j) == SCE_F_LABEL)
						Label[j] = ch;
					else
						break;
				}
				Label[j] = '\0';
				while (doLabels[posLabel] == atoi(Label) && posLabel > -1) {
					levelCurrent--;
					posLabel--;
				}
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
			strcpy(prevWord, "");
		}
		/***************************************/
		if (!isspacechar(ch)) visibleChars++;
	}
	/***************************************/
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
/***************************************/
static const char * const FortranWordLists[] = {
	"Primary keywords and identifiers",
	"Intrinsic functions",
	"Extended and user defined functions",
	0,
};
/***************************************/
static void ColouriseFortranDocFreeFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {
	ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, false);
}
/***************************************/
static void ColouriseFortranDocFixFormat(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {
	ColouriseFortranDoc(startPos, length, initStyle, keywordlists, styler, true);
}
/***************************************/
static void FoldFortranDocFreeFormat(unsigned int startPos, int length, int initStyle,
		WordList *[], Accessor &styler) {
	FoldFortranDoc(startPos, length, initStyle,styler, false);
}
/***************************************/
static void FoldFortranDocFixFormat(unsigned int startPos, int length, int initStyle,
		WordList *[], Accessor &styler) {
	FoldFortranDoc(startPos, length, initStyle,styler, true);
}
/***************************************/
LexerModule lmFortran(SCLEX_FORTRAN, ColouriseFortranDocFreeFormat, "fortran", FoldFortranDocFreeFormat, FortranWordLists);
LexerModule lmF77(SCLEX_F77, ColouriseFortranDocFixFormat, "f77", FoldFortranDocFixFormat, FortranWordLists);

Added lexers/LexGAP.cxx.





















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// Scintilla source code edit control
/** @file LexGAP.cxx
 ** Lexer for the GAP language. (The GAP System for Computational Discrete Algebra)
 ** http://www.gap-system.org
 **/
// Copyright 2007 by Istvan Szollosi ( szteven <at> gmail <dot> com )
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsGAPOperator(char ch) {
	if (isascii(ch) && isalnum(ch)) return false;
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
		ch == '^' || ch == ',' || ch == '!' || ch == '.' ||
		ch == '=' || ch == '<' || ch == '>' || ch == '(' ||
		ch == ')' || ch == ';' || ch == '[' || ch == ']' ||
		ch == '{' || ch == '}' || ch == ':' )
		return true;
	return false;
}

static void GetRange(unsigned int start, unsigned int end, Accessor &styler, char *s, unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(styler[start + i]);
		i++;
	}
	s[i] = '\0';
}

static void ColouriseGAPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {

	WordList &keywords1 = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_GAP_STRINGEOL) initStyle = SCE_GAP_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Prevent SCE_GAP_STRINGEOL from leaking back to previous line
		if ( sc.atLineStart ) {
			if (sc.state == SCE_GAP_STRING) sc.SetState(SCE_GAP_STRING);
			if (sc.state == SCE_GAP_CHAR) sc.SetState(SCE_GAP_CHAR);
		}

		// Handle line continuation generically
		if (sc.ch == '\\' ) {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate
		switch (sc.state) {
			case SCE_GAP_OPERATOR :
				sc.SetState(SCE_GAP_DEFAULT);
				break;

			case SCE_GAP_NUMBER :
				if (!IsADigit(sc.ch)) {
					if (sc.ch == '\\') {
						if (!sc.atLineEnd) {
							if (!IsADigit(sc.chNext)) {
								sc.Forward();
								sc.ChangeState(SCE_GAP_IDENTIFIER);
							}
						}
					} else if (isalpha(sc.ch) || sc.ch == '_') {
						sc.ChangeState(SCE_GAP_IDENTIFIER);
					}
					else sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_IDENTIFIER :
				if (!(iswordstart(static_cast<char>(sc.ch)) || sc.ch == '$')) {
					if (sc.ch == '\\') sc.Forward();
					else {
						char s[1000];
						sc.GetCurrent(s, sizeof(s));
						if (keywords1.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD);
						} else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD2);
						} else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD3);
						} else if (keywords4.InList(s)) {
							sc.ChangeState(SCE_GAP_KEYWORD4);
						}
						sc.SetState(SCE_GAP_DEFAULT);
					}
				}
				break;

			case SCE_GAP_COMMENT :
				if (sc.atLineEnd) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_CHAR:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_GAP_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_GAP_DEFAULT);
				}
				break;

			case SCE_GAP_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_GAP_DEFAULT);
				}
				break;
		}

		// Determine if a new state should be entered
		if (sc.state == SCE_GAP_DEFAULT) {
			if (IsGAPOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_GAP_OPERATOR);
			}
			else if (IsADigit(sc.ch)) {
				sc.SetState(SCE_GAP_NUMBER);
			} else if (isalpha(sc.ch) || sc.ch == '_' || sc.ch == '\\' || sc.ch == '$' || sc.ch == '~') {
				sc.SetState(SCE_GAP_IDENTIFIER);
				if (sc.ch == '\\') sc.Forward();
			} else if (sc.ch == '#') {
				sc.SetState(SCE_GAP_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_GAP_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_GAP_CHAR);
			}
		}

	}
	sc.Complete();
}

static int ClassifyFoldPointGAP(const char* s) {
	int level = 0;
	if (strcmp(s, "function") == 0 ||
		strcmp(s, "do") == 0 ||
		strcmp(s, "if") == 0 ||
		strcmp(s, "repeat") == 0 ) {
		level = 1;
	} else if (strcmp(s, "end") == 0 ||
			strcmp(s, "od") == 0 ||
			strcmp(s, "fi") == 0 ||
			strcmp(s, "until") == 0 ) {
		level = -1;
	}
	return level;
}

static void FoldGAPDoc( unsigned int startPos, int length, int initStyle,   WordList** , Accessor &styler) {
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	int lastStart = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev != SCE_GAP_KEYWORD && style == SCE_GAP_KEYWORD) {
			// Store last word start point.
			lastStart = i;
		}

		if (stylePrev == SCE_GAP_KEYWORD) {
			if(iswordchar(ch) && !iswordchar(chNext)) {
				char s[100];
				GetRange(lastStart, i, styler, s, sizeof(s));
				levelCurrent += ClassifyFoldPointGAP(s);
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const GAPWordListDesc[] = {
	"Keywords 1",
	"Keywords 2",
	"Keywords 3 (unused)",
	"Keywords 4 (unused)",
	0
};

LexerModule lmGAP(
   SCLEX_GAP,
   ColouriseGAPDoc,
   "gap",
   FoldGAPDoc,
   GAPWordListDesc);

Added lexers/LexGui4Cli.cxx.

























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// Scintilla source code edit control
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
/*
This is the Lexer for Gui4Cli, included in SciLexer.dll
- by d. Keletsekis, 2/10/2003

To add to SciLexer.dll:
1. Add the values below to INCLUDE\Scintilla.iface
2. Run the include/HFacer.py script
3. Run the src/lexGen.py script

val SCE_GC_DEFAULT=0
val SCE_GC_COMMENTLINE=1
val SCE_GC_COMMENTBLOCK=2
val SCE_GC_GLOBAL=3
val SCE_GC_EVENT=4
val SCE_GC_ATTRIBUTE=5
val SCE_GC_CONTROL=6
val SCE_GC_COMMAND=7
val SCE_GC_STRING=8
val SCE_GC_OPERATOR=9
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define debug Platform::DebugPrintf

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
}

inline bool isGCOperator(int ch)
{	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		 ch == '(' || ch == ')' || ch == '=' || ch == '%' ||
		 ch == '[' || ch == ']' || ch == '<' || ch == '>' ||
		 ch == ',' || ch == ';' || ch == ':')
		return true;
	return false;
}

#define isSpace(x)		((x)==' ' || (x)=='\t')
#define isNL(x)			((x)=='\n' || (x)=='\r')
#define isSpaceOrNL(x)  (isSpace(x) || isNL(x))
#define BUFFSIZE 500
#define isFoldPoint(x)  ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)

static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
									StyleContext *sc, char *buff, int length, int)
{
	int c = 0;
	while (sc->More() && isSpaceOrNL(sc->ch))
	{	sc->Forward();
	}
	styler.ColourTo(sc->currentPos - 1, sc->state);

	if (!IsAWordChar(sc->ch)) // comment, marker, etc..
		return;

	while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
	{	buff[c] = static_cast<char>(sc->ch);
		++c; sc->Forward();
	}
	buff[c] = '\0';
	char *p = buff;
	while (*p)	// capitalize..
	{	if (islower(*p)) *p = static_cast<char>(toupper(*p));
		++p;
	}

	WordList &kGlobal		= *keywordlists[0];	// keyword lists set by the user
	WordList &kEvent		= *keywordlists[1];
	WordList &kAttribute	= *keywordlists[2];
	WordList &kControl	= *keywordlists[3];
	WordList &kCommand	= *keywordlists[4];

	int state = 0;
	// int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
	// debug ("line = %d, level = %d", line, level);

	if	     (kGlobal.InList(buff))		state = SCE_GC_GLOBAL;
	else if (kAttribute.InList(buff))	state = SCE_GC_ATTRIBUTE;
	else if (kControl.InList(buff))		state = SCE_GC_CONTROL;
	else if (kCommand.InList(buff))		state = SCE_GC_COMMAND;
	else if (kEvent.InList(buff))			state = SCE_GC_EVENT;

	if (state)
	{	sc->ChangeState(state);
		styler.ColourTo(sc->currentPos - 1, sc->state);
		sc->ChangeState(SCE_GC_DEFAULT);
	}
	else
	{	sc->ChangeState(SCE_GC_DEFAULT);
		styler.ColourTo(sc->currentPos - 1, sc->state);
	}
}

// Main colorizing function called by Scintilla
static void
ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
                    WordList *keywordlists[], Accessor &styler)
{
	styler.StartAt(startPos);

	int quotestart = 0, oldstate, currentline = styler.GetLine(startPos);
	styler.StartSegment(startPos);
	bool noforward;
	char buff[BUFFSIZE+1];	// buffer for command name

	StyleContext sc(startPos, length, initStyle, styler);
	buff[0] = '\0'; // cbuff = 0;

	if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
		colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);

	while (sc.More())
	{	noforward = 0;

		switch (sc.ch)
		{
			case '/':
				if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
					break;
				if (sc.chNext == '/')	// line comment
				{	sc.SetState (SCE_GC_COMMENTLINE);
					sc.Forward();
					styler.ColourTo(sc.currentPos, sc.state);
				}
				else if (sc.chNext == '*')	// block comment
				{	sc.SetState(SCE_GC_COMMENTBLOCK);
					sc.Forward();
					styler.ColourTo(sc.currentPos, sc.state);
				}
				else
					styler.ColourTo(sc.currentPos, sc.state);
				break;

			case '*':	// end of comment block, or operator..
				if (sc.state == SCE_GC_STRING)
					break;
				if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
				{	sc.Forward();
					styler.ColourTo(sc.currentPos, sc.state);
					sc.ChangeState (SCE_GC_DEFAULT);
				}
				else
					styler.ColourTo(sc.currentPos, sc.state);
				break;

			case '\'':	case '\"': // strings..
				if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
					break;
				if (sc.state == SCE_GC_STRING)
				{	if (sc.ch == quotestart)	// match same quote char..
					{	styler.ColourTo(sc.currentPos, sc.state);
						sc.ChangeState(SCE_GC_DEFAULT);
						quotestart = 0;
				}	}
				else
				{	styler.ColourTo(sc.currentPos - 1, sc.state);
					sc.ChangeState(SCE_GC_STRING);
					quotestart = sc.ch;
				}
				break;

			case ';':	// end of commandline character
				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
					 sc.state != SCE_GC_STRING)
				{
					styler.ColourTo(sc.currentPos - 1, sc.state);
					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
					sc.ChangeState(SCE_GC_DEFAULT);
					sc.Forward();
					colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
					noforward = 1; // don't move forward - already positioned at next char..
				}
				break;

			case '+': case '-': case '=':	case '!':	// operators..
			case '<': case '>': case '&': case '|': case '$':
				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
					 sc.state != SCE_GC_STRING)
				{
					styler.ColourTo(sc.currentPos - 1, sc.state);
					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
					sc.ChangeState(SCE_GC_DEFAULT);
				}
				break;

			case '\\':	// escape - same as operator, but also mark in strings..
				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
				{
					oldstate = sc.state;
					styler.ColourTo(sc.currentPos - 1, sc.state);
					sc.Forward(); // mark also the next char..
					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
					sc.ChangeState(oldstate);
				}
				break;

			case '\n': case '\r':
				++currentline;
				if (sc.state == SCE_GC_COMMENTLINE)
				{	styler.ColourTo(sc.currentPos, sc.state);
					sc.ChangeState (SCE_GC_DEFAULT);
				}
				else if (sc.state != SCE_GC_COMMENTBLOCK)
				{	colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
					noforward = 1; // don't move forward - already positioned at next char..
				}
				break;

//			case ' ': case '\t':
//			default :
		}

		if (!noforward) sc.Forward();

	}
	sc.Complete();
}

// Main folding function called by Scintilla - (based on props (.ini) files function)
static void FoldGui4Cli(unsigned int startPos, int length, int,
								WordList *[], Accessor &styler)
{
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);

	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	bool headerPoint = false;

	for (unsigned int i = startPos; i < endPos; i++)
	{
		char ch = chNext;
		chNext = styler[i+1];

		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
		{	headerPoint = true; // fold at events and globals
		}

		if (atEOL)
		{	int lev = SC_FOLDLEVELBASE+1;

			if (headerPoint)
				lev = SC_FOLDLEVELBASE;

			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;

			if (headerPoint)
				lev |= SC_FOLDLEVELHEADERFLAG;

			if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
			{	styler.SetLevel(lineCurrent, lev);
			}

			lineCurrent++;		// re-initialize our flags
			visibleChars = 0;
			headerPoint = false;
		}

		if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
			visibleChars++;
	}

	int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, lev | flagsNext);
}

// I have no idea what these are for.. probably accessible by some message.
static const char * const gui4cliWordListDesc[] = {
	"Globals", "Events", "Attributes", "Control", "Commands",
	0
};

// Declare language & pass our function pointers to Scintilla
LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);

#undef debug

Added lexers/LexHTML.cxx.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
// Scintilla source code edit control
/** @file LexHTML.cxx
 ** Lexer for HTML.
 **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)

enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment };
enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc };

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool IsOperator(int ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
	        ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
	        ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
	        ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
	        ch == '?' || ch == '!' || ch == '.' || ch == '~')
		return true;
	return false;
}

static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) {
	unsigned int i = 0;
	for (; (i < end - start + 1) && (i < len-1); i++) {
		s[i] = static_cast<char>(MakeLowerCase(styler[start + i]));
	}
	s[i] = '\0';
}

static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) {

	unsigned int i = 0;
	for (; i < sLen-1; i++) {
		char ch = static_cast<char>(styler.SafeGetCharAt(start + i));
		if ((i == 0) && !IsAWordStart(ch))
			break;
		if ((i > 0) && !IsAWordChar(ch))
			break;
		s[i] = ch;
	}
	s[i] = '\0';

	return s;
}

static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
	char s[100];
	GetTextSegment(styler, start, end, s, sizeof(s));
	//Platform::DebugPrintf("Scripting indicator [%s]\n", s);
	if (strstr(s, "src"))	// External script
		return eScriptNone;
	if (strstr(s, "vbs"))
		return eScriptVBS;
	if (strstr(s, "pyth"))
		return eScriptPython;
	if (strstr(s, "javas"))
		return eScriptJS;
	if (strstr(s, "jscr"))
		return eScriptJS;
	if (strstr(s, "php"))
		return eScriptPHP;
	if (strstr(s, "xml")) {
		const char *xml = strstr(s, "xml");
		for (const char *t=s; t<xml; t++) {
			if (!IsASpace(*t)) {
				return prevValue;
			}
		}
		return eScriptXML;
	}

	return prevValue;
}

static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
	int iResult = 0;
	char s[100];
	GetTextSegment(styler, start, end, s, sizeof(s));
	if (0 == strncmp(s, "php", 3)) {
		iResult = 3;
	}

	return iResult;
}

static script_type ScriptOfState(int state) {
	if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
		return eScriptPython;
	} else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
		return eScriptVBS;
	} else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
		return eScriptJS;
	} else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) {
		return eScriptPHP;
	} else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) {
		return eScriptSGML;
	} else if (state == SCE_H_SGML_BLOCK_DEFAULT) {
		return eScriptSGMLblock;
	} else {
		return eScriptNone;
	}
}

static int statePrintForState(int state, script_mode inScriptType) {
	int StateToPrint = state;

	if (state >= SCE_HJ_START) {
		if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
			StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON);
		} else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
			StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS);
		} else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
			StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS);
		}
	}

	return StateToPrint;
}

static int stateForPrintState(int StateToPrint) {
	int state;

	if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) {
		state = StateToPrint - SCE_HA_PYTHON;
	} else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) {
		state = StateToPrint - SCE_HA_VBS;
	} else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) {
		state = StateToPrint - SCE_HA_JS;
	} else {
		state = StateToPrint;
	}

	return state;
}

static inline bool IsNumber(unsigned int start, Accessor &styler) {
	return IsADigit(styler[start]) || (styler[start] == '.') ||
	       (styler[start] == '-') || (styler[start] == '#');
}

static inline bool isStringState(int state) {
	bool bResult;

	switch (state) {
	case SCE_HJ_DOUBLESTRING:
	case SCE_HJ_SINGLESTRING:
	case SCE_HJA_DOUBLESTRING:
	case SCE_HJA_SINGLESTRING:
	case SCE_HB_STRING:
	case SCE_HBA_STRING:
	case SCE_HP_STRING:
	case SCE_HP_CHARACTER:
	case SCE_HP_TRIPLE:
	case SCE_HP_TRIPLEDOUBLE:
	case SCE_HPA_STRING:
	case SCE_HPA_CHARACTER:
	case SCE_HPA_TRIPLE:
	case SCE_HPA_TRIPLEDOUBLE:
	case SCE_HPHP_HSTRING:
	case SCE_HPHP_SIMPLESTRING:
	case SCE_HPHP_HSTRING_VARIABLE:
	case SCE_HPHP_COMPLEX_VARIABLE:
		bResult = true;
		break;
	default :
		bResult = false;
		break;
	}
	return bResult;
}

static inline bool stateAllowsTermination(int state) {
	bool allowTermination = !isStringState(state);
	if (allowTermination) {
		switch (state) {
		case SCE_HB_COMMENTLINE:
		case SCE_HPHP_COMMENT:
		case SCE_HP_COMMENTLINE:
		case SCE_HPA_COMMENTLINE:
			allowTermination = false;
		}
	}
	return allowTermination;
}

// not really well done, since it's only comments that should lex the %> and <%
static inline bool isCommentASPState(int state) {
	bool bResult;

	switch (state) {
	case SCE_HJ_COMMENT:
	case SCE_HJ_COMMENTLINE:
	case SCE_HJ_COMMENTDOC:
	case SCE_HB_COMMENTLINE:
	case SCE_HP_COMMENTLINE:
	case SCE_HPHP_COMMENT:
	case SCE_HPHP_COMMENTLINE:
		bResult = true;
		break;
	default :
		bResult = false;
		break;
	}
	return bResult;
}

static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	bool wordIsNumber = IsNumber(start, styler);
	char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
	if (wordIsNumber) {
		chAttr = SCE_H_NUMBER;
	} else {
		char s[100];
		GetTextSegment(styler, start, end, s, sizeof(s));
		if (keywords.InList(s))
			chAttr = SCE_H_ATTRIBUTE;
	}
	if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords)
		// No keywords -> all are known
		chAttr = SCE_H_ATTRIBUTE;
	styler.ColourTo(end, chAttr);
}

static int classifyTagHTML(unsigned int start, unsigned int end,
                           WordList &keywords, Accessor &styler, bool &tagDontFold,
			   bool caseSensitive, bool isXml, bool allowScripts) {
	char withSpace[30 + 2] = " ";
	const char *s = withSpace + 1;
	// Copy after the '<'
	unsigned int i = 1;
	for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
		char ch = styler[cPos];
		if ((ch != '<') && (ch != '/')) {
			withSpace[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
		}
	}

	//The following is only a quick hack, to see if this whole thing would work
	//we first need the tagname with a trailing space...
	withSpace[i] = ' ';
	withSpace[i+1] = '\0';

	// if the current language is XML, I can fold any tag
	// if the current language is HTML, I don't want to fold certain tags (input, meta, etc.)
	//...to find it in the list of no-container-tags
	tagDontFold = (!isXml) && (NULL != strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace));

	//now we can remove the trailing space
	withSpace[i] = '\0';

	// No keywords -> all are known
	char chAttr = SCE_H_TAGUNKNOWN;
	if (s[0] == '!') {
		chAttr = SCE_H_SGML_DEFAULT;
	} else if (!keywords || keywords.InList(s)) {
		chAttr = SCE_H_TAG;
	}
	styler.ColourTo(end, chAttr);
	if (chAttr == SCE_H_TAG) {
		if (allowScripts && 0 == strcmp(s, "script")) {
			// check to see if this is a self-closing tag by sniffing ahead
			bool isSelfClose = false;
			for (unsigned int cPos = end; cPos <= end + 200; cPos++) {
				char ch = styler.SafeGetCharAt(cPos, '\0');
				if (ch == '\0' || ch == '>')
					break;
				else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') {
					isSelfClose = true;
					break;
				}
			}

			// do not enter a script state if the tag self-closed
			if (!isSelfClose)
				chAttr = SCE_H_SCRIPT;
		} else if (!isXml && 0 == strcmp(s, "comment")) {
			chAttr = SCE_H_COMMENT;
		}
	}
	return chAttr;
}

static void classifyWordHTJS(unsigned int start, unsigned int end,
                             WordList &keywords, Accessor &styler, script_mode inScriptType) {
	char s[30 + 1];
	unsigned int i = 0;
	for (; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
	}
	s[i] = '\0';

	char chAttr = SCE_HJ_WORD;
	bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1]));
	if (wordIsNumber) {
		chAttr = SCE_HJ_NUMBER;
	} else if (keywords.InList(s)) {
		chAttr = SCE_HJ_KEYWORD;
	}
	styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
}

static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) {
	char chAttr = SCE_HB_IDENTIFIER;
	bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
	if (wordIsNumber)
		chAttr = SCE_HB_NUMBER;
	else {
		char s[100];
		GetTextSegment(styler, start, end, s, sizeof(s));
		if (keywords.InList(s)) {
			chAttr = SCE_HB_WORD;
			if (strcmp(s, "rem") == 0)
				chAttr = SCE_HB_COMMENTLINE;
		}
	}
	styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
	if (chAttr == SCE_HB_COMMENTLINE)
		return SCE_HB_COMMENTLINE;
	else
		return SCE_HB_DEFAULT;
}

static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) {
	bool wordIsNumber = IsADigit(styler[start]);
	char s[30 + 1];
	unsigned int i = 0;
	for (; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
	}
	s[i] = '\0';
	char chAttr = SCE_HP_IDENTIFIER;
	if (0 == strcmp(prevWord, "class"))
		chAttr = SCE_HP_CLASSNAME;
	else if (0 == strcmp(prevWord, "def"))
		chAttr = SCE_HP_DEFNAME;
	else if (wordIsNumber)
		chAttr = SCE_HP_NUMBER;
	else if (keywords.InList(s))
		chAttr = SCE_HP_WORD;
	else if (isMako && 0 == strcmp(s, "block"))
		chAttr = SCE_HP_WORD;
	styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
	strcpy(prevWord, s);
}

// Update the word colour to default or keyword
// Called when in a PHP word
static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char chAttr = SCE_HPHP_DEFAULT;
	bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1]));
	if (wordIsNumber)
		chAttr = SCE_HPHP_NUMBER;
	else {
		char s[100];
		GetTextSegment(styler, start, end, s, sizeof(s));
		if (keywords.InList(s))
			chAttr = SCE_HPHP_WORD;
	}
	styler.ColourTo(end, chAttr);
}

static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[30 + 1];
	unsigned int i = 0;
	for (; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
	}
	s[i] = '\0';
	return keywords.InList(s);
}

static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) {
	char s[30 + 1];
	unsigned int i = 0;
	for (; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
	}
	s[i] = '\0';
	return (0 == strcmp(s, "[CDATA["));
}

// Return the first state to reach when entering a scripting language
static int StateForScript(script_type scriptLanguage) {
	int Result;
	switch (scriptLanguage) {
	case eScriptVBS:
		Result = SCE_HB_START;
		break;
	case eScriptPython:
		Result = SCE_HP_START;
		break;
	case eScriptPHP:
		Result = SCE_HPHP_DEFAULT;
		break;
	case eScriptXML:
		Result = SCE_H_TAGUNKNOWN;
		break;
	case eScriptSGML:
		Result = SCE_H_SGML_DEFAULT;
		break;
	case eScriptComment:
		Result = SCE_H_COMMENT;
		break;
	default :
		Result = SCE_HJ_START;
		break;
	}
	return Result;
}

static inline bool issgmlwordchar(int ch) {
	return !isascii(ch) ||
		(isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
}

static inline bool IsPhpWordStart(int ch) {
	return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f);
}

static inline bool IsPhpWordChar(int ch) {
	return IsADigit(ch) || IsPhpWordStart(ch);
}

static bool InTagState(int state) {
	return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
	       state == SCE_H_SCRIPT ||
	       state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
	       state == SCE_H_NUMBER || state == SCE_H_OTHER ||
	       state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
}

static bool IsCommentState(const int state) {
	return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT;
}

static bool IsScriptCommentState(const int state) {
	return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT ||
		   state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE;
}

static bool isLineEnd(int ch) {
	return ch == '\r' || ch == '\n';
}

static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) {
	if (strlen(blockType) == 0) {
		return ((ch == '%') && (chNext == '>'));
	} else if ((0 == strcmp(blockType, "inherit")) ||
			   (0 == strcmp(blockType, "namespace")) ||
			   (0 == strcmp(blockType, "include")) ||
			   (0 == strcmp(blockType, "page"))) {
		return ((ch == '/') && (chNext == '>'));
	} else if (0 == strcmp(blockType, "%")) {
		if (ch == '/' && isLineEnd(chNext))
			return 1;
		else
		    return isLineEnd(ch);
	} else if (0 == strcmp(blockType, "{")) {
		return ch == '}';
	} else {
		return (ch == '>');
	}
}

static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) {
	if (strlen(blockType) == 0) {
		return 0;
	} else if (0 == strcmp(blockType, "%")) {
		return ((ch == '%') && (chNext == '}'));
	} else if (0 == strcmp(blockType, "{")) {
		return ((ch == '}') && (chNext == '}'));
	} else {
		return 0;
	}
}

static bool isPHPStringState(int state) {
	return
	    (state == SCE_HPHP_HSTRING) ||
	    (state == SCE_HPHP_SIMPLESTRING) ||
	    (state == SCE_HPHP_HSTRING_VARIABLE) ||
	    (state == SCE_HPHP_COMPLEX_VARIABLE);
}

static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) {
	int j;
	const int beginning = i - 1;
	bool isValidSimpleString = false;

	while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
		i++;

	char ch = styler.SafeGetCharAt(i);
	const char chNext = styler.SafeGetCharAt(i + 1);
	if (!IsPhpWordStart(ch)) {
		if (ch == '\'' && IsPhpWordStart(chNext)) {
			i++;
			ch = chNext;
			isSimpleString = true;
		} else {
			phpStringDelimiter[0] = '\0';
			return beginning;
		}
	}
	phpStringDelimiter[0] = ch;
	i++;

	for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) {
		if (!IsPhpWordChar(styler[j])) {
			if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) {
				isValidSimpleString = true;
				j++;
				break;
			} else {
				phpStringDelimiter[0] = '\0';
				return beginning;
			}
		}
		if (j - i < phpStringDelimiterSize - 2)
			phpStringDelimiter[j-i+1] = styler[j];
		else
			i++;
	}
	if (isSimpleString && !isValidSimpleString) {
		phpStringDelimiter[0] = '\0';
		return beginning;
	}
	phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0';
	return j - 1;
}

static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                  Accessor &styler, bool isXml) {
	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords

	// Lexer for HTML requires more lexical states (8 bits worth) than most lexers
	styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
	char prevWord[200];
	prevWord[0] = '\0';
	char phpStringDelimiter[200]; // PHP is not limited in length, we are
	phpStringDelimiter[0] = '\0';
	int StateToPrint = initStyle;
	int state = stateForPrintState(StateToPrint);
	char makoBlockType[200];
	makoBlockType[0] = '\0';
	int makoComment = 0;
	char djangoBlockType[2];
	djangoBlockType[0] = '\0';

	// If inside a tag, it may be a script tag, so reread from the start of line starting tag to ensure any language tags are seen
	if (InTagState(state)) {
		while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) {
			int backLineStart = styler.LineStart(styler.GetLine(startPos-1));
			length += startPos - backLineStart;
			startPos = backLineStart;
		}
		state = SCE_H_DEFAULT;
	}
	// String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState
	if (isPHPStringState(state)) {
		while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) {
			startPos--;
			length++;
			state = styler.StyleAt(startPos);
		}
		if (startPos == 0)
			state = SCE_H_DEFAULT;
	}
	styler.StartAt(startPos, static_cast<char>(STYLE_MAX));

	int lineCurrent = styler.GetLine(startPos);
	int lineState;
	if (lineCurrent > 0) {
		lineState = styler.GetLineState(lineCurrent-1);
	} else {
		// Default client and ASP scripting language is JavaScript
		lineState = eScriptJS << 8;

		// property asp.default.language
		//	Script in ASP code is initially assumed to be in JavaScript.
		//	To change this to VBScript set asp.default.language to 2. Python is 3.
		lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4;
	}
	script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode
	bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag
	bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag
	bool tagDontFold = false; //some HTML tags should not be folded
	script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name
	script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name
	int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state

	script_type scriptLanguage = ScriptOfState(state);
	// If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment
	if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) {
		scriptLanguage = eScriptComment;
	}
	script_type beforeLanguage = ScriptOfState(beforePreProc);

	// property fold.html
	//	Folding is turned on or off for HTML and XML files with this option.
	//	The fold option must also be on for folding to occur.
	const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;

	const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);

	// property fold.html.preprocessor
	//	Folding is turned on or off for scripts embedded in HTML files with this option.
	//	The default is on.
	const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);

	const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;

	// property fold.hypertext.comment
	//	Allow folding for comments in scripts embedded in HTML.
	//	The default is off.
	const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0;

	// property fold.hypertext.heredoc
	//	Allow folding for heredocs in scripts embedded in HTML.
	//	The default is off.
	const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;

	// property html.tags.case.sensitive
	//	For XML and HTML, setting this property to 1 will make tags match in a case
	//	sensitive way which is the expected behaviour for XML and XHTML.
	const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;

	// property lexer.xml.allow.scripts
	//	Set to 0 to disable scripts in XML.
	const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;

	// property lexer.html.mako
	//	Set to 1 to enable the mako template language.
	const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0;

	// property lexer.html.django
	//	Set to 1 to enable the django template language.
	const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0;

	const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
	const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
	const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
	// TODO: also handle + and - (except if they're part of ++ or --) and return keywords
	const CharacterSet setOKBeforeJSRE(CharacterSet::setNone, "([{=,:;!%^&*|?~");

	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	int visibleChars = 0;
	int lineStartVisibleChars = 0;

	int chPrev = ' ';
	int ch = ' ';
	int chPrevNonWhite = ' ';
	// look back to set chPrevNonWhite properly for better regex colouring
	if (scriptLanguage == eScriptJS && startPos > 0) {
		int back = startPos;
		int style = 0;
		while (--back) {
			style = styler.StyleAt(back);
			if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC)
				// includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
				break;
		}
		if (style == SCE_HJ_SYMBOLS) {
			chPrevNonWhite = static_cast<unsigned char>(styler.SafeGetCharAt(back));
		}
	}

	styler.StartSegment(startPos);
	const int lengthDoc = startPos + length;
	for (int i = startPos; i < lengthDoc; i++) {
		const int chPrev2 = chPrev;
		chPrev = ch;
		if (!IsASpace(ch) && state != SCE_HJ_COMMENT &&
			state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
			chPrevNonWhite = ch;
		ch = static_cast<unsigned char>(styler[i]);
		int chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
		const int chNext2 = static_cast<unsigned char>(styler.SafeGetCharAt(i + 2));

		// Handle DBCS codepages
		if (styler.IsLeadByte(static_cast<char>(ch))) {
			chPrev = ' ';
			i += 1;
			continue;
		}

		if ((!IsASpace(ch) || !foldCompact) && fold)
			visibleChars++;
		if (!IsASpace(ch))
			lineStartVisibleChars++;

		// decide what is the current state to print (depending of the script tag)
		StateToPrint = statePrintForState(state, inScriptType);

		// handle script folding
		if (fold) {
			switch (scriptLanguage) {
			case eScriptJS:
			case eScriptPHP:
				//not currently supported				case eScriptVBS:

				if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) {
				//Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
				//if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
					if (ch == '#') {
						int j = i + 1;
						while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
							j++;
						}
						if (styler.Match(j, "region") || styler.Match(j, "if")) {
							levelCurrent++;
						} else if (styler.Match(j, "end")) {
							levelCurrent--;
						}
					} else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) {
						levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1);
					}
				} else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) {
					levelCurrent--;
				}
				break;
			case eScriptPython:
				if (state != SCE_HP_COMMENTLINE && !isMako) {
					if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) {
						levelCurrent++;
					} else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) {
						// check if the number of tabs is lower than the level
						int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8;
						for (int j = 0; Findlevel > 0; j++) {
							char chTmp = styler.SafeGetCharAt(i + j + 1);
							if (chTmp == '\t') {
								Findlevel -= 8;
							} else if (chTmp == ' ') {
								Findlevel--;
							} else {
								break;
							}
						}

						if (Findlevel > 0) {
							levelCurrent -= Findlevel / 8;
							if (Findlevel % 8)
								levelCurrent--;
						}
					}
				}
				break;
			default:
				break;
			}
		}

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// New line -> record any line state onto /next/ line
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;

				styler.SetLevel(lineCurrent, lev);
				visibleChars = 0;
				levelPrev = levelCurrent;
			}
			styler.SetLineState(lineCurrent,
			                    ((inScriptType & 0x03) << 0) |
			                    ((tagOpened & 0x01) << 2) |
			                    ((tagClosing & 0x01) << 3) |
			                    ((aspScript & 0x0F) << 4) |
			                    ((clientScript & 0x0F) << 8) |
			                    ((beforePreProc & 0xFF) << 12));
			lineCurrent++;
			lineStartVisibleChars = 0;
		}

		// handle start of Mako comment line
		if (isMako && ch == '#' && chNext == '#') {
			makoComment = 1;
		}
		
		// handle end of Mako comment line
		else if (isMako && makoComment && (ch == '\r' || ch == '\n')) {
			makoComment = 0;
			styler.ColourTo(i, SCE_HP_COMMENTLINE);
			state = SCE_HP_DEFAULT;
		}
		
		// Allow falling through to mako handling code if newline is going to end a block
		if (((ch == '\r' && chNext != '\n') || (ch == '\n')) &&
			(!isMako || (0 != strcmp(makoBlockType, "%")))) {
		}

		// generic end of script processing
		else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) {
			// Check if it's the end of the script tag (or any other HTML tag)
			switch (state) {
				// in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
			case SCE_H_DOUBLESTRING:
			case SCE_H_SINGLESTRING:
			case SCE_HJ_COMMENT:
			case SCE_HJ_COMMENTDOC:
			//case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
			// the end of script marker from some JS interpreters.
			case SCE_HB_COMMENTLINE:
			case SCE_HBA_COMMENTLINE:
			case SCE_HJ_DOUBLESTRING:
			case SCE_HJ_SINGLESTRING:
			case SCE_HJ_REGEX:
			case SCE_HB_STRING:
			case SCE_HBA_STRING:
			case SCE_HP_STRING:
			case SCE_HP_TRIPLE:
			case SCE_HP_TRIPLEDOUBLE:
			case SCE_HPHP_HSTRING:
			case SCE_HPHP_SIMPLESTRING:
			case SCE_HPHP_COMMENT:
			case SCE_HPHP_COMMENTLINE:
				break;
			default :
				// check if the closing tag is a script tag
				if (const char *tag =
						state == SCE_HJ_COMMENTLINE || isXml ? "script" :
						state == SCE_H_COMMENT ? "comment" : 0) {
					int j = i + 2;
					int chr;
					do {
						chr = static_cast<int>(*tag++);
					} while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++)));
					if (chr != 0) break;
				}
				// closing tag of the script (it's a closing HTML tag anyway)
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_TAGUNKNOWN;
				inScriptType = eHtml;
				scriptLanguage = eScriptNone;
				clientScript = eScriptJS;
				i += 2;
				visibleChars += 2;
				tagClosing = true;
				continue;
			}
		}

		/////////////////////////////////////
		// handle the start of PHP pre-processor = Non-HTML
		else if ((state != SCE_H_ASPAT) &&
		         !isPHPStringState(state) &&
		         (state != SCE_HPHP_COMMENT) &&
		         (state != SCE_HPHP_COMMENTLINE) &&
		         (ch == '<') &&
		         (chNext == '?') &&
				 !IsScriptCommentState(state)) {
 			beforeLanguage = scriptLanguage;
			scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP);
			if ((scriptLanguage != eScriptPHP) && (isStringState(state) || (state==SCE_H_COMMENT))) continue;
			styler.ColourTo(i - 1, StateToPrint);
			beforePreProc = state;
			i++;
			visibleChars++;
			i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6);
			if (scriptLanguage == eScriptXML)
				styler.ColourTo(i, SCE_H_XMLSTART);
			else
				styler.ColourTo(i, SCE_H_QUESTION);
			state = StateForScript(scriptLanguage);
			if (inScriptType == eNonHtmlScript)
				inScriptType = eNonHtmlScriptPreProc;
			else
				inScriptType = eNonHtmlPreProc;
			// Fold whole script, but not if the XML first tag (all XML-like tags in this case)
			if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
				levelCurrent++;
			}
			// should be better
			ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
			continue;
		}

		// handle the start Mako template Python code
		else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') ||
															 (lineStartVisibleChars == 1 && ch == '%') ||
															 (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') ||
															 (ch == '$' && chNext == '{') ||
															 (ch == '<' && chNext == '/' && chNext2 == '%'))) {
			if (ch == '%' || ch == '/')
				strcpy(makoBlockType, "%");
			else if (ch == '$')
				strcpy(makoBlockType, "{");
			else if (chNext == '/')
				GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType));
			else
				GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType));
			styler.ColourTo(i - 1, StateToPrint);
			beforePreProc = state;
			if (inScriptType == eNonHtmlScript)
				inScriptType = eNonHtmlScriptPreProc;
			else
				inScriptType = eNonHtmlPreProc;

			if (chNext == '/') {
				i += 2;
				visibleChars += 2;
			} else if (ch != '%') {
				i++;
				visibleChars++;
			}
			state = SCE_HP_START;
			scriptLanguage = eScriptPython;
			styler.ColourTo(i, SCE_H_ASP);

			if (ch != '%' && ch != '$' && ch != '/') {
				i += static_cast<int>(strlen(makoBlockType));
				visibleChars += static_cast<int>(strlen(makoBlockType));
				if (keywords4.InList(makoBlockType))
					styler.ColourTo(i, SCE_HP_WORD);
				else
					styler.ColourTo(i, SCE_H_TAGUNKNOWN);
			}

			ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
			continue;
		}

		// handle the start/end of Django comment
		else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) {
			styler.ColourTo(i - 1, StateToPrint);
			beforePreProc = state;
			beforeLanguage = scriptLanguage;
			if (inScriptType == eNonHtmlScript)
				inScriptType = eNonHtmlScriptPreProc;
			else
				inScriptType = eNonHtmlPreProc;
			i += 1;
			visibleChars += 1;
			scriptLanguage = eScriptComment;
			state = SCE_H_COMMENT;
			styler.ColourTo(i, SCE_H_ASP);
			ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
			continue;
		} else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) {
			styler.ColourTo(i - 1, StateToPrint);
			i += 1;
			visibleChars += 1;
			styler.ColourTo(i, SCE_H_ASP);
			state = beforePreProc;
			if (inScriptType == eNonHtmlScriptPreProc)
				inScriptType = eNonHtmlScript;
			else
				inScriptType = eHtml;
			scriptLanguage = beforeLanguage;
			continue;
		}

		// handle the start Django template code
		else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' ||  chNext == '{'))) {
			if (chNext == '%')
				strcpy(djangoBlockType, "%");
			else
				strcpy(djangoBlockType, "{");
			styler.ColourTo(i - 1, StateToPrint);
			beforePreProc = state;
			if (inScriptType == eNonHtmlScript)
				inScriptType = eNonHtmlScriptPreProc;
			else
				inScriptType = eNonHtmlPreProc;

			i += 1;
			visibleChars += 1;
			state = SCE_HP_START;
			beforeLanguage = scriptLanguage;
			scriptLanguage = eScriptPython;
			styler.ColourTo(i, SCE_H_ASP);

			ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
			continue;
		}

		// handle the start of ASP pre-processor = Non-HTML
		else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
			styler.ColourTo(i - 1, StateToPrint);
			beforePreProc = state;
			if (inScriptType == eNonHtmlScript)
				inScriptType = eNonHtmlScriptPreProc;
			else
				inScriptType = eNonHtmlPreProc;

			if (chNext2 == '@') {
				i += 2; // place as if it was the second next char treated
				visibleChars += 2;
				state = SCE_H_ASPAT;
			} else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) {
				styler.ColourTo(i + 3, SCE_H_ASP);
				state = SCE_H_XCCOMMENT;
				scriptLanguage = eScriptVBS;
				continue;
			} else {
				if (chNext2 == '=') {
					i += 2; // place as if it was the second next char treated
					visibleChars += 2;
				} else {
					i++; // place as if it was the next char treated
					visibleChars++;
				}

				state = StateForScript(aspScript);
			}
			scriptLanguage = eScriptVBS;
			styler.ColourTo(i, SCE_H_ASP);
			// fold whole script
			if (foldHTMLPreprocessor)
				levelCurrent++;
			// should be better
			ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
			continue;
		}

		/////////////////////////////////////
		// handle the start of SGML language (DTD)
		else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
				 (chPrev == '<') &&
				 (ch == '!') &&
				 (StateToPrint != SCE_H_CDATA) &&
				 (!IsCommentState(StateToPrint)) &&
				 (!IsScriptCommentState(StateToPrint))) {
			beforePreProc = state;
			styler.ColourTo(i - 2, StateToPrint);
			if ((chNext == '-') && (chNext2 == '-')) {
				state = SCE_H_COMMENT; // wait for a pending command
				styler.ColourTo(i + 2, SCE_H_COMMENT);
				i += 2; // follow styling after the --
			} else if (isWordCdata(i + 1, i + 7, styler)) {
				state = SCE_H_CDATA;
			} else {
				styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default
				scriptLanguage = eScriptSGML;
				state = SCE_H_SGML_COMMAND; // wait for a pending command
			}
			// fold whole tag (-- when closing the tag)
			if (foldHTMLPreprocessor || state == SCE_H_COMMENT || state == SCE_H_CDATA)
				levelCurrent++;
			continue;
		}

		// handle the end of Mako Python code
		else if (isMako &&
			     ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
				 (scriptLanguage != eScriptNone) && stateAllowsTermination(state) &&
				 isMakoBlockEnd(ch, chNext, makoBlockType)) {
			if (state == SCE_H_ASPAT) {
				aspScript = segIsScriptingIndicator(styler,
				                                    styler.GetStartSegment(), i - 1, aspScript);
			}
			if (state == SCE_HP_WORD) {
				classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako);
			} else {
				styler.ColourTo(i - 1, StateToPrint);
			}
			if (0 != strcmp(makoBlockType, "%") && (0 != strcmp(makoBlockType, "{")) && ch != '>') {
				i++;
				visibleChars++;
		    }
			else if (0 == strcmp(makoBlockType, "%") && ch == '/') {
				i++;
				visibleChars++;
			}
			if (0 != strcmp(makoBlockType, "%") || ch == '/') {
				styler.ColourTo(i, SCE_H_ASP);
			}
			state = beforePreProc;
			if (inScriptType == eNonHtmlScriptPreProc)
				inScriptType = eNonHtmlScript;
			else
				inScriptType = eHtml;
			scriptLanguage = eScriptNone;
			continue;
		}

		// handle the end of Django template code
		else if (isDjango &&
			     ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
				 (scriptLanguage != eScriptNone) && stateAllowsTermination(state) &&
				 isDjangoBlockEnd(ch, chNext, djangoBlockType)) {
			if (state == SCE_H_ASPAT) {
				aspScript = segIsScriptingIndicator(styler,
				                                    styler.GetStartSegment(), i - 1, aspScript);
			}
			if (state == SCE_HP_WORD) {
				classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako);
			} else {
				styler.ColourTo(i - 1, StateToPrint);
			}
			i += 1;
			visibleChars += 1;
			styler.ColourTo(i, SCE_H_ASP);
			state = beforePreProc;
			if (inScriptType == eNonHtmlScriptPreProc)
				inScriptType = eNonHtmlScript;
			else
				inScriptType = eHtml;
			scriptLanguage = beforeLanguage;
			continue;
		}

		// handle the end of a pre-processor = Non-HTML
		else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
				  (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) &&
				  (((ch == '%') || (ch == '?')) && (chNext == '>'))) ||
		         ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
			if (state == SCE_H_ASPAT) {
				aspScript = segIsScriptingIndicator(styler,
				                                    styler.GetStartSegment(), i - 1, aspScript);
			}
			// Bounce out of any ASP mode
			switch (state) {
			case SCE_HJ_WORD:
				classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
				break;
			case SCE_HB_WORD:
				classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
				break;
			case SCE_HP_WORD:
				classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako);
				break;
			case SCE_HPHP_WORD:
				classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
				break;
			case SCE_H_XCCOMMENT:
				styler.ColourTo(i - 1, state);
				break;
			default :
				styler.ColourTo(i - 1, StateToPrint);
				break;
			}
			if (scriptLanguage != eScriptSGML) {
				i++;
				visibleChars++;
			}
			if (ch == '%')
				styler.ColourTo(i, SCE_H_ASP);
			else if (scriptLanguage == eScriptXML)
				styler.ColourTo(i, SCE_H_XMLEND);
			else if (scriptLanguage == eScriptSGML)
				styler.ColourTo(i, SCE_H_SGML_DEFAULT);
			else
				styler.ColourTo(i, SCE_H_QUESTION);
			state = beforePreProc;
			if (inScriptType == eNonHtmlScriptPreProc)
				inScriptType = eNonHtmlScript;
			else
				inScriptType = eHtml;
			// Unfold all scripting languages, except for XML tag
			if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
				levelCurrent--;
			}
			scriptLanguage = beforeLanguage;
			continue;
		}
		/////////////////////////////////////

		switch (state) {
		case SCE_H_DEFAULT:
			if (ch == '<') {
				// in HTML, fold on tag open and unfold on tag close
				tagOpened = true;
				tagClosing = (chNext == '/');
				styler.ColourTo(i - 1, StateToPrint);
				if (chNext != '!')
					state = SCE_H_TAGUNKNOWN;
			} else if (ch == '&') {
				styler.ColourTo(i - 1, SCE_H_DEFAULT);
				state = SCE_H_ENTITY;
			}
			break;
		case SCE_H_SGML_DEFAULT:
		case SCE_H_SGML_BLOCK_DEFAULT:
//			if (scriptLanguage == eScriptSGMLblock)
//				StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;

			if (ch == '\"') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_SGML_DOUBLESTRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_SGML_SIMPLESTRING;
			} else if ((ch == '-') && (chPrev == '-')) {
				if (static_cast<int>(styler.GetStartSegment()) <= (i - 2)) {
					styler.ColourTo(i - 2, StateToPrint);
				}
				state = SCE_H_SGML_COMMENT;
			} else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) {
				styler.ColourTo(i - 2, StateToPrint);
				state = SCE_H_SGML_ENTITY;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_SGML_SPECIAL;
			} else if (ch == '[') {
				styler.ColourTo(i - 1, StateToPrint);
				scriptLanguage = eScriptSGMLblock;
				state = SCE_H_SGML_BLOCK_DEFAULT;
			} else if (ch == ']') {
				if (scriptLanguage == eScriptSGMLblock) {
					styler.ColourTo(i, StateToPrint);
					scriptLanguage = eScriptSGML;
				} else {
					styler.ColourTo(i - 1, StateToPrint);
					styler.ColourTo(i, SCE_H_SGML_ERROR);
				}
				state = SCE_H_SGML_DEFAULT;
			} else if (scriptLanguage == eScriptSGMLblock) {
				if ((ch == '!') && (chPrev == '<')) {
					styler.ColourTo(i - 2, StateToPrint);
					styler.ColourTo(i, SCE_H_SGML_DEFAULT);
					state = SCE_H_SGML_COMMAND;
				} else if (ch == '>') {
					styler.ColourTo(i - 1, StateToPrint);
					styler.ColourTo(i, SCE_H_SGML_DEFAULT);
				}
			}
			break;
		case SCE_H_SGML_COMMAND:
			if ((ch == '-') && (chPrev == '-')) {
				styler.ColourTo(i - 2, StateToPrint);
				state = SCE_H_SGML_COMMENT;
			} else if (!issgmlwordchar(ch)) {
				if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) {
					styler.ColourTo(i - 1, StateToPrint);
					state = SCE_H_SGML_1ST_PARAM;
				} else {
					state = SCE_H_SGML_ERROR;
				}
			}
			break;
		case SCE_H_SGML_1ST_PARAM:
			// wait for the beginning of the word
			if ((ch == '-') && (chPrev == '-')) {
				if (scriptLanguage == eScriptSGMLblock) {
					styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT);
				} else {
					styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT);
				}
				state = SCE_H_SGML_1ST_PARAM_COMMENT;
			} else if (issgmlwordchar(ch)) {
				if (scriptLanguage == eScriptSGMLblock) {
					styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT);
				} else {
					styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT);
				}
				// find the length of the word
				int size = 1;
				while (setHTMLWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(i + size))))
					size++;
				styler.ColourTo(i + size - 1, StateToPrint);
				i += size - 1;
				visibleChars += size - 1;
				ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
				if (scriptLanguage == eScriptSGMLblock) {
					state = SCE_H_SGML_BLOCK_DEFAULT;
				} else {
					state = SCE_H_SGML_DEFAULT;
				}
				continue;
			}
			break;
		case SCE_H_SGML_ERROR:
			if ((ch == '-') && (chPrev == '-')) {
				styler.ColourTo(i - 2, StateToPrint);
				state = SCE_H_SGML_COMMENT;
			}
		case SCE_H_SGML_DOUBLESTRING:
			if (ch == '\"') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_SGML_DEFAULT;
			}
			break;
		case SCE_H_SGML_SIMPLESTRING:
			if (ch == '\'') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_SGML_DEFAULT;
			}
			break;
		case SCE_H_SGML_COMMENT:
			if ((ch == '-') && (chPrev == '-')) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_SGML_DEFAULT;
			}
			break;
		case SCE_H_CDATA:
			if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_DEFAULT;
				levelCurrent--;
			}
			break;
		case SCE_H_COMMENT:
			if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_DEFAULT;
				levelCurrent--;
			}
			break;
		case SCE_H_SGML_1ST_PARAM_COMMENT:
			if ((ch == '-') && (chPrev == '-')) {
				styler.ColourTo(i, SCE_H_SGML_COMMENT);
				state = SCE_H_SGML_1ST_PARAM;
			}
			break;
		case SCE_H_SGML_SPECIAL:
			if (!(isascii(ch) && isupper(ch))) {
				styler.ColourTo(i - 1, StateToPrint);
				if (isalnum(ch)) {
					state = SCE_H_SGML_ERROR;
				} else {
					state = SCE_H_SGML_DEFAULT;
				}
			}
			break;
		case SCE_H_SGML_ENTITY:
			if (ch == ';') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_SGML_DEFAULT;
			} else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') {
				styler.ColourTo(i, SCE_H_SGML_ERROR);
				state = SCE_H_SGML_DEFAULT;
			}
			break;
		case SCE_H_ENTITY:
			if (ch == ';') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_DEFAULT;
			}
			if (ch != '#' && !(isascii(ch) && isalnum(ch))	// Should check that '#' follows '&', but it is unlikely anyway...
				&& ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML
				if (!isascii(ch))	// Possibly start of a multibyte character so don't allow this byte to be in entity style
					styler.ColourTo(i-1, SCE_H_TAGUNKNOWN);
				else
					styler.ColourTo(i, SCE_H_TAGUNKNOWN);
				state = SCE_H_DEFAULT;
			}
			break;
		case SCE_H_TAGUNKNOWN:
			if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) {
				int eClass = classifyTagHTML(styler.GetStartSegment(),
					i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts);
				if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) {
					if (!tagClosing) {
						inScriptType = eNonHtmlScript;
						scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment;
					} else {
						scriptLanguage = eScriptNone;
					}
					eClass = SCE_H_TAG;
				}
				if (ch == '>') {
					styler.ColourTo(i, eClass);
					if (inScriptType == eNonHtmlScript) {
						state = StateForScript(scriptLanguage);
					} else {
						state = SCE_H_DEFAULT;
					}
					tagOpened = false;
					if (!tagDontFold) {
						if (tagClosing) {
							levelCurrent--;
						} else {
							levelCurrent++;
						}
					}
					tagClosing = false;
				} else if (ch == '/' && chNext == '>') {
					if (eClass == SCE_H_TAGUNKNOWN) {
						styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN);
					} else {
						styler.ColourTo(i - 1, StateToPrint);
						styler.ColourTo(i + 1, SCE_H_TAGEND);
					}
					i++;
					ch = chNext;
					state = SCE_H_DEFAULT;
					tagOpened = false;
				} else {
					if (eClass != SCE_H_TAGUNKNOWN) {
						if (eClass == SCE_H_SGML_DEFAULT) {
							state = SCE_H_SGML_DEFAULT;
						} else {
							state = SCE_H_OTHER;
						}
					}
				}
			}
			break;
		case SCE_H_ATTRIBUTE:
			if (!setAttributeContinue.Contains(ch)) {
				if (inScriptType == eNonHtmlScript) {
					int scriptLanguagePrev = scriptLanguage;
					clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage);
					scriptLanguage = clientScript;
					if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone))
						inScriptType = eHtml;
				}
				classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
				if (ch == '>') {
					styler.ColourTo(i, SCE_H_TAG);
					if (inScriptType == eNonHtmlScript) {
						state = StateForScript(scriptLanguage);
					} else {
						state = SCE_H_DEFAULT;
					}
					tagOpened = false;
					if (!tagDontFold) {
						if (tagClosing) {
							levelCurrent--;
						} else {
							levelCurrent++;
						}
					}
					tagClosing = false;
				} else if (ch == '=') {
					styler.ColourTo(i, SCE_H_OTHER);
					state = SCE_H_VALUE;
				} else {
					state = SCE_H_OTHER;
				}
			}
			break;
		case SCE_H_OTHER:
			if (ch == '>') {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i, SCE_H_TAG);
				if (inScriptType == eNonHtmlScript) {
					state = StateForScript(scriptLanguage);
				} else {
					state = SCE_H_DEFAULT;
				}
				tagOpened = false;
				if (!tagDontFold) {
					if (tagClosing) {
						levelCurrent--;
					} else {
						levelCurrent++;
					}
				}
				tagClosing = false;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_DOUBLESTRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_SINGLESTRING;
			} else if (ch == '=') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_H_VALUE;
			} else if (ch == '/' && chNext == '>') {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i + 1, SCE_H_TAGEND);
				i++;
				ch = chNext;
				state = SCE_H_DEFAULT;
				tagOpened = false;
			} else if (ch == '?' && chNext == '>') {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i + 1, SCE_H_XMLEND);
				i++;
				ch = chNext;
				state = SCE_H_DEFAULT;
			} else if (setHTMLWord.Contains(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_H_ATTRIBUTE;
			}
			break;
		case SCE_H_DOUBLESTRING:
			if (ch == '\"') {
				if (inScriptType == eNonHtmlScript) {
					scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
				}
				styler.ColourTo(i, SCE_H_DOUBLESTRING);
				state = SCE_H_OTHER;
			}
			break;
		case SCE_H_SINGLESTRING:
			if (ch == '\'') {
				if (inScriptType == eNonHtmlScript) {
					scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
				}
				styler.ColourTo(i, SCE_H_SINGLESTRING);
				state = SCE_H_OTHER;
			}
			break;
		case SCE_H_VALUE:
			if (!setHTMLWord.Contains(ch)) {
				if (ch == '\"' && chPrev == '=') {
					// Should really test for being first character
					state = SCE_H_DOUBLESTRING;
				} else if (ch == '\'' && chPrev == '=') {
					state = SCE_H_SINGLESTRING;
				} else {
					if (IsNumber(styler.GetStartSegment(), styler)) {
						styler.ColourTo(i - 1, SCE_H_NUMBER);
					} else {
						styler.ColourTo(i - 1, StateToPrint);
					}
					if (ch == '>') {
						styler.ColourTo(i, SCE_H_TAG);
						if (inScriptType == eNonHtmlScript) {
							state = StateForScript(scriptLanguage);
						} else {
							state = SCE_H_DEFAULT;
						}
						tagOpened = false;
						if (!tagDontFold) {
							if (tagClosing) {
								levelCurrent--;
							} else {
								levelCurrent++;
							}
						}
						tagClosing = false;
					} else {
						state = SCE_H_OTHER;
					}
				}
			}
			break;
		case SCE_HJ_DEFAULT:
		case SCE_HJ_START:
		case SCE_HJ_SYMBOLS:
			if (IsAWordStart(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_WORD;
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i - 1, StateToPrint);
				if (chNext2 == '*')
					state = SCE_HJ_COMMENTDOC;
				else
					state = SCE_HJ_COMMENT;
				if (chNext2 == '/') {
					// Eat the * so it isn't used for the end of the comment
					i++;
				}
			} else if (ch == '/' && chNext == '/') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_COMMENTLINE;
			} else if (ch == '/' && setOKBeforeJSRE.Contains(chPrevNonWhite)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_REGEX;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_DOUBLESTRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_SINGLESTRING;
			} else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
			           styler.SafeGetCharAt(i + 3) == '-') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_COMMENTLINE;
			} else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_COMMENTLINE;
				i += 2;
			} else if (IsOperator(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
				state = SCE_HJ_DEFAULT;
			} else if ((ch == ' ') || (ch == '\t')) {
				if (state == SCE_HJ_START) {
					styler.ColourTo(i - 1, StateToPrint);
					state = SCE_HJ_DEFAULT;
				}
			}
			break;
		case SCE_HJ_WORD:
			if (!IsAWordChar(ch)) {
				classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
				//styler.ColourTo(i - 1, eHTJSKeyword);
				state = SCE_HJ_DEFAULT;
				if (ch == '/' && chNext == '*') {
					if (chNext2 == '*')
						state = SCE_HJ_COMMENTDOC;
					else
						state = SCE_HJ_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					state = SCE_HJ_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_HJ_DOUBLESTRING;
				} else if (ch == '\'') {
					state = SCE_HJ_SINGLESTRING;
				} else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
					styler.ColourTo(i - 1, StateToPrint);
					state = SCE_HJ_COMMENTLINE;
					i += 2;
				} else if (IsOperator(ch)) {
					styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
					state = SCE_HJ_DEFAULT;
				}
			}
			break;
		case SCE_HJ_COMMENT:
		case SCE_HJ_COMMENTDOC:
			if (ch == '/' && chPrev == '*') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HJ_DEFAULT;
				ch = ' ';
			}
			break;
		case SCE_HJ_COMMENTLINE:
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType));
				state = SCE_HJ_DEFAULT;
				ch = ' ';
			}
			break;
		case SCE_HJ_DOUBLESTRING:
			if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
				}
			} else if (ch == '\"') {
				styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType));
				state = SCE_HJ_DEFAULT;
			} else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_COMMENTLINE;
				i += 2;
			} else if (isLineEnd(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_STRINGEOL;
			}
			break;
		case SCE_HJ_SINGLESTRING:
			if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
				}
			} else if (ch == '\'') {
				styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType));
				state = SCE_HJ_DEFAULT;
			} else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_COMMENTLINE;
				i += 2;
			} else if (isLineEnd(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) {
					state = SCE_HJ_STRINGEOL;
				}
			}
			break;
		case SCE_HJ_STRINGEOL:
			if (!isLineEnd(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HJ_DEFAULT;
			} else if (!isLineEnd(chNext)) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HJ_DEFAULT;
			}
			break;
		case SCE_HJ_REGEX:
			if (ch == '\r' || ch == '\n' || ch == '/') {
				if (ch == '/') {
					while (isascii(chNext) && islower(chNext)) {   // gobble regex flags
						i++;
						ch = chNext;
						chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
					}
				}
				styler.ColourTo(i, StateToPrint);
				state = SCE_HJ_DEFAULT;
			} else if (ch == '\\') {
				// Gobble up the quoted character
				if (chNext == '\\' || chNext == '/') {
					i++;
					ch = chNext;
					chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
				}
			}
			break;
		case SCE_HB_DEFAULT:
		case SCE_HB_START:
			if (IsAWordStart(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_WORD;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_COMMENTLINE;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_STRING;
			} else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
			           styler.SafeGetCharAt(i + 3) == '-') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_COMMENTLINE;
			} else if (IsOperator(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
				state = SCE_HB_DEFAULT;
			} else if ((ch == ' ') || (ch == '\t')) {
				if (state == SCE_HB_START) {
					styler.ColourTo(i - 1, StateToPrint);
					state = SCE_HB_DEFAULT;
				}
			}
			break;
		case SCE_HB_WORD:
			if (!IsAWordChar(ch)) {
				state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
				if (state == SCE_HB_DEFAULT) {
					if (ch == '\"') {
						state = SCE_HB_STRING;
					} else if (ch == '\'') {
						state = SCE_HB_COMMENTLINE;
					} else if (IsOperator(ch)) {
						styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
						state = SCE_HB_DEFAULT;
					}
				}
			}
			break;
		case SCE_HB_STRING:
			if (ch == '\"') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HB_DEFAULT;
			} else if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_STRINGEOL;
			}
			break;
		case SCE_HB_COMMENTLINE:
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_DEFAULT;
			}
			break;
		case SCE_HB_STRINGEOL:
			if (!isLineEnd(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HB_DEFAULT;
			} else if (!isLineEnd(chNext)) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HB_DEFAULT;
			}
			break;
		case SCE_HP_DEFAULT:
		case SCE_HP_START:
			if (IsAWordStart(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HP_WORD;
			} else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
			           styler.SafeGetCharAt(i + 3) == '-') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HP_COMMENTLINE;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HP_COMMENTLINE;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, StateToPrint);
				if (chNext == '\"' && chNext2 == '\"') {
					i += 2;
					state = SCE_HP_TRIPLEDOUBLE;
					ch = ' ';
					chPrev = ' ';
					chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
				} else {
					//					state = statePrintForState(SCE_HP_STRING,inScriptType);
					state = SCE_HP_STRING;
				}
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, StateToPrint);
				if (chNext == '\'' && chNext2 == '\'') {
					i += 2;
					state = SCE_HP_TRIPLE;
					ch = ' ';
					chPrev = ' ';
					chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
				} else {
					state = SCE_HP_CHARACTER;
				}
			} else if (IsOperator(ch)) {
				styler.ColourTo(i - 1, StateToPrint);
				styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
			} else if ((ch == ' ') || (ch == '\t')) {
				if (state == SCE_HP_START) {
					styler.ColourTo(i - 1, StateToPrint);
					state = SCE_HP_DEFAULT;
				}
			}
			break;
		case SCE_HP_WORD:
			if (!IsAWordChar(ch)) {
				classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako);
				state = SCE_HP_DEFAULT;
				if (ch == '#') {
					state = SCE_HP_COMMENTLINE;
				} else if (ch == '\"') {
					if (chNext == '\"' && chNext2 == '\"') {
						i += 2;
						state = SCE_HP_TRIPLEDOUBLE;
						ch = ' ';
						chPrev = ' ';
						chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
					} else {
						state = SCE_HP_STRING;
					}
				} else if (ch == '\'') {
					if (chNext == '\'' && chNext2 == '\'') {
						i += 2;
						state = SCE_HP_TRIPLE;
						ch = ' ';
						chPrev = ' ';
						chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
					} else {
						state = SCE_HP_CHARACTER;
					}
				} else if (IsOperator(ch)) {
					styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
				}
			}
			break;
		case SCE_HP_COMMENTLINE:
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HP_DEFAULT;
			}
			break;
		case SCE_HP_STRING:
			if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
					ch = chNext;
					chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
				}
			} else if (ch == '\"') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HP_DEFAULT;
			}
			break;
		case SCE_HP_CHARACTER:
			if (ch == '\\') {
				if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
					i++;
					ch = chNext;
					chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
				}
			} else if (ch == '\'') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HP_DEFAULT;
			}
			break;
		case SCE_HP_TRIPLE:
			if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HP_DEFAULT;
			}
			break;
		case SCE_HP_TRIPLEDOUBLE:
			if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HP_DEFAULT;
			}
			break;
			///////////// start - PHP state handling
		case SCE_HPHP_WORD:
			if (!IsAWordChar(ch)) {
				classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
				if (ch == '/' && chNext == '*') {
					i++;
					state = SCE_HPHP_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					i++;
					state = SCE_HPHP_COMMENTLINE;
				} else if (ch == '#') {
					state = SCE_HPHP_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_HPHP_HSTRING;
					strcpy(phpStringDelimiter, "\"");
				} else if (styler.Match(i, "<<<")) {
					bool isSimpleString = false;
					i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
					if (strlen(phpStringDelimiter)) {
						state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
						if (foldHeredoc) levelCurrent++;
					}
				} else if (ch == '\'') {
					state = SCE_HPHP_SIMPLESTRING;
					strcpy(phpStringDelimiter, "\'");
				} else if (ch == '$' && IsPhpWordStart(chNext)) {
					state = SCE_HPHP_VARIABLE;
				} else if (IsOperator(ch)) {
					state = SCE_HPHP_OPERATOR;
				} else {
					state = SCE_HPHP_DEFAULT;
				}
			}
			break;
		case SCE_HPHP_NUMBER:
			// recognize bases 8,10 or 16 integers OR floating-point numbers
			if (!IsADigit(ch)
				&& strchr(".xXabcdefABCDEF", ch) == NULL
				&& ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
				styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
				if (IsOperator(ch))
					state = SCE_HPHP_OPERATOR;
				else
					state = SCE_HPHP_DEFAULT;
			}
			break;
		case SCE_HPHP_VARIABLE:
			if (!IsPhpWordChar(chNext)) {
				styler.ColourTo(i, SCE_HPHP_VARIABLE);
				state = SCE_HPHP_DEFAULT;
			}
			break;
		case SCE_HPHP_COMMENT:
			if (ch == '/' && chPrev == '*') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HPHP_DEFAULT;
			}
			break;
		case SCE_HPHP_COMMENTLINE:
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HPHP_DEFAULT;
			}
			break;
		case SCE_HPHP_HSTRING:
			if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) {
				// skip the next char
				i++;
			} else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{'))
				&& IsPhpWordStart(chNext2)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HPHP_COMPLEX_VARIABLE;
			} else if (ch == '$' && IsPhpWordStart(chNext)) {
				styler.ColourTo(i - 1, StateToPrint);
				state = SCE_HPHP_HSTRING_VARIABLE;
			} else if (styler.Match(i, phpStringDelimiter)) {
				if (phpStringDelimiter[0] == '\"') {
					styler.ColourTo(i, StateToPrint);
					state = SCE_HPHP_DEFAULT;
				} else if (isLineEnd(chPrev)) {
					const int psdLength = static_cast<int>(strlen(phpStringDelimiter));
					const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
					const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
					if (isLineEnd(chAfterPsd) ||
						(chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
							i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
						styler.ColourTo(i, StateToPrint);
						state = SCE_HPHP_DEFAULT;
						if (foldHeredoc) levelCurrent--;
					}
				}
			}
			break;
		case SCE_HPHP_SIMPLESTRING:
			if (phpStringDelimiter[0] == '\'') {
				if (ch == '\\') {
					// skip the next char
					i++;
				} else if (ch == '\'') {
					styler.ColourTo(i, StateToPrint);
					state = SCE_HPHP_DEFAULT;
				}
			} else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) {
				const int psdLength = static_cast<int>(strlen(phpStringDelimiter));
				const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
				const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
				if (isLineEnd(chAfterPsd) ||
				(chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
					i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
					styler.ColourTo(i, StateToPrint);
					state = SCE_HPHP_DEFAULT;
					if (foldHeredoc) levelCurrent--;
				}
			}
			break;
		case SCE_HPHP_HSTRING_VARIABLE:
			if (!IsPhpWordChar(chNext)) {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HPHP_HSTRING;
			}
			break;
		case SCE_HPHP_COMPLEX_VARIABLE:
			if (ch == '}') {
				styler.ColourTo(i, StateToPrint);
				state = SCE_HPHP_HSTRING;
			}
			break;
		case SCE_HPHP_OPERATOR:
		case SCE_HPHP_DEFAULT:
			styler.ColourTo(i - 1, StateToPrint);
			if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
				state = SCE_HPHP_NUMBER;
			} else if (IsAWordStart(ch)) {
				state = SCE_HPHP_WORD;
			} else if (ch == '/' && chNext == '*') {
				i++;
				state = SCE_HPHP_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				i++;
				state = SCE_HPHP_COMMENTLINE;
			} else if (ch == '#') {
				state = SCE_HPHP_COMMENTLINE;
			} else if (ch == '\"') {
				state = SCE_HPHP_HSTRING;
				strcpy(phpStringDelimiter, "\"");
			} else if (styler.Match(i, "<<<")) {
				bool isSimpleString = false;
				i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
				if (strlen(phpStringDelimiter)) {
					state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
					if (foldHeredoc) levelCurrent++;
				}
			} else if (ch == '\'') {
				state = SCE_HPHP_SIMPLESTRING;
				strcpy(phpStringDelimiter, "\'");
			} else if (ch == '$' && IsPhpWordStart(chNext)) {
				state = SCE_HPHP_VARIABLE;
			} else if (IsOperator(ch)) {
				state = SCE_HPHP_OPERATOR;
			} else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) {
				state = SCE_HPHP_DEFAULT;
			}
			break;
			///////////// end - PHP state handling
		}

		// Some of the above terminated their lexeme but since the same character starts
		// the same class again, only reenter if non empty segment.

		bool nonEmptySegment = i >= static_cast<int>(styler.GetStartSegment());
		if (state == SCE_HB_DEFAULT) {    // One of the above succeeded
			if ((ch == '\"') && (nonEmptySegment)) {
				state = SCE_HB_STRING;
			} else if (ch == '\'') {
				state = SCE_HB_COMMENTLINE;
			} else if (IsAWordStart(ch)) {
				state = SCE_HB_WORD;
			} else if (IsOperator(ch)) {
				styler.ColourTo(i, SCE_HB_DEFAULT);
			}
		} else if (state == SCE_HBA_DEFAULT) {    // One of the above succeeded
			if ((ch == '\"') && (nonEmptySegment)) {
				state = SCE_HBA_STRING;
			} else if (ch == '\'') {
				state = SCE_HBA_COMMENTLINE;
			} else if (IsAWordStart(ch)) {
				state = SCE_HBA_WORD;
			} else if (IsOperator(ch)) {
				styler.ColourTo(i, SCE_HBA_DEFAULT);
			}
		} else if (state == SCE_HJ_DEFAULT) {    // One of the above succeeded
			if (ch == '/' && chNext == '*') {
				if (styler.SafeGetCharAt(i + 2) == '*')
					state = SCE_HJ_COMMENTDOC;
				else
					state = SCE_HJ_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				state = SCE_HJ_COMMENTLINE;
			} else if ((ch == '\"') && (nonEmptySegment)) {
				state = SCE_HJ_DOUBLESTRING;
			} else if ((ch == '\'') && (nonEmptySegment)) {
				state = SCE_HJ_SINGLESTRING;
			} else if (IsAWordStart(ch)) {
				state = SCE_HJ_WORD;
			} else if (IsOperator(ch)) {
				styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
			}
		}
	}

	switch (state) {
	case SCE_HJ_WORD:
		classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType);
		break;
	case SCE_HB_WORD:
		classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType);
		break;
	case SCE_HP_WORD:
		classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType, isMako);
		break;
	case SCE_HPHP_WORD:
		classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler);
		break;
	default:
		StateToPrint = statePrintForState(state, inScriptType);
		if (static_cast<int>(styler.GetStartSegment()) < lengthDoc)
			styler.ColourTo(lengthDoc - 1, StateToPrint);
		break;
	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);
	}
}

static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                  Accessor &styler) {
	// Passing in true because we're lexing XML
	ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true);
}

static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                  Accessor &styler) {
	// Passing in false because we're notlexing XML
	ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false);
}

static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
        Accessor &styler) {
	if (startPos == 0)
		initStyle = SCE_HPHP_DEFAULT;
	ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler);
}

static const char * const htmlWordListDesc[] = {
	"HTML elements and attributes",
	"JavaScript keywords",
	"VBScript keywords",
	"Python keywords",
	"PHP keywords",
	"SGML and DTD keywords",
	0,
};

static const char * const phpscriptWordListDesc[] = {
	"", //Unused
	"", //Unused
	"", //Unused
	"", //Unused
	"PHP keywords",
	"", //Unused
	0,
};

LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8);
LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8);
LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8);

Added lexers/LexHaskell.cxx.

































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/******************************************************************
 *    LexHaskell.cxx
 *
 *    A haskell lexer for the scintilla code control.
 *    Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
 *    External lexer stuff inspired from the caml external lexer.
 *
 *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se
 *
 *    Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com
 *
 *    TODO:
 *    * Implement a folder :)
 *    * Nice Character-lexing (stuff inside '\''), LexPython has
 *      this.
 *
 *
 *****************************************************************/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#ifdef BUILD_AS_EXTERNAL_LEXER

#include "ExternalLexer.h"
#include "WindowAccessor.h"

#define BUILD_EXTERNAL_LEXER 0

#endif

#define HA_MODE_DEFAULT     0
#define HA_MODE_IMPORT1     1
#define HA_MODE_IMPORT2     2
#define HA_MODE_IMPORT3     3
#define HA_MODE_MODULE      4
#define HA_MODE_FFI         5
#define HA_MODE_TYPE        6

static inline bool IsNewline(const int ch) {
   return (ch == '\n' || ch == '\r');
}

static inline bool IsWhitespace(const int ch) {
   return (  ch == ' '
          || ch == '\t'
          || IsNewline(ch) );
}

static inline bool IsAWordStart(const int ch) {
   return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordChar(const int ch) {
   return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
}

static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
                               WordList *keywordlists[], Accessor &styler) {

   WordList &keywords = *keywordlists[0];
   WordList &ffi      = *keywordlists[1];

   StyleContext sc(startPos, length, initStyle, styler);

   int lineCurrent = styler.GetLine(startPos);
   int state = lineCurrent ? styler.GetLineState(lineCurrent-1)
                           : HA_MODE_DEFAULT;
   int mode  = state & 0xF;
   int xmode = state >> 4;

   while (sc.More()) {
      // Check for state end

         // Operator
      if (sc.state == SCE_HA_OPERATOR) {
         if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
            sc.Forward();
         } else {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.ChangeState(SCE_HA_DEFAULT);
         }
      }
         // String
      else if (sc.state == SCE_HA_STRING) {
         if (sc.ch == '\"') {
			sc.Forward();
            styler.ColourTo(sc.currentPos-1, sc.state);
            sc.ChangeState(SCE_HA_DEFAULT);
         } else if (sc.ch == '\\') {
            sc.Forward(2);
         } else if (sc.atLineEnd) {
			styler.ColourTo(sc.currentPos-1, sc.state);
			sc.ChangeState(SCE_HA_DEFAULT);
		 } else {
			sc.Forward();
		 }
      }
         // Char
      else if (sc.state == SCE_HA_CHARACTER) {
         if (sc.ch == '\'') {
			sc.Forward();
            styler.ColourTo(sc.currentPos-1, sc.state);
            sc.ChangeState(SCE_HA_DEFAULT);
         } else if (sc.ch == '\\') {
            sc.Forward(2);
         } else if (sc.atLineEnd) {
			styler.ColourTo(sc.currentPos-1, sc.state);
			sc.ChangeState(SCE_HA_DEFAULT);
		 } else {
			sc.Forward();
		 }
      }
         // Number
      else if (sc.state == SCE_HA_NUMBER) {
         if (IsADigit(sc.ch, xmode)) {
            sc.Forward();
         } else if ((xmode == 10) &&
                    (sc.ch == 'e' || sc.ch == 'E') &&
                    (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) {
			sc.Forward();
			if (sc.ch == '+' || sc.ch == '-')
				sc.Forward();
         } else {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.ChangeState(SCE_HA_DEFAULT);
         }
      }
         // Identifier
      else if (sc.state == SCE_HA_IDENTIFIER) {
         if (IsAWordChar(sc.ch)) {
            sc.Forward();
         } else {
            char s[100];
            sc.GetCurrent(s, sizeof(s));
            int style = sc.state;
            int new_mode = 0;
            if (keywords.InList(s)) {
               style = SCE_HA_KEYWORD;
            } else if (isupper(s[0])) {
               if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) {
                  style    = SCE_HA_MODULE;
                  new_mode = HA_MODE_IMPORT2;
               } else if (mode == HA_MODE_MODULE)
                  style = SCE_HA_MODULE;
               else
                  style = SCE_HA_CAPITAL;
            } else if (mode == HA_MODE_IMPORT1 &&
                       strcmp(s,"qualified") == 0) {
                style    = SCE_HA_KEYWORD;
                new_mode = HA_MODE_IMPORT1;
            } else if (mode == HA_MODE_IMPORT2) {
                if (strcmp(s,"as") == 0) {
                   style    = SCE_HA_KEYWORD;
                   new_mode = HA_MODE_IMPORT3;
               } else if (strcmp(s,"hiding") == 0) {
                   style     = SCE_HA_KEYWORD;
               }
            } else if (mode == HA_MODE_FFI) {
			   if (ffi.InList(s)) {
                  style = SCE_HA_KEYWORD;
                  new_mode = HA_MODE_FFI;
               }
            }
            else if (mode == HA_MODE_TYPE) {
               if (strcmp(s,"family") == 0)
                  style    = SCE_HA_KEYWORD;
			}
            styler.ColourTo(sc.currentPos - 1, style);
            if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
               new_mode = HA_MODE_IMPORT1;
            else if (strcmp(s,"module") == 0)
               new_mode = HA_MODE_MODULE;
            else if (strcmp(s,"foreign") == 0)
               new_mode = HA_MODE_FFI;
            else if (strcmp(s,"type") == 0)
               new_mode = HA_MODE_TYPE;
            sc.ChangeState(SCE_HA_DEFAULT);
            mode = new_mode;
         }
      }

         // Comments
            // Oneliner
      else if (sc.state == SCE_HA_COMMENTLINE) {
         if (sc.atLineEnd) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.ChangeState(SCE_HA_DEFAULT);
         } else {
            sc.Forward();
         }
      }
            // Nested
      else if (sc.state == SCE_HA_COMMENTBLOCK) {
         if (sc.Match("{-")) {
            sc.Forward(2);
            xmode++;
         }
         else if (sc.Match("-}")) {
            sc.Forward(2);
            xmode--;
            if (xmode == 0) {
               styler.ColourTo(sc.currentPos - 1, sc.state);
               sc.ChangeState(SCE_HA_DEFAULT);
            }
         } else {
            if (sc.atLineEnd) {
				// Remember the line state for future incremental lexing
				styler.SetLineState(lineCurrent, (xmode << 4) | mode);
				lineCurrent++;
			}
            sc.Forward();
         }
      }
      // New state?
      if (sc.state == SCE_HA_DEFAULT) {
         // Digit
         if (IsADigit(sc.ch) ||
             (sc.ch == '.' && IsADigit(sc.chNext)) ||
             (sc.ch == '-' && IsADigit(sc.chNext))) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.ChangeState(SCE_HA_NUMBER);
            if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) {
				// Match anything starting with "0x" or "0X", too
				sc.Forward(2);
				xmode = 16;
            } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) {
				// Match anything starting with "0x" or "0X", too
				sc.Forward(2);
				xmode = 8;
            } else {
				sc.Forward();
				xmode = 10;
			}
            mode = HA_MODE_DEFAULT;
         }
         // Comment line
         else if (sc.Match("--")) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward(2);
            sc.ChangeState(SCE_HA_COMMENTLINE);
         // Comment block
         }
         else if (sc.Match("{-")) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward(2);
            sc.ChangeState(SCE_HA_COMMENTBLOCK);
            xmode = 1;
         }
         // String
         else if (sc.Match('\"')) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward();
            sc.ChangeState(SCE_HA_STRING);
         }
         // Character
         else if (sc.Match('\'')) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward();
            sc.ChangeState(SCE_HA_CHARACTER);
         }
         else if (sc.ch == '(' || sc.ch == ')' ||
                  sc.ch == '{' || sc.ch == '}' ||
                  sc.ch == '[' || sc.ch == ']') {
			styler.ColourTo(sc.currentPos - 1, sc.state);
			sc.Forward();
			styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR);
			mode = HA_MODE_DEFAULT;
		 }
         // Operator
         else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward();
            sc.ChangeState(SCE_HA_OPERATOR);
            mode = HA_MODE_DEFAULT;
         }
         // Keyword
         else if (IsAWordStart(sc.ch)) {
            styler.ColourTo(sc.currentPos - 1, sc.state);
            sc.Forward();
            sc.ChangeState(SCE_HA_IDENTIFIER);
         } else {
            if (sc.atLineEnd) {
				// Remember the line state for future incremental lexing
				styler.SetLineState(lineCurrent, (xmode << 4) | mode);
				lineCurrent++;
			}
            sc.Forward();
         }
      }
   }
   sc.Complete();
}

// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
#ifdef BUILD_EXTERNAL_LEXER
static const char* LexerName = "haskell";

void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
                        char *words[], WindowID window, char *props)
{
   PropSetSimple ps;
   ps.SetMultiple(props);
   WindowAccessor wa(window, ps);

   int nWL = 0;
   for (; words[nWL]; nWL++) ;
   WordList** wl = new WordList* [nWL + 1];
   int i = 0;
   for (; i<nWL; i++)
   {
      wl[i] = new WordList();
      wl[i]->Set(words[i]);
   }
   wl[i] = 0;

   ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
   wa.Flush();
   for (i=nWL-1;i>=0;i--)
      delete wl[i];
   delete [] wl;
}

void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
                        char *words[], WindowID window, char *props)
{

}

int EXT_LEXER_DECL GetLexerCount()
{
   return 1;
}

void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
{
   if (buflength > 0) {
      buflength--;
      int n = strlen(LexerName);
      if (n > buflength)
         n = buflength;
      memcpy(name, LexerName, n), name[n] = '\0';
   }
}
#endif

LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");

Added lexers/LexInno.cxx.





































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
// Scintilla source code edit control
/** @file LexInno.cxx
 ** Lexer for Inno Setup scripts.
 **/
// Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
	int state = SCE_INNO_DEFAULT;
	char chPrev;
	char ch = 0;
	char chNext = styler[startPos];
	int lengthDoc = startPos + length;
	char *buffer = new char[length];
	int bufferCount = 0;
	bool isBOL, isEOL, isWS, isBOLWS = 0;
	bool isCStyleComment = false;

	WordList &sectionKeywords = *keywordLists[0];
	WordList &standardKeywords = *keywordLists[1];
	WordList &parameterKeywords = *keywordLists[2];
	WordList &preprocessorKeywords = *keywordLists[3];
	WordList &pascalKeywords = *keywordLists[4];
	WordList &userKeywords = *keywordLists[5];

	int curLine = styler.GetLine(startPos);
	int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0;
	bool isCode = (curLineState == 1);

	// Go through all provided text segment
	// using the hand-written state machine shown below
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	for (int i = startPos; i < lengthDoc; i++) {
		chPrev = ch;
		ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i++;
			continue;
		}

		isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
		isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
		isEOL = (ch == '\n' || ch == '\r');
		isWS = (ch == ' ' || ch == '\t');

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Remember the line state for future incremental lexing
			curLine = styler.GetLine(i);
			styler.SetLineState(curLine, (isCode ? 1 : 0));
		}

		switch(state) {
			case SCE_INNO_DEFAULT:
				if (!isCode && ch == ';' && isBOLWS) {
					// Start of a comment
					state = SCE_INNO_COMMENT;
				} else if (ch == '[' && isBOLWS) {
					// Start of a section name
					bufferCount = 0;
					state = SCE_INNO_SECTION;
				} else if (ch == '#' && isBOLWS) {
					// Start of a preprocessor directive
					state = SCE_INNO_PREPROC;
				} else if (!isCode && ch == '{' && chNext != '{' && chPrev != '{') {
					// Start of an inline expansion
					state = SCE_INNO_INLINE_EXPANSION;
				} else if (isCode && (ch == '{' || (ch == '(' && chNext == '*'))) {
					// Start of a Pascal comment
					state = SCE_INNO_COMMENT_PASCAL;
					isCStyleComment = false;
				} else if (isCode && ch == '/' && chNext == '/') {
					// Apparently, C-style comments are legal, too
					state = SCE_INNO_COMMENT_PASCAL;
					isCStyleComment = true;
				} else if (ch == '"') {
					// Start of a double-quote string
					state = SCE_INNO_STRING_DOUBLE;
				} else if (ch == '\'') {
					// Start of a single-quote string
					state = SCE_INNO_STRING_SINGLE;
				} else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
					// Start of an identifier
					bufferCount = 0;
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
					state = SCE_INNO_IDENTIFIER;
				} else {
					// Style it the default style
					styler.ColourTo(i,SCE_INNO_DEFAULT);
				}
				break;

			case SCE_INNO_COMMENT:
				if (isEOL) {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_COMMENT);
				}
				break;

			case SCE_INNO_IDENTIFIER:
				if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
				} else {
					state = SCE_INNO_DEFAULT;
					buffer[bufferCount] = '\0';

					// Check if the buffer contains a keyword
					if (!isCode && standardKeywords.InList(buffer)) {
						styler.ColourTo(i-1,SCE_INNO_KEYWORD);
					} else if (!isCode && parameterKeywords.InList(buffer)) {
						styler.ColourTo(i-1,SCE_INNO_PARAMETER);
					} else if (isCode && pascalKeywords.InList(buffer)) {
						styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
					} else if (!isCode && userKeywords.InList(buffer)) {
						styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
					} else {
						styler.ColourTo(i-1,SCE_INNO_DEFAULT);
					}

					// Push back the faulty character
					chNext = styler[i--];
					ch = chPrev;
				}
				break;

			case SCE_INNO_SECTION:
				if (ch == ']') {
					state = SCE_INNO_DEFAULT;
					buffer[bufferCount] = '\0';

					// Check if the buffer contains a section name
					if (sectionKeywords.InList(buffer)) {
						styler.ColourTo(i,SCE_INNO_SECTION);
						isCode = !CompareCaseInsensitive(buffer, "code");
					} else {
						styler.ColourTo(i,SCE_INNO_DEFAULT);
					}
				} else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
				} else {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_DEFAULT);
				}
				break;

			case SCE_INNO_PREPROC:
				if (isWS || isEOL) {
					if (isascii(chPrev) && isalpha(chPrev)) {
						state = SCE_INNO_DEFAULT;
						buffer[bufferCount] = '\0';

						// Check if the buffer contains a preprocessor directive
						if (preprocessorKeywords.InList(buffer)) {
							styler.ColourTo(i-1,SCE_INNO_PREPROC);
						} else {
							styler.ColourTo(i-1,SCE_INNO_DEFAULT);
						}

						// Push back the faulty character
						chNext = styler[i--];
						ch = chPrev;
					}
				} else if (isascii(ch) && isalpha(ch)) {
					if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
						bufferCount = 0;
					buffer[bufferCount++] = static_cast<char>(tolower(ch));
				}
				break;

			case SCE_INNO_STRING_DOUBLE:
				if (ch == '"' || isEOL) {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
				}
				break;

			case SCE_INNO_STRING_SINGLE:
				if (ch == '\'' || isEOL) {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
				}
				break;

			case SCE_INNO_INLINE_EXPANSION:
				if (ch == '}') {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_INLINE_EXPANSION);
				} else if (isEOL) {
					state = SCE_INNO_DEFAULT;
					styler.ColourTo(i,SCE_INNO_DEFAULT);
				}
				break;

			case SCE_INNO_COMMENT_PASCAL:
				if (isCStyleComment) {
					if (isEOL) {
						state = SCE_INNO_DEFAULT;
						styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
					}
				} else {
					if (ch == '}' || (ch == ')' && chPrev == '*')) {
						state = SCE_INNO_DEFAULT;
						styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
					} else if (isEOL) {
						state = SCE_INNO_DEFAULT;
						styler.ColourTo(i,SCE_INNO_DEFAULT);
					}
				}
				break;

		}
	}
	delete []buffer;
}

static const char * const innoWordListDesc[] = {
	"Sections",
	"Keywords",
	"Parameters",
	"Preprocessor directives",
	"Pascal keywords",
	"User defined keywords",
	0
};

static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	unsigned int endPos = startPos + length;
	char chNext = styler[startPos];

	int lineCurrent = styler.GetLine(startPos);

	bool sectionFlag = false;
	int levelPrev = lineCurrent > 0 ? styler.LevelAt(lineCurrent - 1) : SC_FOLDLEVELBASE;
	int level;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler[i+1];
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		int style = styler.StyleAt(i);

		if (style == SCE_INNO_SECTION)
			sectionFlag = true;

		if (atEOL || i == endPos - 1) {
			if (sectionFlag) {
				level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
				if (level == levelPrev)
					styler.SetLevel(lineCurrent - 1, levelPrev & ~SC_FOLDLEVELHEADERFLAG);
			} else {
				level = levelPrev & SC_FOLDLEVELNUMBERMASK;
				if (levelPrev & SC_FOLDLEVELHEADERFLAG)
					level++;
			}

			styler.SetLevel(lineCurrent, level);

			levelPrev = level;
			lineCurrent++;
			sectionFlag = false;
		}
	}
}

LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);

Added lexers/LexKix.cxx.



































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexKix.cxx
 ** Lexer for KIX-Scripts.
 **/
// Copyright 2004 by Manfred Becker <manfred@becker-trdf.de>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 || isalnum(ch) || ch == '_';
}

static inline bool IsOperator(const int ch) {
	return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '&' || ch == '|' || ch == '<' || ch == '>' || ch == '=');
}

static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
//	WordList &keywords4 = *keywordlists[3];

	styler.StartAt(startPos);

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_KIX_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_STRING1) {
			// This is a doubles quotes string
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_STRING2) {
			// This is a single quote string
			if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_NUMBER) {
			if (!IsADigit(sc.ch)) {
				sc.SetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_VAR) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_MACRO) {
			if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));

				if (!keywords3.InList(&s[1])) {
					sc.ChangeState(SCE_KIX_DEFAULT);
				}
				sc.SetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_OPERATOR) {
			if (!IsOperator(sc.ch)) {
				sc.SetState(SCE_KIX_DEFAULT);
			}
		} else if (sc.state == SCE_KIX_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));

				if (keywords.InList(s)) {
					sc.ChangeState(SCE_KIX_KEYWORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_KIX_FUNCTIONS);
				}
				sc.SetState(SCE_KIX_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_KIX_DEFAULT) {
			if (sc.ch == ';') {
				sc.SetState(SCE_KIX_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_KIX_STRING1);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_KIX_STRING2);
			} else if (sc.ch == '$') {
				sc.SetState(SCE_KIX_VAR);
			} else if (sc.ch == '@') {
				sc.SetState(SCE_KIX_MACRO);
			} else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) {
				sc.SetState(SCE_KIX_NUMBER);
			} else if (IsOperator(sc.ch)) {
				sc.SetState(SCE_KIX_OPERATOR);
			} else if (IsAWordChar(sc.ch)) {
				sc.SetState(SCE_KIX_IDENTIFIER);
			}
		}
	}
	sc.Complete();
}


LexerModule lmKix(SCLEX_KIX, ColouriseKixDoc, "kix");

Added lexers/LexLaTeX.cxx.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
// Scintilla source code edit control
/** @file LexLaTeX.cxx
 ** Lexer for LaTeX2e.
  **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// Modified by G. HU in 2013. Added folding, syntax highting inside math environments, and changed some minor behaviors.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <vector>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "LexerBase.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

using namespace std;

struct latexFoldSave {
	latexFoldSave() : structLev(0) {
		for (int i = 0; i < 8; ++i) openBegins[i] = 0;
	}
	latexFoldSave(const latexFoldSave &save) : structLev(save.structLev) {
		for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i];
	}
	int openBegins[8];
	int structLev;
};

class LexerLaTeX : public LexerBase {
private:
	vector<int> modes;
	void setMode(int line, int mode) {
		if (line >= static_cast<int>(modes.size())) modes.resize(line + 1, 0);
		modes[line] = mode;
	}
	int getMode(int line) {
		if (line >= 0 && line < static_cast<int>(modes.size())) return modes[line];
		return 0;
	}
	void truncModes(int numLines) {
		if (static_cast<int>(modes.size()) > numLines * 2 + 256)
			modes.resize(numLines + 128);
	}
	
	vector<latexFoldSave> saves;
	void setSave(int line, const latexFoldSave &save) {
		if (line >= static_cast<int>(saves.size())) saves.resize(line + 1);
		saves[line] = save;
	}
	void getSave(int line, latexFoldSave &save) {
		if (line >= 0 && line < static_cast<int>(saves.size())) save = saves[line];
		else {
			save.structLev = 0;
			for (int i = 0; i < 8; ++i) save.openBegins[i] = 0;
		}
	}
	void truncSaves(int numLines) {
		if (static_cast<int>(saves.size()) > numLines * 2 + 256)
			saves.resize(numLines + 128);
	}
public:
	static ILexer *LexerFactoryLaTeX() {
		return new LexerLaTeX();
	}
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
};

static bool latexIsSpecial(int ch) {
	return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') ||
		   (ch == '{') || (ch == '}') || (ch == ' ');
}

static bool latexIsBlank(int ch) {
	return (ch == ' ') || (ch == '\t');
}

static bool latexIsBlankAndNL(int ch) {
	return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
}

static bool latexIsLetter(int ch) {
	return isascii(ch) && isalpha(ch);
}

static bool latexIsTagValid(int &i, int l, Accessor &styler) {
	while (i < l) {
		if (styler.SafeGetCharAt(i) == '{') {
			while (i < l) {
				i++;
				if (styler.SafeGetCharAt(i) == '}') {
					return true;
				}	else if (!latexIsLetter(styler.SafeGetCharAt(i)) &&
                   styler.SafeGetCharAt(i)!='*') {
					return false;
				}
			}
		} else if (!latexIsBlank(styler.SafeGetCharAt(i))) {
			return false;
		}
		i++;
	}
	return false;
}

static bool latexNextNotBlankIs(int i, Accessor &styler, char needle) {
  char ch;
	while (i < styler.Length()) {
    ch = styler.SafeGetCharAt(i);
		if (!latexIsBlankAndNL(ch) && ch != '*') {
      if (ch == needle)
        return true;
      else
        return false;
		}
		i++;
	}
	return false;
}

static bool latexLastWordIs(int start, Accessor &styler, const char *needle) {
	unsigned int i = 0;
	unsigned int l = static_cast<unsigned int>(strlen(needle));
	int ini = start-l+1;
	char s[32];

	while (i < l && i < 31) {
		s[i] = styler.SafeGetCharAt(ini + i);
		i++;
	}
	s[i] = '\0';

	return (strcmp(s, needle) == 0);
}

static bool latexLastWordIsMathEnv(int pos, Accessor &styler) {
	int i, j;
	char s[32];
	const char *mathEnvs[] = { "align", "alignat", "flalign", "gather",
		"multiline", "displaymath", "eqnarray", "equation" };
	if (styler.SafeGetCharAt(pos) != '}') return false;
	for (i = pos - 1; i >= 0; --i) {
		if (styler.SafeGetCharAt(i) == '{') break;
		if (pos - i >= 20) return false;
	}
	if (i < 0 || i == pos - 1) return false;
	++i;
	for (j = 0; i + j < pos; ++j)
		s[j] = styler.SafeGetCharAt(i + j);
	s[j] = '\0';
	if (j == 0) return false;
	if (s[j - 1] == '*') s[--j] = '\0';
	for (i = 0; i < static_cast<int>(sizeof(mathEnvs) / sizeof(const char *)); ++i)
		if (strcmp(s, mathEnvs[i]) == 0) return true;
	return false;
}

static inline void latexStateReset(int &mode, int &state) {
	switch (mode) {
	case 1:     state = SCE_L_MATH; break;
	case 2:     state = SCE_L_MATH2; break;
	default:    state = SCE_L_DEFAULT; break;
	}
}

// There are cases not handled correctly, like $abcd\textrm{what is $x+y$}z+w$.
// But I think it's already good enough.
void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	// startPos is assumed to be the first character of a line
	Accessor styler(pAccess, &props);
	styler.StartAt(startPos);
	int mode = getMode(styler.GetLine(startPos) - 1);
	int state = initStyle;
	if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL)   // should not happen
		latexStateReset(mode, state);
	
	char chNext = styler.SafeGetCharAt(startPos);
	char chVerbatimDelim = '\0';
	styler.StartSegment(startPos);
	int lengthDoc = startPos + length;

	for (int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			i++;
			chNext = styler.SafeGetCharAt(i + 1);
			continue;
		}
		
		if (ch == '\r' || ch == '\n')
			setMode(styler.GetLine(i), mode);

		switch (state) {
		case SCE_L_DEFAULT :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					if (chNext == '(') {
						mode = 1;
						state = SCE_L_MATH;
					} else if (chNext == '[') {
						mode = 2;
						state = SCE_L_MATH2;
					}
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				if (chNext == '$') {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					mode = 2;
					state = SCE_L_MATH2;
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else {
					styler.ColourTo(i, SCE_L_SHORTCMD);
					mode = 1;
					state = SCE_L_MATH;
				}
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;	
		// These 3 will never be reached.
		case SCE_L_ERROR:
		case SCE_L_SPECIAL:
		case SCE_L_SHORTCMD:
			break;
		case SCE_L_COMMAND :
			if (!latexIsLetter(chNext)) {
				styler.ColourTo(i, state);
				if (latexNextNotBlankIs(i + 1, styler, '[' )) {
					state = SCE_L_CMDOPT;
				} else if (latexLastWordIs(i, styler, "\\begin")) {
					state = SCE_L_TAG;
				} else if (latexLastWordIs(i, styler, "\\end")) {
					state = SCE_L_TAG2;
				} else if (latexLastWordIs(i, styler, "\\verb") && chNext != '*' && chNext != ' ') {
					chVerbatimDelim = chNext;
					state = SCE_L_VERBATIM;
				} else {
					latexStateReset(mode, state);
				}
			}
			break;
		case SCE_L_CMDOPT :
			if (ch == ']') {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
			}
			break;
		case SCE_L_TAG :
			if (latexIsTagValid(i, lengthDoc, styler)) {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
				if (latexLastWordIs(i, styler, "{verbatim}")) {
					state = SCE_L_VERBATIM;
				} else if (latexLastWordIs(i, styler, "{comment}")) {
					state = SCE_L_COMMENT2;
				} else if (latexLastWordIs(i, styler, "{math}") && mode == 0) {
					mode = 1;
					state = SCE_L_MATH;
				} else if (latexLastWordIsMathEnv(i, styler) && mode == 0) {
					mode = 2;
					state = SCE_L_MATH2;
				}
			} else {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				ch = styler.SafeGetCharAt(i);
				if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
			}
			chNext = styler.SafeGetCharAt(i+1);
			break;
		case SCE_L_TAG2 :
			if (latexIsTagValid(i, lengthDoc, styler)) {
				styler.ColourTo(i, state);
				latexStateReset(mode, state);
			} else {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				ch = styler.SafeGetCharAt(i);
				if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode);
			}
			chNext = styler.SafeGetCharAt(i+1);
			break;
		case SCE_L_MATH :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					int match = i + 3;
					if (latexLastWordIs(match, styler, "\\end")) {
						match++;
						if (latexIsTagValid(match, lengthDoc, styler)) {
							if (latexLastWordIs(match, styler, "{math}"))
								mode = 0;
						}
					}
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else {
					if (chNext == ')') {
						mode = 0;
						state = SCE_L_DEFAULT;
					}
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_L_SHORTCMD);
				mode = 0;
				state = SCE_L_DEFAULT;
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;
		case SCE_L_MATH2 :
			switch (ch) {
			case '\\' :
				styler.ColourTo(i - 1, state);
				if (latexIsLetter(chNext)) {
					int match = i + 3;
					if (latexLastWordIs(match, styler, "\\end")) {
						match++;
						if (latexIsTagValid(match, lengthDoc, styler)) {
							if (latexLastWordIsMathEnv(match, styler))
								mode = 0;
						}
					}
					state = SCE_L_COMMAND;
				} else if (latexIsSpecial(chNext)) {
					styler.ColourTo(i + 1, SCE_L_SPECIAL);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				} else if (chNext == '\r' || chNext == '\n') {
					styler.ColourTo(i, SCE_L_ERROR);
				} else {
					if (chNext == ']') {
						mode = 0;
						state = SCE_L_DEFAULT;
					}
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
				}
				break;
			case '$' :
				styler.ColourTo(i - 1, state);
				if (chNext == '$') {
					styler.ColourTo(i + 1, SCE_L_SHORTCMD);
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					mode = 0;
					state = SCE_L_DEFAULT;
				} else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation}	
					styler.ColourTo(i, SCE_L_SHORTCMD);
				}
				break;
			case '%' :
				styler.ColourTo(i - 1, state);
				state = SCE_L_COMMENT;
				break;
			}
			break;
		case SCE_L_COMMENT :
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, state);
				latexStateReset(mode, state);
			}
			break;
		case SCE_L_COMMENT2 :
			if (ch == '\\') {
				int match = i + 3;
				if (latexLastWordIs(match, styler, "\\end")) {
					match++;
					if (latexIsTagValid(match, lengthDoc, styler)) {
						if (latexLastWordIs(match, styler, "{comment}")) {
							styler.ColourTo(i - 1, state);
							state = SCE_L_COMMAND;
						}
					}
				}
			}
			break;
		case SCE_L_VERBATIM :
			if (ch == '\\') {
				int match = i + 3;
				if (latexLastWordIs(match, styler, "\\end")) {
					match++;
					if (latexIsTagValid(match, lengthDoc, styler)) {
						if (latexLastWordIs(match, styler, "{verbatim}")) {
							styler.ColourTo(i - 1, state);
							state = SCE_L_COMMAND;
						}
					}
				}
			} else if (chNext == chVerbatimDelim) {
				styler.ColourTo(i + 1, state);
				latexStateReset(mode, state);
				chVerbatimDelim = '\0';
				i++;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) {
				styler.ColourTo(i, SCE_L_ERROR);
				latexStateReset(mode, state);
				chVerbatimDelim = '\0';
			}
			break;
		}
	}
	if (lengthDoc == styler.Length()) truncModes(styler.GetLine(lengthDoc - 1));
	styler.ColourTo(lengthDoc - 1, state);
	styler.Flush();
}

static int latexFoldSaveToInt(const latexFoldSave &save) {
	int sum = 0;
	for (int i = 0; i <= save.structLev; ++i)
		sum += save.openBegins[i];
	return ((sum + save.structLev + SC_FOLDLEVELBASE) & SC_FOLDLEVELNUMBERMASK);
}

// Change folding state while processing a line
// Return the level before the first relevant command
void SCI_METHOD LexerLaTeX::Fold(unsigned int startPos, int length, int, IDocument *pAccess) {
	const char *structWords[7] = {"part", "chapter", "section", "subsection",
		"subsubsection", "paragraph", "subparagraph"};
	Accessor styler(pAccess, &props);
	unsigned int endPos = startPos + length;
	int curLine = styler.GetLine(startPos);
	latexFoldSave save;
	getSave(curLine - 1, save);
	do {
		char ch, buf[16];
		int i, j, lev = -1;
		bool needFold = false;
		for (i = static_cast<int>(startPos); i < static_cast<int>(endPos); ++i) {
			ch = styler.SafeGetCharAt(i);
			if (ch == '\r' || ch == '\n') break;
			if (ch != '\\' || styler.StyleAt(i) != SCE_L_COMMAND) continue;
			for (j = 0; j < 15 && i + 1 < static_cast<int>(endPos); ++j, ++i) {
				buf[j] = styler.SafeGetCharAt(i + 1);
				if (!latexIsLetter(buf[j])) break;
			}
			buf[j] = '\0';
			if (strcmp(buf, "begin") == 0) {
				if (lev < 0) lev = latexFoldSaveToInt(save);
				++save.openBegins[save.structLev];
				needFold = true;
			}
			else if (strcmp(buf, "end") == 0) {
				while (save.structLev > 0 && save.openBegins[save.structLev] == 0)
					--save.structLev;
				if (lev < 0) lev = latexFoldSaveToInt(save);
				if (save.openBegins[save.structLev] > 0) --save.openBegins[save.structLev];
			}
			else {
				for (j = 0; j < 7; ++j)
					if (strcmp(buf, structWords[j]) == 0) break;
				if (j >= 7) continue;
				save.structLev = j;   // level before the command
				for (j = save.structLev + 1; j < 8; ++j) {
					save.openBegins[save.structLev] += save.openBegins[j];
					save.openBegins[j] = 0;
				}
				if (lev < 0) lev = latexFoldSaveToInt(save);
				++save.structLev;   // level after the command
				needFold = true;
			}
		}
		if (lev < 0) lev = latexFoldSaveToInt(save);
		if (needFold) lev |= SC_FOLDLEVELHEADERFLAG;
		styler.SetLevel(curLine, lev);
		setSave(curLine, save);
		++curLine;
		startPos = styler.LineStart(curLine);
		if (static_cast<int>(startPos) == styler.Length()) {
			lev = latexFoldSaveToInt(save);
			styler.SetLevel(curLine, lev);
			setSave(curLine, save);
			truncSaves(curLine);
		}
	} while (startPos < endPos);
	styler.Flush();
}

static const char *const emptyWordListDesc[] = {
	0
};

LexerModule lmLatex(SCLEX_LATEX, LexerLaTeX::LexerFactoryLaTeX, "latex", emptyWordListDesc);

Added lexers/LexLisp.cxx.



























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// Scintilla source code edit control
/** @file LexLisp.cxx
 ** Lexer for Lisp.
 ** Written by Alexey Yutkin.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define SCE_LISP_CHARACTER 29
#define SCE_LISP_MACRO 30
#define SCE_LISP_MACRO_DISPATCH 31

static inline bool isLispoperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '{' || ch == '}')
		return true;
	return false;
}

static inline bool isLispwordstart(char ch) {
	return isascii(ch) && ch != ';'  && !isspacechar(ch) && !isLispoperator(ch) &&
		ch != '\n' && ch != '\r' &&  ch != '\"';
}


static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
	assert(end >= start);
	char s[100];
	unsigned int i;
	bool digit_flag = true;
	for (i = 0; (i < end - start + 1) && (i < 99); i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
		if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
	}
	char chAttr = SCE_LISP_IDENTIFIER;

	if(digit_flag) chAttr = SCE_LISP_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LISP_KEYWORD;
		} else if (keywords_kw.InList(s)) {
			chAttr = SCE_LISP_KEYWORD_KW;
		} else if ((s[0] == '*' && s[i-1] == '*') ||
			   (s[0] == '+' && s[i-1] == '+')) {
			chAttr = SCE_LISP_SPECIAL;
		}
	}
	styler.ColourTo(end, chAttr);
	return;
}


static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords_kw = *keywordlists[1];

	styler.StartAt(startPos);

	int state = initStyle, radix = -1;
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i += 1;
			continue;
		}

		if (state == SCE_LISP_DEFAULT) {
			if (ch == '#') {
				styler.ColourTo(i - 1, state);
				radix = -1;
				state = SCE_LISP_MACRO_DISPATCH;
			} else if (ch == ':' && isLispwordstart(chNext)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_SYMBOL;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_IDENTIFIER;
			}
			else if (ch == ';') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_COMMENT;
			}
			else if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
			else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_STRING;
			}
		} else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
			if (!isLispwordstart(ch)) {
				if (state == SCE_LISP_IDENTIFIER) {
					classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
				} else {
					styler.ColourTo(i - 1, state);
				}
				state = SCE_LISP_DEFAULT;
			} /*else*/
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else if (state == SCE_LISP_MACRO_DISPATCH) {
			if (!(isascii(ch) && isdigit(ch))) {
				if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
					state = SCE_LISP_DEFAULT;
				} else {
					switch (ch) {
						case '|': state = SCE_LISP_MULTI_COMMENT; break;
						case 'o':
						case 'O': radix = 8; state = SCE_LISP_MACRO; break;
						case 'x':
						case 'X': radix = 16; state = SCE_LISP_MACRO; break;
						case 'b':
						case 'B': radix = 2; state = SCE_LISP_MACRO; break;
						case '\\': state = SCE_LISP_CHARACTER; break;
						case ':':
						case '-':
						case '+': state = SCE_LISP_MACRO; break;
						case '\'': if (isLispwordstart(chNext)) {
								   state = SCE_LISP_SPECIAL;
							   } else {
								   styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								   styler.ColourTo(i, SCE_LISP_OPERATOR);
								   state = SCE_LISP_DEFAULT;
							   }
							   break;
						default: if (isLispoperator(ch)) {
								 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								 styler.ColourTo(i, SCE_LISP_OPERATOR);
							 }
							 state = SCE_LISP_DEFAULT;
							 break;
					}
				}
			}
		} else if (state == SCE_LISP_MACRO) {
			if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_CHARACTER) {
			if (isLispoperator(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_DEFAULT;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_SPECIAL) {
			if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_DEFAULT;
			}
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else {
			if (state == SCE_LISP_COMMENT) {
				if (atEOL) {
					styler.ColourTo(i - 1, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_MULTI_COMMENT) {
				if (ch == '|' && chNext == '#') {
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			}
		}

	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LISP_OPERATOR) {
			if (ch == '(' || ch == '[' || ch == '{') {
				levelCurrent++;
			} else if (ch == ')' || ch == ']' || ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const lispWordListDesc[] = {
	"Functions and special operators",
	"Keywords",
	0
};

LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);

Added lexers/LexLout.cxx.















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexLout.cxx
 ** Lexer for the Basser Lout (>= version 3) typesetting language
 **/
// Copyright 2003 by Kein-Hong Man <mkh@pl.jaring.my>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_');
}

static inline bool IsAnOther(const int ch) {
	return (ch < 0x80) && (ch == '{' || ch == '}' ||
	ch == '!' || ch == '$' || ch == '%' || ch == '&' || ch == '\'' ||
	ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
	ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == ';' ||
	ch == '<' || ch == '=' || ch == '>' || ch == '?' || ch == '[' ||
	ch == ']' || ch == '^' || ch == '`' || ch == '|' || ch == '~');
}

static void ColouriseLoutDoc(unsigned int startPos, int length, int initStyle,
			     WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];

	int visibleChars = 0;
	int firstWordInLine = 0;
	int leadingAtSign = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_LOUT_STRING)) {
			// Prevent SCE_LOUT_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LOUT_STRING);
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LOUT_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_LOUT_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_LOUT_NUMBER) {
			if (!IsADigit(sc.ch) && sc.ch != '.') {
				sc.SetState(SCE_LOUT_DEFAULT);
			}
		} else if (sc.state == SCE_LOUT_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LOUT_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LOUT_STRINGEOL);
				sc.ForwardSetState(SCE_LOUT_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_LOUT_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));

				if (leadingAtSign) {
					if (keywords.InList(s)) {
						sc.ChangeState(SCE_LOUT_WORD);
					} else {
						sc.ChangeState(SCE_LOUT_WORD4);
					}
				} else if (firstWordInLine && keywords3.InList(s)) {
					sc.ChangeState(SCE_LOUT_WORD3);
				}
				sc.SetState(SCE_LOUT_DEFAULT);
			}
		} else if (sc.state == SCE_LOUT_OPERATOR) {
			if (!IsAnOther(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));

				if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LOUT_WORD2);
				}
				sc.SetState(SCE_LOUT_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LOUT_DEFAULT) {
			if (sc.ch == '#') {
				sc.SetState(SCE_LOUT_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LOUT_STRING);
			} else if (IsADigit(sc.ch) ||
				  (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LOUT_NUMBER);
			} else if (IsAWordChar(sc.ch)) {
				firstWordInLine = (visibleChars == 0);
				leadingAtSign = (sc.ch == '@');
				sc.SetState(SCE_LOUT_IDENTIFIER);
			} else if (IsAnOther(sc.ch)) {
				sc.SetState(SCE_LOUT_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldLoutDoc(unsigned int startPos, int length, int, WordList *[],
                        Accessor &styler) {

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (style == SCE_LOUT_WORD) {
			if (ch == '@') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!IsAWordChar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}
				if (strcmp(s, "@Begin") == 0) {
					levelCurrent++;
				} else if (strcmp(s, "@End") == 0) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LOUT_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const loutWordLists[] = {
            "Predefined identifiers",
            "Predefined delimiters",
            "Predefined keywords",
            0,
        };

LexerModule lmLout(SCLEX_LOUT, ColouriseLoutDoc, "lout", FoldLoutDoc, loutWordLists);

Added lexers/LexLua.cxx.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	// Accepts accented characters
	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases. [pP] is for hex floats.
	CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP");
	CharacterSet setExponent(CharacterSet::setNone, "eEpP");
	CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#");
	CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\");

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	// Continuation of a string (\z whitespace escaping) is controlled by stringWs.
	int nestLevel = 0;
	int sepCount = 0;
	int stringWs = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT ||
		initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 9;
		sepCount = lineState & 0xFF;
		stringWs = lineState & 0x100;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
			case SCE_LUA_STRING:
			case SCE_LUA_CHARACTER:
				// Inside a literal string, block comment or string, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 9) | stringWs | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
				sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			if (sc.ch == ':' && sc.chPrev == ':') {	// :: <label> :: forward scan
				sc.Forward();
				int ln = 0, maxln = startPos + length - sc.currentPos;
				int c;
				while (ln < maxln) {		// determine line extent
					c = sc.GetRelative(ln);
					if (c == '\r' || c == '\n')
						break;
					ln++;
				}
				maxln = ln; ln = 0;
				while (ln < maxln) {		// skip over spaces/tabs
					if (!IsASpaceOrTab(sc.GetRelative(ln)))
						break;
					ln++;
				}
				int ws1 = ln;
				if (setWordStart.Contains(sc.GetRelative(ln))) {
					int i = 0;
					char s[100];
					while (ln < maxln) {	// get potential label
						c = sc.GetRelative(ln);
						if (!setWord.Contains(c))
							break;
						if (i < 90)
							s[i++] = c;
						ln++;
					}
					s[i] = '\0'; int lbl = ln;
					if (!keywords.InList(s)) {
						while (ln < maxln) {		// skip over spaces/tabs
							if (!IsASpaceOrTab(sc.GetRelative(ln)))
								break;
							ln++;
						}
						int ws2 = ln - lbl;
						if (sc.GetRelative(ln) == ':' && sc.GetRelative(ln + 1) == ':') {
							// final :: found, complete valid label construct
							sc.ChangeState(SCE_LUA_LABEL);
							if (ws1) {
								sc.SetState(SCE_LUA_DEFAULT);
								sc.Forward(ws1);
							}
							sc.SetState(SCE_LUA_LABEL);
							sc.Forward(lbl - ws1);
							if (ws2) {
								sc.SetState(SCE_LUA_DEFAULT);
								sc.Forward(ws2);
							}
							sc.SetState(SCE_LUA_LABEL);
							sc.Forward(2);
						}
					}
				}
			}
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eEpP non-sign non-hexdigit char
			if (!setNumber.Contains(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			} else if (sc.ch == '-' || sc.ch == '+') {
				if (!setExponent.Contains(sc.chPrev))
					sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!(setWord.Contains(sc.ch) || sc.ch == '.') || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
					if (strcmp(s, "goto") == 0) {	// goto <label> forward scan
						sc.SetState(SCE_LUA_DEFAULT);
						while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
							sc.Forward();
						if (setWordStart.Contains(sc.ch)) {
							sc.SetState(SCE_LUA_LABEL);
							sc.Forward();
							while (setWord.Contains(sc.ch))
								sc.Forward();
							sc.GetCurrent(s, sizeof(s));
							if (keywords.InList(s))
								sc.ChangeState(SCE_LUA_WORD);
						}
						sc.SetState(SCE_LUA_DEFAULT);
					}
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (stringWs) {
				if (!IsASpace(sc.ch))
					stringWs = 0;
			}
			if (sc.ch == '\\') {
				if (setEscapeSkip.Contains(sc.chNext)) {
					sc.Forward();
				} else if (sc.chNext == 'z') {
					sc.Forward();
					stringWs = 0x100;
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (stringWs == 0 && sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (stringWs) {
				if (!IsASpace(sc.ch))
					stringWs = 0;
			}
			if (sc.ch == '\\') {
				if (setEscapeSkip.Contains(sc.chNext)) {
					sc.Forward();
				} else if (sc.chNext == 'z') {
					sc.Forward();
					stringWs = 0x100;
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (stringWs == 0 && sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward();
				}
			} else if (setWordStart.Contains(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
				stringWs = 0;
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
				stringWs = 0;
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (setLuaOperator.Contains(sc.ch)) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}

	if (setWord.Contains(sc.chPrev) || sc.chPrev == '.') {
		char s[100];
		sc.GetCurrent(s, sizeof(s));
		if (keywords.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD);
		} else if (keywords2.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD2);
		} else if (keywords3.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD3);
		} else if (keywords4.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD4);
		} else if (keywords5.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD5);
		} else if (keywords6.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD6);
		} else if (keywords7.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD7);
		} else if (keywords8.InList(s)) {
			sc.ChangeState(SCE_LUA_WORD8);
		}
	}

	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				char s[10] = "";
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);

Added lexers/LexMMIXAL.cxx.



























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexMMIXAL.cxx
 ** Lexer for MMIX Assembler Language.
 ** Written by Christoph Hsler <christoph.hoesler@student.uni-tuebingen.de>
 ** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_');
}

inline bool isMMIXALOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '+' || ch == '-' || ch == '|' || ch == '^' ||
		ch == '*' || ch == '/' ||
		ch == '%' || ch == '<' || ch == '>' || ch == '&' ||
		ch == '~' || ch == '$' ||
		ch == ',' || ch == '(' || ch == ')' ||
		ch == '[' || ch == ']')
		return true;
	return false;
}

static void ColouriseMMIXALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &opcodes = *keywordlists[0];
	WordList &special_register = *keywordlists[1];
	WordList &predef_symbols = *keywordlists[2];

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward())
	{
		// No EOL continuation
		if (sc.atLineStart) {
			if (sc.ch ==  '@' && sc.chNext == 'i') {
				sc.SetState(SCE_MMIXAL_INCLUDE);
			} else {
				sc.SetState(SCE_MMIXAL_LEADWS);
			}
		}

		// Check if first non whitespace character in line is alphanumeric
		if (sc.state == SCE_MMIXAL_LEADWS && !isspace(sc.ch)) {	// LEADWS
			if(!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_MMIXAL_COMMENT);
			} else {
				if(sc.atLineStart) {
					sc.SetState(SCE_MMIXAL_LABEL);
				} else {
					sc.SetState(SCE_MMIXAL_OPCODE_PRE);
				}
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_MMIXAL_OPERATOR) {			// OPERATOR
			sc.SetState(SCE_MMIXAL_OPERANDS);
		} else if (sc.state == SCE_MMIXAL_NUMBER) {		// NUMBER
			if (!isdigit(sc.ch)) {
				if (IsAWordChar(sc.ch)) {
					char s[100];
					sc.GetCurrent(s, sizeof(s));
					sc.ChangeState(SCE_MMIXAL_REF);
					sc.SetState(SCE_MMIXAL_REF);
				} else {
					sc.SetState(SCE_MMIXAL_OPERANDS);
				}
			}
		} else if (sc.state == SCE_MMIXAL_LABEL) {			// LABEL
			if (!IsAWordChar(sc.ch) ) {
				sc.SetState(SCE_MMIXAL_OPCODE_PRE);
			}
		} else if (sc.state == SCE_MMIXAL_REF) {			// REF
			if (!IsAWordChar(sc.ch) ) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (*s == ':') {	// ignore base prefix for match
					for (size_t i = 0; i != sizeof(s); ++i) {
						*(s+i) = *(s+i+1);
					}
				}
				if (special_register.InList(s)) {
					sc.ChangeState(SCE_MMIXAL_REGISTER);
				} else if (predef_symbols.InList(s)) {
					sc.ChangeState(SCE_MMIXAL_SYMBOL);
				}
				sc.SetState(SCE_MMIXAL_OPERANDS);
			}
		} else if (sc.state == SCE_MMIXAL_OPCODE_PRE) {	// OPCODE_PRE
				if (!isspace(sc.ch)) {
					sc.SetState(SCE_MMIXAL_OPCODE);
				}
		} else if (sc.state == SCE_MMIXAL_OPCODE) {		// OPCODE
			if (!IsAWordChar(sc.ch) ) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (opcodes.InList(s)) {
					sc.ChangeState(SCE_MMIXAL_OPCODE_VALID);
				} else {
					sc.ChangeState(SCE_MMIXAL_OPCODE_UNKNOWN);
				}
				sc.SetState(SCE_MMIXAL_OPCODE_POST);
			}
		} else if (sc.state == SCE_MMIXAL_STRING) {		// STRING
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
			}
		} else if (sc.state == SCE_MMIXAL_CHAR) {			// CHAR
			if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_MMIXAL_OPERANDS);
			}
		} else if (sc.state == SCE_MMIXAL_REGISTER) {		// REGISTER
			if (!isdigit(sc.ch)) {
				sc.SetState(SCE_MMIXAL_OPERANDS);
			}
		} else if (sc.state == SCE_MMIXAL_HEX) {			// HEX
			if (!isxdigit(sc.ch)) {
				sc.SetState(SCE_MMIXAL_OPERANDS);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_MMIXAL_OPCODE_POST ||		// OPCODE_POST
			sc.state == SCE_MMIXAL_OPERANDS) {			// OPERANDS
			if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) {
				if (!sc.atLineEnd) {
					sc.SetState(SCE_MMIXAL_COMMENT);
				}
			} else if (isdigit(sc.ch)) {
				sc.SetState(SCE_MMIXAL_NUMBER);
			} else if (IsAWordChar(sc.ch) || sc.Match('@')) {
				sc.SetState(SCE_MMIXAL_REF);
			} else if (sc.Match('\"')) {
				sc.SetState(SCE_MMIXAL_STRING);
			} else if (sc.Match('\'')) {
				sc.SetState(SCE_MMIXAL_CHAR);
			} else if (sc.Match('$')) {
				sc.SetState(SCE_MMIXAL_REGISTER);
			} else if (sc.Match('#')) {
				sc.SetState(SCE_MMIXAL_HEX);
			} else if (isMMIXALOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_MMIXAL_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static const char * const MMIXALWordListDesc[] = {
	"Operation Codes",
	"Special Register",
	"Predefined Symbols",
	0
};

LexerModule lmMMIXAL(SCLEX_MMIXAL, ColouriseMMIXALDoc, "mmixal", 0, MMIXALWordListDesc);

Added lexers/LexMPT.cxx.



































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexMPT.cxx
 ** Lexer for MPT specific files. Based on LexOthers.cxx
 ** LOT = the text log file created by the MPT application while running a test program
 ** Other MPT specific files to be added later.
 **/
// Copyright 2003 by Marius Gheorghe <mgheorghe@cabletest.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static int GetLotLineState(std::string &line) {
	if (line.length()) {
		// Most of the time the first non-blank character in line determines that line's type
		// Now finds the first non-blank character
		unsigned i; // Declares counter here to make it persistent after the for loop
		for (i = 0; i < line.length(); ++i) {
			if (!(isascii(line[i]) && isspace(line[i])))
				break;
		}

		// Checks if it was a blank line
		if (i == line.length())
			return SCE_LOT_DEFAULT;

		switch (line[i]) {
		case '*': // Fail measurement
			return SCE_LOT_FAIL;

		case '+': // Header
		case '|': // Header
			return SCE_LOT_HEADER;

		case ':': // Set test limits
			return SCE_LOT_SET;

		case '-': // Section break
			return SCE_LOT_BREAK;

		default:  // Any other line
			// Checks for message at the end of lot file
			if (line.find("PASSED") != std::string::npos) {
				return SCE_LOT_PASS;
			}
			else if (line.find("FAILED") != std::string::npos) {
				return SCE_LOT_FAIL;
			}
			else if (line.find("ABORTED") != std::string::npos) {
				return SCE_LOT_ABORT;
			}
			else {
				return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT;
			}
		}
	}
	else {
		return SCE_LOT_DEFAULT;
	}
}

static void ColourizeLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	bool atLineStart = true;// Arms the 'at line start' flag
	char chNext = styler.SafeGetCharAt(startPos);
	std::string line("");
	line.reserve(256);	// Lot lines are less than 256 chars long most of the time. This should avoid reallocations

	// Styles LOT document
	unsigned int i;			// Declared here because it's used after the for loop
	for (i = startPos; i < startPos + length; ++i) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		line += ch;
		atLineStart = false;

		// LOT files are only used on the Win32 platform, thus EOL == CR+LF
		// Searches for the end of line
		if (ch == '\r' && chNext == '\n') {
			line += chNext; // Gets the '\n'
			++i; // Advances past the '\n'
			chNext = styler.SafeGetCharAt(i + 1); // Gets character of next line
			styler.ColourTo(i, GetLotLineState(line));
			line = "";
			atLineStart = true; // Arms flag for next line
		}
	}

	// Last line may not have a line ending
	if (!atLineStart) {
		styler.ColourTo(i - 1, GetLotLineState(line));
	}
}

// Folds an MPT LOT file: the blocks that can be folded are:
// sections (headed by a set line)
// passes (contiguous pass results within a section)
// fails (contiguous fail results within a section)
static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldCompact = styler.GetPropertyInt("fold.compact", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);

	char chNext = styler.SafeGetCharAt(startPos);
	int style = SCE_LOT_DEFAULT;
	int styleNext = styler.StyleAt(startPos);
	int lev = SC_FOLDLEVELBASE;

	// Gets style of previous line if not at the beginning of the document
	if (startPos > 1)
		style = styler.StyleAt(startPos - 2);

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (ch == '\r' && chNext == '\n') {
			// TO DO:
			// Should really get the state of the previous line from the styler
			int stylePrev = style;
			style = styleNext;
			styleNext = styler.StyleAt(i + 2);

			switch (style) {
/*
			case SCE_LOT_SET:
				lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
				break;
*/
			case SCE_LOT_FAIL:
/*
				if (stylePrev != SCE_LOT_FAIL)
					lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
				else
					lev = SC_FOLDLEVELBASE + 1;
*/
				lev = SC_FOLDLEVELBASE;
				break;

			default:
				if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL)
					lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
				else
					lev = SC_FOLDLEVELBASE + 1;

				if (visibleChars == 0 && foldCompact)
					lev |= SC_FOLDLEVELWHITEFLAG;
				break;
			}

			if (lev != styler.LevelAt(lineCurrent))
				styler.SetLevel(lineCurrent, lev);

			lineCurrent++;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, lev | flagsNext);
}

static const char * const emptyWordListDesc[] = {
	0
};

LexerModule lmLot(SCLEX_LOT, ColourizeLotDoc, "lot", FoldLotDoc, emptyWordListDesc);

Added lexers/LexMSSQL.cxx.































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
// Scintilla source code edit control
/** @file LexMSSQL.cxx
 ** Lexer for MSSQL.
 **/
// By Filip Yaghob <fyaghob@gmail.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define KW_MSSQL_STATEMENTS         0
#define KW_MSSQL_DATA_TYPES         1
#define KW_MSSQL_SYSTEM_TABLES      2
#define KW_MSSQL_GLOBAL_VARIABLES   3
#define KW_MSSQL_FUNCTIONS          4
#define KW_MSSQL_STORED_PROCEDURES  5
#define KW_MSSQL_OPERATORS          6

static bool isMSSQLOperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
        ch == '-' || ch == '+' || ch == '=' || ch == '|' ||
        ch == '<' || ch == '>' || ch == '/' ||
        ch == '!' || ch == '~' || ch == '(' || ch == ')' ||
		ch == ',')
		return true;
	return false;
}

static char classifyWordSQL(unsigned int start,
                            unsigned int end,
                            WordList *keywordlists[],
                            Accessor &styler,
                            unsigned int actualState,
							unsigned int prevState) {
	char s[256];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');

	WordList &kwStatements          = *keywordlists[KW_MSSQL_STATEMENTS];
    WordList &kwDataTypes           = *keywordlists[KW_MSSQL_DATA_TYPES];
    WordList &kwSystemTables        = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
    WordList &kwGlobalVariables     = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
    WordList &kwFunctions           = *keywordlists[KW_MSSQL_FUNCTIONS];
    WordList &kwStoredProcedures    = *keywordlists[KW_MSSQL_STORED_PROCEDURES];
    WordList &kwOperators           = *keywordlists[KW_MSSQL_OPERATORS];

	for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		s[i + 1] = '\0';
	}
	char chAttr = SCE_MSSQL_IDENTIFIER;

	if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) {

        if (kwGlobalVariables.InList(&s[2]))
            chAttr = SCE_MSSQL_GLOBAL_VARIABLE;

	} else if (wordIsNumber) {
		chAttr = SCE_MSSQL_NUMBER;

	} else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
		// Look first in datatypes
        if (kwDataTypes.InList(s))
            chAttr = SCE_MSSQL_DATATYPE;
		else if (kwOperators.InList(s))
			chAttr = SCE_MSSQL_OPERATOR;
		else if (kwStatements.InList(s))
			chAttr = SCE_MSSQL_STATEMENT;
		else if (kwSystemTables.InList(s))
			chAttr = SCE_MSSQL_SYSTABLE;
		else if (kwFunctions.InList(s))
            chAttr = SCE_MSSQL_FUNCTION;
		else if (kwStoredProcedures.InList(s))
			chAttr = SCE_MSSQL_STORED_PROCEDURE;

	} else {
		if (kwOperators.InList(s))
			chAttr = SCE_MSSQL_OPERATOR;
		else if (kwStatements.InList(s))
			chAttr = SCE_MSSQL_STATEMENT;
		else if (kwSystemTables.InList(s))
			chAttr = SCE_MSSQL_SYSTABLE;
		else if (kwFunctions.InList(s))
			chAttr = SCE_MSSQL_FUNCTION;
		else if (kwStoredProcedures.InList(s))
			chAttr = SCE_MSSQL_STORED_PROCEDURE;
		else if (kwDataTypes.InList(s))
			chAttr = SCE_MSSQL_DATATYPE;
	}

	styler.ColourTo(end, chAttr);

	return chAttr;
}

static void ColouriseMSSQLDoc(unsigned int startPos, int length,
                              int initStyle, WordList *keywordlists[], Accessor &styler) {


	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold") != 0;
	int lineCurrent = styler.GetLine(startPos);
	int spaceFlags = 0;

	int state = initStyle;
	int prevState = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	styler.StartSegment(startPos);
	unsigned int lengthDoc = startPos + length;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
			int lev = indentCurrent;
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
				if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				}
			}
			if (fold) {
				styler.SetLevel(lineCurrent, lev);
			}
		}

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		// When the last char isn't part of the state (have to deal with it too)...
		if ( (state == SCE_MSSQL_IDENTIFIER) ||
                    (state == SCE_MSSQL_STORED_PROCEDURE) ||
                    (state == SCE_MSSQL_DATATYPE) ||
                    //~ (state == SCE_MSSQL_COLUMN_NAME) ||
                    (state == SCE_MSSQL_FUNCTION) ||
                    //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) ||
                    (state == SCE_MSSQL_VARIABLE)) {
			if (!iswordchar(ch)) {
				int stateTmp;

                if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) {
                    styler.ColourTo(i - 1, state);
					stateTmp = state;
                } else
                    stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);

				prevState = state;

				if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE)
					state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
				else
					state = SCE_MSSQL_DEFAULT;
			}
		} else if (state == SCE_MSSQL_LINE_COMMENT) {
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, state);
				prevState = state;
				state = SCE_MSSQL_DEFAULT;
			}
		} else if (state == SCE_MSSQL_GLOBAL_VARIABLE) {
			if ((ch != '@') && !iswordchar(ch)) {
				classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState);
				prevState = state;
				state = SCE_MSSQL_DEFAULT;
			}
		}

		// If is the default or one of the above succeeded
		if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) {
			if (iswordstart(ch)) {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_IDENTIFIER;
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_COMMENT;
			} else if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_LINE_COMMENT;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_STRING;
			} else if (ch == '"') {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_COLUMN_NAME;
			} else if (ch == '[') {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
				state = SCE_MSSQL_COLUMN_NAME_2;
			} else if (isMSSQLOperator(ch)) {
				styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				styler.ColourTo(i, SCE_MSSQL_OPERATOR);
                //~ style = SCE_MSSQL_DEFAULT;
				prevState = state;
				state = SCE_MSSQL_DEFAULT;
			} else if (ch == '@') {
                styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT);
				prevState = state;
                if (chNext == '@') {
                    state = SCE_MSSQL_GLOBAL_VARIABLE;
//                    i += 2;
                } else
                    state = SCE_MSSQL_VARIABLE;
            }


		// When the last char is part of the state...
		} else if (state == SCE_MSSQL_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) &&
					    (styler.GetStartSegment() == startPos)))) {
						styler.ColourTo(i, state);
						//~ state = SCE_MSSQL_COMMENT;
					prevState = state;
                        state = SCE_MSSQL_DEFAULT;
					}
				}
			} else if (state == SCE_MSSQL_STRING) {
				if (ch == '\'') {
					if ( chNext == '\'' ) {
						i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
					} else {
						styler.ColourTo(i, state);
					prevState = state;
						state = SCE_MSSQL_DEFAULT;
					//i++;
					}
				//ch = chNext;
				//chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_MSSQL_COLUMN_NAME) {
				if (ch == '"') {
					if (chNext == '"') {
						i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} else {
                    styler.ColourTo(i, state);
					prevState = state;
					state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
					//i++;
                }
                }
		} else if (state == SCE_MSSQL_COLUMN_NAME_2) {
			if (ch == ']') {
                styler.ColourTo(i, state);
				prevState = state;
                state = SCE_MSSQL_DEFAULT_PREF_DATATYPE;
                //i++;
			}
		}

		chPrev = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT);
    char s[10];
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
        // Comment folding
		if (foldComment) {
			if (!inComment && (style == SCE_MSSQL_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_MSSQL_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_MSSQL_COMMENT);
		}
        if (style == SCE_MSSQL_STATEMENT) {
            // Folding between begin or case and end
            if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') {
                for (unsigned int j = 0; j < 5; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = static_cast<char>(tolower(styler[i + j]));
					s[j + 1] = '\0';
                }
				if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 0)) {
					levelCurrent++;
				}
				if (strcmp(s, "end") == 0) {
					levelCurrent--;
				}
            }
        }
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const sqlWordListDesc[] = {
	"Statements",
    "Data Types",
    "System tables",
    "Global variables",
    "Functions",
    "System Stored Procedures",
    "Operators",
	0,
};

LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);

Added lexers/LexMagik.cxx.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
// Scintilla source code edit control
/**
 * @file LexMagik.cxx
 * Lexer for GE(r) Smallworld(tm) MagikSF
 */
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/**
 * Is it a core character (C isalpha(), exclamation and question mark)
 *
 * \param  ch The character
 * \return True if ch is a character, False otherwise
 */
static inline bool IsAlphaCore(int ch) {
    return (isalpha(ch) || ch == '!' || ch == '?');
}

/**
 * Is it a character (IsAlphaCore() and underscore)
 *
 * \param  ch The character
 * \return True if ch is a character, False otherwise
 */
static inline bool IsAlpha(int ch) {
    return (IsAlphaCore(ch) || ch == '_');
}

/**
 * Is it a symbolic character (IsAlpha() and colon)
 *
 * \param  ch The character
 * \return True if ch is a character, False otherwise
 */
static inline bool IsAlphaSym(int ch) {
    return (IsAlpha(ch) || ch == ':');
}

/**
 * Is it a numerical character (IsAlpha() and 0 - 9)
 *
 * \param  ch The character
 * \return True if ch is a character, False otherwise
 */
static inline bool IsAlNum(int ch) {
    return ((ch >= '0' && ch <= '9') || IsAlpha(ch));
}

/**
 * Is it a symbolic numerical character (IsAlNum() and colon)
 *
 * \param  ch The character
 * \return True if ch is a character, False otherwise
 */
static inline bool IsAlNumSym(int ch) {
    return (IsAlNum(ch) || ch == ':');
}

/**
 * The lexer function
 *
 * \param  startPos Where to start scanning
 * \param  length Where to scan to
 * \param  initStyle The style at the initial point, not used in this folder
 * \param  keywordslists The keywordslists, currently, number 5 is used
 * \param  styler The styler
 */
static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler) {
    styler.StartAt(startPos);

    WordList &keywords = *keywordlists[0];
    WordList &pragmatics = *keywordlists[1];
    WordList &containers = *keywordlists[2];
    WordList &flow = *keywordlists[3];
    WordList &characters = *keywordlists[4];

	StyleContext sc(startPos, length, initStyle, styler);


	for (; sc.More(); sc.Forward()) {

    repeat:

        if(sc.ch == '#') {
            if (sc.chNext == '#') sc.SetState(SCE_MAGIK_HYPER_COMMENT);
            else sc.SetState(SCE_MAGIK_COMMENT);
            for(; sc.More() && !(sc.atLineEnd); sc.Forward());
            sc.SetState(SCE_MAGIK_DEFAULT);
            goto repeat;
        }

        if(sc.ch == '"') {
            sc.SetState(SCE_MAGIK_STRING);

            if(sc.More())
            {
                sc.Forward();
                for(; sc.More() && sc.ch != '"'; sc.Forward());
            }

            sc.ForwardSetState(SCE_MAGIK_DEFAULT);
            goto repeat;
        }

	    // The default state
	    if(sc.state == SCE_MAGIK_DEFAULT) {

	        // A certain keyword has been detected
	        if (sc.ch == '_' && (
                    sc.currentPos == 0 || !IsAlNum(sc.chPrev))) {
	            char keyword[50];
	            memset(keyword, '\0', 50);

	            for(
                    int scanPosition = 0;
                    scanPosition < 50;
                    scanPosition++) {
	                char keywordChar = static_cast<char>(
                        tolower(styler.SafeGetCharAt(
                            scanPosition +
                                static_cast<int>(sc.currentPos+1), ' ')));
                    if(IsAlpha(keywordChar)) {
                        keyword[scanPosition] = keywordChar;
                    } else {
                        break;
                    }
	            }

                // It is a pragma
	            if(pragmatics.InList(keyword)) {
	                sc.SetState(SCE_MAGIK_PRAGMA);
	            }

	            // it is a normal keyword like _local, _self, etc.
	            else if(keywords.InList(keyword)) {
	                sc.SetState(SCE_MAGIK_KEYWORD);
	            }

                // It is a container keyword, such as _method, _proc, etc.
	            else if(containers.InList(keyword)) {
	                sc.SetState(SCE_MAGIK_CONTAINER);
	            }

	            // It is a flow keyword, such as _for, _if, _try, etc.
	            else if(flow.InList(keyword)) {
	                sc.SetState(SCE_MAGIK_FLOW);
	            }

	            // Interpret as unknown keyword
	            else {
	                sc.SetState(SCE_MAGIK_UNKNOWN_KEYWORD);
	            }
	        }

            // Symbolic expression
	        else if(sc.ch == ':' && !IsAlNum(sc.chPrev)) {
	            sc.SetState(SCE_MAGIK_SYMBOL);
	            bool firstTrip = true;
	            for(sc.Forward(); sc.More(); sc.Forward()) {
	                if(firstTrip && IsAlphaSym(sc.ch));
	                else if(!firstTrip && IsAlNumSym(sc.ch));
	                else if(sc.ch == '|') {
	                    for(sc.Forward();
                            sc.More() && sc.ch != '|';
                            sc.Forward());
	                }
	                else break;

	                firstTrip = false;
	            }
	            sc.SetState(SCE_MAGIK_DEFAULT);
	            goto repeat;
	        }

            // Identifier (label) expression
	        else if(sc.ch == '@') {
	            sc.SetState(SCE_MAGIK_IDENTIFIER);
	            bool firstTrip = true;
	            for(sc.Forward(); sc.More(); sc.Forward()) {
	                if(firstTrip && IsAlphaCore(sc.ch)) {
	                    firstTrip = false;
	                }
	                else if(!firstTrip && IsAlpha(sc.ch));
	                else break;
	            }
	            sc.SetState(SCE_MAGIK_DEFAULT);
	            goto repeat;
	        }

	        // Start of a character
            else if(sc.ch == '%') {
                sc.SetState(SCE_MAGIK_CHARACTER);
                sc.Forward();
                char keyword[50];
	            memset(keyword, '\0', 50);

	            for(
                    int scanPosition = 0;
                    scanPosition < 50;
                    scanPosition++) {
	                char keywordChar = static_cast<char>(
                        tolower(styler.SafeGetCharAt(
                            scanPosition +
                                static_cast<int>(sc.currentPos), ' ')));
                    if(IsAlpha(keywordChar)) {
                        keyword[scanPosition] = keywordChar;
                    } else {
                        break;
                    }
	            }

	            if(characters.InList(keyword)) {
	                sc.Forward(static_cast<int>(strlen(keyword)));
	            } else {
	                sc.Forward();
	            }

                sc.SetState(SCE_MAGIK_DEFAULT);
                goto repeat;
            }

            // Operators
	        else if(
                sc.ch == '>' ||
                sc.ch == '<' ||
                sc.ch == '.' ||
                sc.ch == ',' ||
                sc.ch == '+' ||
                sc.ch == '-' ||
                sc.ch == '/' ||
                sc.ch == '*' ||
                sc.ch == '~' ||
                sc.ch == '$' ||
                sc.ch == '=') {
                sc.SetState(SCE_MAGIK_OPERATOR);
            }

            // Braces
            else if(sc.ch == '(' || sc.ch == ')') {
                sc.SetState(SCE_MAGIK_BRACE_BLOCK);
            }

            // Brackets
            else if(sc.ch == '{' || sc.ch == '}') {
                sc.SetState(SCE_MAGIK_BRACKET_BLOCK);
            }

            // Square Brackets
            else if(sc.ch == '[' || sc.ch == ']') {
                sc.SetState(SCE_MAGIK_SQBRACKET_BLOCK);
            }


	    }

	    // It is an operator
	    else if(
            sc.state == SCE_MAGIK_OPERATOR ||
            sc.state == SCE_MAGIK_BRACE_BLOCK ||
            sc.state == SCE_MAGIK_BRACKET_BLOCK ||
            sc.state == SCE_MAGIK_SQBRACKET_BLOCK) {
	        sc.SetState(SCE_MAGIK_DEFAULT);
	        goto repeat;
	    }

	    // It is the pragma state
	    else if(sc.state == SCE_MAGIK_PRAGMA) {
	        if(!IsAlpha(sc.ch)) {
	            sc.SetState(SCE_MAGIK_DEFAULT);
                goto repeat;
	        }
	    }

	    // It is the keyword state
	    else if(
            sc.state == SCE_MAGIK_KEYWORD ||
            sc.state == SCE_MAGIK_CONTAINER ||
            sc.state == SCE_MAGIK_FLOW ||
            sc.state == SCE_MAGIK_UNKNOWN_KEYWORD) {
	        if(!IsAlpha(sc.ch)) {
	            sc.SetState(SCE_MAGIK_DEFAULT);
	            goto repeat;
	        }
	    }
	}

	sc.Complete();
}

/**
 * The word list description
 */
static const char * const magikWordListDesc[] = {
    "Accessors (local, global, self, super, thisthread)",
    "Pragmatic (pragma, private)",
    "Containers (method, block, proc)",
    "Flow (if, then, elif, else)",
    "Characters (space, tab, newline, return)",
    "Fold Containers (method, proc, block, if, loop)",
    0};

/**
 * This function detects keywords which are able to have a body. Note that it
 * uses the Fold Containers word description, not the containers description. It
 * only works when the style at that particular position is set on Containers
 * or Flow (number 3 or 4).
 *
 * \param  keywordslist The list of keywords that are scanned, they should only
 *         contain the start keywords, not the end keywords
 * \param  The actual keyword
 * \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword
 *         0 otherwise
 */
static inline int IsFoldingContainer(WordList &keywordslist, char * keyword) {
    if(
        strlen(keyword) > 3 &&
        keyword[0] == 'e' && keyword[1] == 'n' && keyword[2] == 'd') {
        if (keywordslist.InList(keyword + 3)) {
            return -1;
        }

    } else {
        if(keywordslist.InList(keyword)) {
            return 1;
        }
    }

    return 0;
}

/**
 * The folding function
 *
 * \param  startPos Where to start scanning
 * \param  length Where to scan to
 * \param  keywordslists The keywordslists, currently, number 5 is used
 * \param  styler The styler
 */
static void FoldMagikDoc(unsigned int startPos, int length, int,
    WordList *keywordslists[], Accessor &styler) {

    bool compact = styler.GetPropertyInt("fold.compact") != 0;

    WordList &foldingElements = *keywordslists[5];
    int endPos = startPos + length;
    int line = styler.GetLine(startPos);
    int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
    int flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;

    for(
        int currentPos = startPos;
        currentPos < endPos;
        currentPos++) {
            char currentState = styler.StyleAt(currentPos);
            char c = styler.SafeGetCharAt(currentPos, ' ');
            int prevLine = styler.GetLine(currentPos - 1);
            line = styler.GetLine(currentPos);

            // Default situation
            if(prevLine < line) {
                styler.SetLevel(line, (level|flags) & ~SC_FOLDLEVELHEADERFLAG);
                flags = styler.LevelAt(line) & ~SC_FOLDLEVELNUMBERMASK;
            }

            if(
                (
                    currentState == SCE_MAGIK_CONTAINER ||
                    currentState == SCE_MAGIK_FLOW
                ) &&
                c == '_') {

                char keyword[50];
                memset(keyword, '\0', 50);

                for(
                    int scanPosition = 0;
                    scanPosition < 50;
                    scanPosition++) {
                    char keywordChar = static_cast<char>(
                        tolower(styler.SafeGetCharAt(
                            scanPosition +
                                currentPos + 1, ' ')));
                    if(IsAlpha(keywordChar)) {
                        keyword[scanPosition] = keywordChar;
                    } else {
                        break;
                    }
                }

                if(IsFoldingContainer(foldingElements, keyword) > 0) {
                    styler.SetLevel(
                        line,
                        styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
                    level++;
                } else if(IsFoldingContainer(foldingElements, keyword) < 0) {
                    styler.SetLevel(line, styler.LevelAt(line));
                    level--;
                }
            }

            if(
                compact && (
                    currentState == SCE_MAGIK_BRACE_BLOCK ||
                    currentState == SCE_MAGIK_BRACKET_BLOCK ||
                    currentState == SCE_MAGIK_SQBRACKET_BLOCK)) {
                if(c == '{' || c == '[' || c == '(') {
                    styler.SetLevel(
                        line,
                        styler.LevelAt(line) | SC_FOLDLEVELHEADERFLAG);
                    level++;
                } else if(c == '}' || c == ']' || c == ')') {
                    styler.SetLevel(line, styler.LevelAt(line));
                    level--;
                }
            }
        }

}

/**
 * Injecting the module
 */
LexerModule lmMagikSF(
    SCLEX_MAGIK, ColouriseMagikDoc, "magiksf", FoldMagikDoc, magikWordListDesc);

Added lexers/LexMarkdown.cxx.











































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
/******************************************************************
 *  LexMarkdown.cxx
 *
 *  A simple Markdown lexer for scintilla.
 *
 *  Includes highlighting for some extra features from the
 *  Pandoc implementation; strikeout, using '#.' as a default
 *  ordered list item marker, and delimited code blocks.
 *
 *  Limitations:
 *
 *  Standard indented code blocks are not highlighted at all,
 *  as it would conflict with other indentation schemes. Use
 *  delimited code blocks for blanket highlighting of an
 *  entire code block.  Embedded HTML is not highlighted either.
 *  Blanket HTML highlighting has issues, because some Markdown
 *  implementations allow Markdown markup inside of the HTML. Also,
 *  there is a following blank line issue that can't be ignored,
 *  explained in the next paragraph. Embedded HTML and code
 *  blocks would be better supported with language specific
 *  highlighting.
 *
 *  The highlighting aims to accurately reflect correct syntax,
 *  but a few restrictions are relaxed. Delimited code blocks are
 *  highlighted, even if the line following the code block is not blank.
 *  Requiring a blank line after a block, breaks the highlighting
 *  in certain cases, because of the way Scintilla ends up calling
 *  the lexer.
 *
 *  Written by Jon Strait - jstrait@moonloop.net
 *
 *  The License.txt file describes the conditions under which this
 *  software may be distributed.
 *
 *****************************************************************/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsNewline(const int ch) {
    return (ch == '\n' || ch == '\r');
}

// True if can follow ch down to the end with possibly trailing whitespace
static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) {
    unsigned int i = 0;
    while (sc.GetRelative(++i) == ch)
        ;
    // Skip over whitespace
    while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
        ++i;
    if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
        sc.Forward(i);
        sc.ChangeState(state);
        sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
        return true;
    }
    else return false;
}

// Set the state on text section from current to length characters,
// then set the rest until the newline to default, except for any characters matching token
static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) {
    sc.SetState(state);
    sc.Forward(length);
    sc.SetState(SCE_MARKDOWN_DEFAULT);
    sc.Forward();
    bool started = false;
    while (sc.More() && !IsNewline(sc.ch)) {
        if (sc.ch == token && !started) {
            sc.SetState(state);
            started = true;
        }
        else if (sc.ch != token) {
            sc.SetState(SCE_MARKDOWN_DEFAULT);
            started = false;
        }
        sc.Forward();
    }
    sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
}

// Does the previous line have more than spaces and tabs?
static bool HasPrevLineContent(StyleContext &sc) {
    int i = 0;
    // Go back to the previous newline
    while ((--i + (int)sc.currentPos) >= 0 && !IsNewline(sc.GetRelative(i)))
        ;
    while ((--i + (int)sc.currentPos) >= 0) {
        if (IsNewline(sc.GetRelative(i)))
            break;
        if (!IsASpaceOrTab(sc.GetRelative(i)))
            return true;
    }
    return false;
}

static bool AtTermStart(StyleContext &sc) {
    return sc.currentPos == 0 || isspacechar(sc.chPrev);
}

static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) {
    int c, count = 1;
    unsigned int i = 0;
    while (++i) {
        c = sc.GetRelative(i);
        if (c == sc.ch)
            ++count;
        // hit a terminating character
        else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) {
            // Are we a valid HRULE
            if ((IsNewline(c) || sc.currentPos + i == endPos) &&
                    count >= 3 && !HasPrevLineContent(sc)) {
                sc.SetState(SCE_MARKDOWN_HRULE);
                sc.Forward(i);
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
                return true;
            }
            else {
                sc.SetState(SCE_MARKDOWN_DEFAULT);
		return false;
            }
        }
    }
    return false;
}

static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle,
                               WordList **, Accessor &styler) {
    unsigned int endPos = startPos + length;
    int precharCount = 0;
    // Don't advance on a new loop iteration and retry at the same position.
    // Useful in the corner case of having to start at the beginning file position
    // in the default state.
    bool freezeCursor = false;

    StyleContext sc(startPos, length, initStyle, styler);

    while (sc.More()) {
        // Skip past escaped characters
        if (sc.ch == '\\') {
            sc.Forward();
            continue;
        }

        // A blockquotes resets the line semantics
        if (sc.state == SCE_MARKDOWN_BLOCKQUOTE)
            sc.SetState(SCE_MARKDOWN_LINE_BEGIN);

        // Conditional state-based actions
        if (sc.state == SCE_MARKDOWN_CODE2) {
            if (sc.Match("``") && sc.GetRelative(-2) != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
        }
        else if (sc.state == SCE_MARKDOWN_CODE) {
            if (sc.ch == '`' && sc.chPrev != ' ')
                sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
        }
        /* De-activated because it gets in the way of other valid indentation
         * schemes, for example multiple paragraphs inside a list item.
        // Code block
        else if (sc.state == SCE_MARKDOWN_CODEBK) {
            bool d = true;
            if (IsNewline(sc.ch)) {
                if (sc.chNext != '\t') {
                    for (int c = 1; c < 5; ++c) {
                        if (sc.GetRelative(c) != ' ')
                            d = false;
                    }
                }
            }
            else if (sc.atLineStart) {
                if (sc.ch != '\t' ) {
                    for (int i = 0; i < 4; ++i) {
                        if (sc.GetRelative(i) != ' ')
                            d = false;
                    }
                }
            }
            if (!d)
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
        }
        */
        // Strong
        else if (sc.state == SCE_MARKDOWN_STRONG1) {
            if (sc.Match("**") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
        }
        else if (sc.state == SCE_MARKDOWN_STRONG2) {
            if (sc.Match("__") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
        }
        // Emphasis
        else if (sc.state == SCE_MARKDOWN_EM1) {
            if (sc.ch == '*' && sc.chPrev != ' ')
                sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
        }
        else if (sc.state == SCE_MARKDOWN_EM2) {
            if (sc.ch == '_' && sc.chPrev != ' ')
                sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
        }
        else if (sc.state == SCE_MARKDOWN_CODEBK) {
            if (sc.atLineStart && sc.Match("~~~")) {
                int i = 1;
                while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos)
                    i++;
                sc.Forward(i);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
        }
        else if (sc.state == SCE_MARKDOWN_STRIKEOUT) {
            if (sc.Match("~~") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
        }
        else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) {
            // Header
            if (sc.Match("######"))
                SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc);
            else if (sc.Match("#####"))
                SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc);
            else if (sc.Match("####"))
                SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc);
            else if (sc.Match("###"))
                SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc);
            else if (sc.Match("##"))
                SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc);
            else if (sc.Match("#")) {
                // Catch the special case of an unordered list
                if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
                    precharCount = 0;
                    sc.SetState(SCE_MARKDOWN_PRECHAR);
                }
                else
                    SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc);
            }
            // Code block
            else if (sc.Match("~~~")) {
                if (!HasPrevLineContent(sc))
                    sc.SetState(SCE_MARKDOWN_CODEBK);
                else
                    sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
            else if (sc.ch == '=') {
                if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc))
                    ;
                else
                    sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
            else if (sc.ch == '-') {
                if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc))
                    ;
                else {
                    precharCount = 0;
                    sc.SetState(SCE_MARKDOWN_PRECHAR);
                }
            }
            else if (IsNewline(sc.ch))
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
            else {
                precharCount = 0;
                sc.SetState(SCE_MARKDOWN_PRECHAR);
            }
        }

        // The header lasts until the newline
        else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 ||
                sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 ||
                sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) {
            if (IsNewline(sc.ch))
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
        }

        // New state only within the initial whitespace
        if (sc.state == SCE_MARKDOWN_PRECHAR) {
            // Blockquote
            if (sc.ch == '>' && precharCount < 5)
                sc.SetState(SCE_MARKDOWN_BLOCKQUOTE);
            /*
            // Begin of code block
            else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4))
                sc.SetState(SCE_MARKDOWN_CODEBK);
            */
            // HRule - Total of three or more hyphens, asterisks, or underscores
            // on a line by themselves
            else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc))
                ;
            // Unordered list
            else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '+') && IsASpaceOrTab(sc.chNext)) {
                sc.SetState(SCE_MARKDOWN_ULIST_ITEM);
                sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
            }
            // Ordered list
            else if (IsADigit(sc.ch)) {
                int digitCount = 0;
                while (IsADigit(sc.GetRelative(++digitCount)))
                    ;
                if (sc.GetRelative(digitCount) == '.' &&
                        IsASpaceOrTab(sc.GetRelative(digitCount + 1))) {
                    sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
                    sc.Forward(digitCount + 1);
                    sc.SetState(SCE_MARKDOWN_DEFAULT);
                }
            }
            // Alternate Ordered list
            else if (sc.ch == '#' && sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
                sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
                sc.Forward(2);
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            }
            else if (sc.ch != ' ' || precharCount > 2)
                sc.SetState(SCE_MARKDOWN_DEFAULT);
            else
                ++precharCount;
        }

        // New state anywhere in doc
        if (sc.state == SCE_MARKDOWN_DEFAULT) {
            if (sc.atLineStart && sc.ch == '#') {
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
                freezeCursor = true;
            }
            // Links and Images
            if (sc.Match("![") || sc.ch == '[') {
                int i = 0, j = 0, k = 0;
                int len = endPos - sc.currentPos;
                while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
                    ;
                if (sc.GetRelative(i) == ']') {
                    j = i;
                    if (sc.GetRelative(++i) == '(') {
                        while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\'))
                            ;
                        if (sc.GetRelative(i) == ')')
                            k = i;
                    }
                    else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') {
                        while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
                            ;
                        if (sc.GetRelative(i) == ']')
                            k = i;
                    }
                }
                // At least a link text
                if (j) {
                    sc.SetState(SCE_MARKDOWN_LINK);
                    sc.Forward(j);
                    // Also has a URL or reference portion
                    if (k)
                        sc.Forward(k - j);
                    sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
                }
            }
            // Code - also a special case for alternate inside spacing
            if (sc.Match("``") && sc.GetRelative(3) != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_CODE2);
                sc.Forward();
            }
            else if (sc.ch == '`' && sc.chNext != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_CODE);
            }
            // Strong
            else if (sc.Match("**") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_STRONG1);
                sc.Forward();
           }
            else if (sc.Match("__") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_STRONG2);
                sc.Forward();
            }
            // Emphasis
            else if (sc.ch == '*' && sc.chNext != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_EM1);
            }
            else if (sc.ch == '_' && sc.chNext != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_EM2);
            }
            // Strikeout
            else if (sc.Match("~~") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) {
                sc.SetState(SCE_MARKDOWN_STRIKEOUT);
                sc.Forward();
            }
            // Beginning of line
            else if (IsNewline(sc.ch)) {
                sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
            }
        }
        // Advance if not holding back the cursor for this iteration.
        if (!freezeCursor)
            sc.Forward();
        freezeCursor = false;
    }
    sc.Complete();
}

LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown");

Added lexers/LexMatlab.cxx.































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexMatlab.cxx
 ** Lexer for Matlab.
 ** Written by Jos Fonseca
 **
 ** Changes by Christoph Dalitz 2003/12/04:
 **   - added support for Octave
 **   - Strings can now be included both in single or double quotes
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool IsMatlabCommentChar(int c) {
	return (c == '%') ;
}

static bool IsOctaveCommentChar(int c) {
	return (c == '%' || c == '#') ;
}

static bool IsMatlabComment(Accessor &styler, int pos, int len) {
	return len > 0 && IsMatlabCommentChar(styler[pos]) ;
}

static bool IsOctaveComment(Accessor &styler, int pos, int len) {
	return len > 0 && IsOctaveCommentChar(styler[pos]) ;
}

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColouriseMatlabOctaveDoc(
            unsigned int startPos, int length, int initStyle,
            WordList *keywordlists[], Accessor &styler,
            bool (*IsCommentChar)(int)) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool transpose = false;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_MATLAB_OPERATOR) {
			if (sc.chPrev == '.') {
				if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
					sc.ForwardSetState(SCE_MATLAB_DEFAULT);
					transpose = false;
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_MATLAB_DEFAULT);
					transpose = true;
				} else {
					sc.SetState(SCE_MATLAB_DEFAULT);
				}
			} else {
				sc.SetState(SCE_MATLAB_DEFAULT);
			}
		} else if (sc.state == SCE_MATLAB_KEYWORD) {
			if (!isalnum(sc.ch) && sc.ch != '_') {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.SetState(SCE_MATLAB_DEFAULT);
					transpose = false;
				} else {
					sc.ChangeState(SCE_MATLAB_IDENTIFIER);
					sc.SetState(SCE_MATLAB_DEFAULT);
					transpose = true;
				}
			}
		} else if (sc.state == SCE_MATLAB_NUMBER) {
			if (!isdigit(sc.ch) && sc.ch != '.'
			        && !(sc.ch == 'e' || sc.ch == 'E')
			        && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E'))) {
				sc.SetState(SCE_MATLAB_DEFAULT);
				transpose = true;
			}
		} else if (sc.state == SCE_MATLAB_STRING) {
			if (sc.ch == '\'') {
				if (sc.chNext == '\'') {
 					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_MATLAB_DEFAULT);
 				}
			}
		} else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_MATLAB_DEFAULT);
			}
		} else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_MATLAB_DEFAULT);
				transpose = false;
			}
		}

		if (sc.state == SCE_MATLAB_DEFAULT) {
			if (IsCommentChar(sc.ch)) {
				sc.SetState(SCE_MATLAB_COMMENT);
			} else if (sc.ch == '!' && sc.chNext != '=' ) {
				sc.SetState(SCE_MATLAB_COMMAND);
			} else if (sc.ch == '\'') {
				if (transpose) {
					sc.SetState(SCE_MATLAB_OPERATOR);
				} else {
					sc.SetState(SCE_MATLAB_STRING);
				}
			} else if (sc.ch == '"') {
				sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING);
			} else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
				sc.SetState(SCE_MATLAB_NUMBER);
			} else if (isalpha(sc.ch)) {
				sc.SetState(SCE_MATLAB_KEYWORD);
			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
				if (sc.ch == ')' || sc.ch == ']') {
					transpose = true;
				} else {
					transpose = false;
				}
				sc.SetState(SCE_MATLAB_OPERATOR);
			} else {
				transpose = false;
			}
		}
	}
	sc.Complete();
}

static void ColouriseMatlabDoc(unsigned int startPos, int length, int initStyle,
                               WordList *keywordlists[], Accessor &styler) {
	ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabCommentChar);
}

static void ColouriseOctaveDoc(unsigned int startPos, int length, int initStyle,
                               WordList *keywordlists[], Accessor &styler) {
	ColouriseMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveCommentChar);
}

static void FoldMatlabOctaveDoc(unsigned int startPos, int length, int,
                                WordList *[], Accessor &styler,
                                bool (*IsComment)(Accessor&, int, int)) {

	int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsComment);
	char chNext = styler[startPos];
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsComment);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					// Line after is blank so check the next - maybe should continue further?
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsComment);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}
}

static void FoldMatlabDoc(unsigned int startPos, int length, int initStyle,
                          WordList *keywordlists[], Accessor &styler) {
	FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsMatlabComment);
}

static void FoldOctaveDoc(unsigned int startPos, int length, int initStyle,
                          WordList *keywordlists[], Accessor &styler) {
	FoldMatlabOctaveDoc(startPos, length, initStyle, keywordlists, styler, IsOctaveComment);
}

static const char * const matlabWordListDesc[] = {
	"Keywords",
	0
};

static const char * const octaveWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmMatlab(SCLEX_MATLAB, ColouriseMatlabDoc, "matlab", FoldMatlabDoc, matlabWordListDesc);

LexerModule lmOctave(SCLEX_OCTAVE, ColouriseOctaveDoc, "octave", FoldOctaveDoc, octaveWordListDesc);

Added lexers/LexMetapost.cxx.





































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
// Scintilla source code edit control

// File: LexMetapost.cxx - general context conformant metapost coloring scheme
// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
// Version: September 28, 2003
// Modified by instanton: July 10, 2007
// Folding based on keywordlists[]

// Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// This lexer is derived from the one written for the texwork environment (1999++) which in
// turn is inspired on texedit (1991++) which finds its roots in wdt (1986).

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// val SCE_METAPOST_DEFAULT = 0
// val SCE_METAPOST_SPECIAL = 1
// val SCE_METAPOST_GROUP = 2
// val SCE_METAPOST_SYMBOL = 3
// val SCE_METAPOST_COMMAND = 4
// val SCE_METAPOST_TEXT = 5

// Definitions in SciTEGlobal.properties:
//
// Metapost Highlighting
//
// # Default
// style.metapost.0=fore:#7F7F00
// # Special
// style.metapost.1=fore:#007F7F
// # Group
// style.metapost.2=fore:#880000
// # Symbol
// style.metapost.3=fore:#7F7F00
// # Command
// style.metapost.4=fore:#008800
// # Text
// style.metapost.5=fore:#000000

// lexer.tex.comment.process=0

// Auxiliary functions:

static inline bool endOfLine(Accessor &styler, unsigned int i) {
	return
      (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
}

static inline bool isMETAPOSTcomment(int ch) {
	return
      (ch == '%') ;
}

static inline bool isMETAPOSTone(int ch) {
	return
      (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') ||
      (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') ||
      (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ;
}

static inline bool isMETAPOSTtwo(int ch) {
	return
      (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#');
}

static inline bool isMETAPOSTthree(int ch) {
	return
      (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') ||
      (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') ||
      (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') ||
      (ch == '%') ;
}

static inline bool isMETAPOSTidentifier(int ch) {
	return
      ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
      (ch == '_') ;
}

static inline bool isMETAPOSTnumber(int ch) {
	return
      (ch >= '0') && (ch <= '9') ;
}

static inline bool isMETAPOSTstring(int ch) {
	return
      (ch == '\"') ;
}

static inline bool isMETAPOSTcolon(int ch) {
	return
		(ch == ':') ;
}

static inline bool isMETAPOSTequal(int ch) {
	return
		(ch == '=') ;
}

static int CheckMETAPOSTInterface(
    unsigned int startPos,
    int length,
    Accessor &styler,
	int defaultInterface) {

    char lineBuffer[1024] ;
	unsigned int linePos = 0 ;

	// some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)...

    if (styler.SafeGetCharAt(0) == '%') {
        for (unsigned int i = 0; i < startPos + length; i++) {
            lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
            if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
                lineBuffer[linePos] = '\0';
				if (strstr(lineBuffer, "interface=none")) {
                    return 0 ;
				} else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) {
                    return 1 ;
				} else if (strstr(lineBuffer, "interface=metafun")) {
                    return 2 ;
				} else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
					// better would be to limit the search to just one line
					return 2 ;
                } else {
                    return defaultInterface ;
                }
            }
		}
    }

    return defaultInterface ;
}

static void ColouriseMETAPOSTDoc(
    unsigned int startPos,
    int length,
    int,
    WordList *keywordlists[],
    Accessor &styler) {

	styler.StartAt(startPos) ;
	styler.StartSegment(startPos) ;

	bool processComment   = styler.GetPropertyInt("lexer.metapost.comment.process",   0) == 1 ;
    int  defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ;

	int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;

	// 0  no keyword highlighting
	// 1  metapost keyword hightlighting
	// 2+ metafun keyword hightlighting

	int extraInterface = 0 ;

	if (currentInterface != 0) {
		extraInterface = currentInterface ;
	}

	WordList &keywords  = *keywordlists[0] ;
	WordList &keywords2 = *keywordlists[extraInterface-1] ;

	StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ;

	char key[100] ;

    bool inTeX     = false ;
	bool inComment = false ;
	bool inString  = false ;
	bool inClause  = false ;

	bool going = sc.More() ; // needed because of a fuzzy end of file state

	for (; going; sc.Forward()) {

		if (! sc.More()) { going = false ; } // we need to go one behind the end of text

		if (inClause) {
			sc.SetState(SCE_METAPOST_TEXT) ;
			inClause = false ;
		}

		if (inComment) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_METAPOST_TEXT) ;
				inTeX = false ;
				inComment = false ;
				inClause = false ;
				inString = false ; // not correct but we want to stimulate one-lines
			}
		} else if (inString) {
			if (isMETAPOSTstring(sc.ch)) {
				sc.SetState(SCE_METAPOST_SPECIAL) ;
				sc.ForwardSetState(SCE_METAPOST_TEXT) ;
				inString = false ;
			} else if (sc.atLineEnd) {
				sc.SetState(SCE_METAPOST_TEXT) ;
				inTeX = false ;
				inComment = false ;
				inClause = false ;
				inString = false ; // not correct but we want to stimulate one-lines
			}
		} else {
			if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) {
				if (sc.state == SCE_METAPOST_COMMAND) {
					sc.GetCurrent(key, sizeof(key)) ;
					if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) {
    					sc.ChangeState(SCE_METAPOST_GROUP) ;
						inTeX = true ;
					} else if (inTeX) {
						if (strcmp(key,"etex") == 0) {
	    					sc.ChangeState(SCE_METAPOST_GROUP) ;
							inTeX = false ;
						} else {
	    					sc.ChangeState(SCE_METAPOST_TEXT) ;
						}
					} else {
						if (keywords && keywords.InList(key)) {
    						sc.ChangeState(SCE_METAPOST_COMMAND) ;
						} else if (keywords2 && keywords2.InList(key)) {
							sc.ChangeState(SCE_METAPOST_EXTRA) ;
						} else {
							sc.ChangeState(SCE_METAPOST_TEXT) ;
						}
					}
				}
			}
			if (isMETAPOSTcomment(sc.ch)) {
				if (! inTeX) {
					sc.SetState(SCE_METAPOST_SYMBOL) ;
					sc.ForwardSetState(SCE_METAPOST_DEFAULT) ;
					inComment = ! processComment ;
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTstring(sc.ch)) {
				if (! inTeX) {
					sc.SetState(SCE_METAPOST_SPECIAL) ;
					if (! isMETAPOSTstring(sc.chNext)) {
						sc.ForwardSetState(SCE_METAPOST_TEXT) ;
					}
					inString = true ;
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTcolon(sc.ch)) {
				if (! inTeX) {
					if (! isMETAPOSTequal(sc.chNext)) {
						sc.SetState(SCE_METAPOST_COMMAND) ;
						inClause = true ;
					} else {
						sc.SetState(SCE_METAPOST_SPECIAL) ;
					}
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTone(sc.ch)) {
				if (! inTeX) {
					sc.SetState(SCE_METAPOST_SPECIAL) ;
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTtwo(sc.ch)) {
				if (! inTeX) {
					sc.SetState(SCE_METAPOST_GROUP) ;
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTthree(sc.ch)) {
				if (! inTeX) {
					sc.SetState(SCE_METAPOST_SYMBOL) ;
				} else {
					sc.SetState(SCE_METAPOST_TEXT) ;
				}
			} else if (isMETAPOSTidentifier(sc.ch)) {
				if (sc.state != SCE_METAPOST_COMMAND) {
					sc.SetState(SCE_METAPOST_TEXT) ;
					sc.ChangeState(SCE_METAPOST_COMMAND) ;
				}
			} else if (isMETAPOSTnumber(sc.ch)) {
				// rather redundant since for the moment we don't handle numbers
				sc.SetState(SCE_METAPOST_TEXT) ;
			} else if (sc.atLineEnd) {
				sc.SetState(SCE_METAPOST_TEXT) ;
				inTeX = false ;
				inComment = false ;
				inClause = false ;
				inString = false ;
			} else {
				sc.SetState(SCE_METAPOST_TEXT) ;
			}
		}

	}

	sc.Complete();

}

// Hooks info the system:

static const char * const metapostWordListDesc[] = {
	"MetaPost",
	"MetaFun",
	0
} ;

static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) {
	WordList& keywordsStart=*keywordlists[3];
	WordList& keywordsStop1=*keywordlists[4];

	if (keywordsStart.InList(s)) {return 1;}
	else if (keywordsStop1.InList(s)) {return -1;}
	return 0;

}

static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word)
{
  int length=0;
  char ch=styler.SafeGetCharAt(pos);
  *word=0;

  while(isMETAPOSTidentifier(ch) && isalpha(ch) && length<100){
          word[length]=ch;
          length++;
          ch=styler.SafeGetCharAt(pos+length);
  }
  word[length]=0;
  return length;
}

static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler)
{
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos+length;
	int visibleChars=0;
	int lineCurrent=styler.GetLine(startPos);
	int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent=levelPrev;
	char chNext=styler[startPos];

	char buffer[100]="";

	for (unsigned int i=startPos; i < endPos; i++) {
		char ch=chNext;
		chNext=styler.SafeGetCharAt(i+1);
		char chPrev=styler.SafeGetCharAt(i-1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if(i==0 || chPrev == '\r' || chPrev=='\n'|| chPrev==' '|| chPrev=='(' || chPrev=='$')
		{
            ParseMetapostWord(i, styler, buffer);
			levelCurrent += classifyFoldPointMetapost(buffer,keywordlists);
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);

}


LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", FoldMetapostDoc, metapostWordListDesc);

Added lexers/LexModula.cxx.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
//	-*- coding: utf-8 -*-
//	Scintilla source code edit control
/**
 *	@file LexModula.cxx
 *	@author Dariusz "DKnoto" Knociński
 *	@date 2011/02/03
 *	@brief Lexer for Modula-2/3 documents.
 */
//	The License.txt file describes the conditions under which this software may
//	be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#ifdef DEBUG_LEX_MODULA
#define DEBUG_STATE( p, c )\
		fprintf( stderr, "Unknown state: currentPos = %d, char = '%c'\n", p, c );
#else
#define DEBUG_STATE( p, c )
#endif

static inline bool IsDigitOfBase( unsigned ch, unsigned base ) {
	if( ch < '0' || ch > 'f' ) return false;
	if( base <= 10 ) {
		if( ch >= ( '0' + base ) ) return false;
	} else {
		if( ch > '9' ) {
			unsigned nb = base - 10;
			if( ( ch < 'A' ) || ( ch >= ( 'A' + nb ) ) ) {
				if( ( ch < 'a' ) || ( ch >= ( 'a' + nb ) ) ) {
					return false;
				}
			}
		}
	}
	return true;
}

static inline unsigned IsOperator( StyleContext & sc, WordList & op ) {
	int i;
	char s[3];

	s[0] = sc.ch;
	s[1] = sc.chNext;
	s[2] = 0;
	for( i = 0; i < op.len; i++ ) {
		if( ( strlen( op.words[i] ) == 2 ) &&
			( s[0] == op.words[i][0] && s[1] == op.words[i][1] ) ) {
			return 2;
		}
	}
	s[1] = 0;
	for( i = 0; i < op.len; i++ ) {
		if( ( strlen( op.words[i] ) == 1 ) &&
			( s[0] == op.words[i][0] ) ) {
			return 1;
		}
	}
	return 0;
}

static inline bool IsEOL( Accessor &styler, unsigned curPos ) {
	unsigned ch = styler.SafeGetCharAt( curPos );
	if( ( ch == '\r' && styler.SafeGetCharAt( curPos + 1 ) == '\n' ) ||
		( ch == '\n' ) ) {
		return true;
	}
	return false;
}

static inline bool checkStatement(
	Accessor &styler,
	int &curPos,
	const char *stt, bool spaceAfter = true ) {
	int len = static_cast<int>(strlen( stt ));
	int i;
	for( i = 0; i < len; i++ ) {
		if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
			return false;
		}
	}
	if( spaceAfter ) {
		if( ! isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
			return false;
		}
	}
	curPos += ( len - 1 );
	return true;
}

static inline bool checkEndSemicolon(
	Accessor &styler,
	int &curPos, int endPos )
{
	const char *stt = "END";
	int len = static_cast<int>(strlen( stt ));
	int i;
	for( i = 0; i < len; i++ ) {
		if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) {
			return false;
		}
	}
	while( isspace( styler.SafeGetCharAt( curPos + i ) ) ) {
		i++;
		if( ( curPos + i ) >= endPos ) return false;
	}
	if( styler.SafeGetCharAt( curPos + i ) != ';' ) {
		return false;
	}
	curPos += ( i - 1 );
	return true;
}

static inline bool checkKeyIdentOper(

	Accessor &styler,
	int &curPos, int endPos,
	const char *stt, const char etk ) {
	int newPos = curPos;
	if( ! checkStatement( styler, newPos, stt ) )
		return false;
	newPos++;
	if( newPos >= endPos )
		return false;
	if( ! isspace( styler.SafeGetCharAt( newPos ) ) )
		return false;
	newPos++;
	if( newPos >= endPos )
		return false;
	while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
		newPos++;
		if( newPos >= endPos )
			return false;
	}
	if( ! isalpha( styler.SafeGetCharAt( newPos ) ) )
		return false;
	newPos++;
	if( newPos >= endPos )
		return false;
	char ch;
	ch = styler.SafeGetCharAt( newPos );
	while( isalpha( ch ) || isdigit( ch ) || ch == '_' ) {
		newPos++;
		if( newPos >= endPos ) return false;
		ch = styler.SafeGetCharAt( newPos );
	}
	while( isspace( styler.SafeGetCharAt( newPos ) ) ) {
		newPos++;
		if( newPos >= endPos ) return false;
	}
	if( styler.SafeGetCharAt( newPos ) != etk )
		return false;
	curPos = newPos;
	return true;
}

static void FoldModulaDoc( unsigned int startPos,
						 int length,
						 int , WordList *[],
						 Accessor &styler)
{
	int curLine = styler.GetLine(startPos);
	int curLevel = SC_FOLDLEVELBASE;
	int endPos = startPos + length;
	if( curLine > 0 )
		curLevel = styler.LevelAt( curLine - 1 ) >> 16;
	int curPos = startPos;
	int style = styler.StyleAt( curPos );
	int visChars = 0;
	int nextLevel = curLevel;

	while( curPos < endPos ) {
		if( ! isspace( styler.SafeGetCharAt( curPos ) ) ) visChars++;

		switch( style ) {
		case SCE_MODULA_COMMENT:
			if( checkStatement( styler, curPos, "(*" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "*)" ) )
				nextLevel--;
			break;

		case SCE_MODULA_DOXYCOMM:
			if( checkStatement( styler, curPos, "(**", false ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "*)" ) )
				nextLevel--;
			break;

		case SCE_MODULA_KEYWORD:
			if( checkStatement( styler, curPos, "IF" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "BEGIN" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "TRY" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "LOOP" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "FOR" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "WHILE" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "REPEAT" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "UNTIL" ) )
				nextLevel--;
			else
			if( checkStatement( styler, curPos, "WITH" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "CASE" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "TYPECASE" ) )
				nextLevel++;
			else
			if( checkStatement( styler, curPos, "LOCK" ) )
				nextLevel++;
			else
			if( checkKeyIdentOper( styler, curPos, endPos, "PROCEDURE", '(' ) )
				nextLevel++;
			else
			if( checkKeyIdentOper( styler, curPos, endPos, "END", ';' ) ) {
				int cln = curLine;
				int clv_old = curLevel;
				int pos;
				char ch;
				int clv_new;
				while( cln > 0 ) {
					clv_new = styler.LevelAt( cln - 1 ) >> 16;
					if( clv_new < clv_old ) {
						nextLevel--;
						pos = styler.LineStart( cln );
						while( ( ch = styler.SafeGetCharAt( pos ) ) != '\n' ) {
							if( ch == 'P' ) {
								if( styler.StyleAt(pos) == SCE_MODULA_KEYWORD )	{
									if( checkKeyIdentOper( styler, pos, endPos,
														"PROCEDURE", '(' ) ) {
										break;
									}
								}
							}
							pos++;
						}
						clv_old = clv_new;
					}
					cln--;
				}
			}
			else
			if( checkKeyIdentOper( styler, curPos, endPos, "END", '.' ) )
				nextLevel--;
			else
			if( checkEndSemicolon( styler, curPos, endPos ) )
				nextLevel--;
			else {
				while( styler.StyleAt( curPos + 1 ) == SCE_MODULA_KEYWORD )
					curPos++;
			}
			break;

		default:
			break;
		}

		if( IsEOL( styler, curPos ) || ( curPos == endPos - 1 ) ) {
			int efectiveLevel = curLevel | nextLevel << 16;
			if( visChars == 0 )
				efectiveLevel |= SC_FOLDLEVELWHITEFLAG;
			if( curLevel < nextLevel )
				efectiveLevel |= SC_FOLDLEVELHEADERFLAG;
			if( efectiveLevel != styler.LevelAt(curLine) ) {
				styler.SetLevel(curLine, efectiveLevel );
			}
			curLine++;
			curLevel = nextLevel;
			if( IsEOL( styler, curPos ) && ( curPos == endPos - 1 ) ) {
				styler.SetLevel( curLine, ( curLevel | curLevel << 16)
								| SC_FOLDLEVELWHITEFLAG);
			}
			visChars = 0;
		}
		curPos++;
		style = styler.StyleAt( curPos );
	}
}

static inline bool skipWhiteSpaces( StyleContext & sc ) {
	while( isspace( sc.ch ) ) {
		sc.SetState( SCE_MODULA_DEFAULT );
		if( sc.More() )
			sc.Forward();
		else
			return false;
	}
	return true;
}

static void ColouriseModulaDoc(	unsigned int startPos,
									int length,
									int initStyle,
									WordList *wl[],
									Accessor &styler ) {
	WordList& keyWords		= *wl[0];
	WordList& reservedWords	= *wl[1];
	WordList& operators 	= *wl[2];
	WordList& pragmaWords 	= *wl[3];
	WordList& escapeCodes	= *wl[4];
	WordList& doxyKeys		= *wl[5];

	const int BUFLEN = 128;

	char	buf[BUFLEN];
	int		i, kl;

	int  charPos = 0;

	StyleContext sc( startPos, length, initStyle, styler );

	while( sc.More() ) 	{
		switch( sc.state )	{
		case SCE_MODULA_DEFAULT:
			if( ! skipWhiteSpaces( sc ) ) break;

			if( sc.ch == '(' && sc.chNext == '*' ) {
				if( sc.GetRelative(2) == '*' ) {
					sc.SetState( SCE_MODULA_DOXYCOMM );
					sc.Forward();
				} else {
					sc.SetState( SCE_MODULA_COMMENT );
				}
				sc.Forward();
			}
			else
			if( isalpha( sc.ch ) ) {
				if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
					for( i = 0; i < BUFLEN - 1; i++ ) {
						buf[i] = sc.GetRelative(i);
						if( !isalpha( buf[i] ) && !(buf[i] == '_') )
							break;
					}
					kl = i;
					buf[kl] = 0;

					if( keyWords.InList( buf ) ) {
						sc.SetState( SCE_MODULA_KEYWORD );
						sc.Forward( kl );
						sc.SetState( SCE_MODULA_DEFAULT );
						continue;
					}
					else
					if( reservedWords.InList( buf ) ) {
						sc.SetState( SCE_MODULA_RESERVED );
						sc.Forward( kl );
						sc.SetState( SCE_MODULA_DEFAULT );
						continue;
					} else {
						/** check procedure identifier */
					}
				} else {
					for( i = 0; i < BUFLEN - 1; i++ ) {
						buf[i] = sc.GetRelative(i);
						if( !isalpha( buf[i] ) &&
							!isdigit( buf[i] ) &&
							!(buf[i] == '_') )
							break;
					}
					kl = i;
					buf[kl] = 0;

					sc.SetState( SCE_MODULA_DEFAULT );
					sc.Forward( kl );
					continue;
				}
			}
			else
			if( isdigit( sc.ch ) ) {
				sc.SetState( SCE_MODULA_NUMBER );
				continue;
			}
			else
			if( sc.ch == '\"' ) {
				sc.SetState( SCE_MODULA_STRING );
			}
			else
			if( sc.ch == '\'' ) {
				charPos = sc.currentPos;
				sc.SetState( SCE_MODULA_CHAR );
			}
			else
			if( sc.ch == '<' && sc.chNext == '*' ) {
				sc.SetState( SCE_MODULA_PRAGMA );
				sc.Forward();
			} else {
				unsigned len = IsOperator( sc, operators );
				if( len > 0 ) {
					sc.SetState( SCE_MODULA_OPERATOR );
					sc.Forward( len );
					sc.SetState( SCE_MODULA_DEFAULT );
					continue;
				} else {
					DEBUG_STATE( sc.currentPos, sc.ch );
				}
			}
			break;

		case SCE_MODULA_COMMENT:
			if( sc.ch == '*' && sc.chNext == ')' ) {
				sc.Forward( 2 );
				sc.SetState( SCE_MODULA_DEFAULT );
				continue;
			}
			break;

		case SCE_MODULA_DOXYCOMM:
			switch( sc.ch ) {
			case '*':
				if( sc.chNext == ')' ) {
					sc.Forward( 2 );
					sc.SetState( SCE_MODULA_DEFAULT );
					continue;
				}
				break;

			case '@':
				if( islower( sc.chNext ) ) {
					for( i = 0; i < BUFLEN - 1; i++ ) {
						buf[i] = sc.GetRelative(i+1);
						if( isspace( buf[i] ) ) break;
					}
					buf[i] = 0;
					kl = i;

					if( doxyKeys.InList( buf ) ) {
						sc.SetState( SCE_MODULA_DOXYKEY );
						sc.Forward( kl + 1 );
						sc.SetState( SCE_MODULA_DOXYCOMM );
					}
				}
				break;

			default:
				break;
			}
			break;

		case SCE_MODULA_NUMBER:
			{
				buf[0] = sc.ch;
				for( i = 1; i < BUFLEN - 1; i++ ) {
					buf[i] = sc.GetRelative(i);
					if( ! isdigit( buf[i] ) )
						break;
				}
				kl = i;
				buf[kl] = 0;

				switch( sc.GetRelative(kl) ) {
				case '_':
					{
						int base = atoi( buf );
						if( base < 2 || base > 16 ) {
							sc.SetState( SCE_MODULA_BADSTR );
						} else {
							int imax;

							kl++;
							for( i = 0; i < BUFLEN - 1; i++ ) {
								buf[i] = sc.GetRelative(kl+i);
								if( ! IsDigitOfBase( buf[i], 16 ) ) {
									break;
								}
							}
							imax = i;
							for( i = 0; i < imax; i++ ) {
								if( ! IsDigitOfBase( buf[i], base ) ) {
									sc.SetState( SCE_MODULA_BADSTR );
									break;
								}
							}
							kl += imax;
						}
						sc.SetState( SCE_MODULA_BASENUM );
						for( i = 0; i < kl; i++ ) {
							sc.Forward();
						}
						sc.SetState( SCE_MODULA_DEFAULT );
						continue;
					}
					break;

				case '.':
					if( sc.GetRelative(kl+1) == '.' ) {
						kl--;
						for( i = 0; i < kl; i++ ) {
							sc.Forward();
						}
						sc.Forward();
						sc.SetState( SCE_MODULA_DEFAULT );
						continue;
					} else {
						bool doNext = false;

						kl++;

						buf[0] = sc.GetRelative(kl);
						if( isdigit( buf[0] ) ) {
							for( i = 0;; i++ ) {
								if( !isdigit(sc.GetRelative(kl+i)) )
									break;
							}
							kl += i;
							buf[0] = sc.GetRelative(kl);

							switch( buf[0] )
							{
							case 'E':
							case 'e':
							case 'D':
							case 'd':
							case 'X':
							case 'x':
								kl++;
								buf[0] = sc.GetRelative(kl);
								if( buf[0] == '-' || buf[0] == '+' ) {
									kl++;
								}
								buf[0] = sc.GetRelative(kl);
								if( isdigit( buf[0] ) ) {
									for( i = 0;; i++ ) {
										if( !isdigit(sc.GetRelative(kl+i)) ) {
											buf[0] = sc.GetRelative(kl+i);
											break;
										}
									}
									kl += i;
									doNext = true;
								} else {
									sc.SetState( SCE_MODULA_BADSTR );
								}
								break;

							default:
								doNext = true;
								break;
							}
						} else {
							sc.SetState( SCE_MODULA_BADSTR );
						}

						if( doNext ) {
							if( ! isspace( buf[0] ) &&
								buf[0] != ')' &&
								buf[0] != '>' &&
								buf[0] != '<' &&
								buf[0] != '=' &&
								buf[0] != '#' &&
								buf[0] != '+' &&
								buf[0] != '-' &&
								buf[0] != '*' &&
								buf[0] != '/' &&
								buf[0] != ',' &&
								buf[0] != ';'
								) {
								sc.SetState( SCE_MODULA_BADSTR );
							} else {
								kl--;
							}
						}
					}
					sc.SetState( SCE_MODULA_FLOAT );
					for( i = 0; i < kl; i++ ) {
						sc.Forward();
					}
					sc.SetState( SCE_MODULA_DEFAULT );
					continue;
					break;

				default:
					for( i = 0; i < kl; i++ ) {
						sc.Forward();
					}
					break;
				}
				sc.SetState( SCE_MODULA_DEFAULT );
				continue;
			}
			break;

		case SCE_MODULA_STRING:
			if( sc.ch == '\"' ) {
				sc.Forward();
				sc.SetState( SCE_MODULA_DEFAULT );
				continue;
			} else {
				if( sc.ch == '\\' ) {
					i = 1;
					if( IsDigitOfBase( sc.chNext, 8 ) ) {
						for( i = 1; i < BUFLEN - 1; i++ ) {
							if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
								break;
						}
						if( i == 3 ) {
							sc.SetState( SCE_MODULA_STRSPEC );
						} else {
							sc.SetState( SCE_MODULA_BADSTR );
						}
					} else {
						buf[0] = sc.chNext;
						buf[1] = 0;

						if( escapeCodes.InList( buf ) ) {
							sc.SetState( SCE_MODULA_STRSPEC );
						} else {
							sc.SetState( SCE_MODULA_BADSTR );
						}
					}
					sc.Forward(i+1);
					sc.SetState( SCE_MODULA_STRING );
					continue;
				}
			}
			break;

		case SCE_MODULA_CHAR:
			if( sc.ch == '\'' ) {
				sc.Forward();
				sc.SetState( SCE_MODULA_DEFAULT );
				continue;
			}
			else
			if( ( sc.currentPos - charPos ) == 1 ) {
				if( sc.ch == '\\' ) {
					i = 1;
					if( IsDigitOfBase( sc.chNext, 8 ) ) {
						for( i = 1; i < BUFLEN - 1; i++ ) {
							if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) )
								break;
						}
						if( i == 3 ) {
							sc.SetState( SCE_MODULA_CHARSPEC );
						} else {
							sc.SetState( SCE_MODULA_BADSTR );
						}
					} else {
						buf[0] = sc.chNext;
						buf[1] = 0;

						if( escapeCodes.InList( buf ) ) {
							sc.SetState( SCE_MODULA_CHARSPEC );
						} else {
							sc.SetState( SCE_MODULA_BADSTR );
						}
					}
					sc.Forward(i+1);
					sc.SetState( SCE_MODULA_CHAR );
					continue;
				}
			} else {
				sc.SetState( SCE_MODULA_BADSTR );
				sc.Forward();
				sc.SetState( SCE_MODULA_CHAR );
				continue;
			}
			break;

		case SCE_MODULA_PRAGMA:
			if( sc.ch == '*' && sc.chNext == '>' ) {
				sc.Forward();
				sc.Forward();
				sc.SetState( SCE_MODULA_DEFAULT );
				continue;
			}
			else
			if( isupper( sc.ch ) && isupper( sc.chNext ) ) {
				buf[0] = sc.ch;
				buf[1] = sc.chNext;
				for( i = 2; i < BUFLEN - 1; i++ ) {
					buf[i] = sc.GetRelative(i);
					if( !isupper( buf[i] ) )
						break;
				}
				kl = i;
				buf[kl] = 0;
				if( pragmaWords.InList( buf ) ) {
					sc.SetState( SCE_MODULA_PRGKEY );
					sc.Forward( kl );
					sc.SetState( SCE_MODULA_PRAGMA );
					continue;
				}
			}
			break;

		default:
			break;
		}
		sc.Forward();
	}
	sc.Complete();
}

static const char *const modulaWordListDesc[] =
{
	"Keywords",
	"ReservedKeywords",
	"Operators",
	"PragmaKeyswords",
	"EscapeCodes",
	"DoxygeneKeywords",
	0
};

LexerModule lmModula( SCLEX_MODULA, ColouriseModulaDoc, "modula", FoldModulaDoc,
					  modulaWordListDesc);

Added lexers/LexMySQL.cxx.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
/**
 * Scintilla source code edit control
 * @file LexMySQL.cxx
 * Lexer for MySQL
 *
 * Improved by Mike Lischke <mike.lischke@oracle.com>
 * Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
 * Original work by Neil Hodgson <neilh@scintilla.org>
 * Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 * The License.txt file describes the conditions under which this software may be distributed.
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return (ch < 0x80) && (isalpha(ch) || ch == '_');
}

static inline bool IsADoxygenChar(int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
	        ch == '\\' || ch == '&' || ch == '<' ||
	        ch == '>' || ch == '#' || ch == '{' ||
	        ch == '}' || ch == '[' || ch == ']');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
             ch == '.' || ch == '-' || ch == '+');
}

//--------------------------------------------------------------------------------------------------

/**
 * Check if the current content context represent a keyword and set the context state if so.
 */
static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[], int activeState)
{
  int length = sc.LengthCurrent() + 1; // +1 for the next char
  char* s = new char[length];
  sc.GetCurrentLowered(s, length);
  if (keywordlists[0]->InList(s))
    sc.ChangeState(SCE_MYSQL_MAJORKEYWORD | activeState);
  else
    if (keywordlists[1]->InList(s))
      sc.ChangeState(SCE_MYSQL_KEYWORD | activeState);
    else
      if (keywordlists[2]->InList(s))
        sc.ChangeState(SCE_MYSQL_DATABASEOBJECT | activeState);
      else
        if (keywordlists[3]->InList(s))
          sc.ChangeState(SCE_MYSQL_FUNCTION | activeState);
        else
          if (keywordlists[5]->InList(s))
            sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD | activeState);
          else
            if (keywordlists[6]->InList(s))
              sc.ChangeState(SCE_MYSQL_USER1 | activeState);
            else
              if (keywordlists[7]->InList(s))
                sc.ChangeState(SCE_MYSQL_USER2 | activeState);
              else
                if (keywordlists[8]->InList(s))
                  sc.ChangeState(SCE_MYSQL_USER3 | activeState);
  delete [] s;
}

//--------------------------------------------------------------------------------------------------

#define HIDDENCOMMAND_STATE 0x40 // Offset for states within a hidden command.
#define MASKACTIVE(style) (style & ~HIDDENCOMMAND_STATE)

static void SetDefaultState(StyleContext& sc, int activeState)
{
  if (activeState == 0)
    sc.SetState(SCE_MYSQL_DEFAULT);
  else
    sc.SetState(SCE_MYSQL_HIDDENCOMMAND);
}

static void ForwardDefaultState(StyleContext& sc, int activeState)
{
  if (activeState == 0)
    sc.ForwardSetState(SCE_MYSQL_DEFAULT);
  else
    sc.ForwardSetState(SCE_MYSQL_HIDDENCOMMAND);
}

static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler)
{
	StyleContext sc(startPos, length, initStyle, styler, 127);
  int activeState = (initStyle == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : initStyle & HIDDENCOMMAND_STATE;

	for (; sc.More(); sc.Forward())
  {
		// Determine if the current state should terminate.
		switch (MASKACTIVE(sc.state))
    {
      case SCE_MYSQL_OPERATOR:
        SetDefaultState(sc, activeState);
        break;
      case SCE_MYSQL_NUMBER:
        // We stop the number definition on non-numerical non-dot non-eE non-sign char.
        if (!IsANumberChar(sc.ch))
          SetDefaultState(sc, activeState);
        break;
      case SCE_MYSQL_IDENTIFIER:
        // Switch from identifier to keyword state and open a new state for the new char.
        if (!IsAWordChar(sc.ch))
        {
          CheckForKeyword(sc, keywordlists, activeState);

          // Additional check for function keywords needed.
          // A function name must be followed by an opening parenthesis.
          if (MASKACTIVE(sc.state) == SCE_MYSQL_FUNCTION && sc.ch != '(')
          {
            if (activeState > 0)
              sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
            else
              sc.ChangeState(SCE_MYSQL_DEFAULT);
          }

          SetDefaultState(sc, activeState);
        }
        break;
      case SCE_MYSQL_VARIABLE:
        if (!IsAWordChar(sc.ch))
          SetDefaultState(sc, activeState);
        break;
      case SCE_MYSQL_SYSTEMVARIABLE:
        if (!IsAWordChar(sc.ch))
        {
          int length = sc.LengthCurrent() + 1;
          char* s = new char[length];
          sc.GetCurrentLowered(s, length);

          // Check for known system variables here.
          if (keywordlists[4]->InList(&s[2]))
            sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE | activeState);
          delete [] s;

          SetDefaultState(sc, activeState);
        }
        break;
      case SCE_MYSQL_QUOTEDIDENTIFIER:
        if (sc.ch == '`')
        {
          if (sc.chNext == '`')
            sc.Forward();	// Ignore it
          else
            ForwardDefaultState(sc, activeState);
				}
  			break;
      case SCE_MYSQL_COMMENT:
        if (sc.Match('*', '/'))
        {
          sc.Forward();
          ForwardDefaultState(sc, activeState);
        }
        break;
      case SCE_MYSQL_COMMENTLINE:
        if (sc.atLineStart)
          SetDefaultState(sc, activeState);
        break;
      case SCE_MYSQL_SQSTRING:
        if (sc.ch == '\\')
          sc.Forward(); // Escape sequence
        else
          if (sc.ch == '\'')
          {
            // End of single quoted string reached?
            if (sc.chNext == '\'')
              sc.Forward();
            else
              ForwardDefaultState(sc, activeState);
          }
        break;
      case SCE_MYSQL_DQSTRING:
        if (sc.ch == '\\')
          sc.Forward(); // Escape sequence
        else
          if (sc.ch == '\"')
          {
            // End of single quoted string reached?
            if (sc.chNext == '\"')
              sc.Forward();
            else
              ForwardDefaultState(sc, activeState);
          }
        break;
      case SCE_MYSQL_PLACEHOLDER:
        if (sc.Match('}', '>'))
        {
          sc.Forward();
          ForwardDefaultState(sc, activeState);
        }
        break;
    }

    if (sc.state == SCE_MYSQL_HIDDENCOMMAND && sc.Match('*', '/'))
    {
      activeState = 0;
      sc.Forward();
      ForwardDefaultState(sc, activeState);
    }

    // Determine if a new state should be entered.
    if (sc.state == SCE_MYSQL_DEFAULT || sc.state == SCE_MYSQL_HIDDENCOMMAND)
    {
      switch (sc.ch)
      {
        case '@':
          if (sc.chNext == '@')
          {
            sc.SetState(SCE_MYSQL_SYSTEMVARIABLE | activeState);
            sc.Forward(2); // Skip past @@.
          }
          else
            if (IsAWordStart(sc.ch))
            {
              sc.SetState(SCE_MYSQL_VARIABLE | activeState);
              sc.Forward(); // Skip past @.
            }
            else
              sc.SetState(SCE_MYSQL_OPERATOR | activeState);
          break;
        case '`':
          sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER | activeState);
          break;
        case '#':
          sc.SetState(SCE_MYSQL_COMMENTLINE | activeState);
          break;
        case '\'':
          sc.SetState(SCE_MYSQL_SQSTRING | activeState);
          break;
        case '\"':
          sc.SetState(SCE_MYSQL_DQSTRING | activeState);
          break;
        default:
          if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
            sc.SetState(SCE_MYSQL_NUMBER | activeState);
          else
            if (IsAWordStart(sc.ch))
              sc.SetState(SCE_MYSQL_IDENTIFIER | activeState);
            else
              if (sc.Match('/', '*'))
              {
                sc.SetState(SCE_MYSQL_COMMENT | activeState);

                // Skip comment introducer and check for hidden command.
                sc.Forward(2);
                if (sc.ch == '!')
                {
                  activeState = HIDDENCOMMAND_STATE;
                  sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
                }
              }
              else if (sc.Match('<', '{'))
              {
                sc.SetState(SCE_MYSQL_PLACEHOLDER | activeState);
              }
              else
                if (sc.Match("--"))
                {
                  // Special MySQL single line comment.
                  sc.SetState(SCE_MYSQL_COMMENTLINE | activeState);
                  sc.Forward(2);

                  // Check the third character too. It must be a space or EOL.
                  if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r')
                    sc.ChangeState(SCE_MYSQL_OPERATOR | activeState);
                }
                else
                  if (isoperator(static_cast<char>(sc.ch)))
                    sc.SetState(SCE_MYSQL_OPERATOR | activeState);
      }
    }
  }

  // Do a final check for keywords if we currently have an identifier, to highlight them
  // also at the end of a line.
  if (sc.state == SCE_MYSQL_IDENTIFIER)
  {
    CheckForKeyword(sc, keywordlists, activeState);

    // Additional check for function keywords needed.
    // A function name must be followed by an opening parenthesis.
    if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
      SetDefaultState(sc, activeState);
  }

  sc.Complete();
}

//--------------------------------------------------------------------------------------------------

/**
 * Helper function to determine if we have a foldable comment currently.
 */
static bool IsStreamCommentStyle(int style)
{
	return MASKACTIVE(style) == SCE_MYSQL_COMMENT;
}

//--------------------------------------------------------------------------------------------------

/**
 * Code copied from StyleContext and modified to work here. Should go into Accessor as a
 * companion to Match()...
 */
bool MatchIgnoreCase(Accessor &styler, int currentPos, const char *s)
{
  for (int n = 0; *s; n++)
  {
    if (*s != tolower(styler.SafeGetCharAt(currentPos + n)))
      return false;
    s++;
  }
  return true;
}

//--------------------------------------------------------------------------------------------------

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment.
static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
{
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0;

	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
	int levelNext = levelCurrent;

	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
  int activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE;
	
  bool endPending = false;
	bool whenPending = false;
	bool elseIfPending = false;

  char nextChar = styler.SafeGetCharAt(startPos);
  for (unsigned int i = startPos; length > 0; i++, length--)
  {
		int stylePrev = style;
    int lastActiveState = activeState;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
    activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE;
    
    char currentChar = nextChar;
    nextChar = styler.SafeGetCharAt(i + 1);
		bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n');
	
    switch (MASKACTIVE(style))
    {
      case SCE_MYSQL_COMMENT:
        if (foldComment)
        {
          // Multiline comment style /* .. */ just started or is still in progress.
          if (IsStreamCommentStyle(style) && !IsStreamCommentStyle(stylePrev))
            levelNext++;
        }
        break;
      case SCE_MYSQL_COMMENTLINE:
        if (foldComment)
        { 
          // Not really a standard, but we add support for single line comments
          // with special curly braces syntax as foldable comments too.
          // MySQL needs -- comments to be followed by space or control char
          if (styler.Match(i, "--"))
          {
            char chNext2 = styler.SafeGetCharAt(i + 2);
            char chNext3 = styler.SafeGetCharAt(i + 3);
            if (chNext2 == '{' || chNext3 == '{')
              levelNext++;
            else
              if (chNext2 == '}' || chNext3 == '}')
                levelNext--;
          }
        }
        break;
      case SCE_MYSQL_HIDDENCOMMAND:
        /*
        if (endPending)
        {
          // A conditional command is not a white space so it should end the current block
          // before opening a new one.
          endPending = false;
          levelNext--;
          if (levelNext < SC_FOLDLEVELBASE)
            levelNext = SC_FOLDLEVELBASE;
        }
        }*/
        if (activeState != lastActiveState)
          levelNext++;
        break;
      case SCE_MYSQL_OPERATOR:
        if (endPending)
        {
          endPending = false;
          levelNext--;
          if (levelNext < SC_FOLDLEVELBASE)
            levelNext = SC_FOLDLEVELBASE;
        }
        if (currentChar == '(')
          levelNext++;
        else
          if (currentChar == ')')
          {
            levelNext--;
            if (levelNext < SC_FOLDLEVELBASE)
              levelNext = SC_FOLDLEVELBASE;
          }
        break;
      case SCE_MYSQL_MAJORKEYWORD:
      case SCE_MYSQL_KEYWORD:
      case SCE_MYSQL_FUNCTION:
      case SCE_MYSQL_PROCEDUREKEYWORD:
        // Reserved and other keywords.
        if (style != stylePrev)
        {
          // END decreases the folding level, regardless which keyword follows.
          bool endFound = MatchIgnoreCase(styler, i, "end");
          if (endPending)
          {
            levelNext--;
            if (levelNext < SC_FOLDLEVELBASE)
              levelNext = SC_FOLDLEVELBASE;
          }
          else
            if (!endFound)
            {
              if (MatchIgnoreCase(styler, i, "begin"))
                levelNext++;
              else
              {
                if (!foldOnlyBegin)
                {
                  bool whileFound = MatchIgnoreCase(styler, i, "while");
                  bool loopFound = MatchIgnoreCase(styler, i, "loop");
                  bool repeatFound = MatchIgnoreCase(styler, i, "repeat");
                  bool caseFound = MatchIgnoreCase(styler, i, "case");

                  if (whileFound || loopFound || repeatFound || caseFound)
                    levelNext++;
                  else
                  {
                    // IF alone does not increase the fold level as it is also used in non-block'ed
                    // code like DROP PROCEDURE blah IF EXISTS.
                    // Instead THEN opens the new level (if not part of an ELSEIF or WHEN (case) branch).
                    if (MatchIgnoreCase(styler, i, "then"))
                    {
                      if (!elseIfPending && !whenPending)
                        levelNext++;
                      else
                      {
                        elseIfPending = false;
                        whenPending = false;
                      }
                    }
                    else
                    {
                      // Neither of if/then/while/loop/repeat/case, so check for
                      // sub parts of IF and CASE.
                      if (MatchIgnoreCase(styler, i, "elseif"))
                        elseIfPending = true;
                      if (MatchIgnoreCase(styler, i, "when"))
                        whenPending = true;
                    }
                  }
                }
              }
            }
          
          // Keep the current end state for the next round.
          endPending = endFound;
        }
        break;
        
      default:
        if (!isspacechar(currentChar) && endPending)
        {
          // END followed by a non-whitespace character (not covered by other cases like identifiers)
          // also should end a folding block. Typical case: END followed by self defined delimiter.
          levelNext--;
          if (levelNext < SC_FOLDLEVELBASE)
            levelNext = SC_FOLDLEVELBASE;
        }
        break;
    }

    // Go up one level if we just ended a multi line comment.
    if (IsStreamCommentStyle(stylePrev) && !IsStreamCommentStyle(style))
    {
      levelNext--;
      if (levelNext < SC_FOLDLEVELBASE)
        levelNext = SC_FOLDLEVELBASE;
    }

    if (activeState == 0 && lastActiveState != 0)
    {
      // Decrease fold level when we left a hidden command.
      levelNext--;
      if (levelNext < SC_FOLDLEVELBASE)
        levelNext = SC_FOLDLEVELBASE;
    }

    if (atEOL)
    {
      // Apply the new folding level to this line.
      // Leave pending states as they are otherwise a line break will de-sync
      // code folding and valid syntax.
      int levelUse = levelCurrent;
      int lev = levelUse | levelNext << 16;
      if (visibleChars == 0 && foldCompact)
        lev |= SC_FOLDLEVELWHITEFLAG;
      if (levelUse < levelNext)
        lev |= SC_FOLDLEVELHEADERFLAG;
      if (lev != styler.LevelAt(lineCurrent))
        styler.SetLevel(lineCurrent, lev);
      
      lineCurrent++;
      levelCurrent = levelNext;
      visibleChars = 0;
    }

		if (!isspacechar(currentChar))
      visibleChars++;
  }
}

//--------------------------------------------------------------------------------------------------

static const char * const mysqlWordListDesc[] = {
	"Major Keywords",
	"Keywords",
	"Database Objects",
	"Functions",
	"System Variables",
	"Procedure keywords",
	"User Keywords 1",
	"User Keywords 2",
	"User Keywords 3",
	0
};

LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc, 7);

Added lexers/LexNimrod.cxx.



































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
// Scintilla source code edit control
// Nimrod lexer
// (c) 2009 Andreas Rumpf
/** @file LexNimrod.cxx
 ** Lexer for Nimrod.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch) {
	return (ch >= 0x80) || isalnum(ch) || ch == '_';
}

static int tillEndOfTripleQuote(Accessor &styler, int pos, int max) {
  /* search for """ */
  for (;;) {
    if (styler.SafeGetCharAt(pos, '\0') == '\0') return pos;
    if (pos >= max) return pos;
    if (styler.Match(pos, "\"\"\"")) {
      return pos + 2;
    }
    pos++;
  }
}

#define CR 13 /* use both because Scite allows changing the line ending */
#define LF 10

static bool inline isNewLine(int ch) {
  return ch == CR || ch == LF;
}

static int scanString(Accessor &styler, int pos, int max, bool rawMode) {
  for (;;) {
    if (pos >= max) return pos;
    char ch = styler.SafeGetCharAt(pos, '\0');
    if (ch == CR || ch == LF || ch == '\0') return pos;
    if (ch == '"') return pos;
    if (ch == '\\' && !rawMode) {
      pos += 2;
    } else {
      pos++;
    }
  }
}

static int scanChar(Accessor &styler, int pos, int max) {
  for (;;) {
    if (pos >= max) return pos;
    char ch = styler.SafeGetCharAt(pos, '\0');
    if (ch == CR || ch == LF || ch == '\0') return pos;
    if (ch == '\'' && !isalnum(styler.SafeGetCharAt(pos+1, '\0')) )
      return pos;
    if (ch == '\\') {
      pos += 2;
    } else {
      pos++;
    }
  }
}

static int scanIdent(Accessor &styler, int pos, WordList &keywords) {
  char buf[100]; /* copy to lowercase and ignore underscores */
  int i = 0;

  for (;;) {
    char ch = styler.SafeGetCharAt(pos, '\0');
    if (!IsAWordChar(ch)) break;
    if (ch != '_' && i < ((int)sizeof(buf))-1) {
      buf[i] = static_cast<char>(tolower(ch));
      i++;
    }
    pos++;
  }
  buf[i] = '\0';
  /* look for keyword */
  if (keywords.InList(buf)) {
    styler.ColourTo(pos-1, SCE_P_WORD);
  } else {
    styler.ColourTo(pos-1, SCE_P_IDENTIFIER);
  }
  return pos;
}

static int scanNumber(Accessor &styler, int pos) {
  char ch, ch2;
  ch = styler.SafeGetCharAt(pos, '\0');
  ch2 = styler.SafeGetCharAt(pos+1, '\0');
  if (ch == '0' && (ch2 == 'b' || ch2 == 'B')) {
    /* binary number: */
    pos += 2;
    for (;;) {
      ch = styler.SafeGetCharAt(pos, '\0');
      if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos;
      else break;
    }
  } else if (ch == '0' &&
            (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) {
    /* octal number: */
    pos += 2;
    for (;;) {
      ch = styler.SafeGetCharAt(pos, '\0');
      if (ch == '_' || (ch >= '0' && ch <= '7')) ++pos;
      else break;
    }
  } else if (ch == '0' && (ch2 == 'x' || ch2 == 'X')) {
    /* hexadecimal number: */
    pos += 2;
    for (;;) {
      ch = styler.SafeGetCharAt(pos, '\0');
      if (ch == '_' || (ch >= '0' && ch <= '9')
          || (ch >= 'a' && ch <= 'f')
          || (ch >= 'A' && ch <= 'F')) ++pos;
      else break;
    }
  } else {
    // skip decimal part:
    for (;;) {
      ch = styler.SafeGetCharAt(pos, '\0');
      if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
      else break;
    }
    ch2 = styler.SafeGetCharAt(pos+1, '\0');
    if (ch == '.' && ch2 >= '0' && ch2 <= '9') {
      ++pos; // skip '.'
      for (;;) {
        ch = styler.SafeGetCharAt(pos, '\0');
        if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
        else break;
      }
    }
    if (ch == 'e' || ch == 'E') {
      ++pos;
      ch = styler.SafeGetCharAt(pos, '\0');
      if (ch == '-' || ch == '+') ++pos;
      for (;;) {
        ch = styler.SafeGetCharAt(pos, '\0');
        if (ch == '_' || (ch >= '0' && ch <= '9')) ++pos;
        else break;
      }
    }
  }
  if (ch == '\'') {
    /* a type suffix: */
    pos++;
    for (;;) {
      ch = styler.SafeGetCharAt(pos);
      if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z')
         || (ch >= 'a' && ch <= 'z') || ch == '_') ++pos;
      else break;
    }
  }
  styler.ColourTo(pos-1, SCE_P_NUMBER);
  return pos;
}

/* rewritten from scratch, because I couldn't get rid of the bugs...
   (A character based approach sucks!)
*/
static void ColouriseNimrodDoc(unsigned int startPos, int length, int initStyle,
                                WordList *keywordlists[], Accessor &styler) {
  int pos = startPos;
  int max = startPos + length;
  char ch;
  WordList &keywords = *keywordlists[0];

  styler.StartAt(startPos);
  styler.StartSegment(startPos);

  switch (initStyle) {
    /* check where we are: */
    case SCE_P_TRIPLEDOUBLE:
      pos = tillEndOfTripleQuote(styler, pos, max);
      styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
      pos++;
    break;
    default: /* nothing to do: */
    break;
  }
  while (pos < max) {
    ch = styler.SafeGetCharAt(pos, '\0');
    switch (ch) {
      case '\0': return;
      case '#': {
        bool doccomment = (styler.SafeGetCharAt(pos+1) == '#');
        while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++;
        if (doccomment)
          styler.ColourTo(pos, SCE_C_COMMENTLINEDOC);
        else
          styler.ColourTo(pos, SCE_P_COMMENTLINE);
      } break;
      case 'r': case 'R': {
        if (styler.SafeGetCharAt(pos+1) == '"') {
          pos = scanString(styler, pos+2, max, true);
          styler.ColourTo(pos, SCE_P_STRING);
          pos++;
        } else {
          pos = scanIdent(styler, pos, keywords);
        }
      } break;
      case '"':
        if (styler.Match(pos+1, "\"\"")) {
          pos = tillEndOfTripleQuote(styler, pos+3, max);
          styler.ColourTo(pos, SCE_P_TRIPLEDOUBLE);
        } else {
          pos = scanString(styler, pos+1, max, false);
          styler.ColourTo(pos, SCE_P_STRING);
        }
        pos++;
      break;
      case '\'':
        pos = scanChar(styler, pos+1, max);
        styler.ColourTo(pos, SCE_P_CHARACTER);
        pos++;
      break;
      default: // identifers, numbers, operators, whitespace
        if (ch >= '0' && ch <= '9') {
          pos = scanNumber(styler, pos);
        } else if (IsAWordChar(ch)) {
          pos = scanIdent(styler, pos, keywords);
        } else if (ch == '`') {
          pos++;
          while (pos < max) {
            ch = styler.SafeGetCharAt(pos, LF);
            if (ch == '`') {
              ++pos;
              break;
            }
            if (ch == CR || ch == LF) break;
            ++pos;
          }
          styler.ColourTo(pos, SCE_P_IDENTIFIER);
        } else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", ch)) {
          styler.ColourTo(pos, SCE_P_OPERATOR);
          pos++;
        } else {
          styler.ColourTo(pos, SCE_P_DEFAULT);
          pos++;
        }
      break;
    }
  }
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		if (ch == '#')
			return true;
		else if (ch != ' ' && ch != '\t')
			return false;
	}
	return false;
}

static bool IsQuoteLine(int line, Accessor &styler) {
	int style = styler.StyleAt(styler.LineStart(line)) & 31;
	return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
}


static void FoldNimrodDoc(unsigned int startPos, int length,
                          int /*initStyle - unused*/,
                          WordList *[], Accessor &styler) {
	const int maxPos = startPos + length;
	const int maxLines = styler.GetLine(maxPos - 1); // Requested last line
	const int docLines = styler.GetLine(styler.Length() - 1); // Available last line
	const bool foldComment = styler.GetPropertyInt("fold.comment.nimrod") != 0;
	const bool foldQuotes = styler.GetPropertyInt("fold.quotes.nimrod") != 0;

	// Backtrack to previous non-blank line so we can determine indent level
	// for any white space lines (needed esp. within triple quoted strings)
	// and so we can fix any preceding fold level (which is why we go back
	// at least one line in all cases)
	int spaceFlags = 0;
	int lineCurrent = styler.GetLine(startPos);
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
	while (lineCurrent > 0) {
		lineCurrent--;
		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
		        (!IsCommentLine(lineCurrent, styler)) &&
		        (!IsQuoteLine(lineCurrent, styler)))
			break;
	}
	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;

	// Set up initial loop state
	startPos = styler.LineStart(lineCurrent);
	int prev_state = SCE_P_DEFAULT & 31;
	if (lineCurrent >= 1)
		prev_state = styler.StyleAt(startPos - 1) & 31;
	int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) ||
	                               (prev_state == SCE_P_TRIPLEDOUBLE));
	int prevComment = 0;
	if (lineCurrent >= 1)
		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);

	// Process all characters to end of requested range or end of any triple quote
	// or comment that hangs over the end of the range.  Cap processing in all cases
	// to end of document (in case of unclosed quote or comment at end).
	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) ||
	                                      prevQuote || prevComment)) {

		// Gather info
		int lev = indentCurrent;
		int lineNext = lineCurrent + 1;
		int indentNext = indentCurrent;
		int quote = false;
		if (lineNext <= docLines) {
			// Information about next line is only available if not at end of document
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
			int style = styler.StyleAt(styler.LineStart(lineNext)) & 31;
			quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
		}
		const int quote_start = (quote && !prevQuote);
		const int quote_continue = (quote && prevQuote);
		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
		                           IsCommentLine(lineNext, styler) &&
		                           (lev > SC_FOLDLEVELBASE));
		const int comment_continue = (comment && prevComment);
		if ((!quote || !prevQuote) && !comment)
			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
		if (quote)
			indentNext = indentCurrentLevel;
		if (indentNext & SC_FOLDLEVELWHITEFLAG)
			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;

		if (quote_start) {
			// Place fold point at start of triple quoted string
			lev |= SC_FOLDLEVELHEADERFLAG;
		} else if (quote_continue || prevQuote) {
			// Add level to rest of lines in the string
			lev = lev + 1;
		} else if (comment_start) {
			// Place fold point at start of a block of comments
			lev |= SC_FOLDLEVELHEADERFLAG;
		} else if (comment_continue) {
			// Add level to rest of lines in the block
			lev = lev + 1;
		}

		// Skip past any blank lines for next indent level info; we skip also
		// comments (all comments, not just those starting in column 0)
		// which effectively folds them into surrounding code rather
		// than screwing up folding.

		while (!quote &&
		        (lineNext < docLines) &&
		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {

			lineNext++;
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
		}

		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
		const int levelBeforeComments =
		    Maximum(indentCurrentLevel,levelAfterComments);

		// Now set all the indent levels on the lines we skipped
		// Do this from end to start.  Once we encounter one line
		// which is indented more than the line after the end of
		// the comment-block, use the level of the block before

		int skipLine = lineNext;
		int skipLevel = levelAfterComments;

		while (--skipLine > lineCurrent) {
			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);

			if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
				skipLevel = levelBeforeComments;

			int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;

			styler.SetLevel(skipLine, skipLevel | whiteFlag);
		}

		// Set fold header on non-quote/non-comment line
		if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) <
			     (indentNext & SC_FOLDLEVELNUMBERMASK))
				lev |= SC_FOLDLEVELHEADERFLAG;
		}

		// Keep track of triple quote and block comment state of previous line
		prevQuote = quote;
		prevComment = comment_start || comment_continue;

		// Set fold level for this line and move to next line
		styler.SetLevel(lineCurrent, lev);
		indentCurrent = indentNext;
		lineCurrent = lineNext;
	}

	// NOTE: Cannot set level of last line here because indentCurrent doesn't have
	// header flag set; the loop above is crafted to take care of this case!
	//styler.SetLevel(lineCurrent, indentCurrent);
}

static const char * const nimrodWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmNimrod(SCLEX_NIMROD, ColouriseNimrodDoc, "nimrod", FoldNimrodDoc,
				     nimrodWordListDesc);

Added lexers/LexNsis.cxx.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
// Scintilla source code edit control
/** @file LexNsis.cxx
 ** Lexer for NSIS
 **/
// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com>
// Last Updated: 03/13/2005
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
// located in SciLexer.h
#define SCLEX_NSIS 43

#define SCE_NSIS_DEFAULT 0
#define SCE_NSIS_COMMENT 1
#define SCE_NSIS_STRINGDQ 2
#define SCE_NSIS_STRINGLQ 3
#define SCE_NSIS_STRINGRQ 4
#define SCE_NSIS_FUNCTION 5
#define SCE_NSIS_VARIABLE 6
#define SCE_NSIS_LABEL 7
#define SCE_NSIS_USERDEFINED 8
#define SCE_NSIS_SECTIONDEF 9
#define SCE_NSIS_SUBSECTIONDEF 10
#define SCE_NSIS_IFDEFINEDEF 11
#define SCE_NSIS_MACRODEF 12
#define SCE_NSIS_STRINGVAR 13
#define SCE_NSIS_NUMBER 14
// ADDED for Scintilla v1.63
#define SCE_NSIS_SECTIONGROUP 15
#define SCE_NSIS_PAGEEX 16
#define SCE_NSIS_FUNCTIONDEF 17
#define SCE_NSIS_COMMENTBOX 18
*/

static bool isNsisNumber(char ch)
{
  return (ch >= '0' && ch <= '9');
}

static bool isNsisChar(char ch)
{
  return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}

static bool isNsisLetter(char ch)
{
  return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}

static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
{
  int nNextLine = -1;
  for( unsigned int i = start; i < end; i++ )
  {
    char cNext = styler.SafeGetCharAt( i );
    if( cNext == '\n' )
    {
      nNextLine = i+1;
      break;
    }
  }

  if( nNextLine == -1 ) // We never found the next line...
    return false;

  for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ )
  {
    char cNext = styler.SafeGetCharAt( firstChar );
    if( cNext == ' ' )
      continue;
    if( cNext == '\t' )
      continue;
    if( cNext == '!' )
    {
      if( styler.Match(firstChar, "!else") )
        return true;
    }
    break;
  }

  return false;
}

static int NsisCmp( const char *s1, const char *s2, bool bIgnoreCase )
{
  if( bIgnoreCase )
     return CompareCaseInsensitive( s1, s2);

  return strcmp( s1, s2 );
}

static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd )
{
  int style = styler.StyleAt(end);

  // If the word is too long, it is not what we are looking for
  if( end - start > 20 )
    return foldlevel;

  if( foldUtilityCmd )
  {
    // Check the style at this point, if it is not valid, then return zero
    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF &&
        style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP &&
        style != SCE_NSIS_PAGEEX )
          return foldlevel;
  }
  else
  {
    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP &&
        style != SCE_NSIS_PAGEEX )
          return foldlevel;
  }

  int newFoldlevel = foldlevel;
  bool bIgnoreCase = false;
  if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
    bIgnoreCase = true;

  char s[20]; // The key word we are looking for has atmost 13 characters
  s[0] = '\0';
  for (unsigned int i = 0; i < end - start + 1 && i < 19; i++)
	{
		s[i] = static_cast<char>( styler[ start + i ] );
		s[i + 1] = '\0';
	}

  if( s[0] == '!' )
  {
    if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase ) == 0 || NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 )
      newFoldlevel++;
    else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
      newFoldlevel--;
    else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 )
      newFoldlevel++;
  }
  else
  {
    if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 )
      newFoldlevel++;
    else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 )
      newFoldlevel--;
  }

  return newFoldlevel;
}

static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
{
  bool bIgnoreCase = false;
  if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
    bIgnoreCase = true;

  bool bUserVars = false;
  if( styler.GetPropertyInt("nsis.uservars") == 1 )
    bUserVars = true;

	char s[100];

	WordList &Functions = *keywordLists[0];
	WordList &Variables = *keywordLists[1];
	WordList &Lables = *keywordLists[2];
	WordList &UserDefined = *keywordLists[3];

	for (unsigned int i = 0; i < end - start + 1 && i < 99; i++)
	{
    if( bIgnoreCase )
      s[i] = static_cast<char>( tolower(styler[ start + i ] ) );
    else
		  s[i] = static_cast<char>( styler[ start + i ] );
		s[i + 1] = '\0';
	}

	// Check for special words...
	if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !macro and !macroend
		return SCE_NSIS_MACRODEF;

	if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 ) // Covers !ifdef, !ifndef and !endif
		return SCE_NSIS_IFDEFINEDEF;

	if( NsisCmp(s, "!if", bIgnoreCase ) == 0 || NsisCmp(s, "!else", bIgnoreCase )  == 0 ) // Covers !if and else
		return SCE_NSIS_IFDEFINEDEF;

	if (NsisCmp(s, "!ifmacrodef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifmacrondef", bIgnoreCase )  == 0 ) // Covers !ifmacrodef and !ifnmacrodef
		return SCE_NSIS_IFDEFINEDEF;

  if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd
    return SCE_NSIS_SECTIONGROUP;

	if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
		return SCE_NSIS_SECTIONDEF;

	if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
		return SCE_NSIS_SUBSECTIONDEF;

  if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd
    return SCE_NSIS_PAGEEX;

	if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd
		return SCE_NSIS_FUNCTIONDEF;

	if ( Functions.InList(s) )
		return SCE_NSIS_FUNCTION;

	if ( Variables.InList(s) )
		return SCE_NSIS_VARIABLE;

	if ( Lables.InList(s) )
		return SCE_NSIS_LABEL;

	if( UserDefined.InList(s) )
		return SCE_NSIS_USERDEFINED;

	if( strlen(s) > 3 )
	{
		if( s[1] == '{' && s[strlen(s)-1] == '}' )
			return SCE_NSIS_VARIABLE;
	}

  // See if the variable is a user defined variable
  if( s[0] == '$' && bUserVars )
  {
    bool bHasSimpleNsisChars = true;
    for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
	  {
      if( !isNsisChar( s[j] ) )
      {
        bHasSimpleNsisChars = false;
        break;
      }
	  }

    if( bHasSimpleNsisChars )
      return SCE_NSIS_VARIABLE;
  }

  // To check for numbers
  if( isNsisNumber( s[0] ) )
  {
    bool bHasSimpleNsisNumber = true;
    for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
	  {
      if( !isNsisNumber( s[j] ) )
      {
        bHasSimpleNsisNumber = false;
        break;
      }
	  }

    if( bHasSimpleNsisNumber )
      return SCE_NSIS_NUMBER;
  }

	return SCE_NSIS_DEFAULT;
}

static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
{
	int state = SCE_NSIS_DEFAULT;
  if( startPos > 0 )
    state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox

	styler.StartAt( startPos );
	styler.GetLine( startPos );

	unsigned int nLengthDoc = startPos + length;
	styler.StartSegment( startPos );

	char cCurrChar;
	bool bVarInString = false;
  bool bClassicVarInString = false;

	unsigned int i;
	for( i = startPos; i < nLengthDoc; i++ )
	{
		cCurrChar = styler.SafeGetCharAt( i );
		char cNextChar = styler.SafeGetCharAt(i+1);

		switch(state)
		{
			case SCE_NSIS_DEFAULT:
				if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line
				{
					styler.ColourTo(i-1, state );
					state = SCE_NSIS_COMMENT;
					break;
				}
				if( cCurrChar == '"' )
				{
					styler.ColourTo(i-1, state );
					state = SCE_NSIS_STRINGDQ;
					bVarInString = false;
          bClassicVarInString = false;
					break;
				}
				if( cCurrChar == '\'' )
				{
					styler.ColourTo(i-1, state );
					state = SCE_NSIS_STRINGRQ;
					bVarInString = false;
          bClassicVarInString = false;
					break;
				}
				if( cCurrChar == '`' )
				{
					styler.ColourTo(i-1, state );
					state = SCE_NSIS_STRINGLQ;
					bVarInString = false;
          bClassicVarInString = false;
					break;
				}

				// NSIS KeyWord,Function, Variable, UserDefined:
				if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' )
				{
					styler.ColourTo(i-1,state);
				  state = SCE_NSIS_FUNCTION;

          // If it is a number, we must check and set style here first...
          if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
              styler.ColourTo( i, SCE_NSIS_NUMBER);

					break;
				}

        if( cCurrChar == '/' && cNextChar == '*' )
        {
          styler.ColourTo(i-1,state);
          state = SCE_NSIS_COMMENTBOX;
          break;
        }

				break;
			case SCE_NSIS_COMMENT:
				if( cNextChar == '\n' || cNextChar == '\r' )
        {
          // Special case:
          if( cCurrChar == '\\' )
          {
            styler.ColourTo(i-2,state);
            styler.ColourTo(i,SCE_NSIS_DEFAULT);
          }
          else
          {
				    styler.ColourTo(i,state);
            state = SCE_NSIS_DEFAULT;
          }
        }
				break;
			case SCE_NSIS_STRINGDQ:
      case SCE_NSIS_STRINGLQ:
      case SCE_NSIS_STRINGRQ:

        if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
          break; // Ignore the next character, even if it is a quote of some sort

        if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ )
				{
					styler.ColourTo(i,state);
				  state = SCE_NSIS_DEFAULT;
          break;
				}

        if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
        {
					styler.ColourTo(i,state);
				  state = SCE_NSIS_DEFAULT;
          break;
				}

        if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ )
				{
					styler.ColourTo(i,state);
				  state = SCE_NSIS_DEFAULT;
          break;
				}

        if( cNextChar == '\r' || cNextChar == '\n' )
        {
          int nCurLine = styler.GetLine(i+1);
          int nBack = i;
          // We need to check if the previous line has a \ in it...
          bool bNextLine = false;

          while( nBack > 0 )
          {
            if( styler.GetLine(nBack) != nCurLine )
              break;

            char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here

            if( cTemp == '\\' )
            {
              bNextLine = true;
              break;
            }
            if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
              break;

            nBack--;
          }

          if( bNextLine )
          {
            styler.ColourTo(i+1,state);
          }
          if( bNextLine == false )
          {
            styler.ColourTo(i,state);
				    state = SCE_NSIS_DEFAULT;
          }
        }
				break;

			case SCE_NSIS_FUNCTION:

				// NSIS KeyWord:
        if( cCurrChar == '$' )
          state = SCE_NSIS_DEFAULT;
        else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
          state = SCE_NSIS_DEFAULT;
				else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
				{
					state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
					styler.ColourTo( i, state);
					state = SCE_NSIS_DEFAULT;
				}
				else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' )
				{
          if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER )
             styler.ColourTo( i-1, SCE_NSIS_NUMBER );

					state = SCE_NSIS_DEFAULT;

					if( cCurrChar == '"' )
					{
						state = SCE_NSIS_STRINGDQ;
						bVarInString = false;
            bClassicVarInString = false;
					}
					else if( cCurrChar == '`' )
					{
						state = SCE_NSIS_STRINGLQ;
						bVarInString = false;
            bClassicVarInString = false;
					}
					else if( cCurrChar == '\'' )
					{
						state = SCE_NSIS_STRINGRQ;
						bVarInString = false;
            bClassicVarInString = false;
					}
					else if( cCurrChar == '#' || cCurrChar == ';' )
          {
						state = SCE_NSIS_COMMENT;
          }
				}
				break;
      case SCE_NSIS_COMMENTBOX:

        if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' )
        {
          styler.ColourTo(i,state);
          state = SCE_NSIS_DEFAULT;
        }
        break;
		}

		if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX )
		{
			styler.ColourTo(i,state);
		}
		else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ )
		{
      bool bIngoreNextDollarSign = false;
      bool bUserVars = false;
      if( styler.GetPropertyInt("nsis.uservars") == 1 )
        bUserVars = true;

      if( bVarInString && cCurrChar == '$' )
      {
        bVarInString = false;
        bIngoreNextDollarSign = true;
      }
      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
      {
        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
        bVarInString = false;
        bIngoreNextDollarSign = false;
      }

      // Covers "$INSTDIR and user vars like $MYVAR"
      else if( bVarInString && !isNsisChar(cNextChar) )
      {
        int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
				if( nWordState == SCE_NSIS_VARIABLE )
					styler.ColourTo( i, SCE_NSIS_STRINGVAR);
        else if( bUserVars )
          styler.ColourTo( i, SCE_NSIS_STRINGVAR);
        bVarInString = false;
      }
      // Covers "${TEST}..."
      else if( bClassicVarInString && cNextChar == '}' )
      {
        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
				bClassicVarInString = false;
      }

      // Start of var in string
			if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' )
			{
				styler.ColourTo( i-1, state);
				bClassicVarInString = true;
        bVarInString = false;
			}
      else if( !bIngoreNextDollarSign && cCurrChar == '$' )
      {
        styler.ColourTo( i-1, state);
        bVarInString = true;
        bClassicVarInString = false;
      }
		}
	}

  // Colourise remaining document
	styler.ColourTo(nLengthDoc-1,state);
}

static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
	// No folding enabled, no reason to continue...
	if( styler.GetPropertyInt("fold") == 0 )
		return;

  bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
  bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1;
  bool blockComment = false;

  int lineCurrent = styler.GetLine(startPos);
  unsigned int safeStartPos = styler.LineStart( lineCurrent );

  bool bArg1 = true;
  int nWordStart = -1;

  int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelNext = levelCurrent;
  int style = styler.StyleAt(safeStartPos);
  if( style == SCE_NSIS_COMMENTBOX )
  {
    if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' )
      levelNext++;
    blockComment = true;
  }

  for (unsigned int i = safeStartPos; i < startPos + length; i++)
	{
    char chCurr = styler.SafeGetCharAt(i);
    style = styler.StyleAt(i);
    if( blockComment && style != SCE_NSIS_COMMENTBOX )
    {
      levelNext--;
      blockComment = false;
    }
    else if( !blockComment && style == SCE_NSIS_COMMENTBOX )
    {
      levelNext++;
      blockComment = true;
    }

    if( bArg1 && !blockComment)
    {
      if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
      {
        nWordStart = i;
      }
      else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
      {
        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd );

        if( newLevel == levelNext )
        {
          if( foldAtElse && foldUtilityCmd )
          {
            if( NsisNextLineHasElse(i, startPos + length, styler) )
              levelNext--;
          }
        }
        else
          levelNext = newLevel;
        bArg1 = false;
      }
    }

    if( chCurr == '\n' )
    {
      if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment )
      {
        if( NsisNextLineHasElse(i, startPos + length, styler) )
          levelNext--;
      }

      // If we are on a new line...
      int levelUse = levelCurrent;
			int lev = levelUse | levelNext << 16;
      if (levelUse < levelNext )
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent))
				styler.SetLevel(lineCurrent, lev);

			lineCurrent++;
			levelCurrent = levelNext;
      bArg1 = true; // New line, lets look at first argument again
      nWordStart = -1;
    }
  }

	int levelUse = levelCurrent;
	int lev = levelUse | levelNext << 16;
	if (levelUse < levelNext)
		lev |= SC_FOLDLEVELHEADERFLAG;
	if (lev != styler.LevelAt(lineCurrent))
		styler.SetLevel(lineCurrent, lev);
}

static const char * const nsisWordLists[] = {
	"Functions",
	"Variables",
	"Lables",
	"UserDefined",
	0, };


LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);

Added lexers/LexOScript.cxx.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
// Scintilla source code edit control
/** @file LexOScript.cxx
 ** Lexer for OScript sources; ocx files and/or OSpace dumps.
 ** OScript is a programming language used to develop applications for the
 ** Livelink server platform.
 **/
// Written by Ferdinand Prantl <prantlf@gmail.com>, inspired by the code from
// LexVB.cxx and LexPascal.cxx. The License.txt file describes the conditions
// under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// -----------------------------------------
// Functions classifying a single character.

// This function is generic and should be probably moved to CharSet.h where
// IsAlphaNumeric the others reside.
inline bool IsAlpha(int ch) {
	return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}

static inline bool IsIdentifierChar(int ch) {
	// Identifiers cannot contain non-ASCII letters; a word with non-English
	// language-specific characters cannot be an identifier.
	return IsAlphaNumeric(ch) || ch == '_';
}

static inline bool IsIdentifierStart(int ch) {
	// Identifiers cannot contain non-ASCII letters; a word with non-English
	// language-specific characters cannot be an identifier.
	return IsAlpha(ch) || ch == '_';
}

static inline bool IsNumberChar(int ch, int chNext) {
	// Numeric constructs are not checked for lexical correctness. They are
	// expected to look like +1.23-E9 but actually any bunch of the following
	// characters will be styled as number.
	// KNOWN PROBLEM: if you put + or - operators immediately after a number
	// and the next operand starts with the letter E, the operator will not be
	// recognized and it will be styled together with the preceding number.
	// This should not occur; at least not often. The coding style recommends
	// putting spaces around operators.
	return IsADigit(ch) || toupper(ch) == 'E' || ch == '.' ||
		   ((ch == '-' || ch == '+') && toupper(chNext) == 'E');
}

// This function checks for the start or a natural number without any symbols
// or operators as a prefix; the IsPrefixedNumberStart should be called
// immediately after this one to cover all possible numeric constructs.
static inline bool IsNaturalNumberStart(int ch) {
	return IsADigit(ch) != 0;
}

static inline bool IsPrefixedNumberStart(int ch, int chNext) {
	// KNOWN PROBLEM: if you put + or - operators immediately before a number
	// the operator will not be recognized and it will be styled together with
	// the succeeding number. This should not occur; at least not often. The
	// coding style recommends putting spaces around operators.
	return (ch == '.' || ch == '-' || ch == '+') && IsADigit(chNext);
}

static inline bool IsOperator(int ch) {
	return strchr("%^&*()-+={}[]:;<>,/?!.~|\\", ch) != NULL;
}

// ---------------------------------------------------------------
// Functions classifying a token currently processed in the lexer.

// Checks if the current line starts with the preprocessor directive used
// usually to introduce documentation comments: #ifdef DOC. This method is
// supposed to be called if the line has been recognized as a preprocessor
// directive already.
static bool IsDocCommentStart(StyleContext &sc) {
	// Check the line back to its start only if the end looks promising.
	if (sc.LengthCurrent() == 10 && !IsAlphaNumeric(sc.ch)) {
		char s[11];
		sc.GetCurrentLowered(s, sizeof(s));
		return strcmp(s, "#ifdef doc") == 0;
	}
	return false;
}

// Checks if the current line starts with the preprocessor directive that
// is complementary to the #ifdef DOC start: #endif. This method is supposed
// to be called if the current state point to the documentation comment.
// QUESTIONAL ASSUMPTION: The complete #endif directive is not checked; just
// the starting #e. However, there is no other preprocessor directive with
// the same starting letter and thus this optimization should always work.
static bool IsDocCommentEnd(StyleContext &sc) {
	return sc.ch == '#' && sc.chNext == 'e';
}

class IdentifierClassifier {
	WordList &keywords;  // Passed from keywords property.
	WordList &constants; // Passed from keywords2 property.
	WordList &operators; // Passed from keywords3 property.
	WordList &types;     // Passed from keywords4 property.
	WordList &functions; // Passed from keywords5 property.
	WordList &objects;   // Passed from keywords6 property.

	IdentifierClassifier(IdentifierClassifier const&);
	IdentifierClassifier& operator=(IdentifierClassifier const&);

public:
	IdentifierClassifier(WordList *keywordlists[]) :
		keywords(*keywordlists[0]), constants(*keywordlists[1]),
		operators(*keywordlists[2]), types(*keywordlists[3]),
		functions(*keywordlists[4]), objects(*keywordlists[5])
	{}

	void ClassifyIdentifier(StyleContext &sc) {
		// Opening parenthesis following an identifier makes it a possible
		// function call.
		// KNOWN PROBLEM: If some whitespace is inserted between the
		// identifier and the parenthesis they will not be able to be
		// recognized as a function call. This should not occur; at
		// least not often. Such coding style would be weird.
		if (sc.Match('(')) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			// Before an opening brace can be control statements and
			// operators too; function call is the last option.
			if (keywords.InList(s)) {
				sc.ChangeState(SCE_OSCRIPT_KEYWORD);
			} else if (operators.InList(s)) {
				sc.ChangeState(SCE_OSCRIPT_OPERATOR);
			} else if (functions.InList(s)) {
				sc.ChangeState(SCE_OSCRIPT_FUNCTION);
			} else {
				sc.ChangeState(SCE_OSCRIPT_METHOD);
			}
			sc.SetState(SCE_OSCRIPT_OPERATOR);
		} else {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			// A dot following an identifier means an access to an object
			// member. The related object identifier can be special.
			// KNOWN PROBLEM: If there is whitespace between the identifier
			// and the following dot, the identifier will not be recognized
			// as an object in an object member access. If it is one of the
			// listed static objects it will not be styled.
			if (sc.Match('.') && objects.InList(s)) {
				sc.ChangeState(SCE_OSCRIPT_OBJECT);
				sc.SetState(SCE_OSCRIPT_OPERATOR);
			} else {
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_OSCRIPT_KEYWORD);
				} else if (constants.InList(s)) {
					sc.ChangeState(SCE_OSCRIPT_CONSTANT);
				} else if (operators.InList(s)) {
					sc.ChangeState(SCE_OSCRIPT_OPERATOR);
				} else if (types.InList(s)) {
					sc.ChangeState(SCE_OSCRIPT_TYPE);
				} else if (functions.InList(s)) {
					sc.ChangeState(SCE_OSCRIPT_FUNCTION);
				}
				sc.SetState(SCE_OSCRIPT_DEFAULT);
			}
		}
	}
};

// ------------------------------------------------
// Function colourising an excerpt of OScript code.

static void ColouriseOScriptDoc(unsigned int startPos, int length,
								int initStyle, WordList *keywordlists[],
								Accessor &styler) {
	// I wonder how whole-line styles ended by EOLN can escape the resetting
	// code in the loop below and overflow to the next line. Let us make sure
	// that a new line does not start with them carried from the previous one.
	// NOTE: An overflowing string is intentionally not checked; it reminds
	// the developer that the string must be ended on the same line.
	if (initStyle == SCE_OSCRIPT_LINE_COMMENT ||
			initStyle == SCE_OSCRIPT_PREPROCESSOR) {
		initStyle = SCE_OSCRIPT_DEFAULT;
	}

	styler.StartAt(startPos);
	StyleContext sc(startPos, length, initStyle, styler);
	IdentifierClassifier identifierClassifier(keywordlists);

	// It starts with true at the beginning of a line and changes to false as
	// soon as the first non-whitespace character has been processed.
	bool isFirstToken = true;
	// It starts with true at the beginning of a line and changes to false as
	// soon as the first identifier on the line is passed by.
	bool isFirstIdentifier = true; 
	// It becomes false when #ifdef DOC (the preprocessor directive often
	// used to start a documentation comment) is encountered and remain false
	// until the end of the documentation block is not detected. This is done
	// by checking for the complementary #endif preprocessor directive.
	bool endDocComment = false; 

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			isFirstToken = true;
			isFirstIdentifier = true;
		// Detect the current state is neither whitespace nor identifier. It
		// means that no next identifier can be the first token on the line.
		} else if (isFirstIdentifier && sc.state != SCE_OSCRIPT_DEFAULT &&
				   sc.state != SCE_OSCRIPT_IDENTIFIER) {
			isFirstIdentifier = false;
		}

		// Check if the current state should be changed.
		if (sc.state == SCE_OSCRIPT_OPERATOR) {
			// Multiple-symbol operators are marked by single characters.
			sc.SetState(SCE_OSCRIPT_DEFAULT);
		} else if (sc.state == SCE_OSCRIPT_IDENTIFIER) {
			if (!IsIdentifierChar(sc.ch)) {
				// Colon after an identifier makes it a label if it is the
				// first token on the line.
				// KNOWN PROBLEM: If some whitespace is inserted between the
				// identifier and the colon they will not be recognized as a
				// label. This should not occur; at least not often. It would
				// make the code structure less legible and examples in the
				// Livelink documentation do not show it.
				if (sc.Match(':') && isFirstIdentifier) {
					sc.ChangeState(SCE_OSCRIPT_LABEL);
					sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
				} else {
					identifierClassifier.ClassifyIdentifier(sc);
				}
				// Avoid a sequence of two words be mistaken for a label. A
				// switch case would be an example.
				isFirstIdentifier = false;
			}
		} else if (sc.state == SCE_OSCRIPT_GLOBAL) {
			if (!IsIdentifierChar(sc.ch)) {
				sc.SetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_PROPERTY) {
			if (!IsIdentifierChar(sc.ch)) {
				// Any member access introduced by the dot operator is
				// initially marked as a property access. If an opening
				// parenthesis is detected later it is changed to method call.
				// KNOWN PROBLEM: The same as at the function call recognition
				// for SCE_OSCRIPT_IDENTIFIER above.
				if (sc.Match('(')) {
					sc.ChangeState(SCE_OSCRIPT_METHOD);
				}
				sc.SetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_NUMBER) {
			if (!IsNumberChar(sc.ch, sc.chNext)) {
				sc.SetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_SINGLEQUOTE_STRING) {
			if (sc.ch == '\'') {
				// Two consequential apostrophes convert to a single one.
				if (sc.chNext == '\'') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
				}
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_DOUBLEQUOTE_STRING) {
			if (sc.ch == '\"') {
				// Two consequential quotation marks convert to a single one.
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
				}
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_BLOCK_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_LINE_COMMENT) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_PREPROCESSOR) {
			if (IsDocCommentStart(sc)) {
				sc.ChangeState(SCE_OSCRIPT_DOC_COMMENT);
				endDocComment = false;
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		} else if (sc.state == SCE_OSCRIPT_DOC_COMMENT) {
			// KNOWN PROBLEM: The first line detected that would close a
			// conditional preprocessor block (#endif) the documentation
			// comment block will end. (Nested #if-#endif blocks are not
			// supported. Hopefully it will not occur often that a line
			// within the text block would stat with #endif.
			if (isFirstToken && IsDocCommentEnd(sc)) {
				endDocComment = true;
			} else if (sc.atLineEnd && endDocComment) {
				sc.ForwardSetState(SCE_OSCRIPT_DEFAULT);
			}
		}

		// Check what state starts with the current character.
		if (sc.state == SCE_OSCRIPT_DEFAULT) {
			if (sc.Match('\'')) {
				sc.SetState(SCE_OSCRIPT_SINGLEQUOTE_STRING);
			} else if (sc.Match('\"')) {
				sc.SetState(SCE_OSCRIPT_DOUBLEQUOTE_STRING);
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_OSCRIPT_LINE_COMMENT);
				sc.Forward();
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_OSCRIPT_BLOCK_COMMENT);
				sc.Forward();
			} else if (isFirstToken && sc.Match('#')) {
				sc.SetState(SCE_OSCRIPT_PREPROCESSOR);
			} else if (sc.Match('$')) {
				// Both process-global ($xxx) and thread-global ($$xxx)
				// variables are handled as one global.
				sc.SetState(SCE_OSCRIPT_GLOBAL);
			} else if (IsNaturalNumberStart(sc.ch)) {
				sc.SetState(SCE_OSCRIPT_NUMBER);
			} else if (IsPrefixedNumberStart(sc.ch, sc.chNext)) {
				sc.SetState(SCE_OSCRIPT_NUMBER);
				sc.Forward();
			} else if (sc.Match('.') && IsIdentifierStart(sc.chNext)) {
				// Every object member access is marked as a property access
				// initially. The decision between property and method is made
				// after parsing the identifier and looking what comes then.
				// KNOWN PROBLEM: If there is whitespace between the following
				// identifier and the dot, the dot will not be recognized
				// as a member accessing operator. In turn, the identifier
				// will not be recognizable as a property or a method too.
				sc.SetState(SCE_OSCRIPT_OPERATOR);
				sc.Forward();
				sc.SetState(SCE_OSCRIPT_PROPERTY);
			} else if (IsIdentifierStart(sc.ch)) {
				sc.SetState(SCE_OSCRIPT_IDENTIFIER);
			} else if (IsOperator(sc.ch)) {
				sc.SetState(SCE_OSCRIPT_OPERATOR);
			}
		}

		if (isFirstToken && !IsASpaceOrTab(sc.ch)) {
			isFirstToken = false;
		}
	}

	sc.Complete();
}

// ------------------------------------------
// Functions supporting OScript code folding.

static inline bool IsBlockComment(int style) {
	return style == SCE_OSCRIPT_BLOCK_COMMENT;
}

static bool IsLineComment(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eolPos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eolPos; i++) {
		char ch = styler[i];
		char chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		if (ch == '/' && chNext == '/' && style == SCE_OSCRIPT_LINE_COMMENT) {
			return true;
		} else if (!IsASpaceOrTab(ch)) {
			return false;
		}
	}
	return false;
}

static inline bool IsPreprocessor(int style) {
	return style == SCE_OSCRIPT_PREPROCESSOR ||
		   style == SCE_OSCRIPT_DOC_COMMENT;
}

static void GetRangeLowered(unsigned int start, unsigned int end,
							Accessor &styler, char *s, unsigned int len) {
	unsigned int i = 0;
	while (i < end - start + 1 && i < len - 1) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

static void GetForwardWordLowered(unsigned int start, Accessor &styler,
								  char *s, unsigned int len) {
	unsigned int i = 0;
	while (i < len - 1 && IsAlpha(styler.SafeGetCharAt(start + i))) {
		s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
		i++;
	}
	s[i] = '\0';
}

static void UpdatePreprocessorFoldLevel(int &levelCurrent,
		unsigned int startPos, Accessor &styler) {
	char s[7]; // Size of the longest possible keyword + null.
	GetForwardWordLowered(startPos, styler, s, sizeof(s));

	if (strcmp(s, "ifdef") == 0 ||
		strcmp(s, "ifndef") == 0) {
		levelCurrent++;
	} else if (strcmp(s, "endif") == 0) {
		levelCurrent--;
		if (levelCurrent < SC_FOLDLEVELBASE) {
			levelCurrent = SC_FOLDLEVELBASE;
		}
	}
}

static void UpdateKeywordFoldLevel(int &levelCurrent, unsigned int lastStart,
		unsigned int currentPos, Accessor &styler) {
	char s[9];
	GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));

	if (strcmp(s, "if") == 0 || strcmp(s, "for") == 0 ||
		strcmp(s, "switch") == 0 || strcmp(s, "function") == 0 ||
		strcmp(s, "while") == 0 || strcmp(s, "repeat") == 0) {
		levelCurrent++;
	} else if (strcmp(s, "end") == 0 || strcmp(s, "until") == 0) {
		levelCurrent--;
		if (levelCurrent < SC_FOLDLEVELBASE) {
			levelCurrent = SC_FOLDLEVELBASE;
		}
	}
}

// ------------------------------
// Function folding OScript code.

static void FoldOScriptDoc(unsigned int startPos, int length, int initStyle,
						   WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	int lastStart = 0;

	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atLineEnd = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (foldComment && IsBlockComment(style)) {
			if (!IsBlockComment(stylePrev)) {
				levelCurrent++;
			} else if (!IsBlockComment(styleNext) && !atLineEnd) {
				// Comments do not end at end of line and the next character
				// may not be styled.
				levelCurrent--;
			}
		}
		if (foldComment && atLineEnd && IsLineComment(lineCurrent, styler)) {
			if (!IsLineComment(lineCurrent - 1, styler) &&
				IsLineComment(lineCurrent + 1, styler))
				levelCurrent++;
			else if (IsLineComment(lineCurrent - 1, styler) &&
					 !IsLineComment(lineCurrent+1, styler))
				levelCurrent--;
		}
		if (foldPreprocessor) {
			if (ch == '#' && IsPreprocessor(style)) {
				UpdatePreprocessorFoldLevel(levelCurrent, i + 1, styler);
			}
		}

		if (stylePrev != SCE_OSCRIPT_KEYWORD && style == SCE_OSCRIPT_KEYWORD) {
			lastStart = i;
		}
		if (stylePrev == SCE_OSCRIPT_KEYWORD) {
			if(IsIdentifierChar(ch) && !IsIdentifierChar(chNext)) {
				UpdateKeywordFoldLevel(levelCurrent, lastStart, i, styler);
			}
		}

		if (!IsASpace(ch))
			visibleChars++;

		if (atLineEnd) {
			int level = levelPrev;
			if (visibleChars == 0 && foldCompact)
				level |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				level |= SC_FOLDLEVELHEADERFLAG;
			if (level != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, level);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
	}

	// If we did not reach EOLN in the previous loop, store the line level and
	// whitespace information. The rest will be filled in later.
	int lev = levelPrev;
	if (visibleChars == 0 && foldCompact)
		lev |= SC_FOLDLEVELWHITEFLAG;
	styler.SetLevel(lineCurrent, lev);
}

// --------------------------------------------
// Declaration of the OScript lexer descriptor.

static const char * const oscriptWordListDesc[] = {
	"Keywords and reserved words",
	"Literal constants",
	"Literal operators",
	"Built-in value and reference types",
	"Built-in global functions",
	"Built-in static objects",
	0
};

LexerModule lmOScript(SCLEX_OSCRIPT, ColouriseOScriptDoc, "oscript", FoldOScriptDoc, oscriptWordListDesc);

Added lexers/LexOpal.cxx.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
// Scintilla source code edit control
/** @file LexOpal.cxx
 ** Lexer for OPAL (functional language similar to Haskell)
 ** Written by Sebastian Pipping <webmaster@hartwork.org>
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

inline static void getRange( unsigned int start, unsigned int end, Accessor & styler, char * s, unsigned int len )
{
	unsigned int i = 0;
	while( ( i < end - start + 1 ) && ( i < len - 1 ) )
	{
		s[i] = static_cast<char>( styler[ start + i ] );
		i++;
	}
	s[ i ] = '\0';
}

inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
{
	char ch;

	// Wait for string to close
	bool even_backslash_count = true; // Without gaps in between
	cur++; // Skip initial quote
	for( ; ; )
	{
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_STRING );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( ( ch == '\015' ) || ( ch == '\012' ) ) // Deny multi-line strings
		{
			styler.ColourTo( cur - 1, SCE_OPAL_STRING );
			styler.StartSegment( cur );
			return true;
		}
		else
		{
			if( even_backslash_count )
			{
				if( ch == '"' )
				{
					styler.ColourTo( cur, SCE_OPAL_STRING );
					cur++;
					if( cur >= one_too_much )
					{
						return false; // STOP
					}
					else
					{
						styler.StartSegment( cur );
						return true;
					}
				}
				else if( ch == '\\' )
				{
					even_backslash_count = false;
				}
			}
			else
			{
				even_backslash_count = true;
			}
		}

		cur++;
	}
}

inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
{
	char ch;

	if( could_fail )
	{
		cur++;
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( ch != '*' )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			styler.StartSegment( cur );
			return true;
		}
	}

	// Wait for comment close
	cur++;
	bool star_found = false;
	for( ; ; )
	{
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( star_found )
		{
			if( ch == '/' )
			{
				styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK );
				cur++;
				if( cur >= one_too_much )
				{
					return false; // STOP
				}
				else
				{
					styler.StartSegment( cur );
					return true;
				}
			}
			else if( ch != '*' )
			{
				star_found = false;
			}
		}
		else if( ch == '*' )
		{
			star_found = true;
		}
		cur++;
	}
}

inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail )
{
	char ch;

	if( could_fail )
	{
		cur++;
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( ch != '-' )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			styler.StartSegment( cur );
			return true;
		}

		cur++;
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( ( ch != ' ' ) && ( ch != '\t' ) )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
			styler.StartSegment( cur );
			return true;
		}
	}

	// Wait for end of line
	bool fifteen_found = false;

	for( ; ; )
	{
		cur++;

		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( fifteen_found )
		{
/*
			if( ch == '\012' )
			{
				// One newline on Windows (015, 012)
			}
			else
			{
				// One newline on MAC (015) and another char
			}
*/
			cur--;
			styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
			styler.StartSegment( cur );
			return true;
		}
		else
		{
			if( ch == '\015' )
			{
				fifteen_found = true;
			}
			else if( ch == '\012' )
			{
				// One newline on Linux (012)
				styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE );
				styler.StartSegment( cur );
				return true;
			}
		}
	}
}

inline bool HandlePar( unsigned int & cur, Accessor & styler )
{
	styler.ColourTo( cur, SCE_OPAL_PAR );

	cur++;

	styler.StartSegment( cur );
	return true;
}

inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
{
	char ch;

	cur++;
	for( ; ; )
	{
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
			return false;
		}

		ch = styler.SafeGetCharAt( cur );
		switch( ch )
		{
		case ' ':
		case '\t':
		case '\015':
		case '\012':
			cur++;
			break;

		default:
			styler.ColourTo( cur - 1, SCE_OPAL_SPACE );
			styler.StartSegment( cur );
			return true;
		}
	}
}

inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
{
	char ch;

	for( ; ; )
	{
		cur++;
		if( cur >= one_too_much )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
			return false; // STOP
		}

		ch = styler.SafeGetCharAt( cur );
		if( !( isascii( ch ) && isdigit( ch ) ) )
		{
			styler.ColourTo( cur - 1, SCE_OPAL_INTEGER );
			styler.StartSegment( cur );
			return true;
		}
	}
}

inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] )
{
	char ch;
	const unsigned int beg = cur;

	cur++;
	for( ; ; )
	{
		ch = styler.SafeGetCharAt( cur );
		if( ( ch != '_' ) && ( ch != '-' ) &&
			!( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break;

		cur++;
		if( cur >= one_too_much )
		{
			break;
		}
	}

	const int ide_len = cur - beg + 1;
	char * ide = new char[ ide_len ];
	getRange( beg, cur, styler, ide, ide_len );

	WordList & keywords    = *keywordlists[ 0 ];
	WordList & classwords  = *keywordlists[ 1 ];

	if( keywords.InList( ide ) ) // Keyword
	{
		delete [] ide;

		styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD );
		if( cur >= one_too_much )
		{
			return false; // STOP
		}
		else
		{
			styler.StartSegment( cur );
			return true;
		}
	}
	else if( classwords.InList( ide ) ) // Sort
	{
		delete [] ide;

		styler.ColourTo( cur - 1, SCE_OPAL_SORT );
		if( cur >= one_too_much )
		{
			return false; // STOP
		}
		else
		{
			styler.StartSegment( cur );
			return true;
		}
	}
	else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const
	{
		delete [] ide;

		styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST );
		if( cur >= one_too_much )
		{
			return false; // STOP
		}
		else
		{
			styler.StartSegment( cur );
			return true;
		}
	}
	else // Unknown keyword
	{
		delete [] ide;

		styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
		if( cur >= one_too_much )
		{
			return false; // STOP
		}
		else
		{
			styler.StartSegment( cur );
			return true;
		}
	}

}

inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor & styler )
{
	cur++;
	styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT );
	if( cur >= one_too_much )
	{
		return false; // STOP
	}
	else
	{
		styler.StartSegment( cur );
		return true;
	}
}

static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler )
{
	styler.StartAt( startPos );
	styler.StartSegment( startPos );

	unsigned int & cur = startPos;
	const unsigned int one_too_much = startPos + length;

	int state = initStyle;

	for( ; ; )
	{
		switch( state )
		{
		case SCE_OPAL_KEYWORD:
		case SCE_OPAL_SORT:
			if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;
			state = SCE_OPAL_DEFAULT;
			break;

		case SCE_OPAL_INTEGER:
			if( !HandleInteger( cur, one_too_much, styler ) ) return;
			state = SCE_OPAL_DEFAULT;
			break;

		case SCE_OPAL_COMMENT_BLOCK:
			if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return;
			state = SCE_OPAL_DEFAULT;
			break;

		case SCE_OPAL_COMMENT_LINE:
			if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return;
			state = SCE_OPAL_DEFAULT;
			break;

		case SCE_OPAL_STRING:
			if( !HandleString( cur, one_too_much, styler ) ) return;
			state = SCE_OPAL_DEFAULT;
			break;

		default: // SCE_OPAL_DEFAULT:
			{
				char ch = styler.SafeGetCharAt( cur );

				switch( ch )
				{
				// String
				case '"':
					if( !HandleString( cur, one_too_much, styler ) ) return;
					break;

				// Comment block
				case '/':
					if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return;
					break;

				// Comment line
				case '-':
					if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return;
					break;

				// Par
				case '(':
				case ')':
				case '[':
				case ']':
				case '{':
				case '}':
					if( !HandlePar( cur, styler ) ) return;
					break;

				// Whitespace
				case ' ':
				case '\t':
				case '\015':
				case '\012':
					if( !HandleSpace( cur, one_too_much, styler ) ) return;
					break;

				default:
					{
						// Integer
						if( isascii( ch ) && isdigit( ch ) )
						{
							if( !HandleInteger( cur, one_too_much, styler ) ) return;
						}

						// Keyword
						else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) )
						{
							if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return;

						}

						// Skip
						else
						{
							if( !HandleSkip( cur, one_too_much, styler ) ) return;
						}
					}
				}

				break;
			}
		}
	}
}

static const char * const opalWordListDesc[] = {
	"Keywords",
	"Sorts",
	0
};

LexerModule lmOpal(SCLEX_OPAL, ColouriseOpalDoc, "opal", NULL, opalWordListDesc);

Added lexers/LexOthers.cxx.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
// Scintilla source code edit control
/** @file LexOthers.cxx
 ** Lexers for batch files, diff results, properties files, make files and error lists.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static bool strstart(const char *haystack, const char *needle) {
	return strncmp(haystack, needle, strlen(needle)) == 0;
}

static bool Is0To9(char ch) {
	return (ch >= '0') && (ch <= '9');
}

static bool Is1To9(char ch) {
	return (ch >= '1') && (ch <= '9');
}

static bool IsAlphabetic(int ch) {
	return isascii(ch) && isalpha(ch);
}

static inline bool AtEOL(Accessor &styler, unsigned int i) {
	return (styler[i] == '\n') ||
	       ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}

// Tests for BATCH Operators
static bool IsBOperator(char ch) {
	return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
		(ch == '|') || (ch == '?') || (ch == '*');
}

// Tests for BATCH Separators
static bool IsBSeparator(char ch) {
	return (ch == '\\') || (ch == '.') || (ch == ';') ||
		(ch == '\"') || (ch == '\'') || (ch == '/');
}

static void ColouriseBatchLine(
    char *lineBuffer,
    unsigned int lengthLine,
    unsigned int startLine,
    unsigned int endPos,
    WordList *keywordlists[],
    Accessor &styler) {

	unsigned int offset = 0;	// Line Buffer Offset
	unsigned int cmdLoc;		// External Command / Program Location
	char wordBuffer[81];		// Word Buffer - large to catch long paths
	unsigned int wbl;		// Word Buffer Length
	unsigned int wbo;		// Word Buffer Offset - also Special Keyword Buffer Length
	WordList &keywords = *keywordlists[0];      // Internal Commands
	WordList &keywords2 = *keywordlists[1];     // External Commands (optional)

	// CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
	//   Toggling Regular Keyword Checking off improves readability
	// Other Regular Keywords and External Commands / Programs might also benefit from toggling
	//   Need a more robust algorithm to properly toggle Regular Keyword Checking
	bool continueProcessing = true;	// Used to toggle Regular Keyword Checking
	// Special Keywords are those that allow certain characters without whitespace after the command
	// Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
	// Special Keyword Buffer used to determine if the first n characters is a Keyword
	char sKeywordBuffer[10];	// Special Keyword Buffer
	bool sKeywordFound;		// Exit Special Keyword for-loop if found

	// Skip initial spaces
	while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
		offset++;
	}
	// Colorize Default Text
	styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
	// Set External Command / Program Location
	cmdLoc = offset;

	// Check for Fake Label (Comment) or Real Label - return if found
	if (lineBuffer[offset] == ':') {
		if (lineBuffer[offset + 1] == ':') {
			// Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
			styler.ColourTo(endPos, SCE_BAT_COMMENT);
		} else {
			// Colorize Real Label
			styler.ColourTo(endPos, SCE_BAT_LABEL);
		}
		return;
	// Check for Drive Change (Drive Change is internal command) - return if found
	} else if ((IsAlphabetic(lineBuffer[offset])) &&
		(lineBuffer[offset + 1] == ':') &&
		((isspacechar(lineBuffer[offset + 2])) ||
		(((lineBuffer[offset + 2] == '\\')) &&
		(isspacechar(lineBuffer[offset + 3]))))) {
		// Colorize Regular Keyword
		styler.ColourTo(endPos, SCE_BAT_WORD);
		return;
	}

	// Check for Hide Command (@ECHO OFF/ON)
	if (lineBuffer[offset] == '@') {
		styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
		offset++;
	}
	// Skip next spaces
	while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
		offset++;
	}

	// Read remainder of line word-at-a-time or remainder-of-word-at-a-time
	while (offset < lengthLine) {
		if (offset > startLine) {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
		}
		// Copy word from Line Buffer into Word Buffer
		wbl = 0;
		for (; offset < lengthLine && wbl < 80 &&
		        !isspacechar(lineBuffer[offset]); wbl++, offset++) {
			wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
		}
		wordBuffer[wbl] = '\0';
		wbo = 0;

		// Check for Comment - return if found
		if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
			styler.ColourTo(endPos, SCE_BAT_COMMENT);
			return;
		}
		// Check for Separator
		if (IsBSeparator(wordBuffer[0])) {
			// Check for External Command / Program
			if ((cmdLoc == offset - wbl) &&
				((wordBuffer[0] == ':') ||
				(wordBuffer[0] == '\\') ||
				(wordBuffer[0] == '.'))) {
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
				// Colorize External Command / Program
				if (!keywords2) {
					styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
				} else if (keywords2.InList(wordBuffer)) {
					styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
				} else {
					styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
				}
				// Reset External Command / Program Location
				cmdLoc = offset;
			} else {
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
				// Colorize Default Text
				styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
			}
		// Check for Regular Keyword in list
		} else if ((keywords.InList(wordBuffer)) &&
			(continueProcessing)) {
			// ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
			if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "prompt") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "set") == 0)) {
				continueProcessing = false;
			}
			// Identify External Command / Program Location for ERRORLEVEL, and EXIST
			if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
				// Reset External Command / Program Location
				cmdLoc = offset;
				// Skip next spaces
				while ((cmdLoc < lengthLine) &&
					(isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
				// Skip comparison
				while ((cmdLoc < lengthLine) &&
					(!isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
				// Skip next spaces
				while ((cmdLoc < lengthLine) &&
					(isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
			// Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
			} else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "do") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
				(CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
				// Reset External Command / Program Location
				cmdLoc = offset;
				// Skip next spaces
				while ((cmdLoc < lengthLine) &&
					(isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
			}
			// Colorize Regular keyword
			styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
			// No need to Reset Offset
		// Check for Special Keyword in list, External Command / Program, or Default Text
		} else if ((wordBuffer[0] != '%') &&
				   (wordBuffer[0] != '!') &&
			(!IsBOperator(wordBuffer[0])) &&
			(continueProcessing)) {
			// Check for Special Keyword
			//     Affected Commands are in Length range 2-6
			//     Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
			sKeywordFound = false;
			for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
				wbo = 0;
				// Copy Keyword Length from Word Buffer into Special Keyword Buffer
				for (; wbo < keywordLength; wbo++) {
					sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
				}
				sKeywordBuffer[wbo] = '\0';
				// Check for Special Keyword in list
				if ((keywords.InList(sKeywordBuffer)) &&
					((IsBOperator(wordBuffer[wbo])) ||
					(IsBSeparator(wordBuffer[wbo])))) {
					sKeywordFound = true;
					// ECHO requires no further Regular Keyword Checking
					if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
						continueProcessing = false;
					}
					// Colorize Special Keyword as Regular Keyword
					styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
					// Reset Offset to re-process remainder of word
					offset -= (wbl - wbo);
				}
			}
			// Check for External Command / Program or Default Text
			if (!sKeywordFound) {
				wbo = 0;
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					// Read up to %, Operator or Separator
					while ((wbo < wbl) &&
						(wordBuffer[wbo] != '%') &&
						(wordBuffer[wbo] != '!') &&
						(!IsBOperator(wordBuffer[wbo])) &&
						(!IsBSeparator(wordBuffer[wbo]))) {
						wbo++;
					}
					// Reset External Command / Program Location
					cmdLoc = offset - (wbl - wbo);
					// Reset Offset to re-process remainder of word
					offset -= (wbl - wbo);
					// CHOICE requires no further Regular Keyword Checking
					if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
						continueProcessing = false;
					}
					// Check for START (and its switches) - What follows is External Command \ Program
					if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
						// Reset External Command / Program Location
						cmdLoc = offset;
						// Skip next spaces
						while ((cmdLoc < lengthLine) &&
							(isspacechar(lineBuffer[cmdLoc]))) {
							cmdLoc++;
						}
						// Reset External Command / Program Location if command switch detected
						if (lineBuffer[cmdLoc] == '/') {
							// Skip command switch
							while ((cmdLoc < lengthLine) &&
								(!isspacechar(lineBuffer[cmdLoc]))) {
								cmdLoc++;
							}
							// Skip next spaces
							while ((cmdLoc < lengthLine) &&
								(isspacechar(lineBuffer[cmdLoc]))) {
								cmdLoc++;
							}
						}
					}
					// Colorize External Command / Program
					if (!keywords2) {
						styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
					} else if (keywords2.InList(wordBuffer)) {
						styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
					} else {
						styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
					}
					// No need to Reset Offset
				// Check for Default Text
				} else {
					// Read up to %, Operator or Separator
					while ((wbo < wbl) &&
						(wordBuffer[wbo] != '%') &&
						(wordBuffer[wbo] != '!') &&
						(!IsBOperator(wordBuffer[wbo])) &&
						(!IsBSeparator(wordBuffer[wbo]))) {
						wbo++;
					}
					// Colorize Default Text
					styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
					// Reset Offset to re-process remainder of word
					offset -= (wbl - wbo);
				}
			}
		// Check for Argument  (%n), Environment Variable (%x...%) or Local Variable (%%a)
		} else if (wordBuffer[0] == '%') {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
			wbo++;
			// Search to end of word for second % (can be a long path)
			while ((wbo < wbl) &&
				(wordBuffer[wbo] != '%') &&
				(!IsBOperator(wordBuffer[wbo])) &&
				(!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}
			// Check for Argument (%n) or (%*)
			if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) &&
				(wordBuffer[wbo] != '%')) {
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					cmdLoc = offset - (wbl - 2);
				}
				// Colorize Argument
				styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 2);
			// Check for Expanded Argument (%~...) / Variable (%%~...)
			} else if (((wbl > 1) && (wordBuffer[1] == '~')) ||
				((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) {
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					cmdLoc = offset - (wbl - wbo);
				}
				// Colorize Expanded Argument / Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);
			// Check for Environment Variable (%x...%)
			} else if ((wordBuffer[1] != '%') &&
				(wordBuffer[wbo] == '%')) {
				wbo++;
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					cmdLoc = offset - (wbl - wbo);
				}
				// Colorize Environment Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);
			// Check for Local Variable (%%a)
			} else if (
				(wbl > 2) &&
				(wordBuffer[1] == '%') &&
				(wordBuffer[2] != '%') &&
				(!IsBOperator(wordBuffer[2])) &&
				(!IsBSeparator(wordBuffer[2]))) {
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					cmdLoc = offset - (wbl - 3);
				}
				// Colorize Local Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 3);
			}
		// Check for Environment Variable (!x...!)
		} else if (wordBuffer[0] == '!') {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
			wbo++;
			// Search to end of word for second ! (can be a long path)
			while ((wbo < wbl) &&
				(wordBuffer[wbo] != '!') &&
				(!IsBOperator(wordBuffer[wbo])) &&
				(!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}
			if (wordBuffer[wbo] == '!') {
				wbo++;
				// Check for External Command / Program
				if (cmdLoc == offset - wbl) {
					cmdLoc = offset - (wbl - wbo);
				}
				// Colorize Environment Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);
			}
		// Check for Operator
		} else if (IsBOperator(wordBuffer[0])) {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
			// Check for Comparison Operator
			if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
				// Identify External Command / Program Location for IF
				cmdLoc = offset;
				// Skip next spaces
				while ((cmdLoc < lengthLine) &&
					(isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
				// Colorize Comparison Operator
				styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 2);
			// Check for Pipe Operator
			} else if (wordBuffer[0] == '|') {
				// Reset External Command / Program Location
				cmdLoc = offset - wbl + 1;
				// Skip next spaces
				while ((cmdLoc < lengthLine) &&
					(isspacechar(lineBuffer[cmdLoc]))) {
					cmdLoc++;
				}
				// Colorize Pipe Operator
				styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
			// Check for Other Operator
			} else {
				// Check for > Operator
				if (wordBuffer[0] == '>') {
					// Turn Keyword and External Command / Program checking back on
					continueProcessing = true;
				}
				// Colorize Other Operator
				styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
			}
		// Check for Default Text
		} else {
			// Read up to %, Operator or Separator
			while ((wbo < wbl) &&
				(wordBuffer[wbo] != '%') &&
				(wordBuffer[wbo] != '!') &&
				(!IsBOperator(wordBuffer[wbo])) &&
				(!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
			// Reset Offset to re-process remainder of word
			offset -= (wbl - wbo);
		}
		// Skip next spaces - nothing happens if Offset was Reset
		while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
			offset++;
		}
	}
	// Colorize Default Text for remainder of line - currently not lexed
	styler.ColourTo(endPos, SCE_BAT_DEFAULT);
}

static void ColouriseBatchDoc(
    unsigned int startPos,
    int length,
    int /*initStyle*/,
    WordList *keywordlists[],
    Accessor &styler) {

	char lineBuffer[1024];

	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	unsigned int startLine = startPos;
	for (unsigned int i = startPos; i < startPos + length; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler);
			linePos = 0;
			startLine = i + 1;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		lineBuffer[linePos] = '\0';
		ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
		                   keywordlists, styler);
	}
}

#define DIFF_BUFFER_START_SIZE 16
// Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE
// characters of each line to classify the line.

static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
	// It is needed to remember the current state to recognize starting
	// comment lines before the first "diff " or "--- ". If a real
	// difference starts then each line starting with ' ' is a whitespace
	// otherwise it is considered a comment (Only in..., Binary file...)
	if (0 == strncmp(lineBuffer, "diff ", 5)) {
		styler.ColourTo(endLine, SCE_DIFF_COMMAND);
	} else if (0 == strncmp(lineBuffer, "Index: ", 7)) {  // For subversion's diff
		styler.ColourTo(endLine, SCE_DIFF_COMMAND);
	} else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') {
		// In a context diff, --- appears in both the header and the position markers
		if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/'))
			styler.ColourTo(endLine, SCE_DIFF_POSITION);
		else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n')
			styler.ColourTo(endLine, SCE_DIFF_POSITION);
		else
			styler.ColourTo(endLine, SCE_DIFF_HEADER);
	} else if (0 == strncmp(lineBuffer, "+++ ", 4)) {
		// I don't know of any diff where "+++ " is a position marker, but for
		// consistency, do the same as with "--- " and "*** ".
		if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
			styler.ColourTo(endLine, SCE_DIFF_POSITION);
		else
			styler.ColourTo(endLine, SCE_DIFF_HEADER);
	} else if (0 == strncmp(lineBuffer, "====", 4)) {  // For p4's diff
		styler.ColourTo(endLine, SCE_DIFF_HEADER);
	} else if (0 == strncmp(lineBuffer, "***", 3)) {
		// In a context diff, *** appears in both the header and the position markers.
		// Also ******** is a chunk header, but here it's treated as part of the
		// position marker since there is no separate style for a chunk header.
		if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
			styler.ColourTo(endLine, SCE_DIFF_POSITION);
		else if (lineBuffer[3] == '*')
			styler.ColourTo(endLine, SCE_DIFF_POSITION);
		else
			styler.ColourTo(endLine, SCE_DIFF_HEADER);
	} else if (0 == strncmp(lineBuffer, "? ", 2)) {    // For difflib
		styler.ColourTo(endLine, SCE_DIFF_HEADER);
	} else if (lineBuffer[0] == '@') {
		styler.ColourTo(endLine, SCE_DIFF_POSITION);
	} else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') {
		styler.ColourTo(endLine, SCE_DIFF_POSITION);
	} else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
		styler.ColourTo(endLine, SCE_DIFF_DELETED);
	} else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
		styler.ColourTo(endLine, SCE_DIFF_ADDED);
	} else if (lineBuffer[0] == '!') {
		styler.ColourTo(endLine, SCE_DIFF_CHANGED);
	} else if (lineBuffer[0] != ' ') {
		styler.ColourTo(endLine, SCE_DIFF_COMMENT);
	} else {
		styler.ColourTo(endLine, SCE_DIFF_DEFAULT);
	}
}

static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	char lineBuffer[DIFF_BUFFER_START_SIZE] = "";
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	for (unsigned int i = startPos; i < startPos + length; i++) {
		if (AtEOL(styler, i)) {
			if (linePos < DIFF_BUFFER_START_SIZE) {
				lineBuffer[linePos] = 0;
			}
			ColouriseDiffLine(lineBuffer, i, styler);
			linePos = 0;
		} else if (linePos < DIFF_BUFFER_START_SIZE - 1) {
			lineBuffer[linePos++] = styler[i];
		} else if (linePos == DIFF_BUFFER_START_SIZE - 1) {
			lineBuffer[linePos++] = 0;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		if (linePos < DIFF_BUFFER_START_SIZE) {
			lineBuffer[linePos] = 0;
		}
		ColouriseDiffLine(lineBuffer, startPos + length - 1, styler);
	}
}

static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	int curLine = styler.GetLine(startPos);
	int curLineStart = styler.LineStart(curLine);
	int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE;
	int nextLevel;

	do {
		int lineType = styler.StyleAt(curLineStart);
		if (lineType == SCE_DIFF_COMMAND)
			nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
		else if (lineType == SCE_DIFF_HEADER)
			nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
		else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-')
			nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
		else if (prevLevel & SC_FOLDLEVELHEADERFLAG)
			nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
		else
			nextLevel = prevLevel;

		if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel))
			styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG);

		styler.SetLevel(curLine, nextLevel);
		prevLevel = nextLevel;

		curLineStart = styler.LineStart(++curLine);
	} while (static_cast<int>(startPos) + length > curLineStart);
}

static inline bool isassignchar(unsigned char ch) {
	return (ch == '=') || (ch == ':');
}

static void ColourisePropsLine(
    char *lineBuffer,
    unsigned int lengthLine,
    unsigned int startLine,
    unsigned int endPos,
    Accessor &styler,
    bool allowInitialSpaces) {

	unsigned int i = 0;
	if (allowInitialSpaces) {
		while ((i < lengthLine) && isspacechar(lineBuffer[i]))	// Skip initial spaces
			i++;
	} else {
		if (isspacechar(lineBuffer[i])) // don't allow initial spaces
			i = lengthLine;
	}

	if (i < lengthLine) {
		if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
			styler.ColourTo(endPos, SCE_PROPS_COMMENT);
		} else if (lineBuffer[i] == '[') {
			styler.ColourTo(endPos, SCE_PROPS_SECTION);
		} else if (lineBuffer[i] == '@') {
			styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
			if (isassignchar(lineBuffer[i++]))
				styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
			styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
		} else {
			// Search for the '=' character
			while ((i < lengthLine) && !isassignchar(lineBuffer[i]))
				i++;
			if ((i < lengthLine) && isassignchar(lineBuffer[i])) {
				styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY);
				styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
				styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
			} else {
				styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
			}
		}
	} else {
		styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
	}
}

static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	char lineBuffer[1024];
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	unsigned int startLine = startPos;

	// property lexer.props.allow.initial.spaces
	//	For properties files, set to 0 to style all lines that start with whitespace in the default style.
	//	This is not suitable for SciTE .properties files which use indentation for flow control but
	//	can be used for RFC2822 text where indentation is used for continuation lines.
	bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;

	for (unsigned int i = startPos; i < startPos + length; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces);
			linePos = 0;
			startLine = i + 1;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces);
	}
}

// adaption by ksc, using the "} else {" trick of 1.53
// 030721
static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);

	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	bool headerPoint = false;
	int lev;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler[i+1];

		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (style == SCE_PROPS_SECTION) {
			headerPoint = true;
		}

		if (atEOL) {
			lev = SC_FOLDLEVELBASE;

			if (lineCurrent > 0) {
				int levelPrevious = styler.LevelAt(lineCurrent - 1);

				if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
					lev = SC_FOLDLEVELBASE + 1;
				} else {
					lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
				}
			}

			if (headerPoint) {
				lev = SC_FOLDLEVELBASE;
			}
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;

			if (headerPoint) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}

			lineCurrent++;
			visibleChars = 0;
			headerPoint = false;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}

	if (lineCurrent > 0) {
		int levelPrevious = styler.LevelAt(lineCurrent - 1);
		if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
			lev = SC_FOLDLEVELBASE + 1;
		} else {
			lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
		}
	} else {
		lev = SC_FOLDLEVELBASE;
	}
	int flagsNext = styler.LevelAt(lineCurrent);
	styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK));
}

static void ColouriseMakeLine(
    char *lineBuffer,
    unsigned int lengthLine,
    unsigned int startLine,
    unsigned int endPos,
    Accessor &styler) {

	unsigned int i = 0;
	int lastNonSpace = -1;
	unsigned int state = SCE_MAKE_DEFAULT;
	bool bSpecial = false;

	// check for a tab character in column 0 indicating a command
	bool bCommand = false;
	if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
		bCommand = true;

	// Skip initial spaces
	while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
		i++;
	}
	if (i < lengthLine) {
		if (lineBuffer[i] == '#') {	// Comment
			styler.ColourTo(endPos, SCE_MAKE_COMMENT);
			return;
		}
		if (lineBuffer[i] == '!') {	// Special directive
			styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
			return;
		}
	}
	int varCount = 0;
	while (i < lengthLine) {
		if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) {
			styler.ColourTo(startLine + i - 1, state);
			state = SCE_MAKE_IDENTIFIER;
			varCount++;
		} else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
			if (--varCount == 0) {
				styler.ColourTo(startLine + i, state);
				state = SCE_MAKE_DEFAULT;
			}
		}

		// skip identifier and target styling if this is a command line
		if (!bSpecial && !bCommand) {
			if (lineBuffer[i] == ':') {
				if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
					// it's a ':=', so style as an identifier
					if (lastNonSpace >= 0)
						styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
					styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
					styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
				} else {
					// We should check that no colouring was made since the beginning of the line,
					// to avoid colouring stuff like /OUT:file
					if (lastNonSpace >= 0)
						styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
					styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
					styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
				}
				bSpecial = true;	// Only react to the first ':' of the line
				state = SCE_MAKE_DEFAULT;
			} else if (lineBuffer[i] == '=') {
				if (lastNonSpace >= 0)
					styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
				styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
				styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
				bSpecial = true;	// Only react to the first '=' of the line
				state = SCE_MAKE_DEFAULT;
			}
		}
		if (!isspacechar(lineBuffer[i])) {
			lastNonSpace = i;
		}
		i++;
	}
	if (state == SCE_MAKE_IDENTIFIER) {
		styler.ColourTo(endPos, SCE_MAKE_IDEOL);	// Error, variable reference not ended
	} else {
		styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
	}
}

static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	char lineBuffer[1024];
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	unsigned int startLine = startPos;
	for (unsigned int i = startPos; i < startPos + length; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
			linePos = 0;
			startLine = i + 1;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
	}
}

static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) {
	if (lineBuffer[0] == '>') {
		// Command or return status
		return SCE_ERR_CMD;
	} else if (lineBuffer[0] == '<') {
		// Diff removal.
		return SCE_ERR_DIFF_DELETION;
	} else if (lineBuffer[0] == '!') {
		return SCE_ERR_DIFF_CHANGED;
	} else if (lineBuffer[0] == '+') {
		if (strstart(lineBuffer, "+++ ")) {
			return SCE_ERR_DIFF_MESSAGE;
		} else {
			return SCE_ERR_DIFF_ADDITION;
		}
	} else if (lineBuffer[0] == '-') {
		if (strstart(lineBuffer, "--- ")) {
			return SCE_ERR_DIFF_MESSAGE;
		} else {
			return SCE_ERR_DIFF_DELETION;
		}
	} else if (strstart(lineBuffer, "cf90-")) {
		// Absoft Pro Fortran 90/95 v8.2 error and/or warning message
		return SCE_ERR_ABSF;
	} else if (strstart(lineBuffer, "fortcom:")) {
		// Intel Fortran Compiler v8.0 error/warning message
		return SCE_ERR_IFORT;
	} else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
		return SCE_ERR_PYTHON;
	} else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
		return SCE_ERR_PHP;
	} else if ((strstart(lineBuffer, "Error ") ||
	            strstart(lineBuffer, "Warning ")) &&
	           strstr(lineBuffer, " at (") &&
	           strstr(lineBuffer, ") : ") &&
	           (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
		// Intel Fortran Compiler error/warning message
		return SCE_ERR_IFC;
	} else if (strstart(lineBuffer, "Error ")) {
		// Borland error message
		return SCE_ERR_BORLAND;
	} else if (strstart(lineBuffer, "Warning ")) {
		// Borland warning message
		return SCE_ERR_BORLAND;
	} else if (strstr(lineBuffer, "at line ") &&
	        (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) &&
	           strstr(lineBuffer, "file ") &&
	           (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
		// Lua 4 error message
		return SCE_ERR_LUA;
	} else if (strstr(lineBuffer, " at ") &&
	        (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) &&
	           strstr(lineBuffer, " line ") &&
	           (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
	        (strstr(lineBuffer, " at ") < (strstr(lineBuffer, " line ")))) {
		// perl error message
		return SCE_ERR_PERL;
	} else if ((memcmp(lineBuffer, "   at ", 6) == 0) &&
	           strstr(lineBuffer, ":line ")) {
		// A .NET traceback
		return SCE_ERR_NET;
	} else if (strstart(lineBuffer, "Line ") &&
	           strstr(lineBuffer, ", file ")) {
		// Essential Lahey Fortran error message
		return SCE_ERR_ELF;
	} else if (strstart(lineBuffer, "line ") &&
	           strstr(lineBuffer, " column ")) {
		// HTML tidy style: line 42 column 1
		return SCE_ERR_TIDY;
	} else if (strstart(lineBuffer, "\tat ") &&
	           strstr(lineBuffer, "(") &&
	           strstr(lineBuffer, ".java:")) {
		// Java stack back trace
		return SCE_ERR_JAVA_STACK;
	} else if (strstart(lineBuffer, "In file included from ") ||
	           strstart(lineBuffer, "                 from ")) {
		// GCC showing include path to following error
		return SCE_ERR_GCC_INCLUDED_FROM;
	} else {
		// Look for one of the following formats:
		// GCC: <filename>:<line>:<message>
		// Microsoft: <filename>(<line>) :<message>
		// Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
		// Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
		// Microsoft: <filename>(<line>,<column>)<message>
		// CTags: \t<message>
		// Lua 5 traceback: \t<filename>:<line>:<message>
		// Lua 5.1: <exe>: <filename>:<line>:<message>
		bool initialTab = (lineBuffer[0] == '\t');
		bool initialColonPart = false;
		enum { stInitial,
			stGccStart, stGccDigit, stGccColumn, stGcc,
			stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
			stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags,
			stUnrecognized
		} state = stInitial;
		for (unsigned int i = 0; i < lengthLine; i++) {
			char ch = lineBuffer[i];
			char chNext = ' ';
			if ((i + 1) < lengthLine)
				chNext = lineBuffer[i + 1];
			if (state == stInitial) {
				if (ch == ':') {
					// May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
					if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) {
						// This check is not completely accurate as may be on
						// GTK+ with a file name that includes ':'.
						state = stGccStart;
					} else if (chNext == ' ') { // indicates a Lua 5.1 error message
						initialColonPart = true;
					}
				} else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
					// May be Microsoft
					// Check against '0' often removes phone numbers
					state = stMsStart;
				} else if ((ch == '\t') && (!initialTab)) {
					// May be CTags
					state = stCtagsStart;
				}
			} else if (state == stGccStart) {	// <filename>:
				state = Is1To9(ch) ? stGccDigit : stUnrecognized;
			} else if (state == stGccDigit) {	// <filename>:<line>
				if (ch == ':') {
					state = stGccColumn;	// :9.*: is GCC
					startValue = i + 1;
				} else if (!Is0To9(ch)) {
					state = stUnrecognized;
				}
			} else if (state == stGccColumn) {	// <filename>:<line>:<column>
				if (!Is0To9(ch)) {
					state = stGcc;
					if (ch == ':')
						startValue = i + 1;
					break;
				}
			} else if (state == stMsStart) {	// <filename>(
				state = Is0To9(ch) ? stMsDigit : stUnrecognized;
			} else if (state == stMsDigit) {	// <filename>(<line>
				if (ch == ',') {
					state = stMsDigitComma;
				} else if (ch == ')') {
					state = stMsBracket;
				} else if ((ch != ' ') && !Is0To9(ch)) {
					state = stUnrecognized;
				}
			} else if (state == stMsBracket) {	// <filename>(<line>)
				if ((ch == ' ') && (chNext == ':')) {
					state = stMsVc;
				} else if ((ch == ':' && chNext == ' ') || (ch == ' ')) {
					// Possibly Delphi.. don't test against chNext as it's one of the strings below.
					char word[512];
					unsigned int j, chPos;
					unsigned numstep;
					chPos = 0;
					if (ch == ' ')
						numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
					else
						numstep = 2; // otherwise add 2.
					for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
						word[chPos++] = lineBuffer[j];
					word[chPos] = 0;
					if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") ||
						!CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") ||
						!CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) {
						state = stMsVc;
					} else
						state = stUnrecognized;
				} else {
					state = stUnrecognized;
				}
			} else if (state == stMsDigitComma) {	// <filename>(<line>,
				if (ch == ')') {
					state = stMsDotNet;
					break;
				} else if ((ch != ' ') && !Is0To9(ch)) {
					state = stUnrecognized;
				}
			} else if (state == stCtagsStart) {
				if ((lineBuffer[i - 1] == '\t') &&
				        ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) {
					state = stCtags;
					break;
				} else if ((ch == '/') && (lineBuffer[i + 1] == '^')) {
					state = stCtagsStartString;
				}
			} else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
				state = stCtagsStringDollar;
				break;
			}
		}
		if (state == stGcc) {
			return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC;
		} else if ((state == stMsVc) || (state == stMsDotNet)) {
			return SCE_ERR_MS;
		} else if ((state == stCtagsStringDollar) || (state == stCtags)) {
			return SCE_ERR_CTAG;
		} else {
			return SCE_ERR_DEFAULT;
		}
	}
}

static void ColouriseErrorListLine(
    char *lineBuffer,
    unsigned int lengthLine,
    unsigned int endPos,
    Accessor &styler,
	bool valueSeparate) {
	int startValue = -1;
	int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue);
	if (valueSeparate && (startValue >= 0)) {
		styler.ColourTo(endPos - (lengthLine - startValue), style);
		styler.ColourTo(endPos, SCE_ERR_VALUE);
	} else {
		styler.ColourTo(endPos, style);
	}
}

static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	char lineBuffer[10000];
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;

	// property lexer.errorlist.value.separate
	//	For lines in the output pane that are matches from Find in Files or GCC-style
	//	diagnostics, style the path and line number separately from the rest of the
	//	line with style 21 used for the rest of the line.
	//	This allows matched text to be more easily distinguished from its location.
	bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
	for (unsigned int i = startPos; i < startPos + length; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate);
			linePos = 0;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate);
	}
}

static const char *const batchWordListDesc[] = {
	"Internal Commands",
	"External Commands",
	0
};

static const char *const emptyWordListDesc[] = {
	0
};

static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
                            Accessor &styler) {
	// Null language means all style bytes are 0 so just mark the end - no need to fill in.
	if (length > 0) {
		styler.StartAt(startPos + length - 1);
		styler.StartSegment(startPos + length - 1);
		styler.ColourTo(startPos + length - 1, 0);
	}
}

LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc);
LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");

Added lexers/LexPB.cxx.



























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
// Scintilla source code edit control
// @file LexPB.cxx
// Lexer for PowerBasic by Roland Walter, roland@rowalt.de (for PowerBasic see www.powerbasic.com)
//
// Changes:
// 17.10.2003: Toggling of subs/functions now until next sub/function - this gives better results
// 29.10.2003: 1. Bug: Toggling didn't work for subs/functions added in editor
//             2. Own colors for PB constants and Inline Assembler SCE_B_CONSTANT and SCE_B_ASM
//             3. Several smaller syntax coloring improvements and speed optimizations
// 12.07.2004: 1. Toggling for macros added
//             2. Further folding speed optimitations (for people dealing with very large listings)
//
// Necessary changes for the PB lexer in Scintilla project:
//  - In SciLexer.h and Scintilla.iface:
//
//    #define SCLEX_POWERBASIC 51       //ID for PowerBasic lexer
//    (...)
//    #define SCE_B_DEFAULT 0           //in both VB and PB lexer
//    #define SCE_B_COMMENT 1           //in both VB and PB lexer
//    #define SCE_B_NUMBER 2            //in both VB and PB lexer
//    #define SCE_B_KEYWORD 3           //in both VB and PB lexer
//    #define SCE_B_STRING 4            //in both VB and PB lexer
//    #define SCE_B_PREPROCESSOR 5      //VB lexer only, not in PB lexer
//    #define SCE_B_OPERATOR 6          //in both VB and PB lexer
//    #define SCE_B_IDENTIFIER 7        //in both VB and PB lexer
//    #define SCE_B_DATE 8              //VB lexer only, not in PB lexer
//    #define SCE_B_CONSTANT 13         //PB lexer only, not in VB lexer
//    #define SCE_B_ASM 14              //PB lexer only, not in VB lexer

//  - Statement added to KeyWords.cxx:      'LINK_LEXER(lmPB);'
//  - Statement added to scintilla_vc6.mak: '$(DIR_O)\LexPB.obj: ...\src\LexPB.cxx $(LEX_HEADERS)'
//
// Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsTypeCharacter(const int ch)
{
    return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$' || ch == '?';
}

static inline bool IsAWordChar(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch)
{
    return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

bool MatchUpperCase(Accessor &styler, int pos, const char *s)   //Same as styler.Match() but uppercase comparison (a-z,A-Z and space only)
{
    char ch;
    for (int i=0; *s; i++)
    {
        ch=styler.SafeGetCharAt(pos+i);
        if (ch > 0x60) ch -= '\x20';
        if (*s != ch) return false;
        s++;
    }
    return true;
}

static void ColourisePBDoc(unsigned int startPos, int length, int initStyle,WordList *keywordlists[],Accessor &styler) {

    WordList &keywords = *keywordlists[0];

    styler.StartAt(startPos);

    StyleContext sc(startPos, length, initStyle, styler);

    for (; sc.More(); sc.Forward()) {
        switch (sc.state)
        {
            case SCE_B_OPERATOR:
            {
                sc.SetState(SCE_B_DEFAULT);
                break;
            }
            case SCE_B_KEYWORD:
            {
                if (!IsAWordChar(sc.ch))
                {
                    if (!IsTypeCharacter(sc.ch))
                    {
                        char s[100];
                        sc.GetCurrentLowered(s, sizeof(s));
                        if (keywords.InList(s))
                        {
                            if (strcmp(s, "rem") == 0)
                            {
                                sc.ChangeState(SCE_B_COMMENT);
                                if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
                            }
                            else if (strcmp(s, "asm") == 0)
                            {
                                sc.ChangeState(SCE_B_ASM);
                                if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
                            }
                            else
                            {
                                sc.SetState(SCE_B_DEFAULT);
                            }
                        }
                        else
                        {
                            sc.ChangeState(SCE_B_IDENTIFIER);
                            sc.SetState(SCE_B_DEFAULT);
                        }
                    }
                }
                break;
            }
            case SCE_B_NUMBER:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);}
                break;
            }
            case SCE_B_STRING:
            {
                if (sc.ch == '\"'){sc.ForwardSetState(SCE_B_DEFAULT);}
                break;
            }
            case SCE_B_CONSTANT:
            {
                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_B_DEFAULT);}
                break;
            }
            case SCE_B_COMMENT:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
                break;
            }
            case SCE_B_ASM:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_B_DEFAULT);}
                break;
            }
        }  //switch (sc.state)

        // Determine if a new state should be entered:
        if (sc.state == SCE_B_DEFAULT)
        {
            if (sc.ch == '\'') {sc.SetState(SCE_B_COMMENT);}
            else if (sc.ch == '\"') {sc.SetState(SCE_B_STRING);}
            else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {sc.SetState(SCE_B_NUMBER);}
            else if (sc.ch == '&' && tolower(sc.chNext) == 'b') {sc.SetState(SCE_B_NUMBER);}
            else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {sc.SetState(SCE_B_NUMBER);}
            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_B_NUMBER);}
            else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_B_KEYWORD);}
            else if (sc.ch == '%') {sc.SetState(SCE_B_CONSTANT);}
            else if (sc.ch == '$') {sc.SetState(SCE_B_CONSTANT);}
            else if (sc.ch == '#') {sc.SetState(SCE_B_KEYWORD);}
            else if (sc.ch == '!') {sc.SetState(SCE_B_ASM);}
            else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {sc.SetState(SCE_B_OPERATOR);}
        }
    }      //for (; sc.More(); sc.Forward())
    sc.Complete();
}

//The folding routine for PowerBasic toggles SUBs and FUNCTIONs only. This was exactly what I wanted,
//nothing more. I had worked with this kind of toggling for several years when I used the great good old
//GFA Basic which is dead now. After testing the feature of toggling FOR-NEXT loops, WHILE-WEND loops
//and so on too I found this is more disturbing then helping (for me). So if You think in another way
//you can (or must) write Your own toggling routine ;-)
static void FoldPBDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
    // No folding enabled, no reason to continue...
    if( styler.GetPropertyInt("fold") == 0 )
        return;

    unsigned int endPos = startPos + length;
    int lineCurrent = styler.GetLine(startPos);
    int levelCurrent = SC_FOLDLEVELBASE;
    if (lineCurrent > 0)
        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
    int levelNext = levelCurrent;
    char chNext = styler[startPos];

    bool fNewLine=true;
    bool fMightBeMultiLineMacro=false;
    bool fBeginOfCommentFound=false;
    for (unsigned int i = startPos; i < endPos; i++)
    {
        char ch = chNext;
        chNext = styler.SafeGetCharAt(i + 1);

        if (fNewLine)            //Begin of a new line (The Sub/Function/Macro keywords may occur at begin of line only)
        {
            fNewLine=false;
            fBeginOfCommentFound=false;
            switch (ch)
            {
            case ' ':      //Most lines start with space - so check this first, the code is the same as for 'default:'
            case '\t':     //Handle tab too
                {
                    int levelUse = levelCurrent;
                    int lev = levelUse | levelNext << 16;
                    styler.SetLevel(lineCurrent, lev);
                    break;
                }
            case 'F':
            case 'f':
                {
					switch (chNext)
					{
                    case 'U':
                    case 'u':
						{
							if( MatchUpperCase(styler,i,"FUNCTION") )
							{
								styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
								levelNext=SC_FOLDLEVELBASE+1;
							}
							break;
						}
					}
                break;
                }
            case 'S':
            case 's':
                {
					switch (chNext)
					{
                    case 'U':
                    case 'u':
						{
							if( MatchUpperCase(styler,i,"SUB") )
							{
								styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
								levelNext=SC_FOLDLEVELBASE+1;
							}
							break;
						}
                    case 'T':
                    case 't':
						{
							if( MatchUpperCase(styler,i,"STATIC FUNCTION") )
							{
								styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
								levelNext=SC_FOLDLEVELBASE+1;
							}
							else if( MatchUpperCase(styler,i,"STATIC SUB") )
							{
								styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
								levelNext=SC_FOLDLEVELBASE+1;
							}
							break;
						}
					}
                break;
                }
            case 'C':
            case 'c':
                {
					switch (chNext)
					{
                    case 'A':
                    case 'a':
						{
							if( MatchUpperCase(styler,i,"CALLBACK FUNCTION") )
							{
								styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
								levelNext=SC_FOLDLEVELBASE+1;
							}
							break;
						}
					}
                break;
                }
            case 'M':
            case 'm':
                {
					switch (chNext)
					{
                    case 'A':
                    case 'a':
						{
							if( MatchUpperCase(styler,i,"MACRO") )
							{
								fMightBeMultiLineMacro=true;  //Set folder level at end of line, we have to check for single line macro
							}
							break;
						}
					}
                break;
                }
            default:
                {
                    int levelUse = levelCurrent;
                    int lev = levelUse | levelNext << 16;
                    styler.SetLevel(lineCurrent, lev);
                    break;
                }
            }  //switch (ch)
        }  //if( fNewLine )

        switch (ch)
        {
            case '=':                              //To test single line macros
            {
                if (fBeginOfCommentFound==false)
                    fMightBeMultiLineMacro=false;  //The found macro is a single line macro only;
                break;
            }
            case '\'':                             //A comment starts
            {
                fBeginOfCommentFound=true;
                break;
            }
            case '\n':
            {
                if (fMightBeMultiLineMacro)        //The current line is the begin of a multi line macro
                {
                    fMightBeMultiLineMacro=false;
                    styler.SetLevel(lineCurrent, (SC_FOLDLEVELBASE << 16) | SC_FOLDLEVELHEADERFLAG);
                    levelNext=SC_FOLDLEVELBASE+1;
                }
                lineCurrent++;
                levelCurrent = levelNext;
                fNewLine=true;
                break;
            }
            case '\r':
            {
                if (chNext != '\n')
                {
                    lineCurrent++;
                    levelCurrent = levelNext;
                    fNewLine=true;
                }
                break;
            }
        }  //switch (ch)
    }  //for (unsigned int i = startPos; i < endPos; i++)
}

static const char * const pbWordListDesc[] = {
    "Keywords",
    0
};

LexerModule lmPB(SCLEX_POWERBASIC, ColourisePBDoc, "powerbasic", FoldPBDoc, pbWordListDesc);

Added lexers/LexPLM.cxx.



















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Copyright (c) 1990-2007, Scientific Toolworks, Inc.
// Author: Jason Haslam
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void GetRange(unsigned int start,
                     unsigned int end,
                     Accessor &styler,
                     char *s,
                     unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

static void ColourisePlmDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler)
{
	unsigned int endPos = startPos + length;
	int state = initStyle;

	styler.StartAt(startPos);
	styler.StartSegment(startPos);

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = styler.SafeGetCharAt(i);
		char chNext = styler.SafeGetCharAt(i + 1);

		if (state == SCE_PLM_DEFAULT) {
			if (ch == '/' && chNext == '*') {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_COMMENT;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_STRING;
			} else if (isdigit(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_NUMBER;
			} else if (isalpha(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_IDENTIFIER;
			} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
			           ch == '=' || ch == '<' || ch == '>' || ch == ':') {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_OPERATOR;
			} else if (ch == '$') {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_CONTROL;
			}
		} else if (state == SCE_PLM_COMMENT) {
			if (ch == '*' && chNext == '/') {
				i++;
				styler.ColourTo(i, state);
				state = SCE_PLM_DEFAULT;
			}
		} else if (state == SCE_PLM_STRING) {
			if (ch == '\'') {
				if (chNext == '\'') {
					i++;
				} else {
					styler.ColourTo(i, state);
					state = SCE_PLM_DEFAULT;
				}
			}
		} else if (state == SCE_PLM_NUMBER) {
			if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
				i--;
				styler.ColourTo(i, state);
				state = SCE_PLM_DEFAULT;
			}
		} else if (state == SCE_PLM_IDENTIFIER) {
			if (!isdigit(ch) && !isalpha(ch) && ch != '$') {
				// Get the entire identifier.
				char word[1024];
				int segmentStart = styler.GetStartSegment();
				GetRange(segmentStart, i - 1, styler, word, sizeof(word));

				i--;
				if (keywordlists[0]->InList(word))
					styler.ColourTo(i, SCE_PLM_KEYWORD);
				else
					styler.ColourTo(i, state);
				state = SCE_PLM_DEFAULT;
			}
		} else if (state == SCE_PLM_OPERATOR) {
			if (ch != '=' && ch != '>') {
				i--;
				styler.ColourTo(i, state);
				state = SCE_PLM_DEFAULT;
			}
		} else if (state == SCE_PLM_CONTROL) {
			if (ch == '\r' || ch == '\n') {
				styler.ColourTo(i - 1, state);
				state = SCE_PLM_DEFAULT;
			}
		}
	}
	styler.ColourTo(endPos - 1, state);
}

static void FoldPlmDoc(unsigned int startPos,
                       int length,
                       int initStyle,
                       WordList *[],
                       Accessor &styler)
{
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	int startKeyword = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev != SCE_PLM_KEYWORD && style == SCE_PLM_KEYWORD)
			startKeyword = i;

		if (style == SCE_PLM_KEYWORD && styleNext != SCE_PLM_KEYWORD) {
			char word[1024];
			GetRange(startKeyword, i, styler, word, sizeof(word));

			if (strcmp(word, "procedure") == 0 || strcmp(word, "do") == 0)
				levelCurrent++;
			else if (strcmp(word, "end") == 0)
				levelCurrent--;
		}

		if (foldComment) {
			if (stylePrev != SCE_PLM_COMMENT && style == SCE_PLM_COMMENT)
				levelCurrent++;
			else if (stylePrev == SCE_PLM_COMMENT && style != SCE_PLM_COMMENT)
				levelCurrent--;
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char *const plmWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmPLM(SCLEX_PLM, ColourisePlmDoc, "PL/M", FoldPlmDoc, plmWordListDesc);

Added lexers/LexPO.cxx.











































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexPO.cxx
 ** Lexer for GetText Translation (PO) files.
 **/
// Copyright 2012 by Colomban Wendling <ban@herbesfolles.org>
// The License.txt file describes the conditions under which this software may be distributed.

// see https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files for the syntax reference
// some details are taken from the GNU msgfmt behavior (like that indent is allows in front of lines)

// TODO:
// * add keywords for flags (fuzzy, c-format, ...)
// * highlight formats inside c-format strings (%s, %d, etc.)
// * style for previous untranslated string? ("#|" comment)

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColourisePODoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) {
	StyleContext sc(startPos, length, initStyle, styler);
	bool escaped = false;
	int curLine = styler.GetLine(startPos);
	// the line state holds the last state on or before the line that isn't the default style
	int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : SCE_PO_DEFAULT;
	
	for (; sc.More(); sc.Forward()) {
		// whether we should leave a state
		switch (sc.state) {
			case SCE_PO_COMMENT:
			case SCE_PO_PROGRAMMER_COMMENT:
			case SCE_PO_REFERENCE:
			case SCE_PO_FLAGS:
			case SCE_PO_FUZZY:
				if (sc.atLineEnd)
					sc.SetState(SCE_PO_DEFAULT);
				else if (sc.state == SCE_PO_FLAGS && sc.Match("fuzzy"))
					// here we behave like the previous parser, but this should probably be highlighted
					// on its own like a keyword rather than changing the whole flags style
					sc.ChangeState(SCE_PO_FUZZY);
				break;
			
			case SCE_PO_MSGCTXT:
			case SCE_PO_MSGID:
			case SCE_PO_MSGSTR:
				if (isspacechar(sc.ch))
					sc.SetState(SCE_PO_DEFAULT);
				break;
			
			case SCE_PO_ERROR:
				if (sc.atLineEnd)
					sc.SetState(SCE_PO_DEFAULT);
				break;
			
			case SCE_PO_MSGCTXT_TEXT:
			case SCE_PO_MSGID_TEXT:
			case SCE_PO_MSGSTR_TEXT:
				if (sc.atLineEnd) { // invalid inside a string
					if (sc.state == SCE_PO_MSGCTXT_TEXT)
						sc.ChangeState(SCE_PO_MSGCTXT_TEXT_EOL);
					else if (sc.state == SCE_PO_MSGID_TEXT)
						sc.ChangeState(SCE_PO_MSGID_TEXT_EOL);
					else if (sc.state == SCE_PO_MSGSTR_TEXT)
						sc.ChangeState(SCE_PO_MSGSTR_TEXT_EOL);
					sc.SetState(SCE_PO_DEFAULT);
					escaped = false;
				} else {
					if (escaped)
						escaped = false;
					else if (sc.ch == '\\')
						escaped = true;
					else if (sc.ch == '"')
						sc.ForwardSetState(SCE_PO_DEFAULT);
				}
				break;
		}
		
		// whether we should enter a new state
		if (sc.state == SCE_PO_DEFAULT) {
			// forward to the first non-white character on the line
			bool atLineStart = sc.atLineStart;
			if (atLineStart) {
				// reset line state if it is set to comment state so empty lines don't get
				// comment line state, and the folding code folds comments separately,
				// and anyway the styling don't use line state for comments
				if (curLineState == SCE_PO_COMMENT)
					curLineState = SCE_PO_DEFAULT;
				
				while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch))
					sc.Forward();
			}
			
			if (atLineStart && sc.ch == '#') {
				if (sc.chNext == '.')
					sc.SetState(SCE_PO_PROGRAMMER_COMMENT);
				else if (sc.chNext == ':')
					sc.SetState(SCE_PO_REFERENCE);
				else if (sc.chNext == ',')
					sc.SetState(SCE_PO_FLAGS);
				else
					sc.SetState(SCE_PO_COMMENT);
			} else if (atLineStart && sc.Match("msgid")) { // includes msgid_plural
				sc.SetState(SCE_PO_MSGID);
			} else if (atLineStart && sc.Match("msgstr")) { // includes [] suffixes
				sc.SetState(SCE_PO_MSGSTR);
			} else if (atLineStart && sc.Match("msgctxt")) {
				sc.SetState(SCE_PO_MSGCTXT);
			} else if (sc.ch == '"') {
				if (curLineState == SCE_PO_MSGCTXT || curLineState == SCE_PO_MSGCTXT_TEXT)
					sc.SetState(SCE_PO_MSGCTXT_TEXT);
				else if (curLineState == SCE_PO_MSGID || curLineState == SCE_PO_MSGID_TEXT)
					sc.SetState(SCE_PO_MSGID_TEXT);
				else if (curLineState == SCE_PO_MSGSTR || curLineState == SCE_PO_MSGSTR_TEXT)
					sc.SetState(SCE_PO_MSGSTR_TEXT);
				else
					sc.SetState(SCE_PO_ERROR);
			} else if (! isspacechar(sc.ch))
				sc.SetState(SCE_PO_ERROR);
			
			if (sc.state != SCE_PO_DEFAULT)
				curLineState = sc.state;
		}
		
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			curLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(curLine, curLineState);
		}
	}
	sc.Complete();
}

static int FindNextNonEmptyLineState(unsigned int startPos, Accessor &styler) {
	unsigned int length = styler.Length();
	for (unsigned int i = startPos; i < length; i++) {
		if (! isspacechar(styler[i])) {
			return styler.GetLineState(styler.GetLine(i));
		}
	}
	return 0;
}

static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	if (! styler.GetPropertyInt("fold"))
		return;
	bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	
	unsigned int endPos = startPos + length;
	int curLine = styler.GetLine(startPos);
	int lineState = styler.GetLineState(curLine);
	int nextLineState;
	int level = styler.LevelAt(curLine) & SC_FOLDLEVELNUMBERMASK;
	int nextLevel;
	int visible = 0;
	int chNext = styler[startPos];
	
	for (unsigned int i = startPos; i < endPos; i++) {
		int ch = chNext;
		chNext = styler.SafeGetCharAt(i+1);
		
		if (! isspacechar(ch)) {
			visible++;
		} else if ((ch == '\r' && chNext != '\n') || ch == '\n' || i+1 >= endPos) {
			int lvl = level;
			int nextLine = curLine + 1;
			
			nextLineState = styler.GetLineState(nextLine);
			if ((lineState != SCE_PO_COMMENT || foldComment) &&
					nextLineState == lineState &&
					FindNextNonEmptyLineState(i, styler) == lineState)
				nextLevel = SC_FOLDLEVELBASE + 1;
			else
				nextLevel = SC_FOLDLEVELBASE;
			
			if (nextLevel > level)
				lvl |= SC_FOLDLEVELHEADERFLAG;
			if (visible == 0 && foldCompact)
				lvl |= SC_FOLDLEVELWHITEFLAG;
			
			styler.SetLevel(curLine, lvl);
			
			lineState = nextLineState;
			curLine = nextLine;
			level = nextLevel;
			visible = 0;
		}
	}
}

static const char *const poWordListDesc[] = {
	0
};

LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", FoldPODoc, poWordListDesc);

Added lexers/LexPOV.cxx.































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
// Scintilla source code edit control
/** @file LexPOV.cxx
 ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language).
 ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...
 **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// Some points that distinguish from a simple C lexer:
// Identifiers start only by a character.
// No line continuation character.
// Strings are limited to 256 characters.
// Directives are similar to preprocessor commands,
// but we match directive keywords and colorize incorrect ones.
// Block comments can be nested (code stolen from my code in LexLua).

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch) {
	return ch < 0x80 && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch < 0x80 && isalpha(ch);
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
             ch == '.' || ch == '-' || ch == '+');
}

static void ColourisePovDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
    Accessor &styler) {

	WordList &keywords1 = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize the block comment /* */ nesting level, if we are inside such a comment.
	int blockCommentLevel = 0;
	if (initStyle == SCE_POV_COMMENT) {
		blockCommentLevel = styler.GetLineState(currentLine - 1);
	}

	// Do not leak onto next line
	if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) {
		initStyle = SCE_POV_DEFAULT;
	}

	short stringLen = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			if (sc.state == SCE_POV_COMMENT) {
				// Inside a block comment, we set the line state
				styler.SetLineState(currentLine, blockCommentLevel);
			} else {
				// Reset the line state
				styler.SetLineState(currentLine, 0);
			}
		}

		if (sc.atLineStart && (sc.state == SCE_POV_STRING)) {
			// Prevent SCE_POV_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_POV_STRING);
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_POV_OPERATOR) {
			sc.SetState(SCE_POV_DEFAULT);
		} else if (sc.state == SCE_POV_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords2.InList(s)) {
					sc.ChangeState(SCE_POV_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_POV_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_POV_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_POV_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_POV_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_POV_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_POV_WORD8);
				}
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_DIRECTIVE) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				char *p;
				sc.GetCurrent(s, sizeof(s));
				p = s;
				// Skip # and whitespace between # and directive word
				do {
					p++;
				} while ((*p == ' ' || *p == '\t') && *p != '\0');
				if (!keywords1.InList(p)) {
					sc.ChangeState(SCE_POV_BADDIRECTIVE);
				}
				sc.SetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_COMMENT) {
			if (sc.Match('/', '*')) {
				blockCommentLevel++;
				sc.Forward();
			} else if (sc.Match('*', '/') && blockCommentLevel > 0) {
				blockCommentLevel--;
				sc.Forward();
				if (blockCommentLevel == 0) {
					sc.ForwardSetState(SCE_POV_DEFAULT);
				}
			}
		} else if (sc.state == SCE_POV_COMMENTLINE) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		} else if (sc.state == SCE_POV_STRING) {
			if (sc.ch == '\\') {
				stringLen++;
				if (strchr("abfnrtuv0'\"", sc.chNext)) {
					// Compound characters are counted as one.
					// Note: for Unicode chars \u, we shouldn't count the next 4 digits...
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_POV_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_POV_STRINGEOL);
				sc.ForwardSetState(SCE_POV_DEFAULT);
			} else {
				stringLen++;
			}
			if (stringLen > 256) {
				// Strings are limited to 256 chars
				sc.SetState(SCE_POV_STRINGEOL);
			}
		} else if (sc.state == SCE_POV_STRINGEOL) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_POV_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_POV_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_POV_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_POV_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
				blockCommentLevel = 1;
				sc.SetState(SCE_POV_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_POV_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_POV_STRING);
				stringLen = 0;
			} else if (sc.ch == '#') {
				sc.SetState(SCE_POV_DIRECTIVE);
				// Skip whitespace between # and directive word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_POV_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_POV_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldPovDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *[],
	Accessor &styler) {

	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldDirective = styler.GetPropertyInt("fold.directive") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && (style == SCE_POV_COMMENT)) {
			if (stylePrev != SCE_POV_COMMENT) {
				levelCurrent++;
			} else if ((styleNext != SCE_POV_COMMENT) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (foldComment && (style == SCE_POV_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelCurrent++;
				} else if (chNext2 == '}') {
					levelCurrent--;
				}
			}
		}
		if (foldDirective && (style == SCE_POV_DIRECTIVE)) {
			if (ch == '#') {
				unsigned int j=i+1;
				while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
			}
		}
		if (style == SCE_POV_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const povWordLists[] = {
	"Language directives",
	"Objects & CSG & Appearance",
	"Types & Modifiers & Items",
	"Predefined Identifiers",
	"Predefined Functions",
	"User defined 1",
	"User defined 2",
	"User defined 3",
	0,
};

LexerModule lmPOV(SCLEX_POV, ColourisePovDoc, "pov", FoldPovDoc, povWordLists);

Added lexers/LexPS.cxx.





























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// Scintilla source code edit control
/** @file LexPS.cxx
 ** Lexer for PostScript
 **
 ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
 ** The License.txt file describes the conditions under which this software may be distributed.
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsASelfDelimitingChar(const int ch) {
    return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||
            ch == '/' || ch == '<' || ch == '>' ||
            ch == '(' || ch == ')' || ch == '%');
}

static inline bool IsAWhitespaceChar(const int ch) {
    return (ch == ' '  || ch == '\t' || ch == '\r' ||
            ch == '\n' || ch == '\f' || ch == '\0');
}

static bool IsABaseNDigit(const int ch, const int base) {
    int maxdig = '9';
    int letterext = -1;

    if (base <= 10)
        maxdig = '0' + base - 1;
    else
        letterext = base - 11;

    return ((ch >= '0' && ch <= maxdig) ||
            (ch >= 'A' && ch <= ('A' + letterext)) ||
            (ch >= 'a' && ch <= ('a' + letterext)));
}

static inline bool IsABase85Char(const int ch) {
    return ((ch >= '!' && ch <= 'u') || ch == 'z');
}

static void ColourisePSDoc(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler) {

    WordList &keywords1 = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    WordList &keywords4 = *keywordlists[3];
    WordList &keywords5 = *keywordlists[4];

    StyleContext sc(startPos, length, initStyle, styler);

    bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0;
    int pslevel = styler.GetPropertyInt("ps.level", 3);
    int lineCurrent = styler.GetLine(startPos);
    int nestTextCurrent = 0;
    if (lineCurrent > 0 && initStyle == SCE_PS_TEXT)
        nestTextCurrent = styler.GetLineState(lineCurrent - 1);
    int numRadix = 0;
    bool numHasPoint = false;
    bool numHasExponent = false;
    bool numHasSign = false;

    // Clear out existing tokenization
    if (tokenizing && length > 0) {
        styler.StartAt(startPos, static_cast<char>(INDIC2_MASK));
        styler.ColourTo(startPos + length-1, 0);
        styler.Flush();
        styler.StartAt(startPos);
        styler.StartSegment(startPos);
    }

    for (; sc.More(); sc.Forward()) {
        if (sc.atLineStart)
            lineCurrent = styler.GetLine(sc.currentPos);

        // Determine if the current state should terminate.
        if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) {
            if (sc.atLineEnd) {
                sc.SetState(SCE_C_DEFAULT);
            }
        } else if (sc.state == SCE_PS_DSC_COMMENT) {
            if (sc.ch == ':') {
                sc.Forward();
                if (!sc.atLineEnd)
                    sc.SetState(SCE_PS_DSC_VALUE);
                else
                    sc.SetState(SCE_C_DEFAULT);
            } else if (sc.atLineEnd) {
                sc.SetState(SCE_C_DEFAULT);
            } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') {
                sc.ChangeState(SCE_PS_COMMENT);
            }
        } else if (sc.state == SCE_PS_NUMBER) {
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
                if ((sc.chPrev == '+' || sc.chPrev == '-' ||
                     sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0)
                    sc.ChangeState(SCE_PS_NAME);
                sc.SetState(SCE_C_DEFAULT);
            } else if (sc.ch == '#') {
                if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) {
                    sc.ChangeState(SCE_PS_NAME);
                } else {
                    char szradix[5];
                    sc.GetCurrent(szradix, 4);
                    numRadix = atoi(szradix);
                    if (numRadix < 2 || numRadix > 36)
                        sc.ChangeState(SCE_PS_NAME);
                }
            } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) {
                if (numHasExponent) {
                    sc.ChangeState(SCE_PS_NAME);
                } else {
                    numHasExponent = true;
                    if (sc.chNext == '+' || sc.chNext == '-')
                        sc.Forward();
                }
            } else if (sc.ch == '.') {
                if (numHasPoint || numHasExponent || numRadix != 0) {
                    sc.ChangeState(SCE_PS_NAME);
                } else {
                    numHasPoint = true;
                }
            } else if (numRadix == 0) {
                if (!IsABaseNDigit(sc.ch, 10))
                    sc.ChangeState(SCE_PS_NAME);
            } else {
                if (!IsABaseNDigit(sc.ch, numRadix))
                    sc.ChangeState(SCE_PS_NAME);
            }
        } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) {
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
                char s[100];
                sc.GetCurrent(s, sizeof(s));
                if ((pslevel >= 1 && keywords1.InList(s)) ||
                    (pslevel >= 2 && keywords2.InList(s)) ||
                    (pslevel >= 3 && keywords3.InList(s)) ||
                    keywords4.InList(s) || keywords5.InList(s)) {
                    sc.ChangeState(SCE_PS_KEYWORD);
                }
                sc.SetState(SCE_C_DEFAULT);
            }
        } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) {
            if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch))
                sc.SetState(SCE_C_DEFAULT);
        } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT ||
                   sc.state == SCE_PS_PAREN_PROC) {
            sc.SetState(SCE_C_DEFAULT);
        } else if (sc.state == SCE_PS_TEXT) {
            if (sc.ch == '(') {
                nestTextCurrent++;
            } else if (sc.ch == ')') {
                if (--nestTextCurrent == 0)
                   sc.ForwardSetState(SCE_PS_DEFAULT);
            } else if (sc.ch == '\\') {
                sc.Forward();
            }
        } else if (sc.state == SCE_PS_HEXSTRING) {
            if (sc.ch == '>') {
                sc.ForwardSetState(SCE_PS_DEFAULT);
            } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) {
                sc.SetState(SCE_PS_HEXSTRING);
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
            }
        } else if (sc.state == SCE_PS_BASE85STRING) {
            if (sc.Match('~', '>')) {
                sc.Forward();
                sc.ForwardSetState(SCE_PS_DEFAULT);
            } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) {
                sc.SetState(SCE_PS_BASE85STRING);
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
            }
        }

        // Determine if a new state should be entered.
        if (sc.state == SCE_C_DEFAULT) {
            unsigned int tokenpos = sc.currentPos;

            if (sc.ch == '[' || sc.ch == ']') {
                sc.SetState(SCE_PS_PAREN_ARRAY);
            } else if (sc.ch == '{' || sc.ch == '}') {
                sc.SetState(SCE_PS_PAREN_PROC);
            } else if (sc.ch == '/') {
                if (sc.chNext == '/') {
                    sc.SetState(SCE_PS_IMMEVAL);
                    sc.Forward();
                } else {
                    sc.SetState(SCE_PS_LITERAL);
                }
            } else if (sc.ch == '<') {
                if (sc.chNext == '<') {
                    sc.SetState(SCE_PS_PAREN_DICT);
                    sc.Forward();
                } else if (sc.chNext == '~') {
                    sc.SetState(SCE_PS_BASE85STRING);
                    sc.Forward();
                } else {
                    sc.SetState(SCE_PS_HEXSTRING);
                }
            } else if (sc.ch == '>' && sc.chNext == '>') {
                    sc.SetState(SCE_PS_PAREN_DICT);
                    sc.Forward();
            } else if (sc.ch == '>' || sc.ch == ')') {
                sc.SetState(SCE_C_DEFAULT);
                styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
            } else if (sc.ch == '(') {
                sc.SetState(SCE_PS_TEXT);
                nestTextCurrent = 1;
            } else if (sc.ch == '%') {
                if (sc.chNext == '%' && sc.atLineStart) {
                    sc.SetState(SCE_PS_DSC_COMMENT);
                    sc.Forward();
                    if (sc.chNext == '+') {
                        sc.Forward();
                        sc.ForwardSetState(SCE_PS_DSC_VALUE);
                    }
                } else {
                    sc.SetState(SCE_PS_COMMENT);
                }
            } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') &&
                       IsABaseNDigit(sc.chNext, 10)) {
                sc.SetState(SCE_PS_NUMBER);
                numRadix = 0;
                numHasPoint = (sc.ch == '.');
                numHasExponent = false;
                numHasSign = (sc.ch == '+' || sc.ch == '-');
            } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' &&
                       IsABaseNDigit(sc.GetRelative(2), 10)) {
                sc.SetState(SCE_PS_NUMBER);
                numRadix = 0;
                numHasPoint = false;
                numHasExponent = false;
                numHasSign = true;
            } else if (IsABaseNDigit(sc.ch, 10)) {
                sc.SetState(SCE_PS_NUMBER);
                numRadix = 0;
                numHasPoint = false;
                numHasExponent = false;
                numHasSign = false;
            } else if (!IsAWhitespaceChar(sc.ch)) {
                sc.SetState(SCE_PS_NAME);
            }

            // Mark the start of tokens
            if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT &&
                sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) {
                styler.Flush();
                styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK));
                styler.ColourTo(tokenpos, INDIC2_MASK);
                styler.Flush();
                styler.StartAt(tokenpos);
                styler.StartSegment(tokenpos);
            }
        }

        if (sc.atLineEnd)
            styler.SetLineState(lineCurrent, nestTextCurrent);
    }

    sc.Complete();
}

static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[],
                       Accessor &styler) {
    bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
    bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
    unsigned int endPos = startPos + length;
    int visibleChars = 0;
    int lineCurrent = styler.GetLine(startPos);
    int levelCurrent = SC_FOLDLEVELBASE;
    if (lineCurrent > 0)
        levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
    int levelMinCurrent = levelCurrent;
    int levelNext = levelCurrent;
    char chNext = styler[startPos];
    int styleNext = styler.StyleAt(startPos);
    int style;
    for (unsigned int i = startPos; i < endPos; i++) {
        char ch = chNext;
        chNext = styler.SafeGetCharAt(i + 1);
        style = styleNext;
        styleNext = styler.StyleAt(i + 1);
        bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');  //mac??
        if ((style & 31) == SCE_PS_PAREN_PROC) {
            if (ch == '{') {
                // Measure the minimum before a '{' to allow
                // folding on "} {"
                if (levelMinCurrent > levelNext) {
                    levelMinCurrent = levelNext;
                }
                levelNext++;
            } else if (ch == '}') {
                levelNext--;
            }
        }
        if (atEOL) {
            int levelUse = levelCurrent;
            if (foldAtElse) {
                levelUse = levelMinCurrent;
            }
            int lev = levelUse | levelNext << 16;
            if (visibleChars == 0 && foldCompact)
                lev |= SC_FOLDLEVELWHITEFLAG;
            if (levelUse < levelNext)
                lev |= SC_FOLDLEVELHEADERFLAG;
            if (lev != styler.LevelAt(lineCurrent)) {
                styler.SetLevel(lineCurrent, lev);
            }
            lineCurrent++;
            levelCurrent = levelNext;
            levelMinCurrent = levelCurrent;
            visibleChars = 0;
        }
        if (!isspacechar(ch))
            visibleChars++;
    }
}

static const char * const psWordListDesc[] = {
    "PS Level 1 operators",
    "PS Level 2 operators",
    "PS Level 3 operators",
    "RIP-specific operators",
    "User-defined operators",
    0
};

LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc);

Added lexers/LexPascal.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
// Scintilla source code edit control
/** @file LexPascal.cxx
 ** Lexer for Pascal.
 ** Written by Laurent le Tynevez
 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
 ** Completely rewritten by Marko Njezic <sf@maxempire.com> October 2008
 **/

/*

A few words about features of the new completely rewritten LexPascal...

Generally speaking LexPascal tries to support all available Delphi features (up
to Delphi 2009 at this time), including .NET specific features.

~ HIGHLIGHTING:

If you enable "lexer.pascal.smart.highlighting" property, some keywords will
only be highlighted in appropriate context. As implemented those are keywords
related to property and DLL exports declarations (similar to how Delphi IDE
works).

For example, keywords "read" and "write" will only be highlighted if they are in
property declaration:

property MyProperty: boolean read FMyProperty write FMyProperty;

~ FOLDING:

Folding is supported in the following cases:

- Folding of stream-like comments
- Folding of groups of consecutive line comments
- Folding of preprocessor blocks (the following preprocessor blocks are
supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION
blocks), including nesting of preprocessor blocks up to 255 levels
- Folding of code blocks on appropriate keywords (the following code blocks are
supported: "begin, asm, record, try, case / end" blocks, class & object
declarations and interface declarations)

Remarks:

- Folding of code blocks tries to handle all special cases in which folding
should not occur. As implemented those are:

1. Structure "record case / end" (there's only one "end" statement and "case" is
ignored as fold point)
2. Forward class declarations ("type TMyClass = class;") and object method
declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are
ignored as fold points
3. Simplified complete class declarations ("type TMyClass = class(TObject);")
are ignored as fold points
4. Every other situation when class keyword doesn't actually start class
declaration ("class procedure", "class function", "class of", "class var",
"class property" and "class operator")
5. Forward (disp)interface declarations ("type IMyInterface = interface;") are
ignored as fold points

- Folding of code blocks inside preprocessor blocks is disabled (any comments
inside them will be folded fine) because there is no guarantee that complete
code block will be contained inside folded preprocessor block in which case
folded code block could end prematurely at the end of preprocessor block if
there is no closing statement inside. This was done in order to properly process
document that may contain something like this:

type
{$IFDEF UNICODE}
  TMyClass = class(UnicodeAncestor)
{$ELSE}
  TMyClass = class(AnsiAncestor)
{$ENDIF}
  private
  ...
  public
  ...
  published
  ...
end;

If class declarations were folded, then the second class declaration would end
at "$ENDIF" statement, first class statement would end at "end;" statement and
preprocessor "$IFDEF" block would go all the way to the end of document.
However, having in mind all this, if you want to enable folding of code blocks
inside preprocessor blocks, you can disable folding of preprocessor blocks by
changing "fold.preprocessor" property, in which case everything inside them
would be folded.

~ KEYWORDS:

The list of keywords that can be used in pascal.properties file (up to Delphi
2009):

- Keywords: absolute abstract and array as asm assembler automated begin case
cdecl class const constructor deprecated destructor dispid dispinterface div do
downto dynamic else end except export exports external far file final
finalization finally for forward function goto if implementation in inherited
initialization inline interface is label library message mod near nil not object
of on or out overload override packed pascal platform private procedure program
property protected public published raise record register reintroduce repeat
resourcestring safecall sealed set shl shr static stdcall strict string then
threadvar to try type unit unsafe until uses var varargs virtual while with xor

- Keywords related to the "smart highlithing" feature: add default implements
index name nodefault read readonly remove stored write writeonly

- Keywords related to Delphi packages (in addition to all above): package
contains requires

*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void GetRangeLowered(unsigned int start,
		unsigned int end,
		Accessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

static void GetForwardRangeLowered(unsigned int start,
		CharacterSet &charSet,
		Accessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) {
		s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
		i++;
	}
	s[i] = '\0';

}

enum {
	stateInAsm = 0x1000,
	stateInProperty = 0x2000,
	stateInExport = 0x4000,
	stateFoldInPreprocessor = 0x0100,
	stateFoldInRecord = 0x0200,
	stateFoldInPreprocessorLevelMask = 0x00FF,
	stateFoldMaskAll = 0x0FFF
};

static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) {
	WordList& keywords = *keywordlists[0];

	char s[100];
	sc.GetCurrentLowered(s, sizeof(s));
	if (keywords.InList(s)) {
		if (curLineState & stateInAsm) {
			if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') {
				curLineState &= ~stateInAsm;
				sc.ChangeState(SCE_PAS_WORD);
			} else {
				sc.ChangeState(SCE_PAS_ASM);
			}
		} else {
			bool ignoreKeyword = false;
			if (strcmp(s, "asm") == 0) {
				curLineState |= stateInAsm;
			} else if (bSmartHighlighting) {
				if (strcmp(s, "property") == 0) {
					curLineState |= stateInProperty;
				} else if (strcmp(s, "exports") == 0) {
					curLineState |= stateInExport;
				} else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) {
					ignoreKeyword = true;
				} else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) {
					ignoreKeyword = true;
				} else if (!(curLineState & stateInProperty) &&
					(strcmp(s, "read") == 0 || strcmp(s, "write") == 0 ||
					 strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 ||
					 strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 ||
					 strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 ||
					 strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) {
					ignoreKeyword = true;
				}
			}
			if (!ignoreKeyword) {
				sc.ChangeState(SCE_PAS_WORD);
			}
		}
	} else if (curLineState & stateInAsm) {
		sc.ChangeState(SCE_PAS_ASM);
	}
	sc.SetState(SCE_PAS_DEFAULT);
}

static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
		Accessor &styler) {
	bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0;

	CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
	CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
	CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
	CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}");

	int curLine = styler.GetLine(startPos);
	int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			curLine = styler.GetLine(sc.currentPos);
			styler.SetLineState(curLine, curLineState);
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_PAS_NUMBER:
				if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) {
					sc.SetState(SCE_PAS_DEFAULT);
				} else if (sc.ch == '-' || sc.ch == '+') {
					if (sc.chPrev != 'E' && sc.chPrev != 'e') {
						sc.SetState(SCE_PAS_DEFAULT);
					}
				}
				break;
			case SCE_PAS_IDENTIFIER:
				if (!setWord.Contains(sc.ch)) {
					ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
				}
				break;
			case SCE_PAS_HEXNUMBER:
				if (!setHexNumber.Contains(sc.ch)) {
					sc.SetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_COMMENT:
			case SCE_PAS_PREPROCESSOR:
				if (sc.ch == '}') {
					sc.ForwardSetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_COMMENT2:
			case SCE_PAS_PREPROCESSOR2:
				if (sc.Match('*', ')')) {
					sc.Forward();
					sc.ForwardSetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_STRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_PAS_STRINGEOL);
				} else if (sc.ch == '\'' && sc.chNext == '\'') {
					sc.Forward();
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_CHARACTER:
				if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') {
					sc.SetState(SCE_PAS_DEFAULT);
				}
				break;
			case SCE_PAS_OPERATOR:
				if (bSmartHighlighting && sc.chPrev == ';') {
					curLineState &= ~(stateInProperty | stateInExport);
				}
				sc.SetState(SCE_PAS_DEFAULT);
				break;
			case SCE_PAS_ASM:
				sc.SetState(SCE_PAS_DEFAULT);
				break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_PAS_DEFAULT) {
			if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) {
				sc.SetState(SCE_PAS_NUMBER);
			} else if (setWordStart.Contains(sc.ch)) {
				sc.SetState(SCE_PAS_IDENTIFIER);
			} else if (sc.ch == '$' && !(curLineState & stateInAsm)) {
				sc.SetState(SCE_PAS_HEXNUMBER);
			} else if (sc.Match('{', '$')) {
				sc.SetState(SCE_PAS_PREPROCESSOR);
			} else if (sc.ch == '{') {
				sc.SetState(SCE_PAS_COMMENT);
			} else if (sc.Match("(*$")) {
				sc.SetState(SCE_PAS_PREPROCESSOR2);
			} else if (sc.Match('(', '*')) {
				sc.SetState(SCE_PAS_COMMENT2);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_PAS_COMMENTLINE);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_PAS_STRING);
			} else if (sc.ch == '#') {
				sc.SetState(SCE_PAS_CHARACTER);
			} else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) {
				sc.SetState(SCE_PAS_OPERATOR);
			} else if (curLineState & stateInAsm) {
				sc.SetState(SCE_PAS_ASM);
			}
		}
	}

	if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) {
		ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
	}

	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2;
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eolPos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eolPos; i++) {
		char ch = styler[i];
		char chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) {
			return true;
		} else if (!IsASpaceOrTab(ch)) {
			return false;
		}
	}
	return false;
}

static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) {
	return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask;
}

static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) {
	lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask;
	lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask;
}

static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
		unsigned int startPos, Accessor &styler) {
	CharacterSet setWord(CharacterSet::setAlpha);

	char s[11];	// Size of the longest possible keyword + one additional character + null
	GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));

	unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent);

	if (strcmp(s, "if") == 0 ||
		strcmp(s, "ifdef") == 0 ||
		strcmp(s, "ifndef") == 0 ||
		strcmp(s, "ifopt") == 0 ||
		strcmp(s, "region") == 0) {
		nestLevel++;
		SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
		lineFoldStateCurrent |= stateFoldInPreprocessor;
		levelCurrent++;
	} else if (strcmp(s, "endif") == 0 ||
		strcmp(s, "ifend") == 0 ||
		strcmp(s, "endregion") == 0) {
		nestLevel--;
		SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
		if (nestLevel == 0) {
			lineFoldStateCurrent &= ~stateFoldInPreprocessor;
		}
		levelCurrent--;
		if (levelCurrent < SC_FOLDLEVELBASE) {
			levelCurrent = SC_FOLDLEVELBASE;
		}
	}
}

static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos,
		Accessor &styler, bool includeChars = false) {
	CharacterSet setWord(CharacterSet::setAlphaNum, "_");
	unsigned int j = currentPos + 1;
	char ch = styler.SafeGetCharAt(j);
	while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
		IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) {
		j++;
		ch = styler.SafeGetCharAt(j);
	}
	return j;
}

static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
		int startPos, unsigned int endPos,
		unsigned int lastStart, unsigned int currentPos, Accessor &styler) {
	char s[100];
	GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));

	if (strcmp(s, "record") == 0) {
		lineFoldStateCurrent |= stateFoldInRecord;
		levelCurrent++;
	} else if (strcmp(s, "begin") == 0 ||
		strcmp(s, "asm") == 0 ||
		strcmp(s, "try") == 0 ||
		(strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) {
		levelCurrent++;
	} else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) {
		// "class" & "object" keywords require special handling...
		bool ignoreKeyword = false;
		unsigned int j = SkipWhiteSpace(currentPos, endPos, styler);
		if (j < endPos) {
			CharacterSet setWordStart(CharacterSet::setAlpha, "_");
			CharacterSet setWord(CharacterSet::setAlphaNum, "_");

			if (styler.SafeGetCharAt(j) == ';') {
				// Handle forward class declarations ("type TMyClass = class;")
				// and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;")
				ignoreKeyword = true;
			} else if (strcmp(s, "class") == 0) {
				// "class" keyword has a few more special cases...
				if (styler.SafeGetCharAt(j) == '(') {
					// Handle simplified complete class declarations ("type TMyClass = class(TObject);")
					j = SkipWhiteSpace(j, endPos, styler, true);
					if (j < endPos && styler.SafeGetCharAt(j) == ')') {
						j = SkipWhiteSpace(j, endPos, styler);
						if (j < endPos && styler.SafeGetCharAt(j) == ';') {
							ignoreKeyword = true;
						}
					}
				} else if (setWordStart.Contains(styler.SafeGetCharAt(j))) {
					char s2[11];	// Size of the longest possible keyword + one additional character + null
					GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2));

					if (strcmp(s2, "procedure") == 0 ||
						strcmp(s2, "function") == 0 ||
						strcmp(s2, "of") == 0 ||
						strcmp(s2, "var") == 0 ||
						strcmp(s2, "property") == 0 ||
						strcmp(s2, "operator") == 0) {
						ignoreKeyword = true;
					}
				}
			}
		}
		if (!ignoreKeyword) {
			levelCurrent++;
		}
	} else if (strcmp(s, "interface") == 0) {
		// "interface" keyword requires special handling...
		bool ignoreKeyword = true;
		int j = lastStart - 1;
		char ch = styler.SafeGetCharAt(j);
		while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
			IsStreamCommentStyle(styler.StyleAt(j)))) {
			j--;
			ch = styler.SafeGetCharAt(j);
		}
		if (j >= startPos && styler.SafeGetCharAt(j) == '=') {
			ignoreKeyword = false;
		}
		if (!ignoreKeyword) {
			unsigned int k = SkipWhiteSpace(currentPos, endPos, styler);
			if (k < endPos && styler.SafeGetCharAt(k) == ';') {
				// Handle forward interface declarations ("type IMyInterface = interface;")
				ignoreKeyword = true;
			}
		}
		if (!ignoreKeyword) {
			levelCurrent++;
		}
	} else if (strcmp(s, "dispinterface") == 0) {
		// "dispinterface" keyword requires special handling...
		bool ignoreKeyword = false;
		unsigned int j = SkipWhiteSpace(currentPos, endPos, styler);
		if (j < endPos && styler.SafeGetCharAt(j) == ';') {
			// Handle forward dispinterface declarations ("type IMyInterface = dispinterface;")
			ignoreKeyword = true;
		}
		if (!ignoreKeyword) {
			levelCurrent++;
		}
	} else if (strcmp(s, "end") == 0) {
		lineFoldStateCurrent &= ~stateFoldInRecord;
		levelCurrent--;
		if (levelCurrent < SC_FOLDLEVELBASE) {
			levelCurrent = SC_FOLDLEVELBASE;
		}
	}
}

static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[],
		Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;

	int lastStart = 0;
	CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
		{
			if (!IsCommentLine(lineCurrent - 1, styler)
			    && IsCommentLine(lineCurrent + 1, styler))
				levelCurrent++;
			else if (IsCommentLine(lineCurrent - 1, styler)
			         && !IsCommentLine(lineCurrent+1, styler))
				levelCurrent--;
		}
		if (foldPreprocessor) {
			if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') {
				ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler);
			} else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*'
			           && styler.SafeGetCharAt(i + 2) == '$') {
				ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler);
			}
		}

		if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD)
		{
			// Store last word start point.
			lastStart = i;
		}
		if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) {
			if(setWord.Contains(ch) && !setWord.Contains(chNext)) {
				ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler);
			}
		}

		if (!IsASpace(ch))
			visibleChars++;

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
			styler.SetLineState(lineCurrent, newLineState);
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
	}

	// If we didn't reach the EOL in previous loop, store line level and whitespace information.
	// The rest will be filled in later...
	int lev = levelPrev;
	if (visibleChars == 0 && foldCompact)
		lev |= SC_FOLDLEVELWHITEFLAG;
	styler.SetLevel(lineCurrent, lev);
}

static const char * const pascalWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc);

Added lexers/LexPerl.cxx.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
// Scintilla source code edit control
/** @file LexPerl.cxx
 ** Lexer for Perl.
 ** Converted to lexer object by "Udo Lechner" <dlchnr(at)gmx(dot)net>
 **/
// Copyright 1998-2008 by Neil Hodgson <neilh@scintilla.org>
// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>
#include <map>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Info for HERE document handling from perldata.pod (reformatted):
// ----------------------------------------------------------------
// A line-oriented form of quoting is based on the shell ``here-doc'' syntax.
// Following a << you specify a string to terminate the quoted material, and
// all lines following the current line down to the terminating string are
// the value of the item.
// * The terminating string may be either an identifier (a word), or some
//   quoted text.
// * If quoted, the type of quotes you use determines the treatment of the
//   text, just as in regular quoting.
// * An unquoted identifier works like double quotes.
// * There must be no space between the << and the identifier.
//   (If you put a space it will be treated as a null identifier,
//    which is valid, and matches the first empty line.)
//   (This is deprecated, -w warns of this syntax)
// * The terminating string must appear by itself (unquoted and
//   with no surrounding whitespace) on the terminating line.

#define HERE_DELIM_MAX 256		// maximum length of HERE doc delimiter

#define PERLNUM_BINARY		1	// order is significant: 1-4 cannot have a dot
#define PERLNUM_HEX			2
#define PERLNUM_OCTAL		3
#define PERLNUM_FLOAT_EXP	4	// exponent part only
#define PERLNUM_DECIMAL		5	// 1-5 are numbers; 6-7 are strings
#define PERLNUM_VECTOR		6
#define PERLNUM_V_VECTOR	7
#define PERLNUM_BAD			8

#define BACK_NONE		0	// lookback state for bareword disambiguation:
#define BACK_OPERATOR	1	// whitespace/comments are insignificant
#define BACK_KEYWORD	2	// operators/keywords are needed for disambiguation

// all interpolated styles are different from their parent styles by a constant difference
// we also assume SCE_PL_STRING_VAR is the interpolated style with the smallest value
#define	INTERPOLATE_SHIFT	(SCE_PL_STRING_VAR - SCE_PL_STRING)

static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, LexAccessor &styler) {
	// old-style keyword matcher; needed because GetCurrent() needs
	// current segment to be committed, but we may abandon early...
	char s[100];
	unsigned int i, len = end - start;
	if (len > 30) { len = 30; }
	for (i = 0; i < len; i++, start++) s[i] = styler[start];
	s[i] = '\0';
	return keywords.InList(s);
}

static int disambiguateBareword(LexAccessor &styler, unsigned int bk, unsigned int fw,
        int backFlag, unsigned int backPos, unsigned int endPos) {
	// identifiers are recognized by Perl as barewords under some
	// conditions, the following attempts to do the disambiguation
	// by looking backward and forward; result in 2 LSB
	int result = 0;
	bool moreback = false;		// true if passed newline/comments
	bool brace = false;			// true if opening brace found
	// if BACK_NONE, neither operator nor keyword, so skip test
	if (backFlag == BACK_NONE)
		return result;
	// first look backwards past whitespace/comments to set EOL flag
	// (some disambiguation patterns must be on a single line)
	if (backPos <= static_cast<unsigned int>(styler.LineStart(styler.GetLine(bk))))
		moreback = true;
	// look backwards at last significant lexed item for disambiguation
	bk = backPos - 1;
	int ch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
	if (ch == '{' && !moreback) {
		// {bareword: possible variable spec
		brace = true;
	} else if ((ch == '&' && styler.SafeGetCharAt(bk - 1) != '&')
	        // &bareword: subroutine call
	        || styler.Match(bk - 1, "->")
	        // ->bareword: part of variable spec
	        || styler.Match(bk - 2, "sub")) {
		// sub bareword: subroutine declaration
		// (implied BACK_KEYWORD, no keywords end in 'sub'!)
		result |= 1;
	}
	// next, scan forward after word past tab/spaces only;
	// if ch isn't one of '[{(,' we can skip the test
	if ((ch == '{' || ch == '(' || ch == '['|| ch == ',')
	        && fw < endPos) {
		while (ch = static_cast<unsigned char>(styler.SafeGetCharAt(fw)),
		        IsASpaceOrTab(ch) && fw < endPos) {
			fw++;
		}
		if ((ch == '}' && brace)
		        // {bareword}: variable spec
		        || styler.Match(fw, "=>")) {
			// [{(, bareword=>: hash literal
			result |= 2;
		}
	}
	return result;
}

static void skipWhitespaceComment(LexAccessor &styler, unsigned int &p) {
	// when backtracking, we need to skip whitespace and comments
	int style;
	while ((p > 0) && (style = styler.StyleAt(p),
	        style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE))
		p--;
}

static int styleBeforeBracePair(LexAccessor &styler, unsigned int bk) {
	// backtrack to find open '{' corresponding to a '}', balanced
	// return significant style to be tested for '/' disambiguation
	int braceCount = 1;
	if (bk == 0)
		return SCE_PL_DEFAULT;
	while (--bk > 0) {
		if (styler.StyleAt(bk) == SCE_PL_OPERATOR) {
			int bkch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
			if (bkch == ';') {	// early out
				break;
			} else if (bkch == '}') {
				braceCount++;
			} else if (bkch == '{') {
				if (--braceCount == 0) break;
			}
		}
	}
	if (bk > 0 && braceCount == 0) {
		// balanced { found, bk > 0, skip more whitespace/comments
		bk--;
		skipWhitespaceComment(styler, bk);
		return styler.StyleAt(bk);
	}
	return SCE_PL_DEFAULT;
}

static int styleCheckIdentifier(LexAccessor &styler, unsigned int bk) {
	// backtrack to classify sub-styles of identifier under test
	// return sub-style to be tested for '/' disambiguation
	if (styler.SafeGetCharAt(bk) == '>')	// inputsymbol, like <foo>
		return 1;
	// backtrack to check for possible "->" or "::" before identifier
	while (bk > 0 && styler.StyleAt(bk) == SCE_PL_IDENTIFIER) {
		bk--;
	}
	while (bk > 0) {
		int bkstyle = styler.StyleAt(bk);
		if (bkstyle == SCE_PL_DEFAULT
		        || bkstyle == SCE_PL_COMMENTLINE) {
			// skip whitespace, comments
		} else if (bkstyle == SCE_PL_OPERATOR) {
			// test for "->" and "::"
			if (styler.Match(bk - 1, "->") || styler.Match(bk - 1, "::"))
				return 2;
		} else
			return 3;	// bare identifier
		bk--;
	}
	return 0;
}

static int inputsymbolScan(LexAccessor &styler, unsigned int pos, unsigned int endPos) {
	// looks forward for matching > on same line; a bit ugly
	unsigned int fw = pos;
	while (++fw < endPos) {
		int fwch = static_cast<unsigned char>(styler.SafeGetCharAt(fw));
		if (fwch == '\r' || fwch == '\n') {
			return 0;
		} else if (fwch == '>') {
			if (styler.Match(fw - 2, "<=>"))	// '<=>' case
				return 0;
			return fw - pos;
		}
	}
	return 0;
}

static int podLineScan(LexAccessor &styler, unsigned int &pos, unsigned int endPos) {
	// forward scan the current line to classify line for POD style
	int state = -1;
	while (pos <= endPos) {
		int ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
		if (ch == '\n' || ch == '\r' || pos >= endPos) {
			if (ch == '\r' && styler.SafeGetCharAt(pos + 1) == '\n') pos++;
			break;
		}
		if (IsASpaceOrTab(ch)) {	// whitespace, take note
			if (state == -1)
				state = SCE_PL_DEFAULT;
		} else if (state == SCE_PL_DEFAULT) {	// verbatim POD line
			state = SCE_PL_POD_VERB;
		} else if (state != SCE_PL_POD_VERB) {	// regular POD line
			state = SCE_PL_POD;
		}
		pos++;
	}
	if (state == -1)
		state = SCE_PL_DEFAULT;
	return state;
}

static bool styleCheckSubPrototype(LexAccessor &styler, unsigned int bk) {
	// backtrack to identify if we're starting a subroutine prototype
	// we also need to ignore whitespace/comments:
	// 'sub' [whitespace|comment] <identifier> [whitespace|comment]
	styler.Flush();
	skipWhitespaceComment(styler, bk);
	if (bk == 0 || styler.StyleAt(bk) != SCE_PL_IDENTIFIER)	// check identifier
		return false;
	while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_IDENTIFIER)) {
		bk--;
	}
	skipWhitespaceComment(styler, bk);
	if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD	// check "sub" keyword
	        || !styler.Match(bk - 2, "sub"))	// assume suffix is unique!
		return false;
	return true;
}

static int actualNumStyle(int numberStyle) {
	if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) {
		return SCE_PL_STRING;
	} else if (numberStyle == PERLNUM_BAD) {
		return SCE_PL_ERROR;
	}
	return SCE_PL_NUMBER;
}

static int opposite(int ch) {
	if (ch == '(') return ')';
	if (ch == '[') return ']';
	if (ch == '{') return '}';
	if (ch == '<') return '>';
	return ch;
}

static bool IsCommentLine(int line, LexAccessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		int style = styler.StyleAt(i);
		if (ch == '#' && style == SCE_PL_COMMENTLINE)
			return true;
		else if (!IsASpaceOrTab(ch))
			return false;
	}
	return false;
}

static bool IsPackageLine(int line, LexAccessor &styler) {
	int pos = styler.LineStart(line);
	int style = styler.StyleAt(pos);
	if (style == SCE_PL_WORD && styler.Match(pos, "package")) {
		return true;
	}
	return false;
}

static int PodHeadingLevel(int pos, LexAccessor &styler) {
	int lvl = static_cast<unsigned char>(styler.SafeGetCharAt(pos + 5));
	if (lvl >= '1' && lvl <= '4') {
		return lvl - '0';
	}
	return 0;
}

// An individual named option for use in an OptionSet

// Options used for LexerPerl
struct OptionsPerl {
	bool fold;
	bool foldComment;
	bool foldCompact;
	// Custom folding of POD and packages
	bool foldPOD;            // fold.perl.pod
	// Enable folding Pod blocks when using the Perl lexer.
	bool foldPackage;        // fold.perl.package
	// Enable folding packages when using the Perl lexer.

	bool foldCommentExplicit;

	bool foldAtElse;

	OptionsPerl() {
		fold = false;
		foldComment = false;
		foldCompact = true;
		foldPOD = true;
		foldPackage = true;
		foldCommentExplicit = true;
		foldAtElse = false;
	}
};

static const char *const perlWordListDesc[] = {
	"Keywords",
	0
};

struct OptionSetPerl : public OptionSet<OptionsPerl> {
	OptionSetPerl() {
		DefineProperty("fold", &OptionsPerl::fold);

		DefineProperty("fold.comment", &OptionsPerl::foldComment);

		DefineProperty("fold.compact", &OptionsPerl::foldCompact);

		DefineProperty("fold.perl.pod", &OptionsPerl::foldPOD,
		        "Set to 0 to disable folding Pod blocks when using the Perl lexer.");

		DefineProperty("fold.perl.package", &OptionsPerl::foldPackage,
		        "Set to 0 to disable folding packages when using the Perl lexer.");

		DefineProperty("fold.perl.comment.explicit", &OptionsPerl::foldCommentExplicit,
		        "Set to 0 to disable explicit folding.");

		DefineProperty("fold.perl.at.else", &OptionsPerl::foldAtElse,
		               "This option enables Perl folding on a \"} else {\" line of an if statement.");

		DefineWordListSets(perlWordListDesc);
	}
};

class LexerPerl : public ILexer {
	CharacterSet setWordStart;
	CharacterSet setWord;
	CharacterSet setSpecialVar;
	CharacterSet setControlVar;
	WordList keywords;
	OptionsPerl options;
	OptionSetPerl osPerl;
public:
	LexerPerl() :
		setWordStart(CharacterSet::setAlpha, "_", 0x80, true),
		setWord(CharacterSet::setAlphaNum, "_", 0x80, true),
		setSpecialVar(CharacterSet::setNone, "\"$;<>&`'+,./\\%:=~!?@[]"),
		setControlVar(CharacterSet::setNone, "ACDEFHILMNOPRSTVWX") {
	}
	virtual ~LexerPerl() {
	}
	void SCI_METHOD Release() {
		delete this;
	}
	int SCI_METHOD Version() const {
		return lvOriginal;
	}
	const char *SCI_METHOD PropertyNames() {
		return osPerl.PropertyNames();
	}
	int SCI_METHOD PropertyType(const char *name) {
		return osPerl.PropertyType(name);
	}
	const char *SCI_METHOD DescribeProperty(const char *name) {
		return osPerl.DescribeProperty(name);
	}
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char *SCI_METHOD DescribeWordListSets() {
		return osPerl.DescribeWordListSets();
	}
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

	void *SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}

	static ILexer *LexerFactoryPerl() {
		return new LexerPerl();
	}
	void InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern=false);
};

int SCI_METHOD LexerPerl::PropertySet(const char *key, const char *val) {
	if (osPerl.PropertySet(&options, key, val)) {
		return 0;
	}
	return -1;
}

int SCI_METHOD LexerPerl::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &keywords;
		break;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
		}
	}
	return firstModification;
}

void LexerPerl::InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern) {
	// interpolate a segment (with no active backslashes or delimiters within)
	// switch in or out of an interpolation style or continue current style
	// commit variable patterns if found, trim segment, repeat until done
	while (maxSeg > 0) {
		bool isVar = false;
		int sLen = 0;
		if ((maxSeg > 1) && (sc.ch == '$' || sc.ch == '@')) {
			// $#[$]*word [$@][$]*word (where word or {word} is always present)
			bool braces = false;
			sLen = 1;
			if (sc.ch == '$' && sc.chNext == '#') {	// starts with $#
				sLen++;
			}
			while ((maxSeg > sLen) && (sc.GetRelative(sLen) == '$'))	// >0 $ dereference within
				sLen++;
			if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '{')) {	// { start for {word}
				sLen++;
				braces = true;
			}
			if (maxSeg > sLen) {
				int c = sc.GetRelative(sLen);
				if (setWordStart.Contains(c)) {	// word (various)
					sLen++;
					isVar = true;
					while ((maxSeg > sLen) && setWord.Contains(sc.GetRelative(sLen)))
						sLen++;
				} else if (braces && IsADigit(c) && (sLen == 2)) {	// digit for ${digit}
					sLen++;
					isVar = true;
				}
			}
			if (braces) {
				if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '}')) {	// } end for {word}
					sLen++;
				} else
					isVar = false;
			}
		}
		if (!isVar && (maxSeg > 1)) {	// $- or @-specific variable patterns
			sLen = 1;
			int c = sc.chNext;
			if (sc.ch == '$') {
				if (IsADigit(c)) {	// $[0-9] and slurp trailing digits
					sLen++;
					isVar = true;
					while ((maxSeg > sLen) && IsADigit(sc.GetRelative(sLen)))
						sLen++;
				} else if (setSpecialVar.Contains(c)) {	// $ special variables
					sLen++;
					isVar = true;
				} else if (!isPattern && ((c == '(') || (c == ')') || (c == '|'))) {	// $ additional
					sLen++;
					isVar = true;
				} else if (c == '^') {	// $^A control-char style
					sLen++;
					if ((maxSeg > sLen) && setControlVar.Contains(sc.GetRelative(sLen))) {
						sLen++;
						isVar = true;
					}
				}
			} else if (sc.ch == '@') {
				if (!isPattern && ((c == '+') || (c == '-'))) {	// @ specials non-pattern
					sLen++;
					isVar = true;
				}
			}
		}
		if (isVar) {	// commit as interpolated variable or normal character
			if (sc.state < SCE_PL_STRING_VAR)
				sc.SetState(sc.state + INTERPOLATE_SHIFT);
			sc.Forward(sLen);
			maxSeg -= sLen;
		} else {
			if (sc.state >= SCE_PL_STRING_VAR)
				sc.SetState(sc.state - INTERPOLATE_SHIFT);
			sc.Forward();
			maxSeg--;
		}
	}
	if (sc.state >= SCE_PL_STRING_VAR)
		sc.SetState(sc.state - INTERPOLATE_SHIFT);
}

void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);

	// keywords that forces /PATTERN/ at all times; should track vim's behaviour
	WordList reWords;
	reWords.Set("elsif if split while");

	// charset classes
	CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC");
	// lexing of "%*</" operators is non-trivial; these are missing in the set below
	CharacterSet setPerlOperator(CharacterSet::setNone, "^&\\()-+=|{}[]:;>,?!.~");
	CharacterSet setQDelim(CharacterSet::setNone, "qrwx");
	CharacterSet setModifiers(CharacterSet::setAlpha);
	CharacterSet setPreferRE(CharacterSet::setNone, "*/<%");
	// setArray and setHash also accepts chars for special vars like $_,
	// which are then truncated when the next char does not match setVar
	CharacterSet setVar(CharacterSet::setAlphaNum, "#$_'", 0x80, true);
	CharacterSet setArray(CharacterSet::setAlpha, "#$_+-", 0x80, true);
	CharacterSet setHash(CharacterSet::setAlpha, "#$_!^+-", 0x80, true);
	CharacterSet &setPOD = setModifiers;
	CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@");
	CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_");
	CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*+];");
	// for format identifiers
	CharacterSet setFormatStart(CharacterSet::setAlpha, "_=");
	CharacterSet &setFormat = setHereDocDelim;

	// Lexer for perl often has to backtrack to start of current style to determine
	// which characters are being used as quotes, how deeply nested is the
	// start position and what the termination string is for HERE documents.

	class HereDocCls {	// Class to manage HERE doc sequence
	public:
		int State;
		// 0: '<<' encountered
		// 1: collect the delimiter
		// 2: here doc text (lines after the delimiter)
		int Quote;		// the char after '<<'
		bool Quoted;		// true if Quote in ('\'','"','`')
		int DelimiterLength;	// strlen(Delimiter)
		char *Delimiter;	// the Delimiter, 256: sizeof PL_tokenbuf
		HereDocCls() {
			State = 0;
			Quote = 0;
			Quoted = false;
			DelimiterLength = 0;
			Delimiter = new char[HERE_DELIM_MAX];
			Delimiter[0] = '\0';
		}
		void Append(int ch) {
			Delimiter[DelimiterLength++] = static_cast<char>(ch);
			Delimiter[DelimiterLength] = '\0';
		}
		~HereDocCls() {
			delete []Delimiter;
		}
	};
	HereDocCls HereDoc;		// TODO: FIFO for stacked here-docs

	class QuoteCls {	// Class to manage quote pairs
	public:
		int Rep;
		int Count;
		int Up, Down;
		QuoteCls() {
			this->New(1);
		}
		void New(int r = 1) {
			Rep   = r;
			Count = 0;
			Up    = '\0';
			Down  = '\0';
		}
		void Open(int u) {
			Count++;
			Up    = u;
			Down  = opposite(Up);
		}
	};
	QuoteCls Quote;

	// additional state for number lexing
	int numState = PERLNUM_DECIMAL;
	int dotCount = 0;

	unsigned int endPos = startPos + length;

	// Backtrack to beginning of style if required...
	// If in a long distance lexical state, backtrack to find quote characters.
	// Includes strings (may be multi-line), numbers (additional state), format
	// bodies, as well as POD sections.
	if (initStyle == SCE_PL_HERE_Q
	    || initStyle == SCE_PL_HERE_QQ
	    || initStyle == SCE_PL_HERE_QX
	    || initStyle == SCE_PL_FORMAT
	    || initStyle == SCE_PL_HERE_QQ_VAR
	    || initStyle == SCE_PL_HERE_QX_VAR
	   ) {
		// backtrack through multiple styles to reach the delimiter start
		int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM;
		while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) {
			startPos--;
		}
		startPos = styler.LineStart(styler.GetLine(startPos));
		initStyle = styler.StyleAt(startPos - 1);
	}
	if (initStyle == SCE_PL_STRING
	    || initStyle == SCE_PL_STRING_QQ
	    || initStyle == SCE_PL_BACKTICKS
	    || initStyle == SCE_PL_STRING_QX
	    || initStyle == SCE_PL_REGEX
	    || initStyle == SCE_PL_STRING_QR
	    || initStyle == SCE_PL_REGSUBST
	    || initStyle == SCE_PL_STRING_VAR
	    || initStyle == SCE_PL_STRING_QQ_VAR
	    || initStyle == SCE_PL_BACKTICKS_VAR
	    || initStyle == SCE_PL_STRING_QX_VAR
	    || initStyle == SCE_PL_REGEX_VAR
	    || initStyle == SCE_PL_STRING_QR_VAR
	    || initStyle == SCE_PL_REGSUBST_VAR
	   ) {
		// for interpolation, must backtrack through a mix of two different styles
		int otherStyle = (initStyle >= SCE_PL_STRING_VAR) ?
			initStyle - INTERPOLATE_SHIFT : initStyle + INTERPOLATE_SHIFT;
		while (startPos > 1) {
			int st = styler.StyleAt(startPos - 1);
			if ((st != initStyle) && (st != otherStyle))
				break;
			startPos--;
		}
		initStyle = SCE_PL_DEFAULT;
	} else if (initStyle == SCE_PL_STRING_Q
	        || initStyle == SCE_PL_STRING_QW
	        || initStyle == SCE_PL_XLAT
	        || initStyle == SCE_PL_CHARACTER
	        || initStyle == SCE_PL_NUMBER
	        || initStyle == SCE_PL_IDENTIFIER
	        || initStyle == SCE_PL_ERROR
	        || initStyle == SCE_PL_SUB_PROTOTYPE
	   ) {
		while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) {
			startPos--;
		}
		initStyle = SCE_PL_DEFAULT;
	} else if (initStyle == SCE_PL_POD
	        || initStyle == SCE_PL_POD_VERB
	          ) {
		// POD backtracking finds preceeding blank lines and goes back past them
		int ln = styler.GetLine(startPos);
		if (ln > 0) {
			initStyle = styler.StyleAt(styler.LineStart(--ln));
			if (initStyle == SCE_PL_POD || initStyle == SCE_PL_POD_VERB) {
				while (ln > 0 && styler.GetLineState(ln) == SCE_PL_DEFAULT)
					ln--;
			}
			startPos = styler.LineStart(++ln);
			initStyle = styler.StyleAt(startPos - 1);
		} else {
			startPos = 0;
			initStyle = SCE_PL_DEFAULT;
		}
	}

	// backFlag, backPos are additional state to aid identifier corner cases.
	// Look backwards past whitespace and comments in order to detect either
	// operator or keyword. Later updated as we go along.
	int backFlag = BACK_NONE;
	unsigned int backPos = startPos;
	if (backPos > 0) {
		backPos--;
		skipWhitespaceComment(styler, backPos);
		if (styler.StyleAt(backPos) == SCE_PL_OPERATOR)
			backFlag = BACK_OPERATOR;
		else if (styler.StyleAt(backPos) == SCE_PL_WORD)
			backFlag = BACK_KEYWORD;
		backPos++;
	}

	StyleContext sc(startPos, endPos - startPos, initStyle, styler, static_cast<char>(STYLE_MAX));

	for (; sc.More(); sc.Forward()) {

		// Determine if the current state should terminate.
		switch (sc.state) {
		case SCE_PL_OPERATOR:
			sc.SetState(SCE_PL_DEFAULT);
			backFlag = BACK_OPERATOR;
			backPos = sc.currentPos;
			break;
		case SCE_PL_IDENTIFIER:		// identifier, bareword, inputsymbol
			if ((!setWord.Contains(sc.ch) && sc.ch != '\'')
			        || sc.Match('.', '.')
			        || sc.chPrev == '>') {	// end of inputsymbol
				sc.SetState(SCE_PL_DEFAULT);
			}
			break;
		case SCE_PL_WORD:		// keyword, plus special cases
			if (!setWord.Contains(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) {
					sc.ChangeState(SCE_PL_DATASECTION);
				} else {
					if ((strcmp(s, "format") == 0)) {
						sc.SetState(SCE_PL_FORMAT_IDENT);
						HereDoc.State = 0;
					} else {
						sc.SetState(SCE_PL_DEFAULT);
					}
					backFlag = BACK_KEYWORD;
					backPos = sc.currentPos;
				}
			}
			break;
		case SCE_PL_SCALAR:
		case SCE_PL_ARRAY:
		case SCE_PL_HASH:
		case SCE_PL_SYMBOLTABLE:
			if (sc.Match(':', ':')) {	// skip ::
				sc.Forward();
			} else if (!setVar.Contains(sc.ch)) {
				if (sc.LengthCurrent() == 1) {
					// Special variable: $(, $_ etc.
					sc.Forward();
				}
				sc.SetState(SCE_PL_DEFAULT);
			}
			break;
		case SCE_PL_NUMBER:
			// if no early break, number style is terminated at "(go through)"
			if (sc.ch == '.') {
				if (sc.chNext == '.') {
					// double dot is always an operator (go through)
				} else if (numState <= PERLNUM_FLOAT_EXP) {
					// non-decimal number or float exponent, consume next dot
					sc.SetState(SCE_PL_OPERATOR);
					break;
				} else {	// decimal or vectors allows dots
					dotCount++;
					if (numState == PERLNUM_DECIMAL) {
						if (dotCount <= 1)	// number with one dot in it
							break;
						if (IsADigit(sc.chNext)) {	// really a vector
							numState = PERLNUM_VECTOR;
							break;
						}
						// number then dot (go through)
					} else if (IsADigit(sc.chNext))	// vectors
						break;
					// vector then dot (go through)
				}
			} else if (sc.ch == '_') {
				// permissive underscoring for number and vector literals
				break;
			} else if (numState == PERLNUM_DECIMAL) {
				if (sc.ch == 'E' || sc.ch == 'e') {	// exponent, sign
					numState = PERLNUM_FLOAT_EXP;
					if (sc.chNext == '+' || sc.chNext == '-') {
						sc.Forward();
					}
					break;
				} else if (IsADigit(sc.ch))
					break;
				// number then word (go through)
			} else if (numState == PERLNUM_HEX) {
				if (IsADigit(sc.ch, 16))
					break;
			} else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
				if (IsADigit(sc.ch))	// vector
					break;
				if (setWord.Contains(sc.ch) && dotCount == 0) {	// change to word
					sc.ChangeState(SCE_PL_IDENTIFIER);
					break;
				}
				// vector then word (go through)
			} else if (IsADigit(sc.ch)) {
				if (numState == PERLNUM_FLOAT_EXP) {
					break;
				} else if (numState == PERLNUM_OCTAL) {
					if (sc.ch <= '7') break;
				} else if (numState == PERLNUM_BINARY) {
					if (sc.ch <= '1') break;
				}
				// mark invalid octal, binary numbers (go through)
				numState = PERLNUM_BAD;
				break;
			}
			// complete current number or vector
			sc.ChangeState(actualNumStyle(numState));
			sc.SetState(SCE_PL_DEFAULT);
			break;
		case SCE_PL_COMMENTLINE:
			if (sc.atLineEnd) {
				sc.SetState(SCE_PL_DEFAULT);
			}
			break;
		case SCE_PL_HERE_DELIM:
			if (HereDoc.State == 0) { // '<<' encountered
				int delim_ch = sc.chNext;
				int ws_skip = 0;
				HereDoc.State = 1;	// pre-init HERE doc class
				HereDoc.Quote = sc.chNext;
				HereDoc.Quoted = false;
				HereDoc.DelimiterLength = 0;
				HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
				if (IsASpaceOrTab(delim_ch)) {
					// skip whitespace; legal only for quoted delimiters
					unsigned int i = sc.currentPos + 1;
					while ((i < endPos) && IsASpaceOrTab(delim_ch)) {
						i++;
						delim_ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
					}
					ws_skip = i - sc.currentPos - 1;
				}
				if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') {
					// a quoted here-doc delimiter; skip any whitespace
					sc.Forward(ws_skip + 1);
					HereDoc.Quote = delim_ch;
					HereDoc.Quoted = true;
				} else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext))
				        || ws_skip > 0) {
					// left shift << or <<= operator cases
					// restore position if operator
					sc.ChangeState(SCE_PL_OPERATOR);
					sc.ForwardSetState(SCE_PL_DEFAULT);
					backFlag = BACK_OPERATOR;
					backPos = sc.currentPos;
					HereDoc.State = 0;
				} else {
					// specially handle initial '\' for identifier
					if (ws_skip == 0 && HereDoc.Quote == '\\')
						sc.Forward();
					// an unquoted here-doc delimiter, no special handling
					// (cannot be prefixed by spaces/tabs), or
					// symbols terminates; deprecated zero-length delimiter
				}
			} else if (HereDoc.State == 1) { // collect the delimiter
				backFlag = BACK_NONE;
				if (HereDoc.Quoted) { // a quoted here-doc delimiter
					if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter
						sc.ForwardSetState(SCE_PL_DEFAULT);
					} else if (!sc.atLineEnd) {
						if (sc.Match('\\', static_cast<char>(HereDoc.Quote))) { // escaped quote
							sc.Forward();
						}
						if (sc.ch != '\r') {	// skip CR if CRLF
							HereDoc.Append(sc.ch);
						}
					}
				} else { // an unquoted here-doc delimiter
					if (setHereDocDelim.Contains(sc.ch)) {
						HereDoc.Append(sc.ch);
					} else {
						sc.SetState(SCE_PL_DEFAULT);
					}
				}
				if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) {
					sc.SetState(SCE_PL_ERROR);
					HereDoc.State = 0;
				}
			}
			break;
		case SCE_PL_HERE_Q:
		case SCE_PL_HERE_QQ:
		case SCE_PL_HERE_QX:
			// also implies HereDoc.State == 2
			sc.Complete();
			if (HereDoc.DelimiterLength == 0 || sc.Match(HereDoc.Delimiter)) {
				int c = sc.GetRelative(HereDoc.DelimiterLength);
				if (c == '\r' || c == '\n') {	// peek first, do not consume match
					sc.Forward(HereDoc.DelimiterLength);
					sc.SetState(SCE_PL_DEFAULT);
					backFlag = BACK_NONE;
					HereDoc.State = 0;
					if (!sc.atLineEnd)
						sc.Forward();
					break;
				}
			}
			if (sc.state == SCE_PL_HERE_Q) {	// \EOF and 'EOF' non-interpolated
				while (!sc.atLineEnd)
					sc.Forward();
				break;
			}
			while (!sc.atLineEnd) {		// "EOF" and `EOF` interpolated
				int s = 0, endType = 0;
				int maxSeg = endPos - sc.currentPos;
				while (s < maxSeg) {	// scan to break string into segments
					int c = sc.GetRelative(s);
					if (c == '\\') {
						endType = 1; break;
					} else if (c == '\r' || c == '\n') {
						endType = 2; break;
					}
					s++;
				}
				if (s > 0)	// process non-empty segments
					InterpolateSegment(sc, s);
				if (endType == 1) {
					sc.Forward();
					// \ at end-of-line does not appear to have any effect, skip
					if (sc.ch != '\r' && sc.ch != '\n')
						sc.Forward();
				} else if (endType == 2) {
					if (!sc.atLineEnd)
						sc.Forward();
				}
			}
			break;
		case SCE_PL_POD:
		case SCE_PL_POD_VERB: {
				unsigned int fw = sc.currentPos;
				int ln = styler.GetLine(fw);
				if (sc.atLineStart && sc.Match("=cut")) {	// end of POD
					sc.SetState(SCE_PL_POD);
					sc.Forward(4);
					sc.SetState(SCE_PL_DEFAULT);
					styler.SetLineState(ln, SCE_PL_POD);
					break;
				}
				int pod = podLineScan(styler, fw, endPos);	// classify POD line
				styler.SetLineState(ln, pod);
				if (pod == SCE_PL_DEFAULT) {
					if (sc.state == SCE_PL_POD_VERB) {
						unsigned int fw2 = fw;
						while (fw2 <= endPos && pod == SCE_PL_DEFAULT) {
							fw = fw2++;	// penultimate line (last blank line)
							pod = podLineScan(styler, fw2, endPos);
							styler.SetLineState(styler.GetLine(fw2), pod);
						}
						if (pod == SCE_PL_POD) {	// truncate verbatim POD early
							sc.SetState(SCE_PL_POD);
						} else
							fw = fw2;
					}
				} else {
					if (pod == SCE_PL_POD_VERB	// still part of current paragraph
					        && (styler.GetLineState(ln - 1) == SCE_PL_POD)) {
						pod = SCE_PL_POD;
						styler.SetLineState(ln, pod);
					} else if (pod == SCE_PL_POD
					        && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) {
						pod = SCE_PL_POD_VERB;
						styler.SetLineState(ln, pod);
					}
					sc.SetState(pod);
				}
				sc.Forward(fw - sc.currentPos);	// commit style
			}
			break;
		case SCE_PL_REGEX:
		case SCE_PL_STRING_QR:
			if (Quote.Rep <= 0) {
				if (!setModifiers.Contains(sc.ch))
					sc.SetState(SCE_PL_DEFAULT);
			} else if (!Quote.Up && !IsASpace(sc.ch)) {
				Quote.Open(sc.ch);
			} else {
				int s = 0, endType = 0;
				int maxSeg = endPos - sc.currentPos;
				while (s < maxSeg) {	// scan to break string into segments
					int c = sc.GetRelative(s);
					if (IsASpace(c)) {
						break;
					} else if (c == '\\' && Quote.Up != '\\') {
						endType = 1; break;
					} else if (c == Quote.Down) {
						Quote.Count--;
						if (Quote.Count == 0) {
							Quote.Rep--;
							break;
						}
					} else if (c == Quote.Up)
						Quote.Count++;
					s++;
				}
				if (s > 0) {	// process non-empty segments
					if (Quote.Up != '\'') {
						InterpolateSegment(sc, s, true);
					} else		// non-interpolated path
						sc.Forward(s);
				}
				if (endType == 1)
					sc.Forward();
			}
			break;
		case SCE_PL_REGSUBST:
		case SCE_PL_XLAT:
			if (Quote.Rep <= 0) {
				if (!setModifiers.Contains(sc.ch))
					sc.SetState(SCE_PL_DEFAULT);
			} else if (!Quote.Up && !IsASpace(sc.ch)) {
				Quote.Open(sc.ch);
			} else {
				int s = 0, endType = 0;
				int maxSeg = endPos - sc.currentPos;
				bool isPattern = (Quote.Rep == 2);
				while (s < maxSeg) {	// scan to break string into segments
					int c = sc.GetRelative(s);
					if (c == '\\' && Quote.Up != '\\') {
						endType = 2; break;
					} else if (Quote.Count == 0 && Quote.Rep == 1) {
						// We matched something like s(...) or tr{...}, Perl 5.10
						// appears to allow almost any character for use as the
						// next delimiters. Whitespace and comments are accepted in
						// between, but we'll limit to whitespace here.
						// For '#', if no whitespace in between, it's a delimiter.
						if (IsASpace(c)) {
							// Keep going
						} else if (c == '#' && IsASpaceOrTab(sc.GetRelative(s - 1))) {
							endType = 3;
						} else
							Quote.Open(c);
						break;
					} else if (c == Quote.Down) {
						Quote.Count--;
						if (Quote.Count == 0) {
							Quote.Rep--;
							endType = 1;
						}
						if (Quote.Up == Quote.Down)
							Quote.Count++;
						if (endType == 1)
							break;
					} else if (c == Quote.Up) {
						Quote.Count++;
					} else if (IsASpace(c))
						break;
					s++;
				}
				if (s > 0) {	// process non-empty segments
					if (sc.state == SCE_PL_REGSUBST && Quote.Up != '\'') {
						InterpolateSegment(sc, s, isPattern);
					} else		// non-interpolated path
						sc.Forward(s);
				}
				if (endType == 2) {
					sc.Forward();
				} else if (endType == 3)
					sc.SetState(SCE_PL_DEFAULT);
			}
			break;
		case SCE_PL_STRING_Q:
		case SCE_PL_STRING_QQ:
		case SCE_PL_STRING_QX:
		case SCE_PL_STRING_QW:
		case SCE_PL_STRING:
		case SCE_PL_CHARACTER:
		case SCE_PL_BACKTICKS:
			if (!Quote.Down && !IsASpace(sc.ch)) {
				Quote.Open(sc.ch);
			} else {
				int s = 0, endType = 0;
				int maxSeg = endPos - sc.currentPos;
				while (s < maxSeg) {	// scan to break string into segments
					int c = sc.GetRelative(s);
					if (IsASpace(c)) {
						break;
					} else if (c == '\\' && Quote.Up != '\\') {
						endType = 2; break;
					} else if (c == Quote.Down) {
						Quote.Count--;
						if (Quote.Count == 0) {
							endType = 3; break;
						}
					} else if (c == Quote.Up)
						Quote.Count++;
					s++;
				}
				if (s > 0) {	// process non-empty segments
					switch (sc.state) {
					case SCE_PL_STRING:
					case SCE_PL_STRING_QQ:
					case SCE_PL_BACKTICKS:
						InterpolateSegment(sc, s);
						break;
					case SCE_PL_STRING_QX:
						if (Quote.Up != '\'') {
							InterpolateSegment(sc, s);
							break;
						}
						// (continued for ' delim)
					default:	// non-interpolated path
						sc.Forward(s);
					}
				}
				if (endType == 2) {
					sc.Forward();
				} else if (endType == 3)
					sc.ForwardSetState(SCE_PL_DEFAULT);
			}
			break;
		case SCE_PL_SUB_PROTOTYPE: {
				int i = 0;
				// forward scan; must all be valid proto characters
				while (setSubPrototype.Contains(sc.GetRelative(i)))
					i++;
				if (sc.GetRelative(i) == ')') {	// valid sub prototype
					sc.Forward(i);
					sc.ForwardSetState(SCE_PL_DEFAULT);
				} else {
					// abandon prototype, restart from '('
					sc.ChangeState(SCE_PL_OPERATOR);
					sc.SetState(SCE_PL_DEFAULT);
				}
			}
			break;
		case SCE_PL_FORMAT: {
				sc.Complete();
				if (sc.Match('.')) {
					sc.Forward();
					if (sc.atLineEnd || ((sc.ch == '\r' && sc.chNext == '\n')))
						sc.SetState(SCE_PL_DEFAULT);
				}
				while (!sc.atLineEnd)
					sc.Forward();
			}
			break;
		case SCE_PL_ERROR:
			break;
		}
		// Needed for specific continuation styles (one follows the other)
		switch (sc.state) {
			// continued from SCE_PL_WORD
		case SCE_PL_FORMAT_IDENT:
			// occupies HereDoc state 3 to avoid clashing with HERE docs
			if (IsASpaceOrTab(sc.ch)) {		// skip whitespace
				sc.ChangeState(SCE_PL_DEFAULT);
				while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
					sc.Forward();
				sc.SetState(SCE_PL_FORMAT_IDENT);
			}
			if (setFormatStart.Contains(sc.ch)) {	// identifier or '='
				if (sc.ch != '=') {
					do {
						sc.Forward();
					} while (setFormat.Contains(sc.ch));
				}
				while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
					sc.Forward();
				if (sc.ch == '=') {
					sc.ForwardSetState(SCE_PL_DEFAULT);
					HereDoc.State = 3;
				} else {
					// invalid indentifier; inexact fallback, but hey
					sc.ChangeState(SCE_PL_IDENTIFIER);
					sc.SetState(SCE_PL_DEFAULT);
				}
			} else {
				sc.ChangeState(SCE_PL_DEFAULT);	// invalid indentifier
			}
			backFlag = BACK_NONE;
			break;
		}

		// Must check end of HereDoc states here before default state is handled
		if (HereDoc.State == 1 && sc.atLineEnd) {
			// Begin of here-doc (the line after the here-doc delimiter):
			// Lexically, the here-doc starts from the next line after the >>, but the
			// first line of here-doc seem to follow the style of the last EOL sequence
			int st_new = SCE_PL_HERE_QQ;
			HereDoc.State = 2;
			if (HereDoc.Quoted) {
				if (sc.state == SCE_PL_HERE_DELIM) {
					// Missing quote at end of string! We are stricter than perl.
					// Colour here-doc anyway while marking this bit as an error.
					sc.ChangeState(SCE_PL_ERROR);
				}
				switch (HereDoc.Quote) {
				case '\'':
					st_new = SCE_PL_HERE_Q ;
					break;
				case '"' :
					st_new = SCE_PL_HERE_QQ;
					break;
				case '`' :
					st_new = SCE_PL_HERE_QX;
					break;
				}
			} else {
				if (HereDoc.Quote == '\\')
					st_new = SCE_PL_HERE_Q;
			}
			sc.SetState(st_new);
		}
		if (HereDoc.State == 3 && sc.atLineEnd) {
			// Start of format body.
			HereDoc.State = 0;
			sc.SetState(SCE_PL_FORMAT);
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_PL_DEFAULT) {
			if (IsADigit(sc.ch) ||
			        (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) {
				sc.SetState(SCE_PL_NUMBER);
				backFlag = BACK_NONE;
				numState = PERLNUM_DECIMAL;
				dotCount = 0;
				if (sc.ch == '0') {		// hex,bin,octal
					if (sc.chNext == 'x' || sc.chNext == 'X') {
						numState = PERLNUM_HEX;
					} else if (sc.chNext == 'b' || sc.chNext == 'B') {
						numState = PERLNUM_BINARY;
					} else if (IsADigit(sc.chNext)) {
						numState = PERLNUM_OCTAL;
					}
					if (numState != PERLNUM_DECIMAL) {
						sc.Forward();
					}
				} else if (sc.ch == 'v') {		// vector
					numState = PERLNUM_V_VECTOR;
				}
			} else if (setWord.Contains(sc.ch)) {
				// if immediately prefixed by '::', always a bareword
				sc.SetState(SCE_PL_WORD);
				if (sc.chPrev == ':' && sc.GetRelative(-2) == ':') {
					sc.ChangeState(SCE_PL_IDENTIFIER);
				}
				unsigned int bk = sc.currentPos;
				unsigned int fw = sc.currentPos + 1;
				// first check for possible quote-like delimiter
				if (sc.ch == 's' && !setWord.Contains(sc.chNext)) {
					sc.ChangeState(SCE_PL_REGSUBST);
					Quote.New(2);
				} else if (sc.ch == 'm' && !setWord.Contains(sc.chNext)) {
					sc.ChangeState(SCE_PL_REGEX);
					Quote.New();
				} else if (sc.ch == 'q' && !setWord.Contains(sc.chNext)) {
					sc.ChangeState(SCE_PL_STRING_Q);
					Quote.New();
				} else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) {
					sc.ChangeState(SCE_PL_XLAT);
					Quote.New(2);
				} else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) {
					sc.ChangeState(SCE_PL_XLAT);
					Quote.New(2);
					sc.Forward();
					fw++;
				} else if (sc.ch == 'q' && setQDelim.Contains(sc.chNext)
				        && !setWord.Contains(sc.GetRelative(2))) {
					if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ);
					else if (sc.chNext == 'x') sc.ChangeState(SCE_PL_STRING_QX);
					else if (sc.chNext == 'r') sc.ChangeState(SCE_PL_STRING_QR);
					else sc.ChangeState(SCE_PL_STRING_QW);	// sc.chNext == 'w'
					Quote.New();
					sc.Forward();
					fw++;
				} else if (sc.ch == 'x' && (sc.chNext == '=' ||	// repetition
				        !setWord.Contains(sc.chNext) ||
				        (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) {
					sc.ChangeState(SCE_PL_OPERATOR);
				}
				// if potentially a keyword, scan forward and grab word, then check
				// if it's really one; if yes, disambiguation test is performed
				// otherwise it is always a bareword and we skip a lot of scanning
				if (sc.state == SCE_PL_WORD) {
					while (setWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(fw))))
						fw++;
					if (!isPerlKeyword(styler.GetStartSegment(), fw, keywords, styler)) {
						sc.ChangeState(SCE_PL_IDENTIFIER);
					}
				}
				// if already SCE_PL_IDENTIFIER, then no ambiguity, skip this
				// for quote-like delimiters/keywords, attempt to disambiguate
				// to select for bareword, change state -> SCE_PL_IDENTIFIER
				if (sc.state != SCE_PL_IDENTIFIER && bk > 0) {
					if (disambiguateBareword(styler, bk, fw, backFlag, backPos, endPos))
						sc.ChangeState(SCE_PL_IDENTIFIER);
				}
				backFlag = BACK_NONE;
			} else if (sc.ch == '#') {
				sc.SetState(SCE_PL_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_PL_STRING);
				Quote.New();
				Quote.Open(sc.ch);
				backFlag = BACK_NONE;
			} else if (sc.ch == '\'') {
				if (sc.chPrev == '&' && setWordStart.Contains(sc.chNext)) {
					// Archaic call
					sc.SetState(SCE_PL_IDENTIFIER);
				} else {
					sc.SetState(SCE_PL_CHARACTER);
					Quote.New();
					Quote.Open(sc.ch);
				}
				backFlag = BACK_NONE;
			} else if (sc.ch == '`') {
				sc.SetState(SCE_PL_BACKTICKS);
				Quote.New();
				Quote.Open(sc.ch);
				backFlag = BACK_NONE;
			} else if (sc.ch == '$') {
				sc.SetState(SCE_PL_SCALAR);
				if (sc.chNext == '{') {
					sc.ForwardSetState(SCE_PL_OPERATOR);
				} else if (IsASpace(sc.chNext)) {
					sc.ForwardSetState(SCE_PL_DEFAULT);
				} else {
					sc.Forward();
					if (sc.Match('`', '`') || sc.Match(':', ':')) {
						sc.Forward();
					}
				}
				backFlag = BACK_NONE;
			} else if (sc.ch == '@') {
				sc.SetState(SCE_PL_ARRAY);
				if (setArray.Contains(sc.chNext)) {
					// no special treatment
				} else if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
					sc.Forward(2);
				} else if (sc.chNext == '{' || sc.chNext == '[') {
					sc.ForwardSetState(SCE_PL_OPERATOR);
				} else {
					sc.ChangeState(SCE_PL_OPERATOR);
				}
				backFlag = BACK_NONE;
			} else if (setPreferRE.Contains(sc.ch)) {
				// Explicit backward peeking to set a consistent preferRE for
				// any slash found, so no longer need to track preferRE state.
				// Find first previous significant lexed element and interpret.
				// A few symbols shares this code for disambiguation.
				bool preferRE = false;
				bool isHereDoc = sc.Match('<', '<');
				bool hereDocSpace = false;		// for: SCALAR [whitespace] '<<'
				unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0;
				sc.Complete();
				styler.Flush();
				if (styler.StyleAt(bk) == SCE_PL_DEFAULT)
					hereDocSpace = true;
				skipWhitespaceComment(styler, bk);
				if (bk == 0) {
					// avoid backward scanning breakage
					preferRE = true;
				} else {
					int bkstyle = styler.StyleAt(bk);
					int bkch = static_cast<unsigned char>(styler.SafeGetCharAt(bk));
					switch (bkstyle) {
					case SCE_PL_OPERATOR:
						preferRE = true;
						if (bkch == ')' || bkch == ']') {
							preferRE = false;
						} else if (bkch == '}') {
							// backtrack by counting balanced brace pairs
							// needed to test for variables like ${}, @{} etc.
							bkstyle = styleBeforeBracePair(styler, bk);
							if (bkstyle == SCE_PL_SCALAR
							        || bkstyle == SCE_PL_ARRAY
							        || bkstyle == SCE_PL_HASH
							        || bkstyle == SCE_PL_SYMBOLTABLE
							        || bkstyle == SCE_PL_OPERATOR) {
								preferRE = false;
							}
						} else if (bkch == '+' || bkch == '-') {
							if (bkch == static_cast<unsigned char>(styler.SafeGetCharAt(bk - 1))
							        && bkch != static_cast<unsigned char>(styler.SafeGetCharAt(bk - 2)))
								// exceptions for operators: unary suffixes ++, --
								preferRE = false;
						}
						break;
					case SCE_PL_IDENTIFIER:
						preferRE = true;
						bkstyle = styleCheckIdentifier(styler, bk);
						if ((bkstyle == 1) || (bkstyle == 2)) {
							// inputsymbol or var with "->" or "::" before identifier
							preferRE = false;
						} else if (bkstyle == 3) {
							// bare identifier, test cases follows:
							if (sc.ch == '/') {
								// if '/', /PATTERN/ unless digit/space immediately after '/'
								// if '//', always expect defined-or operator to follow identifier
								if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/')
									preferRE = false;
							} else if (sc.ch == '*' || sc.ch == '%') {
								if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*'))
									preferRE = false;
							} else if (sc.ch == '<') {
								if (IsASpace(sc.chNext) || sc.chNext == '=')
									preferRE = false;
							}
						}
						break;
					case SCE_PL_SCALAR:		// for $var<< case:
						if (isHereDoc && hereDocSpace)	// if SCALAR whitespace '<<', *always* a HERE doc
							preferRE = true;
						break;
					case SCE_PL_WORD:
						preferRE = true;
						// for HERE docs, always true
						if (sc.ch == '/') {
							// adopt heuristics similar to vim-style rules:
							// keywords always forced as /PATTERN/: split, if, elsif, while
							// everything else /PATTERN/ unless digit/space immediately after '/'
							// for '//', defined-or favoured unless special keywords
							unsigned int bkend = bk + 1;
							while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) {
								bk--;
							}
							if (isPerlKeyword(bk, bkend, reWords, styler))
								break;
							if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.chNext == '/')
								preferRE = false;
						} else if (sc.ch == '*' || sc.ch == '%') {
							if (IsASpace(sc.chNext) || IsADigit(sc.chNext) || sc.Match('*', '*'))
								preferRE = false;
						} else if (sc.ch == '<') {
							if (IsASpace(sc.chNext) || sc.chNext == '=')
								preferRE = false;
						}
						break;

						// other styles uses the default, preferRE=false
					case SCE_PL_POD:
					case SCE_PL_HERE_Q:
					case SCE_PL_HERE_QQ:
					case SCE_PL_HERE_QX:
						preferRE = true;
						break;
					}
				}
				backFlag = BACK_NONE;
				if (isHereDoc) {	// handle '<<', HERE doc
					if (preferRE) {
						sc.SetState(SCE_PL_HERE_DELIM);
						HereDoc.State = 0;
					} else {		// << operator
						sc.SetState(SCE_PL_OPERATOR);
						sc.Forward();
					}
				} else if (sc.ch == '*') {	// handle '*', typeglob
					if (preferRE) {
						sc.SetState(SCE_PL_SYMBOLTABLE);
						if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
							sc.Forward(2);
						} else if (sc.chNext == '{') {
							sc.ForwardSetState(SCE_PL_OPERATOR);
						} else {
							sc.Forward();
						}
					} else {
						sc.SetState(SCE_PL_OPERATOR);
						if (sc.chNext == '*') 	// exponentiation
							sc.Forward();
					}
				} else if (sc.ch == '%') {	// handle '%', hash
					if (preferRE) {
						sc.SetState(SCE_PL_HASH);
						if (setHash.Contains(sc.chNext)) {
							sc.Forward();
						} else if (sc.chNext == ':' && sc.GetRelative(2) == ':') {
							sc.Forward(2);
						} else if (sc.chNext == '{') {
							sc.ForwardSetState(SCE_PL_OPERATOR);
						} else {
							sc.ChangeState(SCE_PL_OPERATOR);
						}
					} else {
						sc.SetState(SCE_PL_OPERATOR);
					}
				} else if (sc.ch == '<') {	// handle '<', inputsymbol
					if (preferRE) {
						// forward scan
						int i = inputsymbolScan(styler, sc.currentPos, endPos);
						if (i > 0) {
							sc.SetState(SCE_PL_IDENTIFIER);
							sc.Forward(i);
						} else {
							sc.SetState(SCE_PL_OPERATOR);
						}
					} else {
						sc.SetState(SCE_PL_OPERATOR);
					}
				} else {			// handle '/', regexp
					if (preferRE) {
						sc.SetState(SCE_PL_REGEX);
						Quote.New();
						Quote.Open(sc.ch);
					} else {		// / and // operators
						sc.SetState(SCE_PL_OPERATOR);
						if (sc.chNext == '/') {
							sc.Forward();
						}
					}
				}
			} else if (sc.ch == '='		// POD
			        && setPOD.Contains(sc.chNext)
			        && sc.atLineStart) {
				sc.SetState(SCE_PL_POD);
				backFlag = BACK_NONE;
			} else if (sc.ch == '-' && setWordStart.Contains(sc.chNext)) {	// extended '-' cases
				unsigned int bk = sc.currentPos;
				unsigned int fw = 2;
				if (setSingleCharOp.Contains(sc.chNext) &&	// file test operators
				        !setWord.Contains(sc.GetRelative(2))) {
					sc.SetState(SCE_PL_WORD);
				} else {
					// nominally a minus and bareword; find extent of bareword
					while (setWord.Contains(sc.GetRelative(fw)))
						fw++;
					sc.SetState(SCE_PL_OPERATOR);
				}
				// force to bareword for hash key => or {variable literal} cases
				if (disambiguateBareword(styler, bk, bk + fw, backFlag, backPos, endPos) & 2) {
					sc.ChangeState(SCE_PL_IDENTIFIER);
				}
				backFlag = BACK_NONE;
			} else if (sc.ch == '(' && sc.currentPos > 0) {	// '(' or subroutine prototype
				sc.Complete();
				if (styleCheckSubPrototype(styler, sc.currentPos - 1)) {
					sc.SetState(SCE_PL_SUB_PROTOTYPE);
					backFlag = BACK_NONE;
				} else {
					sc.SetState(SCE_PL_OPERATOR);
				}
			} else if (setPerlOperator.Contains(sc.ch)) {	// operators
				sc.SetState(SCE_PL_OPERATOR);
				if (sc.Match('.', '.')) {	// .. and ...
					sc.Forward();
					if (sc.chNext == '.') sc.Forward();
				}
			} else if (sc.ch == 4 || sc.ch == 26) {		// ^D and ^Z ends valid perl source
				sc.SetState(SCE_PL_DATASECTION);
			} else {
				// keep colouring defaults
				sc.Complete();
			}
		}
	}
	sc.Complete();
	if (sc.state == SCE_PL_HERE_Q
	        || sc.state == SCE_PL_HERE_QQ
	        || sc.state == SCE_PL_HERE_QX
	        || sc.state == SCE_PL_FORMAT) {
		styler.ChangeLexerState(sc.currentPos, styler.Length());
	}
	sc.Complete();
}

#define PERL_HEADFOLD_SHIFT		4
#define PERL_HEADFOLD_MASK		0xF0

void SCI_METHOD LexerPerl::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) {

	if (!options.fold)
		return;

	LexAccessor styler(pAccess);

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);

	// Backtrack to previous line in case need to fix its fold status
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}

	int levelPrev = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	char chPrev = styler.SafeGetCharAt(startPos - 1);
	int styleNext = styler.StyleAt(startPos);
	// Used at end of line to determine if the line was a package definition
	bool isPackageLine = false;
	int podHeading = 0;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT;
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		bool atLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0;
		// Comment folding
		if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) {
			if (!IsCommentLine(lineCurrent - 1, styler)
			        && IsCommentLine(lineCurrent + 1, styler))
				levelCurrent++;
			else if (IsCommentLine(lineCurrent - 1, styler)
			        && !IsCommentLine(lineCurrent + 1, styler))
				levelCurrent--;
		}
		// {} [] block folding
		if (style == SCE_PL_OPERATOR) {
			if (ch == '{') {
				if (options.foldAtElse && levelCurrent < levelPrev)
					--levelPrev;
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
			if (ch == '[') {
				if (options.foldAtElse && levelCurrent < levelPrev)
					--levelPrev;
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}
		// POD folding
		if (options.foldPOD && atLineStart) {
			if (style == SCE_PL_POD) {
				if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB)
					levelCurrent++;
				else if (styler.Match(i, "=cut"))
					levelCurrent = (levelCurrent & ~PERL_HEADFOLD_MASK) - 1;
				else if (styler.Match(i, "=head"))
					podHeading = PodHeadingLevel(i, styler);
			} else if (style == SCE_PL_DATASECTION) {
				if (ch == '=' && isascii(chNext) && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE)
					levelCurrent++;
				else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE)
					levelCurrent = (levelCurrent & ~PERL_HEADFOLD_MASK) - 1;
				else if (styler.Match(i, "=head"))
					podHeading = PodHeadingLevel(i, styler);
				// if package used or unclosed brace, level > SC_FOLDLEVELBASE!
				// reset needed as level test is vs. SC_FOLDLEVELBASE
				else if (stylePrevCh != SCE_PL_DATASECTION)
					levelCurrent = SC_FOLDLEVELBASE;
			}
		}
		// package folding
		if (options.foldPackage && atLineStart) {
			if (IsPackageLine(lineCurrent, styler)
			        && !IsPackageLine(lineCurrent + 1, styler))
				isPackageLine = true;
		}

		//heredoc folding
		switch (style) {
		case SCE_PL_HERE_QQ :
		case SCE_PL_HERE_Q :
		case SCE_PL_HERE_QX :
			switch (stylePrevCh) {
			case SCE_PL_HERE_QQ :
			case SCE_PL_HERE_Q :
			case SCE_PL_HERE_QX :
				//do nothing;
				break;
			default :
				levelCurrent++;
				break;
			}
			break;
		default:
			switch (stylePrevCh) {
			case SCE_PL_HERE_QQ :
			case SCE_PL_HERE_Q :
			case SCE_PL_HERE_QX :
				levelCurrent--;
				break;
			default :
				//do nothing;
				break;
			}
			break;
		}

		//explicit folding
		if (options.foldCommentExplicit && style == SCE_PL_COMMENTLINE && ch == '#') {
			if (chNext == '{') {
				levelCurrent++;
			} else if (levelCurrent > SC_FOLDLEVELBASE  && chNext == '}') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			// POD headings occupy bits 7-4, leaving some breathing room for
			// non-standard practice -- POD sections stuck in blocks, etc.
			if (podHeading > 0) {
				levelCurrent = (lev & ~PERL_HEADFOLD_MASK) | (podHeading << PERL_HEADFOLD_SHIFT);
				lev = levelCurrent - 1;
				lev |= SC_FOLDLEVELHEADERFLAG;
				podHeading = 0;
			}
			// Check if line was a package declaration
			// because packages need "special" treatment
			if (isPackageLine) {
				lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
				levelCurrent = SC_FOLDLEVELBASE + 1;
				isPackageLine = false;
			}
			lev |= levelCurrent << 16;
			if (visibleChars == 0 && options.foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
		chPrev = ch;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmPerl(SCLEX_PERL, LexerPerl::LexerFactoryPerl, "perl", perlWordListDesc, 8);

Added lexers/LexPowerPro.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
// Scintilla source code edit control
// @file LexPowerPro.cxx
// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com
// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net)
//
// Lexer code heavily borrowed from:
//	LexAU3.cxx by Jos van der Zande
//	LexCPP.cxx by Neil Hodgson
//	LexVB.cxx by Neil Hodgson
//
// Changes:
// 	2008-10-25 - Initial release
//	2008-10-26 - Changed how <name> is hilighted in  'function <name>' so that
//				 local isFunction = "" and local functions = "" don't get falsely highlighted
//	2008-12-14 - Added bounds checking for szFirstWord and szDo
//			   - Replaced SetOfCharacters with CharacterSet
//			   - Made sure that CharacterSet::Contains is passed only positive values
//			   - Made sure that the return value of Accessor::SafeGetCharAt is positive before
//				 passing to functions that require positive values like isspacechar()
//			   - Removed unused visibleChars processing from ColourisePowerProDoc()
//			   - Fixed bug with folding logic where line continuations didn't end where
//				 they were supposed to
//			   - Moved all helper functions to the top of the file
//	2010-06-03 - Added onlySpaces variable to allow the @function and ;comment styles to be indented
//			   - Modified HasFunction function to be a bit more robust
//			   - Renamed HasFunction function to IsFunction
//			   - Cleanup
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsStreamCommentStyle(int style) {
	return style == SCE_POWERPRO_COMMENTBLOCK;
}

static inline bool IsLineEndChar(unsigned char ch) {
	return 	ch == 0x0a 		//LF
			|| ch == 0x0c	//FF
			|| ch == 0x0d;	//CR
}

static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
{
	int startPos = styler.LineStart(szLine);
	int endPos = styler.LineStart(szLine + 1) - 2;
	while (startPos < endPos)
	{
		char stylech = styler.StyleAt(startPos);
		if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) {
			char ch = styler.SafeGetCharAt(endPos);
			char chPrev = styler.SafeGetCharAt(endPos - 1);
			char chPrevPrev = styler.SafeGetCharAt(endPos - 2);
			if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) )
				return (chPrevPrev == ';' && chPrev == ';' && ch == '+');
			}
		endPos--; // skip to next char
	}
	return false;
}

// Routine to find first none space on the current line and return its Style
// needed for comment lines not starting on pos 1
static int GetStyleFirstWord(int szLine, Accessor &styler)
{
	int startPos = styler.LineStart(szLine);
	int endPos = styler.LineStart(szLine + 1) - 1;
	char ch = styler.SafeGetCharAt(startPos);

	while (ch > 0 && isspacechar(ch) && startPos < endPos)
	{
		startPos++; // skip to next char
		ch = styler.SafeGetCharAt(startPos);
	}
	return styler.StyleAt(startPos);
}

//returns true if there is a function to highlight
//used to highlight <name> in 'function <name>'
//note:
//		sample line (without quotes): "\tfunction asdf()
//		currentPos will be the position of 'a'
static bool IsFunction(Accessor &styler, unsigned int currentPos) {

	const char function[10] = "function "; //10 includes \0
	unsigned int numberOfCharacters = sizeof(function) - 1;
	unsigned int position = currentPos - numberOfCharacters;

	//compare each character with the letters in the function array
	//return false if ALL don't match
	for (unsigned int i = 0; i < numberOfCharacters; i++) {
		char c = styler.SafeGetCharAt(position++);
		if (c != function[i])
			return false;
	}

	//make sure that there are only spaces (or tabs) between the beginning
	//of the line and the function declaration
	position = currentPos - numberOfCharacters - 1; 		//-1 to move to char before 'function'
	for (unsigned int j = 0; j < 16; j++) {					//check up to 16 preceeding characters
		char c = styler.SafeGetCharAt(position--, '\0');	//if can't read char, return NUL (past beginning of document)
		if (c <= 0)	//reached beginning of document
			return true;
		if (c > 0 && IsLineEndChar(c))
			return true;
		else if (c > 0 && !IsASpaceOrTab(c))
			return false;
	}

	//fall-through
	return false;
}

static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler, bool caseSensitive) {

	WordList &keywords  = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	//define the character sets
	CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);

	StyleContext sc(startPos, length, initStyle, styler);
	char s_save[100]; //for last line highlighting

	//are there only spaces between the first letter of the line and the beginning of the line
	bool onlySpaces = true;

	for (; sc.More(); sc.Forward()) {

		// save the total current word for eof processing
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));

		if ((sc.ch > 0) && setWord.Contains(sc.ch))
		{
			strcpy(s_save,s);
			int tp = static_cast<int>(strlen(s_save));
			if (tp < 99) {
				s_save[tp] = static_cast<char>(tolower(sc.ch));
				s_save[tp+1] = '\0';
			}
		}

		if (sc.atLineStart) {
			if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) {
				// Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which
				// ends with a line continuation by locking in the state upto this position.
				sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
			}
		}

		// Determine if the current state should terminate.
		switch (sc.state) {
			case SCE_POWERPRO_OPERATOR:
				sc.SetState(SCE_POWERPRO_DEFAULT);
				break;

			case SCE_POWERPRO_NUMBER:

				if (!IsADigit(sc.ch))
					sc.SetState(SCE_POWERPRO_DEFAULT);

				break;

			case SCE_POWERPRO_IDENTIFIER:
				//if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized
				if ((sc.ch > 0) && !setWord.Contains(sc.ch)){  // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately
					char s[1000];
					if (caseSensitive) {
						sc.GetCurrent(s, sizeof(s));
					} else {
						sc.GetCurrentLowered(s, sizeof(s));
					}

					if (keywords.InList(s)) {
						sc.ChangeState(SCE_POWERPRO_WORD);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_POWERPRO_WORD2);
					} else if (keywords3.InList(s)) {
						sc.ChangeState(SCE_POWERPRO_WORD3);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_POWERPRO_WORD4);
					}
					sc.SetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_LINECONTINUE:
				if (sc.atLineStart) {
					sc.SetState(SCE_POWERPRO_DEFAULT);
				} else if (sc.Match('/', '*') || sc.Match('/', '/')) {
					sc.SetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_COMMENTBLOCK:
				if (sc.Match('*', '/')) {
					sc.Forward();
					sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_COMMENTLINE:
				if (sc.atLineStart) {
					sc.SetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_DOUBLEQUOTEDSTRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_POWERPRO_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_SINGLEQUOTEDSTRING:
				if (sc.atLineEnd) {
					sc.ChangeState(SCE_POWERPRO_STRINGEOL);
				} else if (sc.ch == '\\') {
					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
						sc.Forward();
					}
				} else if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_STRINGEOL:
				if (sc.atLineStart) {
					sc.SetState(SCE_POWERPRO_DEFAULT);
				}
				break;

			case SCE_POWERPRO_VERBATIM:
				if (sc.ch == '\"') {
					if (sc.chNext == '\"') {
						sc.Forward();
					} else {
						sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
					}
				}
				break;

			case SCE_POWERPRO_ALTQUOTE:
				if (sc.ch == '#') {
					if (sc.chNext == '#') {
						sc.Forward();
					} else {
						sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
					}
				}
				break;

			case SCE_POWERPRO_FUNCTION:
				if (isspacechar(sc.ch) || sc.ch == '(') {
					sc.SetState(SCE_POWERPRO_DEFAULT);
				}
			break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_POWERPRO_DEFAULT) {
			if (sc.Match('?', '\"')) {
				sc.SetState(SCE_POWERPRO_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_POWERPRO_NUMBER);
			}else if (sc.Match('?','#')) {
				if (sc.ch == '?' && sc.chNext == '#') {
					sc.SetState(SCE_POWERPRO_ALTQUOTE);
					sc.Forward();
				}
			} else if (IsFunction(styler, sc.currentPos)) {	//highlight <name> in 'function <name>'
				sc.SetState(SCE_POWERPRO_FUNCTION);
			} else if (onlySpaces && sc.ch == '@') { 		//alternate function definition [label]
				sc.SetState(SCE_POWERPRO_FUNCTION);
			} else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) {
				sc.SetState(SCE_POWERPRO_IDENTIFIER);
			} else if (sc.Match(";;+")) {
				sc.SetState(SCE_POWERPRO_LINECONTINUE);
			} else if (sc.Match('/', '*')) {
				sc.SetState(SCE_POWERPRO_COMMENTBLOCK);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				sc.SetState(SCE_POWERPRO_COMMENTLINE);
			} else if (onlySpaces && sc.ch == ';') {		//legacy comment that can only have blank space in front of it
				sc.SetState(SCE_POWERPRO_COMMENTLINE);
			} else if (sc.Match(";;")) {
				sc.SetState(SCE_POWERPRO_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING);
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_POWERPRO_OPERATOR);
			}
		}

		//maintain a record of whether or not all the preceding characters on
		//a line are space characters
		if (onlySpaces && !IsASpaceOrTab(sc.ch))
			onlySpaces = false;

		//reset when starting a new line
		if (sc.atLineEnd)
			onlySpaces = true;
	}

	//*************************************
	// Colourize the last word correctly
	//*************************************
	if (sc.state == SCE_POWERPRO_IDENTIFIER)
	{
		if (keywords.InList(s_save)) {
			sc.ChangeState(SCE_POWERPRO_WORD);
			sc.SetState(SCE_POWERPRO_DEFAULT);
		}
		else if (keywords2.InList(s_save)) {
			sc.ChangeState(SCE_POWERPRO_WORD2);
			sc.SetState(SCE_POWERPRO_DEFAULT);
		}
		else if (keywords3.InList(s_save)) {
			sc.ChangeState(SCE_POWERPRO_WORD3);
			sc.SetState(SCE_POWERPRO_DEFAULT);
		}
		else if (keywords4.InList(s_save)) {
			sc.ChangeState(SCE_POWERPRO_WORD4);
			sc.SetState(SCE_POWERPRO_DEFAULT);
		}
		else {
			sc.SetState(SCE_POWERPRO_DEFAULT);
		}
	}
	sc.Complete();
}

static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
	//define the character sets
	CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
	CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);

	//used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
	bool isFoldingAll = true;

	int endPos = startPos + length;
	int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly

	// get settings from the config files for folding comments and preprocessor lines
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
	bool foldCompact = true;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		isFoldingAll = false;
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	// vars for style of previous/current/next lines
	int style = GetStyleFirstWord(lineCurrent,styler);
	int stylePrev = 0;

	// find the first previous line without continuation character at the end
	while ((lineCurrent > 0 && IsContinuationLine(lineCurrent, styler))
	       || (lineCurrent > 1 && IsContinuationLine(lineCurrent - 1, styler))) {
		lineCurrent--;
		startPos = styler.LineStart(lineCurrent);
	}

	if (lineCurrent > 0) {
		stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
	}

	// vars for getting first word to check for keywords
	bool isFirstWordStarted = false;
	bool isFirstWordEnded = false;

	const unsigned int FIRST_WORD_MAX_LEN = 10;
	char szFirstWord[FIRST_WORD_MAX_LEN] = "";
	unsigned int firstWordLen = 0;

	char szDo[3]="";
	int	 szDolen = 0;
	bool isDoLastWord = false;

	// var for indentlevel
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelNext = levelCurrent;

	int	visibleChars = 0;
	int functionCount = 0;

	char chNext = styler.SafeGetCharAt(startPos);
	char chPrev = '\0';
	char chPrevPrev = '\0';
	char chPrevPrevPrev = '\0';

	for (int i = startPos; i < endPos; i++) {

		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch > 0) && setWord.Contains(ch))
			visibleChars++;

		// get the syle for the current character neede to check in comment
		int stylech = styler.StyleAt(i);

		// start the capture of the first word
		if (!isFirstWordStarted && (ch > 0)) {
			if (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/') {
				isFirstWordStarted = true;
				if (firstWordLen < FIRST_WORD_MAX_LEN - 1) {
					szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
					szFirstWord[firstWordLen] = '\0';
				}
			}
		} // continue capture of the first word on the line
		else if (isFirstWordStarted && !isFirstWordEnded && (ch > 0)) {
			if (!setWord.Contains(ch)) {
				isFirstWordEnded = true;
			}
			else if (firstWordLen < (FIRST_WORD_MAX_LEN - 1)) {
				szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
				szFirstWord[firstWordLen] = '\0';
			}
		}

		if (stylech != SCE_POWERPRO_COMMENTLINE) {

			//reset isDoLastWord if we find a character(ignoring spaces) after 'do'
			if (isDoLastWord && (ch > 0) && setWord.Contains(ch))
				isDoLastWord = false;

			// --find out if the word "do" is the last on a "if" line--
			// collect each letter and put it into a buffer 2 chars long
			// if we end up with "do" in the buffer when we reach the end of
			// the line, "do" was the last word on the line
			if ((ch > 0) && isFirstWordEnded && strcmp(szFirstWord, "if") == 0) {
				if (szDolen == 2) {
					szDo[0] = szDo[1];
					szDo[1] = static_cast<char>(tolower(ch));
					szDo[2] = '\0';

					if (strcmp(szDo, "do") == 0)
						isDoLastWord = true;

				} else if (szDolen < 2) {
					szDo[szDolen++] = static_cast<char>(tolower(ch));
					szDo[szDolen] = '\0';
				}
			}
		}

		// End of Line found so process the information
		 if ((ch == '\r' && chNext != '\n') // \r\n
			|| ch == '\n' 					// \n
			|| i == endPos) {				// end of selection

			// **************************
			// Folding logic for Keywords
			// **************************

			// if a keyword is found on the current line and the line doesn't end with ;;+ (continuation)
			//    and we are not inside a commentblock.
			if (firstWordLen > 0
				&& chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev !=';'
				&& (!IsStreamCommentStyle(style) || foldInComment) ) {

				// only fold "if" last keyword is "then"  (else its a one line if)
				if (strcmp(szFirstWord, "if") == 0  && isDoLastWord)
						levelNext++;

				// create new fold for these words
				if (strcmp(szFirstWord, "for") == 0)
					levelNext++;

				//handle folding for functions/labels
				//Note: Functions and labels don't have an explicit end like [end function]
				//	1. functions/labels end at the start of another function
				//	2. functions/labels end at the end of the file
				if ((strcmp(szFirstWord, "function") == 0) || (firstWordLen > 0 && szFirstWord[0] == '@')) {
					if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script)

						if (functionCount > 0) {
							levelCurrent--;
						} else {
							levelNext++;
						}
						functionCount++;

					} else { //if just folding a small piece (by clicking on the minus sign next to the word)
						levelCurrent--;
					}
				}

				// end the fold for these words before the current line
				if (strcmp(szFirstWord, "endif") == 0 || strcmp(szFirstWord, "endfor") == 0) {
						levelNext--;
						levelCurrent--;
				}

				// end the fold for these words before the current line and Start new fold
				if (strcmp(szFirstWord, "else") == 0 || strcmp(szFirstWord, "elseif") == 0 )
						levelCurrent--;

			}
			// Preprocessor and Comment folding
			int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);

			// *********************************
			// Folding logic for Comment blocks
			// *********************************
			if (foldComment && IsStreamCommentStyle(style)) {

				// Start of a comment block
				if (stylePrev != style && IsStreamCommentStyle(styleNext) && styleNext == style) {
				    levelNext++;
				} // fold till the last line for normal comment lines
				else if (IsStreamCommentStyle(stylePrev)
						&& styleNext != SCE_POWERPRO_COMMENTLINE
						&& stylePrev == SCE_POWERPRO_COMMENTLINE
						&& style == SCE_POWERPRO_COMMENTLINE) {
					levelNext--;
				} // fold till the one but last line for Blockcomment lines
				else if (IsStreamCommentStyle(stylePrev)
						&& styleNext != SCE_POWERPRO_COMMENTBLOCK
						&& style == SCE_POWERPRO_COMMENTBLOCK) {
					levelNext--;
					levelCurrent--;
				}
			}

			int levelUse = levelCurrent;
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent))
				styler.SetLevel(lineCurrent, lev);

			// reset values for the next line
			lineCurrent++;
			stylePrev = style;
			style = styleNext;
			levelCurrent = levelNext;
			visibleChars = 0;

			// if the last characters are ;;+ then don't reset since the line continues on the next line.
			if (chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev != ';') {
				firstWordLen = 0;
				szDolen = 0;
				isFirstWordStarted = false;
				isFirstWordEnded = false;
				isDoLastWord = false;

				//blank out first word
				for (unsigned int i = 0; i < FIRST_WORD_MAX_LEN; i++)
					szFirstWord[i] = '\0';
			}
		}

		// save the last processed characters
		if ((ch > 0) && !isspacechar(ch)) {
			chPrevPrevPrev = chPrevPrev;
			chPrevPrev = chPrev;
			chPrev = ch;
		}
	}

	//close folds on the last line - without this a 'phantom'
	//fold can appear when an open fold is on the last line
	//this can occur because functions and labels don't have an explicit end
	if (lineCurrent >= lastLine) {
		int lev = 0;
		lev |= SC_FOLDLEVELWHITEFLAG;
		styler.SetLevel(lineCurrent, lev);
	}

}

static const char * const powerProWordLists[] = {
            "Keyword list 1",
            "Keyword list 2",
            "Keyword list 3",
            "Keyword list 4",
            0,
        };

static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                       Accessor &styler) {
	ColourisePowerProDoc(startPos, length, initStyle, keywordlists, styler, false);
}

LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists);


Added lexers/LexPowerShell.cxx.



















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexPowerShell.cxx
 ** Lexer for PowerShell scripts.
 **/
// Copyright 2008 by Tim Gerundt <tim@gerundt.de>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_';
}

static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];

	styler.StartAt(startPos);

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_POWERSHELL_COMMENT) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) {
			if (sc.ch == '>' && sc.chPrev == '#') {
				sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_STRING) {
			// This is a doubles quotes string
			if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_CHARACTER) {
			// This is a single quote string
			if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_NUMBER) {
			if (!IsADigit(sc.ch)) {
				sc.SetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_VARIABLE) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_OPERATOR) {
			if (!isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_POWERSHELL_DEFAULT);
			}
		} else if (sc.state == SCE_POWERSHELL_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));

				if (keywords.InList(s)) {
					sc.ChangeState(SCE_POWERSHELL_KEYWORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_POWERSHELL_CMDLET);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_POWERSHELL_ALIAS);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_POWERSHELL_FUNCTION);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_POWERSHELL_USER1);
				}
				sc.SetState(SCE_POWERSHELL_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_POWERSHELL_DEFAULT) {
			if (sc.ch == '#') {
				sc.SetState(SCE_POWERSHELL_COMMENT);
			} else if (sc.ch == '<' && sc.chNext == '#') {
				sc.SetState(SCE_POWERSHELL_COMMENTSTREAM);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_POWERSHELL_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_POWERSHELL_CHARACTER);
			} else if (sc.ch == '$') {
				sc.SetState(SCE_POWERSHELL_VARIABLE);
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_POWERSHELL_NUMBER);
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_POWERSHELL_OPERATOR);
			} else if (IsAWordChar(sc.ch)) {
				sc.SetState(SCE_POWERSHELL_IDENTIFIER);
			}
		}
	}
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldPowerShellDoc(unsigned int startPos, int length, int initStyle,
                           WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_POWERSHELL_OPERATOR) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		} else if (foldComment && style == SCE_POWERSHELL_COMMENTSTREAM) {
			if (stylePrev != SCE_POWERSHELL_COMMENTSTREAM) {
				levelNext++;
			} else if (styleNext != SCE_POWERSHELL_COMMENTSTREAM) {
				levelNext--;
			}
		}
		if (!IsASpace(ch))
			visibleChars++;
		if (atEOL || (i == endPos-1)) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
	}
}

static const char * const powershellWordLists[] = {
	"Commands",
	"Cmdlets",
	"Aliases",
	"Functions",
	"User1",
	0
};

LexerModule lmPowerShell(SCLEX_POWERSHELL, ColourisePowerShellDoc, "powershell", FoldPowerShellDoc, powershellWordLists);

Added lexers/LexProgress.cxx.





















































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// Scintilla source code edit control
/** @file LexProgress.cxx
 **  Lexer for Progress 4GL.
 ** Based on LexCPP.cxx of Neil Hodgson <neilh@scintilla.org>
  **/
// Copyright 2006-2007 by Yuval Papish <Yuval@YuvCom.com>
// The License.txt file describes the conditions under which this software may be distributed.

/** TODO:
WebSpeed support in html lexer
Support "end triggers" expression of the triggers phrase
Support more than 6 comments levels
**/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return (ch < 0x80) && (isalpha(ch) || ch == '_');
}

enum SentenceStart { SetSentenceStart = 0xf, ResetSentenceStart = 0x10}; // true -> bit = 0

static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

    WordList &keywords1 = *keywordlists[0];   // regular keywords
    WordList &keywords2 = *keywordlists[1];   // block opening keywords, only when SentenceStart
    WordList &keywords3 = *keywordlists[2];   // block opening keywords
    //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented


	int visibleChars = 0;
	int mask;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}

		// Handle line continuation generically.
		if ((sc.state & 0xf) < SCE_4GL_COMMENT1) {
		if (sc.ch == '~') {
			if (sc.chNext > ' ') {
				// skip special char after ~
				sc.Forward();
				continue;
			}
			else {
				// Skip whitespace between ~ and EOL
				while (sc.More() && (sc.chNext == ' ' || sc.chNext == '\t') ) {
					sc.Forward();
				}
				if (sc.chNext == '\n' || sc.chNext == '\r') {
					sc.Forward();
					if (sc.ch == '\r' && sc.chNext == '\n') {
						sc.Forward();
					}
					sc.Forward();
					continue;
				}
			}
		}
		}
		// Determine if a new state should be terminated.
		mask = sc.state & 0x10;
		switch (sc.state & 0xf) {
			case SCE_4GL_OPERATOR:
				sc.SetState(SCE_4GL_DEFAULT | mask);
				break;
			case SCE_4GL_NUMBER:
				if (!(IsADigit(sc.ch))) {
					sc.SetState(SCE_4GL_DEFAULT | mask);
				}
				break;
			case SCE_4GL_IDENTIFIER:
				if (!IsAWordChar(sc.ch) && sc.ch != '-') {
					char s[1000];
					sc.GetCurrentLowered(s, sizeof(s));
					if ((((sc.state & 0x10) == 0) && keywords2.InList(s)) || keywords3.InList(s)) {
						sc.ChangeState(SCE_4GL_BLOCK | ResetSentenceStart);
					}
					else if (keywords1.InList(s)) {
						if ((s[0] == 'e' && s[1] =='n' && s[2] == 'd' && !isalnum(s[3]) && s[3] != '-') ||
							(s[0] == 'f' && s[1] =='o' && s[2] == 'r' && s[3] == 'w' && s[4] =='a' && s[5] == 'r' && s[6] == 'd'&& !isalnum(s[7]))) {
							sc.ChangeState(SCE_4GL_END | ResetSentenceStart);
						}
						else if	((s[0] == 'e' && s[1] =='l' && s[2] == 's' && s[3] == 'e') ||
								 (s[0] == 't' && s[1] =='h' && s[2] == 'e' && s[3] == 'n')) {
							sc.ChangeState(SCE_4GL_WORD & SetSentenceStart);
						}
						else {
							sc.ChangeState(SCE_4GL_WORD | ResetSentenceStart);
						}
					}
					sc.SetState(SCE_4GL_DEFAULT | (sc.state & 0x10));
				}
				break;
			case SCE_4GL_PREPROCESSOR:
				if (sc.atLineStart) {
					sc.SetState(SCE_4GL_DEFAULT & SetSentenceStart);
				}
				/* code removed to allow comments inside preprocessor
					else if (sc.ch == '*' && sc.chNext == '/') {
					sc.ForwardSetState(SCE_4GL_DEFAULT | sentenceStartState); } */
				break;
			case SCE_4GL_STRING:
				if (sc.ch == '\"') {
					sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
				}
				break;
			case SCE_4GL_CHARACTER:
				if (sc.ch == '\'') {
					sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
				}
				break;
			default:
				if ((sc.state & 0xf) >= SCE_4GL_COMMENT1) {
					if (sc.ch == '*' && sc.chNext == '/') {
						sc.Forward();
						if ((sc.state & 0xf) == SCE_4GL_COMMENT1) {
							sc.ForwardSetState(SCE_4GL_DEFAULT | mask);
						}
						else
							sc.SetState((sc.state & 0x1f) - 1);
					} else if (sc.ch == '/' && sc.chNext == '*') {
						sc.Forward();
						sc.SetState((sc.state & 0x1f) + 1);
					}
				}
		}

		// Determine if a new state should be entered.
		mask = sc.state & 0x10;
		if ((sc.state & 0xf) == SCE_4GL_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_4GL_NUMBER | ResetSentenceStart);
			} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
				sc.SetState(SCE_4GL_IDENTIFIER | mask);
			} else if (sc.ch == '/' && sc.chNext == '*') {
				sc.SetState(SCE_4GL_COMMENT1 | mask);
				sc.Forward();
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_4GL_STRING | ResetSentenceStart);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_4GL_CHARACTER | ResetSentenceStart);
			} else if (sc.ch == '&' && visibleChars == 0 && ((sc.state & 0x10) == 0)) {
				sc.SetState(SCE_4GL_PREPROCESSOR | ResetSentenceStart);
				// Skip whitespace between & and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
			// Handle syntactical line termination
			} else if ((sc.ch == '.' || sc.ch == ':' || sc.ch == '}') && (sc.chNext == ' ' || sc.chNext == '\t' || sc.chNext == '\n' || sc.chNext == '\r')) {
				sc.SetState(sc.state & SetSentenceStart);
			} else if (isoperator(static_cast<char>(sc.ch))) {
		/* 	This code allows highlight of handles. Alas, it would cause the phrase "last-event:function"
			to be recognized as a BlockBegin */

				if (sc.ch == ':')
					sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart);
				/* else */
					sc.SetState(SCE_4GL_OPERATOR | ResetSentenceStart);
			}
		}

		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return (style & 0xf) >= SCE_4GL_COMMENT1 ;
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBox4glDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = static_cast<char>(tolower(styler[startPos]));
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = static_cast<char>(tolower(styler.SafeGetCharAt(i + 1)));
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext)) { // && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		else if ((style & 0xf) == SCE_4GL_BLOCK && !isalnum(chNext)) {
			levelNext++;
		}
		else if ((style & 0xf) == SCE_4GL_END  && (ch == 'e' || ch == 'f')) {
			levelNext--;
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}

static void Fold4glDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	FoldNoBox4glDoc(startPos, length, initStyle, styler);
}

static const char * const FglWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "Documentation comment keywords",
            "Unused",
            "Global classes and typedefs",
            0,
        };

LexerModule lmProgress(SCLEX_PROGRESS, Colourise4glDoc, "progress", Fold4glDoc, FglWordLists);

Added lexers/LexPython.cxx.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
// Scintilla source code edit control
/** @file LexPython.cxx
 ** Lexer for Python.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/* kwCDef, kwCTypeName only used for Cython */
enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName, kwCPDef };

static const int indicatorWhitespace = 1;

static bool IsPyComment(Accessor &styler, int pos, int len) {
	return len > 0 && styler[pos] == '#';
}

enum literalsAllowed { litNone=0, litU=1, litB=2};

static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) {
	return
		((allowed & litB) && (ch == 'b' || ch == 'B')) ||
		((allowed & litU) && (ch == 'u' || ch == 'U'));
}

static bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) {
	if (ch == '\'' || ch == '"')
		return true;
	if (IsPyStringTypeChar(ch, allowed)) {
		if (chNext == '"' || chNext == '\'')
			return true;
		if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\''))
			return true;
	}
	if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\''))
		return true;

	return false;
}

/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */
static int GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex, literalsAllowed allowed) {
	char ch = styler.SafeGetCharAt(i);
	char chNext = styler.SafeGetCharAt(i + 1);

	// Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), but bail if there are any unexpected chars
	if (ch == 'r' || ch == 'R') {
		i++;
		ch = styler.SafeGetCharAt(i);
		chNext = styler.SafeGetCharAt(i + 1);
	} else if (IsPyStringTypeChar(ch, allowed)) {
		if (chNext == 'r' || chNext == 'R')
			i += 2;
		else
			i += 1;
		ch = styler.SafeGetCharAt(i);
		chNext = styler.SafeGetCharAt(i + 1);
	}

	if (ch != '"' && ch != '\'') {
		*nextIndex = i + 1;
		return SCE_P_DEFAULT;
	}

	if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) {
		*nextIndex = i + 3;

		if (ch == '"')
			return SCE_P_TRIPLEDOUBLE;
		else
			return SCE_P_TRIPLE;
	} else {
		*nextIndex = i + 1;

		if (ch == '"')
			return SCE_P_STRING;
		else
			return SCE_P_CHARACTER;
	}
}

static inline bool IsAWordChar(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
        WordList *keywordlists[], Accessor &styler) {

	int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its tab whinging
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			// Look for backslash-continued lines
			while (lineCurrent > 0) {
				int eolPos = styler.LineStart(lineCurrent) - 1;
				int eolStyle = styler.StyleAt(eolPos);
				if (eolStyle == SCE_P_STRING
				    || eolStyle == SCE_P_CHARACTER
				    || eolStyle == SCE_P_STRINGEOL) {
					lineCurrent -= 1;
				} else {
					break;
				}
			}
			startPos = styler.LineStart(lineCurrent);
		}
		initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1);
	}

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];

	// property tab.timmy.whinge.level
	//	For Python code, checks whether indenting is consistent.
	//	The default, 0 turns off indentation checking,
	//	1 checks whether each line is potentially inconsistent with the previous line,
	//	2 checks whether any space characters occur before a tab character in the indentation,
	//	3 checks whether any spaces are in the indentation, and
	//	4 checks for any tab characters in the indentation.
	//	1 is a good level to use.
	const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");

	// property lexer.python.literals.binary
	//	Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712.
	bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0;

	// property lexer.python.strings.u
	//	Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3.
	literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone;

	// property lexer.python.strings.b
	//	Set to 0 to not recognise Python 3 bytes literals b"x".
	if (styler.GetPropertyInt("lexer.python.strings.b", 1))
		allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litB);

	// property lexer.python.strings.over.newline
	//      Set to 1 to allow strings to span newline characters.
	bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0;

	// property lexer.python.keywords2.no.sub.identifiers
	//	When enabled, it will not style keywords2 items that are used as a sub-identifier.
	//      Example: when set, will not highlight "foo.open" when "open" is a keywords2 item.
	const bool keywords2NoSubIdentifiers = styler.GetPropertyInt("lexer.python.keywords2.no.sub.identifiers") != 0;

	initStyle = initStyle & 31;
	if (initStyle == SCE_P_STRINGEOL) {
		initStyle = SCE_P_DEFAULT;
	}

	kwType kwLast = kwOther;
	int spaceFlags = 0;
	styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
	bool base_n_number = false;

	StyleContext sc(startPos, endPos - startPos, initStyle, styler);

	bool indentGood = true;
	int startIndicator = sc.currentPos;
	bool inContinuedString = false;

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart) {
			styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
			indentGood = true;
			if (whingeLevel == 1) {
				indentGood = (spaceFlags & wsInconsistent) == 0;
			} else if (whingeLevel == 2) {
				indentGood = (spaceFlags & wsSpaceTab) == 0;
			} else if (whingeLevel == 3) {
				indentGood = (spaceFlags & wsSpace) == 0;
			} else if (whingeLevel == 4) {
				indentGood = (spaceFlags & wsTab) == 0;
			}
			if (!indentGood) {
				styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0);
				startIndicator = sc.currentPos;
			}
		}

		if (sc.atLineEnd) {
			if ((sc.state == SCE_P_DEFAULT) ||
			        (sc.state == SCE_P_TRIPLE) ||
			        (sc.state == SCE_P_TRIPLEDOUBLE)) {
				// Perform colourisation of white space and triple quoted strings at end of each line to allow
				// tab marking to work inside white space and triple quoted strings
				sc.SetState(sc.state);
			}
			lineCurrent++;
			if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
				if (inContinuedString || stringsOverNewline) {
					inContinuedString = false;
				} else {
					sc.ChangeState(SCE_P_STRINGEOL);
					sc.ForwardSetState(SCE_P_DEFAULT);
				}
			}
			if (!sc.More())
				break;
		}

		bool needEOLCheck = false;

		// Check for a state end
		if (sc.state == SCE_P_OPERATOR) {
			kwLast = kwOther;
			sc.SetState(SCE_P_DEFAULT);
		} else if (sc.state == SCE_P_NUMBER) {
			if (!IsAWordChar(sc.ch) &&
			        !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
				sc.SetState(SCE_P_DEFAULT);
			}
		} else if (sc.state == SCE_P_IDENTIFIER) {
			if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				int style = SCE_P_IDENTIFIER;
				if ((kwLast == kwImport) && (strcmp(s, "as") == 0)) {
					style = SCE_P_WORD;
				} else if (keywords.InList(s)) {
					style = SCE_P_WORD;
				} else if (kwLast == kwClass) {
					style = SCE_P_CLASSNAME;
				} else if (kwLast == kwDef) {
					style = SCE_P_DEFNAME;
				} else if (kwLast == kwCDef || kwLast == kwCPDef) {
					int pos = sc.currentPos;
					unsigned char ch = styler.SafeGetCharAt(pos, '\0');
					while (ch != '\0') {
						if (ch == '(') {
							style = SCE_P_DEFNAME;
							break;
						} else if (ch == ':') {
							style = SCE_P_CLASSNAME;
							break;
						} else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
							pos++;
							ch = styler.SafeGetCharAt(pos, '\0');
						} else {
							break;
						}
					}
				} else if (keywords2.InList(s)) {
					if (keywords2NoSubIdentifiers) {
						// We don't want to highlight keywords2
						// that are used as a sub-identifier,
						// i.e. not open in "foo.open".
						int pos = styler.GetStartSegment() - 1;
						if (pos < 0 || (styler.SafeGetCharAt(pos, '\0') != '.'))
							style = SCE_P_WORD2;
					} else {
						style = SCE_P_WORD2;
					}
				}
				sc.ChangeState(style);
				sc.SetState(SCE_P_DEFAULT);
				if (style == SCE_P_WORD) {
					if (0 == strcmp(s, "class"))
						kwLast = kwClass;
					else if (0 == strcmp(s, "def"))
						kwLast = kwDef;
					else if (0 == strcmp(s, "import"))
						kwLast = kwImport;
					else if (0 == strcmp(s, "cdef"))
						kwLast = kwCDef;
					else if (0 == strcmp(s, "cpdef"))
						kwLast = kwCPDef;
					else if (0 == strcmp(s, "cimport"))
						kwLast = kwImport;
					else if (kwLast != kwCDef && kwLast != kwCPDef)
						kwLast = kwOther;
				} else if (kwLast != kwCDef && kwLast != kwCPDef) {
					kwLast = kwOther;
				}
			}
		} else if ((sc.state == SCE_P_COMMENTLINE) || (sc.state == SCE_P_COMMENTBLOCK)) {
			if (sc.ch == '\r' || sc.ch == '\n') {
				sc.SetState(SCE_P_DEFAULT);
			}
		} else if (sc.state == SCE_P_DECORATOR) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_P_DEFAULT);
			}
		} else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
			if (sc.ch == '\\') {
				if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) {
					sc.Forward();
				}
				if (sc.chNext == '\n' || sc.chNext == '\r') {
					inContinuedString = true;
				} else {
					// Don't roll over the newline.
					sc.Forward();
				}
			} else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) {
				sc.ForwardSetState(SCE_P_DEFAULT);
				needEOLCheck = true;
			} else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) {
				sc.ForwardSetState(SCE_P_DEFAULT);
				needEOLCheck = true;
			}
		} else if (sc.state == SCE_P_TRIPLE) {
			if (sc.ch == '\\') {
				sc.Forward();
			} else if (sc.Match("\'\'\'")) {
				sc.Forward();
				sc.Forward();
				sc.ForwardSetState(SCE_P_DEFAULT);
				needEOLCheck = true;
			}
		} else if (sc.state == SCE_P_TRIPLEDOUBLE) {
			if (sc.ch == '\\') {
				sc.Forward();
			} else if (sc.Match("\"\"\"")) {
				sc.Forward();
				sc.Forward();
				sc.ForwardSetState(SCE_P_DEFAULT);
				needEOLCheck = true;
			}
		}

		if (!indentGood && !IsASpaceOrTab(sc.ch)) {
			styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1);
			startIndicator = sc.currentPos;
			indentGood = true;
		}

		// One cdef or cpdef line, clear kwLast only at end of line
		if ((kwLast == kwCDef || kwLast == kwCPDef) && sc.atLineEnd) {
			kwLast = kwOther;
		}

		// State exit code may have moved on to end of line
		if (needEOLCheck && sc.atLineEnd) {
			lineCurrent++;
			styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
			if (!sc.More())
				break;
		}

		// Check for a new state starting character
		if (sc.state == SCE_P_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) {
					base_n_number = true;
					sc.SetState(SCE_P_NUMBER);
				} else if (sc.ch == '0' &&
					(sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) {
					if (base2or8Literals) {
						base_n_number = true;
						sc.SetState(SCE_P_NUMBER);
					} else {
						sc.SetState(SCE_P_NUMBER);
						sc.ForwardSetState(SCE_P_IDENTIFIER);
					}
				} else {
					base_n_number = false;
					sc.SetState(SCE_P_NUMBER);
				}
			} else if ((isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) || sc.ch == '`') {
				sc.SetState(SCE_P_OPERATOR);
			} else if (sc.ch == '#') {
				sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE);
			} else if (sc.ch == '@') {
				sc.SetState(SCE_P_DECORATOR);
			} else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2), allowedLiterals)) {
				unsigned int nextIndex = 0;
				sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals));
				while (nextIndex > (sc.currentPos + 1) && sc.More()) {
					sc.Forward();
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_P_IDENTIFIER);
			}
		}
	}
	styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0);
	sc.Complete();
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		if (ch == '#')
			return true;
		else if (ch != ' ' && ch != '\t')
			return false;
	}
	return false;
}

static bool IsQuoteLine(int line, Accessor &styler) {
	int style = styler.StyleAt(styler.LineStart(line)) & 31;
	return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
}


static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/,
                      WordList *[], Accessor &styler) {
	const int maxPos = startPos + length;
	const int maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1);	// Requested last line
	const int docLines = styler.GetLine(styler.Length());	// Available last line

	// property fold.quotes.python
	//	This option enables folding multi-line quoted strings when using the Python lexer.
	const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 0;

	const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0;

	// Backtrack to previous non-blank line so we can determine indent level
	// for any white space lines (needed esp. within triple quoted strings)
	// and so we can fix any preceding fold level (which is why we go back
	// at least one line in all cases)
	int spaceFlags = 0;
	int lineCurrent = styler.GetLine(startPos);
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
	while (lineCurrent > 0) {
		lineCurrent--;
		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
		        (!IsCommentLine(lineCurrent, styler)) &&
		        (!IsQuoteLine(lineCurrent, styler)))
			break;
	}
	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;

	// Set up initial loop state
	startPos = styler.LineStart(lineCurrent);
	int prev_state = SCE_P_DEFAULT & 31;
	if (lineCurrent >= 1)
		prev_state = styler.StyleAt(startPos - 1) & 31;
	int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE));

	// Process all characters to end of requested range or end of any triple quote
	//that hangs over the end of the range.  Cap processing in all cases
	// to end of document (in case of unclosed quote at end).
	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote)) {

		// Gather info
		int lev = indentCurrent;
		int lineNext = lineCurrent + 1;
		int indentNext = indentCurrent;
		int quote = false;
		if (lineNext <= docLines) {
			// Information about next line is only available if not at end of document
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
			int lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext);
			int style = styler.StyleAt(lookAtPos) & 31;
			quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
		}
		const int quote_start = (quote && !prevQuote);
		const int quote_continue = (quote && prevQuote);
		if (!quote || !prevQuote)
			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
		if (quote)
			indentNext = indentCurrentLevel;
		if (indentNext & SC_FOLDLEVELWHITEFLAG)
			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;

		if (quote_start) {
			// Place fold point at start of triple quoted string
			lev |= SC_FOLDLEVELHEADERFLAG;
		} else if (quote_continue || prevQuote) {
			// Add level to rest of lines in the string
			lev = lev + 1;
		}

		// Skip past any blank lines for next indent level info; we skip also
		// comments (all comments, not just those starting in column 0)
		// which effectively folds them into surrounding code rather
		// than screwing up folding.

		while (!quote &&
		        (lineNext < docLines) &&
		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {

			lineNext++;
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
		}

		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
		const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments);

		// Now set all the indent levels on the lines we skipped
		// Do this from end to start.  Once we encounter one line
		// which is indented more than the line after the end of
		// the comment-block, use the level of the block before

		int skipLine = lineNext;
		int skipLevel = levelAfterComments;

		while (--skipLine > lineCurrent) {
			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);

			if (foldCompact) {
				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
					skipLevel = levelBeforeComments;

				int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;

				styler.SetLevel(skipLine, skipLevel | whiteFlag);
			} else {
				if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments &&
					!(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
					!IsCommentLine(skipLine, styler))
					skipLevel = levelBeforeComments;

				styler.SetLevel(skipLine, skipLevel);
			}
		}

		// Set fold header on non-quote line
		if (!quote && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
				lev |= SC_FOLDLEVELHEADERFLAG;
		}

		// Keep track of triple quote state of previous line
		prevQuote = quote;

		// Set fold level for this line and move to next line
		styler.SetLevel(lineCurrent, foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG);
		indentCurrent = indentNext;
		lineCurrent = lineNext;
	}

	// NOTE: Cannot set level of last line here because indentCurrent doesn't have
	// header flag set; the loop above is crafted to take care of this case!
	//styler.SetLevel(lineCurrent, indentCurrent);
}

static const char *const pythonWordListDesc[] = {
	"Keywords",
	"Highlighted identifiers",
	0
};

LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc, "python", FoldPyDoc,
					 pythonWordListDesc);

Added lexers/LexR.cxx.

















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Lexr.cxx
 ** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer).
 **
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

static inline bool IsAnOperator(const int ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '-' || ch == '+' || ch == '!' || ch == '~' ||
	        ch == '?' || ch == ':' || ch == '*' || ch == '/' ||
	        ch == '^' || ch == '<' || ch == '>' || ch == '=' ||
	        ch == '&' || ch == '|' || ch == '$' || ch == '(' ||
	        ch == ')' || ch == '}' || ch == '{' || ch == '[' ||
		ch == ']')
		return true;
	return false;
}

static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords   = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];


	// Do not leak onto next line
	if (initStyle == SCE_R_INFIXEOL)
		initStyle = SCE_R_DEFAULT;


	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_R_STRING)) {
			// Prevent SCE_R_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_R_STRING);
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_R_OPERATOR) {
			sc.SetState(SCE_R_DEFAULT);
		} else if (sc.state == SCE_R_NUMBER) {
			if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_R_DEFAULT);
			}
		} else if (sc.state == SCE_R_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_R_KWORD);
				} else if  (keywords2.InList(s)) {
					sc.ChangeState(SCE_R_BASEKWORD);
				} else if  (keywords3.InList(s)) {
					sc.ChangeState(SCE_R_OTHERKWORD);
				}
				sc.SetState(SCE_R_DEFAULT);
			}
		} else if (sc.state == SCE_R_COMMENT) {
			if (sc.ch == '\r' || sc.ch == '\n') {
				sc.SetState(SCE_R_DEFAULT);
			}
		} else if (sc.state == SCE_R_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_R_DEFAULT);
			}
		} else if (sc.state == SCE_R_INFIX) {
			if (sc.ch == '%') {
				sc.ForwardSetState(SCE_R_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_R_INFIXEOL);
				sc.ForwardSetState(SCE_R_DEFAULT);
			}
		}else if (sc.state == SCE_R_STRING2) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_R_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_R_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_R_NUMBER);
			} else if (IsAWordStart(sc.ch) ) {
				sc.SetState(SCE_R_IDENTIFIER);
			} else if (sc.Match('#')) {
					sc.SetState(SCE_R_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_R_STRING);
			} else if (sc.ch == '%') {
				sc.SetState(SCE_R_INFIX);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_R_STRING2);
			} else if (IsAnOperator(sc.ch)) {
				sc.SetState(SCE_R_OPERATOR);
			}
		}
	}
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldRDoc(unsigned int startPos, int length, int, WordList *[],
                       Accessor &styler) {
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_R_OPERATOR) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}


static const char * const RWordLists[] = {
            "Language Keywords",
            "Base / Default package function",
            "Other Package Functions",
            "Unused",
            "Unused",
            0,
        };



LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists);

Added lexers/LexRebol.cxx.











































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
// Scintilla source code edit control
/** @file LexRebol.cxx
 ** Lexer for REBOL.
 ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste
 **
 ** History:
 **		2005-04-07	First release.
 **		2005-04-10	Closing parens and brackets go now in default style
 **					String and comment nesting should be more safe
 **/
// Copyright 2005 by Pascal Hurni <pascal_hurni@fastmail.fm>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
}

static inline bool IsAWordStart(const int ch, const int ch2) {
	return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) ||
		(isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
}

static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) {
	// One char operators
	if (IsASpaceOrTab(ch2)) {
		return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?';
	}

	// Two char operators
	if (IsASpaceOrTab(ch3)) {
		return (ch == '*' && ch2 == '*') ||
			   (ch == '/' && ch2 == '/') ||
			   (ch == '<' && (ch2 == '=' || ch2 == '>')) ||
			   (ch == '>' && ch2 == '=') ||
			   (ch == '=' && (ch2 == '=' || ch2 == '?')) ||
			   (ch == '?' && ch2 == '?');
	}

	return false;
}

static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) {
	return (ch == '#' && ch2 == '{') ||
		   (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) ||
		   (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' );
}


static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string.
	int stringLevel = 0;
	if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) {
		stringLevel = styler.GetLineState(currentLine - 1);
	}

	bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK;
	int dotCount = 0;

	// Do not leak onto next line
	if (initStyle == SCE_REBOL_COMMENTLINE) {
		initStyle = SCE_REBOL_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0) {
		sc.SetState(SCE_REBOL_PREFACE);
	}
	for (; sc.More(); sc.Forward()) {

		//--- What to do at line end ?
		if (sc.atLineEnd) {
			// Can be either inside a {} string or simply at eol
			if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK &&
				sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE)
				sc.SetState(SCE_REBOL_DEFAULT);

			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_REBOL_BRACEDSTRING:
			case SCE_REBOL_COMMENTBLOCK:
				// Inside a braced string, we set the line state
				styler.SetLineState(currentLine, stringLevel);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}

			// continue with next char
			continue;
		}

		//--- What to do on white-space ?
		if (IsASpaceOrTab(sc.ch))
		{
			// Return to default if any of these states
			if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER ||
				sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR ||
				sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE ||
				sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME ||
				sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE ||
				sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) {
				sc.SetState(SCE_REBOL_DEFAULT);
			}
		}

		//--- Specialize state ?
		// URL, Email look like identifier
		if (sc.state == SCE_REBOL_IDENTIFIER)
		{
			if (sc.ch == ':' && !IsASpace(sc.chNext)) {
				sc.ChangeState(SCE_REBOL_URL);
			} else if (sc.ch == '@') {
				sc.ChangeState(SCE_REBOL_EMAIL);
			} else if (sc.ch == '$') {
				sc.ChangeState(SCE_REBOL_MONEY);
			}
		}
		// Words look like identifiers
		if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) {
			// Keywords ?
			if (!IsAWordChar(sc.ch) || sc.Match('/')) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				blockComment = strcmp(s, "comment") == 0;
				if (keywords8.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD8);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD7);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD6);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD5);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD4);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD3);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD2);
				} else if (keywords.InList(s)) {
					sc.ChangeState(SCE_REBOL_WORD);
				}
				// Keep same style if there are refinements
				if (!sc.Match('/')) {
					sc.SetState(SCE_REBOL_DEFAULT);
				}
			}
		// special numbers
		} else if (sc.state == SCE_REBOL_NUMBER) {
			switch (sc.ch) {
			case 'x':	sc.ChangeState(SCE_REBOL_PAIR);
						break;
			case ':':	sc.ChangeState(SCE_REBOL_TIME);
						break;
			case '-':
			case '/':	sc.ChangeState(SCE_REBOL_DATE);
						break;
			case '.':	if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE);
						break;
			}
		}

		//--- Determine if the current state should terminate
		if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) {
			if (sc.ch == '^' && sc.chNext == '\"') {
				sc.Forward();
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_REBOL_DEFAULT);
			}
		} else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) {
			if (sc.ch == '}') {
				if (--stringLevel == 0) {
					sc.ForwardSetState(SCE_REBOL_DEFAULT);
				}
			} else if (sc.ch == '{') {
				stringLevel++;
			}
		} else if (sc.state == SCE_REBOL_BINARY) {
			if (sc.ch == '}') {
				sc.ForwardSetState(SCE_REBOL_DEFAULT);
			}
		} else if (sc.state == SCE_REBOL_TAG) {
			if (sc.ch == '>') {
				sc.ForwardSetState(SCE_REBOL_DEFAULT);
			}
		} else if (sc.state == SCE_REBOL_PREFACE) {
			if (sc.MatchIgnoreCase("rebol"))
			{
				int i;
				for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++);
				if (sc.GetRelative(i) == '[')
					sc.SetState(SCE_REBOL_DEFAULT);
			}
		}

		//--- Parens and bracket changes to default style when the current is a number
		if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE ||
			sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL ||
			sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) {
			if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') {
				sc.SetState(SCE_REBOL_DEFAULT);
			}
		}

		//--- Determine if a new state should be entered.
		if (sc.state == SCE_REBOL_DEFAULT) {
			if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) {
				sc.SetState(SCE_REBOL_OPERATOR);
			} else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) {
				sc.SetState(SCE_REBOL_BINARY);
			} else if (IsAWordStart(sc.ch, sc.chNext)) {
				sc.SetState(SCE_REBOL_IDENTIFIER);
			} else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') {
				dotCount = 0;
				sc.SetState(SCE_REBOL_NUMBER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_REBOL_QUOTEDSTRING);
			} else if (sc.ch == '{') {
				sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING);
				++stringLevel;
			} else if (sc.ch == ';') {
				sc.SetState(SCE_REBOL_COMMENTLINE);
			} else if (sc.ch == '$') {
				sc.SetState(SCE_REBOL_MONEY);
			} else if (sc.ch == '%') {
				sc.SetState(SCE_REBOL_FILE);
			} else if (sc.ch == '<') {
				sc.SetState(SCE_REBOL_TAG);
			} else if (sc.ch == '#' && sc.chNext == '"') {
				sc.SetState(SCE_REBOL_CHARACTER);
				sc.Forward();
			} else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) {
				sc.SetState(SCE_REBOL_ISSUE);
			}
		}
	}
	sc.Complete();
}


static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_REBOL_DEFAULT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const rebolWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc);

Added lexers/LexRuby.cxx.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
// Scintilla source code edit control
/** @file LexRuby.cxx
 ** Lexer for Ruby.
 **/
// Copyright 2001- by Clemens Wyss <wys@helbling.ch>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

//XXX Identical to Perl, put in common area
static inline bool isEOLChar(char ch) {
	return (ch == '\r') || (ch == '\n');
}

#define isSafeASCII(ch) ((unsigned int)(ch) <= 127)
// This one's redundant, but makes for more readable code
#define isHighBitChar(ch) ((unsigned int)(ch) > 127)

static inline bool isSafeAlpha(char ch) {
    return (isSafeASCII(ch) && isalpha(ch)) || ch == '_';
}

static inline bool isSafeAlnum(char ch) {
    return (isSafeASCII(ch) && isalnum(ch)) || ch == '_';
}

static inline bool isSafeAlnumOrHigh(char ch) {
    return isHighBitChar(ch) || isalnum(ch) || ch == '_';
}

static inline bool isSafeDigit(char ch) {
    return isSafeASCII(ch) && isdigit(ch);
}

static inline bool isSafeWordcharOrHigh(char ch) {
    // Error: scintilla's KeyWords.h includes '.' as a word-char
    // we want to separate things that can take methods from the
    // methods.
    return isHighBitChar(ch) || isalnum(ch) || ch == '_';
}

static bool inline iswhitespace(char ch) {
	return ch == ' ' || ch == '\t';
}

#define MAX_KEYWORD_LENGTH 200

#define STYLE_MASK 63
#define actual_style(style) (style & STYLE_MASK)

static bool followsDot(unsigned int pos, Accessor &styler) {
    styler.Flush();
    for (; pos >= 1; --pos) {
        int style = actual_style(styler.StyleAt(pos));
        char ch;
        switch (style) {
            case SCE_RB_DEFAULT:
                ch = styler[pos];
                if (ch == ' ' || ch == '\t') {
                    //continue
                } else {
                    return false;
                }
                break;

            case SCE_RB_OPERATOR:
                return styler[pos] == '.';

            default:
                return false;
        }
    }
    return false;
}

// Forward declarations
static bool keywordIsAmbiguous(const char *prevWord);
static bool keywordDoStartsLoop(int pos,
                                Accessor &styler);
static bool keywordIsModifier(const char *word,
                              int pos,
                              Accessor &styler);

static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
	char s[MAX_KEYWORD_LENGTH];
    unsigned int i, j;
	unsigned int lim = end - start + 1; // num chars to copy
	if (lim >= MAX_KEYWORD_LENGTH) {
		lim = MAX_KEYWORD_LENGTH - 1;
	}
	for (i = start, j = 0; j < lim; i++, j++) {
		s[j] = styler[i];
	}
    s[j] = '\0';
	int chAttr;
	if (0 == strcmp(prevWord, "class"))
		chAttr = SCE_RB_CLASSNAME;
	else if (0 == strcmp(prevWord, "module"))
		chAttr = SCE_RB_MODULE_NAME;
	else if (0 == strcmp(prevWord, "def"))
		chAttr = SCE_RB_DEFNAME;
    else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
        if (keywordIsAmbiguous(s)
            && keywordIsModifier(s, start, styler)) {

            // Demoted keywords are colored as keywords,
            // but do not affect changes in indentation.
            //
            // Consider the word 'if':
            // 1. <<if test ...>> : normal
            // 2. <<stmt if test>> : demoted
            // 3. <<lhs = if ...>> : normal: start a new indent level
            // 4. <<obj.if = 10>> : color as identifer, since it follows '.'

            chAttr = SCE_RB_WORD_DEMOTED;
        } else {
            chAttr = SCE_RB_WORD;
        }
	} else
        chAttr = SCE_RB_IDENTIFIER;
	styler.ColourTo(end, chAttr);
	if (chAttr == SCE_RB_WORD) {
		strcpy(prevWord, s);
	} else {
		prevWord[0] = 0;
	}
    return chAttr;
}


//XXX Identical to Perl, put in common area
static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
	if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
		return false;
	}
	while (*val) {
		if (*val != styler[pos++]) {
			return false;
		}
		val++;
	}
	return true;
}

// Do Ruby better -- find the end of the line, work back,
// and then check for leading white space

// Precondition: the here-doc target can be indented
static bool lookingAtHereDocDelim(Accessor	   &styler,
                                  int 			pos,
                                  int 			lengthDoc,
                                  const char   *HereDocDelim)
{
    if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) {
        return false;
    }
    while (--pos > 0) {
        char ch = styler[pos];
        if (isEOLChar(ch)) {
            return true;
        } else if (ch != ' ' && ch != '\t') {
            return false;
        }
    }
    return false;
}

//XXX Identical to Perl, put in common area
static char opposite(char ch) {
	if (ch == '(')
		return ')';
	if (ch == '[')
		return ']';
	if (ch == '{')
		return '}';
	if (ch == '<')
		return '>';
	return ch;
}

// Null transitions when we see we've reached the end
// and need to relex the curr char.

static void redo_char(int &i, char &ch, char &chNext, char &chNext2,
                      int &state) {
    i--;
    chNext2 = chNext;
    chNext = ch;
    state = SCE_RB_DEFAULT;
}

static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {
    i++;
    ch = chNext;
    chNext = chNext2;
}

// precondition: startPos points to one after the EOL char
static bool currLineContainsHereDelims(int& startPos,
                                       Accessor &styler) {
    if (startPos <= 1)
        return false;

    int pos;
    for (pos = startPos - 1; pos > 0; pos--) {
        char ch = styler.SafeGetCharAt(pos);
        if (isEOLChar(ch)) {
            // Leave the pointers where they are -- there are no
            // here doc delims on the current line, even if
            // the EOL isn't default style

            return false;
        } else {
            styler.Flush();
            if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) {
                break;
            }
        }
    }
    if (pos == 0) {
        return false;
    }
    // Update the pointers so we don't have to re-analyze the string
    startPos = pos;
    return true;
}

// This class is used by the enter and exit methods, so it needs
// to be hoisted out of the function.

class QuoteCls {
    public:
    int  Count;
    char Up;
    char Down;
    QuoteCls() {
        this->New();
    }
    void New() {
        Count = 0;
        Up    = '\0';
        Down  = '\0';
    }
    void Open(char u) {
        Count++;
        Up    = u;
        Down  = opposite(Up);
    }
    QuoteCls(const QuoteCls& q) {
        // copy constructor -- use this for copying in
        Count = q.Count;
        Up    = q.Up;
        Down  = q.Down;
    }
    QuoteCls& operator=(const QuoteCls& q) { // assignment constructor
        if (this != &q) {
            Count = q.Count;
            Up    = q.Up;
            Down  = q.Down;
        }
		return *this;
    }

};


static void enterInnerExpression(int  *p_inner_string_types,
                                 int  *p_inner_expn_brace_counts,
                                 QuoteCls *p_inner_quotes,
                                 int&  inner_string_count,
                                 int&  state,
                                 int&  brace_counts,
                                 QuoteCls curr_quote
                                 ) {
    p_inner_string_types[inner_string_count] = state;
    state = SCE_RB_DEFAULT;
    p_inner_expn_brace_counts[inner_string_count] = brace_counts;
    brace_counts = 0;
    p_inner_quotes[inner_string_count] = curr_quote;
    ++inner_string_count;
}

static void exitInnerExpression(int *p_inner_string_types,
                                 int *p_inner_expn_brace_counts,
                                 QuoteCls *p_inner_quotes,
                                 int& inner_string_count,
                                 int& state,
                                 int&  brace_counts,
                                 QuoteCls& curr_quote
                                ) {
    --inner_string_count;
    state = p_inner_string_types[inner_string_count];
    brace_counts = p_inner_expn_brace_counts[inner_string_count];
    curr_quote = p_inner_quotes[inner_string_count];
}

static bool isEmptyLine(int pos,
                        Accessor &styler) {
	int spaceFlags = 0;
	int lineCurrent = styler.GetLine(pos);
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
    return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0;
}

static bool RE_CanFollowKeyword(const char *keyword) {
    if (!strcmp(keyword, "and")
        || !strcmp(keyword, "begin")
        || !strcmp(keyword, "break")
        || !strcmp(keyword, "case")
        || !strcmp(keyword, "do")
        || !strcmp(keyword, "else")
        || !strcmp(keyword, "elsif")
        || !strcmp(keyword, "if")
        || !strcmp(keyword, "next")
        || !strcmp(keyword, "return")
        || !strcmp(keyword, "when")
        || !strcmp(keyword, "unless")
        || !strcmp(keyword, "until")
        || !strcmp(keyword, "not")
        || !strcmp(keyword, "or")) {
        return true;
    }
    return false;
}

// Look at chars up to but not including endPos
// Don't look at styles in case we're looking forward

static int skipWhitespace(int startPos,
                           int endPos,
                           Accessor &styler) {
    for (int i = startPos; i < endPos; i++) {
        if (!iswhitespace(styler[i])) {
            return i;
        }
    }
    return endPos;
}

// This routine looks for false positives like
// undef foo, <<
// There aren't too many.
//
// iPrev points to the start of <<

static bool sureThisIsHeredoc(int iPrev,
                              Accessor &styler,
                              char *prevWord) {

    // Not so fast, since Ruby's so dynamic.  Check the context
    // to make sure we're OK.
    int prevStyle;
    int lineStart = styler.GetLine(iPrev);
    int lineStartPosn = styler.LineStart(lineStart);
    styler.Flush();

    // Find the first word after some whitespace
    int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler);
    if (firstWordPosn >= iPrev) {
        // Have something like {^     <<}
		//XXX Look at the first previous non-comment non-white line
		// to establish the context.  Not too likely though.
        return true;
    } else {
        switch (prevStyle = styler.StyleAt(firstWordPosn)) {
        case SCE_RB_WORD:
        case SCE_RB_WORD_DEMOTED:
        case SCE_RB_IDENTIFIER:
            break;
        default:
            return true;
        }
    }
    int firstWordEndPosn = firstWordPosn;
    char *dst = prevWord;
    for (;;) {
        if (firstWordEndPosn >= iPrev ||
            styler.StyleAt(firstWordEndPosn) != prevStyle) {
            *dst = 0;
            break;
        }
        *dst++ = styler[firstWordEndPosn];
        firstWordEndPosn += 1;
    }
    //XXX Write a style-aware thing to regex scintilla buffer objects
    if (!strcmp(prevWord, "undef")
        || !strcmp(prevWord, "def")
        || !strcmp(prevWord, "alias")) {
        // These keywords are what we were looking for
        return false;
    }
    return true;
}

// Routine that saves us from allocating a buffer for the here-doc target
// targetEndPos points one past the end of the current target
static bool haveTargetMatch(int currPos,
                            int lengthDoc,
                            int targetStartPos,
                            int targetEndPos,
                            Accessor &styler) {
    if (lengthDoc - currPos < targetEndPos - targetStartPos) {
        return false;
    }
    int i, j;
    for (i = targetStartPos, j = currPos;
         i < targetEndPos && j < lengthDoc;
         i++, j++) {
        if (styler[i] != styler[j]) {
            return false;
        }
    }
    return true;
}

// We need a check because the form
// [identifier] <<[target]
// is ambiguous.  The Ruby lexer/parser resolves it by
// looking to see if [identifier] names a variable or a
// function.  If it's the first, it's the start of a here-doc.
// If it's a var, it's an operator.  This lexer doesn't
// maintain a symbol table, so it looks ahead to see what's
// going on, in cases where we have
// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target]
//
// If there's no occurrence of [target] on a line, assume we don't.

// return true == yes, we have no heredocs

static bool sureThisIsNotHeredoc(int lt2StartPos,
                                 Accessor &styler) {
    int prevStyle;
     // Use full document, not just part we're styling
    int lengthDoc = styler.Length();
    int lineStart = styler.GetLine(lt2StartPos);
    int lineStartPosn = styler.LineStart(lineStart);
    styler.Flush();
    const bool definitely_not_a_here_doc = true;
    const bool looks_like_a_here_doc = false;

    // Find the first word after some whitespace
    int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler);
    if (firstWordPosn >= lt2StartPos) {
        return definitely_not_a_here_doc;
    }
    prevStyle = styler.StyleAt(firstWordPosn);
    // If we have '<<' following a keyword, it's not a heredoc
    if (prevStyle != SCE_RB_IDENTIFIER
        && prevStyle != SCE_RB_INSTANCE_VAR
        && prevStyle != SCE_RB_CLASS_VAR) {
        return definitely_not_a_here_doc;
    }
    int newStyle = prevStyle;
    // Some compilers incorrectly warn about uninit newStyle
    for (firstWordPosn += 1; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
        // Inner loop looks at the name
        for (; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
            newStyle = styler.StyleAt(firstWordPosn);
            if (newStyle != prevStyle) {
                break;
            }
        }
        // Do we have '::' or '.'?
        if (firstWordPosn < lt2StartPos && newStyle == SCE_RB_OPERATOR) {
            char ch = styler[firstWordPosn];
            if (ch == '.') {
                // yes
            } else if (ch == ':') {
                if (styler.StyleAt(++firstWordPosn) != SCE_RB_OPERATOR) {
                    return definitely_not_a_here_doc;
                } else if (styler[firstWordPosn] != ':') {
                    return definitely_not_a_here_doc;
                }
            } else {
                break;
            }
        } else {
            break;
        }
        // on second and next passes, only identifiers may appear since
        // class and instance variable are private
        prevStyle = SCE_RB_IDENTIFIER;
    }
    // Skip next batch of white-space
    firstWordPosn = skipWhitespace(firstWordPosn, lt2StartPos, styler);
    if (firstWordPosn != lt2StartPos) {
        // Have [[^ws[identifier]ws[*something_else*]ws<<
        return definitely_not_a_here_doc;
    }
    // OK, now 'j' will point to the current spot moving ahead
	int j = firstWordPosn + 1;
    if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') {
        // This shouldn't happen
        return definitely_not_a_here_doc;
    }
    int nextLineStartPosn = styler.LineStart(lineStart + 1);
    if (nextLineStartPosn >= lengthDoc) {
        return definitely_not_a_here_doc;
    }
    j = skipWhitespace(j + 1, nextLineStartPosn, styler);
    if (j >= lengthDoc) {
        return definitely_not_a_here_doc;
    }
    bool allow_indent;
    int target_start, target_end;
    // From this point on no more styling, since we're looking ahead
    if (styler[j] == '-') {
        allow_indent = true;
        j++;
    } else {
        allow_indent = false;
    }

    // Allow for quoted targets.
    char target_quote = 0;
    switch (styler[j]) {
    case '\'':
    case '"':
    case '`':
        target_quote = styler[j];
        j += 1;
    }

    if (isSafeAlnum(styler[j])) {
        // Init target_end because some compilers think it won't
        // be initialized by the time it's used
        target_start = target_end = j;
        j++;
    } else {
        return definitely_not_a_here_doc;
    }
    for (; j < lengthDoc; j++) {
        if (!isSafeAlnum(styler[j])) {
            if (target_quote && styler[j] != target_quote) {
                // unquoted end
                return definitely_not_a_here_doc;
            }

            // And for now make sure that it's a newline
            // don't handle arbitrary expressions yet

            target_end = j;
			if (target_quote) {
				// Now we can move to the character after the string delimiter.
				j += 1;
			}
            j = skipWhitespace(j, lengthDoc, styler);
            if (j >= lengthDoc) {
                return definitely_not_a_here_doc;
            } else {
                char ch = styler[j];
                if (ch == '#' || isEOLChar(ch)) {
                    // This is OK, so break and continue;
                    break;
                } else {
                    return definitely_not_a_here_doc;
                }
            }
        }
    }

    // Just look at the start of each line
    int last_line = styler.GetLine(lengthDoc - 1);
    // But don't go too far
    if (last_line > lineStart + 50) {
        last_line = lineStart + 50;
    }
    for (int line_num = lineStart + 1; line_num <= last_line; line_num++) {
        if (allow_indent) {
            j = skipWhitespace(styler.LineStart(line_num), lengthDoc, styler);
        } else {
            j = styler.LineStart(line_num);
        }
        // target_end is one past the end
        if (haveTargetMatch(j, lengthDoc, target_start, target_end, styler)) {
            // We got it
            return looks_like_a_here_doc;
        }
    }
    return definitely_not_a_here_doc;
}

//todo: if we aren't looking at a stdio character,
// move to the start of the first line that is not in a
// multi-line construct

static void synchronizeDocStart(unsigned int& startPos,
                                int &length,
                                int &initStyle,
                                Accessor &styler,
                                bool skipWhiteSpace=false) {

    styler.Flush();
    int style = actual_style(styler.StyleAt(startPos));
    switch (style) {
        case SCE_RB_STDIN:
        case SCE_RB_STDOUT:
        case SCE_RB_STDERR:
            // Don't do anything else with these.
            return;
    }

    int pos = startPos;
    // Quick way to characterize each line
    int lineStart;
    for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) {
        // Now look at the style before the previous line's EOL
        pos = styler.LineStart(lineStart) - 1;
        if (pos <= 10) {
            lineStart = 0;
            break;
        }
        char ch = styler.SafeGetCharAt(pos);
        char chPrev = styler.SafeGetCharAt(pos - 1);
        if (ch == '\n' && chPrev == '\r') {
            pos--;
        }
        if (styler.SafeGetCharAt(pos - 1) == '\\') {
            // Continuation line -- keep going
        } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) {
            // Part of multi-line construct -- keep going
        } else if (currLineContainsHereDelims(pos, styler)) {
            // Keep going, with pos and length now pointing
            // at the end of the here-doc delimiter
        } else if (skipWhiteSpace && isEmptyLine(pos, styler)) {
            // Keep going
        } else {
            break;
        }
    }
    pos = styler.LineStart(lineStart);
    length += (startPos - pos);
    startPos = pos;
    initStyle = SCE_RB_DEFAULT;
}

static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
						   WordList *keywordlists[], Accessor &styler) {

	// Lexer for Ruby often has to backtrack to start of current style to determine
	// which characters are being used as quotes, how deeply nested is the
	// start position and what the termination string is for here documents

	WordList &keywords = *keywordlists[0];

	class HereDocCls {
	public:
		int State;
        // States
        // 0: '<<' encountered
		// 1: collect the delimiter
        // 1b: text between the end of the delimiter and the EOL
		// 2: here doc text (lines after the delimiter)
		char Quote;		// the char after '<<'
		bool Quoted;		// true if Quote in ('\'','"','`')
		int DelimiterLength;	// strlen(Delimiter)
		char Delimiter[256];	// the Delimiter, limit of 256: from Perl
        bool CanBeIndented;
		HereDocCls() {
			State = 0;
			DelimiterLength = 0;
			Delimiter[0] = '\0';
            CanBeIndented = false;
		}
	};
	HereDocCls HereDoc;

	QuoteCls Quote;

    int numDots = 0;  // For numbers --
                      // Don't start lexing in the middle of a num

    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
                        false);

	bool preferRE = true;
    int state = initStyle;
	int lengthDoc = startPos + length;

	char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
	prevWord[0] = '\0';
	if (length == 0)
		return;

	char chPrev = styler.SafeGetCharAt(startPos - 1);
	char chNext = styler.SafeGetCharAt(startPos);
	bool is_real_number = true;   // Differentiate between constants and ?-sequences.
	// Ruby uses a different mask because bad indentation is marked by oring with 32
	styler.StartAt(startPos, 127);
	styler.StartSegment(startPos);

    static int q_states[] = {SCE_RB_STRING_Q,
                             SCE_RB_STRING_QQ,
                             SCE_RB_STRING_QR,
                             SCE_RB_STRING_QW,
                             SCE_RB_STRING_QW,
                             SCE_RB_STRING_QX};
    static const char* q_chars = "qQrwWx";

    // In most cases a value of 2 should be ample for the code in the
    // Ruby library, and the code the user is likely to enter.
    // For example,
    // fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}"
    //     if options[:verbose]
    // from fileutils.rb nests to a level of 2
    // If the user actually hits a 6th occurrence of '#{' in a double-quoted
    // string (including regex'es, %Q, %<sym>, %w, and other strings
    // that interpolate), it will stay as a string.  The problem with this
    // is that quotes might flip, a 7th '#{' will look like a comment,
    // and code-folding might be wrong.

    // If anyone runs into this problem, I recommend raising this
    // value slightly higher to replacing the fixed array with a linked
    // list.  Keep in mind this code will be called everytime the lexer
    // is invoked.

#define INNER_STRINGS_MAX_COUNT 5
    // These vars track our instances of "...#{,,,%Q<..#{,,,}...>,,,}..."
    int inner_string_types[INNER_STRINGS_MAX_COUNT];
    // Track # braces when we push a new #{ thing
    int inner_expn_brace_counts[INNER_STRINGS_MAX_COUNT];
    QuoteCls inner_quotes[INNER_STRINGS_MAX_COUNT];
    int inner_string_count = 0;
    int brace_counts = 0;   // Number of #{ ... } things within an expression

    int i;
	for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) {
        inner_string_types[i] = 0;
        inner_expn_brace_counts[i] = 0;
    }
	for (i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		char chNext2 = styler.SafeGetCharAt(i + 2);

        if (styler.IsLeadByte(ch)) {
			chNext = chNext2;
			chPrev = ' ';
			i += 1;
			continue;
		}

        // skip on DOS/Windows
        //No, don't, because some things will get tagged on,
        // so we won't recognize keywords, for example
#if 0
		if (ch == '\r' && chNext == '\n') {
	    	continue;
        }
#endif

        if (HereDoc.State == 1 && isEOLChar(ch)) {
			// Begin of here-doc (the line after the here-doc delimiter):
			HereDoc.State = 2;
			styler.ColourTo(i-1, state);
            // Don't check for a missing quote, just jump into
            // the here-doc state
            state = SCE_RB_HERE_Q;
        }

        // Regular transitions
		if (state == SCE_RB_DEFAULT) {
            if (isSafeDigit(ch)) {
            	styler.ColourTo(i - 1, state);
				state = SCE_RB_NUMBER;
                is_real_number = true;
                numDots = 0;
            } else if (isHighBitChar(ch) || iswordstart(ch)) {
            	styler.ColourTo(i - 1, state);
				state = SCE_RB_WORD;
			} else if (ch == '#') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_COMMENTLINE;
			} else if (ch == '=') {
				// =begin indicates the start of a comment (doc) block
                if ((i == 0 || isEOLChar(chPrev))
                    && chNext == 'b'
                    && styler.SafeGetCharAt(i + 2) == 'e'
                    && styler.SafeGetCharAt(i + 3) == 'g'
                    && styler.SafeGetCharAt(i + 4) == 'i'
                    && styler.SafeGetCharAt(i + 5) == 'n'
                    && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) {
                    styler.ColourTo(i - 1, state);
                    state = SCE_RB_POD;
				} else {
					styler.ColourTo(i - 1, state);
					styler.ColourTo(i, SCE_RB_OPERATOR);
					preferRE = true;
				}
			} else if (ch == '"') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_STRING;
				Quote.New();
				Quote.Open(ch);
			} else if (ch == '\'') {
                styler.ColourTo(i - 1, state);
                state = SCE_RB_CHARACTER;
                Quote.New();
                Quote.Open(ch);
			} else if (ch == '`') {
				styler.ColourTo(i - 1, state);
				state = SCE_RB_BACKTICKS;
				Quote.New();
				Quote.Open(ch);
			} else if (ch == '@') {
                // Instance or class var
				styler.ColourTo(i - 1, state);
                if (chNext == '@') {
                    state = SCE_RB_CLASS_VAR;
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                } else {
                    state = SCE_RB_INSTANCE_VAR;
                }
			} else if (ch == '$') {
                // Check for a builtin global
				styler.ColourTo(i - 1, state);
                // Recognize it bit by bit
                state = SCE_RB_GLOBAL;
            } else if (ch == '/' && preferRE) {
                // Ambigous operator
				styler.ColourTo(i - 1, state);
				state = SCE_RB_REGEX;
                Quote.New();
                Quote.Open(ch);
			} else if (ch == '<' && chNext == '<' && chNext2 != '=') {

                // Recognise the '<<' symbol - either a here document or a binary op
				styler.ColourTo(i - 1, state);
                i++;
                chNext = chNext2;
				styler.ColourTo(i, SCE_RB_OPERATOR);

                if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
                    // It's definitely not a here-doc,
                    // based on Ruby's lexer/parser in the
                    // heredoc_identifier routine.
                    // Nothing else to do.
                } else if (preferRE) {
                    if (sureThisIsHeredoc(i - 1, styler, prevWord)) {
                        state = SCE_RB_HERE_DELIM;
                        HereDoc.State = 0;
                    }
                    // else leave it in default state
                } else {
                    if (sureThisIsNotHeredoc(i - 1, styler)) {
                        // leave state as default
                        // We don't have all the heuristics Perl has for indications
                        // of a here-doc, because '<<' is overloadable and used
                        // for so many other classes.
                    } else {
                        state = SCE_RB_HERE_DELIM;
                        HereDoc.State = 0;
                    }
                }
                preferRE = (state != SCE_RB_HERE_DELIM);
            } else if (ch == ':') {
				styler.ColourTo(i - 1, state);
                if (chNext == ':') {
                    // Mark "::" as an operator, not symbol start
                    styler.ColourTo(i + 1, SCE_RB_OPERATOR);
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                    state = SCE_RB_DEFAULT;
					preferRE = false;
                } else if (isSafeWordcharOrHigh(chNext)) {
					state = SCE_RB_SYMBOL;
                } else if (strchr("[*!~+-*/%=<>&^|", chNext)) {
                    // Do the operator analysis in-line, looking ahead
                    // Based on the table in pickaxe 2nd ed., page 339
                    bool doColoring = true;
                    switch (chNext) {
                    case '[':
                        if (chNext2 == ']' ) {
                            char ch_tmp = styler.SafeGetCharAt(i + 3);
                            if (ch_tmp == '=') {
                                i += 3;
                                ch = ch_tmp;
                                chNext = styler.SafeGetCharAt(i + 1);
                            } else {
                                i += 2;
                                ch = chNext2;
                                chNext = ch_tmp;
                            }
                        } else {
                            doColoring = false;
                        }
                        break;

                    case '*':
                        if (chNext2 == '*') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    case '!':
                        if (chNext2 == '=' || chNext2 == '~') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    case '<':
                        if (chNext2 == '<') {
                            i += 2;
                            ch = chNext2;
                            chNext = styler.SafeGetCharAt(i + 1);
                        } else if (chNext2 == '=') {
                            char ch_tmp = styler.SafeGetCharAt(i + 3);
                            if (ch_tmp == '>') {  // <=> operator
                                i += 3;
                                ch = ch_tmp;
                                chNext = styler.SafeGetCharAt(i + 1);
                            } else {
                                i += 2;
                                ch = chNext2;
                                chNext = ch_tmp;
                            }
                        } else {
                            advance_char(i, ch, chNext, chNext2);
                        }
                        break;

                    default:
                        // Simple one-character operators
                        advance_char(i, ch, chNext, chNext2);
                        break;
                    }
                    if (doColoring) {
                        styler.ColourTo(i, SCE_RB_SYMBOL);
                        state = SCE_RB_DEFAULT;
                    }
				} else if (!preferRE) {
					// Don't color symbol strings (yet)
					// Just color the ":" and color rest as string
					styler.ColourTo(i, SCE_RB_SYMBOL);
					state = SCE_RB_DEFAULT;
                } else {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    state = SCE_RB_DEFAULT;
                    preferRE = true;
                }
            } else if (ch == '%') {
                styler.ColourTo(i - 1, state);
                bool have_string = false;
                if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
                    Quote.New();
                    const char *hit = strchr(q_chars, chNext);
                    if (hit != NULL) {
                        state = q_states[hit - q_chars];
                        Quote.Open(chNext2);
                        i += 2;
                        ch = chNext2;
						chNext = styler.SafeGetCharAt(i + 1);
                        have_string = true;
                    }
                } else if (preferRE && !isSafeWordcharOrHigh(chNext)) {
                    // Ruby doesn't allow high bit chars here,
                    // but the editor host might
                    Quote.New();
                    state = SCE_RB_STRING_QQ;
                    Quote.Open(chNext);
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                    have_string = true;
                } else if (!isSafeWordcharOrHigh(chNext) && !iswhitespace(chNext) && !isEOLChar(chNext)) {
                    // Ruby doesn't allow high bit chars here,
                    // but the editor host might
                    Quote.New();
                    state = SCE_RB_STRING_QQ;
                    Quote.Open(chNext);
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                    have_string = true;
                }
                if (!have_string) {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    // stay in default
                    preferRE = true;
                }
            } else if (ch == '?') {
                styler.ColourTo(i - 1, state);
                if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                } else {
                    // It's the start of a character code escape sequence
                    // Color it as a number.
                    state = SCE_RB_NUMBER;
                    is_real_number = false;
                }
            } else if (isoperator(ch) || ch == '.') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_RB_OPERATOR);
                // If we're ending an expression or block,
                // assume it ends an object, and the ambivalent
                // constructs are binary operators
                //
                // So if we don't have one of these chars,
                // we aren't ending an object exp'n, and ops
                // like : << / are unary operators.

                if (ch == '{') {
                    ++brace_counts;
                    preferRE = true;
                } else if (ch == '}' && --brace_counts < 0
                           && inner_string_count > 0) {
                    styler.ColourTo(i, SCE_RB_OPERATOR);
                    exitInnerExpression(inner_string_types,
                                        inner_expn_brace_counts,
                                        inner_quotes,
                                        inner_string_count,
                                        state, brace_counts, Quote);
                } else {
                    preferRE = (strchr(")}].", ch) == NULL);
                }
                // Stay in default state
            } else if (isEOLChar(ch)) {
                // Make sure it's a true line-end, with no backslash
                if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
                    && chPrev != '\\') {
                    // Assume we've hit the end of the statement.
                    preferRE = true;
                }
            }
        } else if (state == SCE_RB_WORD) {
            if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
                // Words include x? in all contexts,
                // and <letters>= after either 'def' or a dot
                // Move along until a complete word is on our left

                // Default accessor treats '.' as word-chars,
                // but we don't for now.

                if (ch == '='
                    && isSafeWordcharOrHigh(chPrev)
                    && (chNext == '('
                        || strchr(" \t\n\r", chNext) != NULL)
                    && (!strcmp(prevWord, "def")
                        || followsDot(styler.GetStartSegment(), styler))) {
                    // <name>= is a name only when being def'd -- Get it the next time
                    // This means that <name>=<name> is always lexed as
                    // <name>, (op, =), <name>
                } else if ((ch == '?' || ch == '!')
                           && isSafeWordcharOrHigh(chPrev)
                           && !isSafeWordcharOrHigh(chNext)) {
                    // <name>? is a name -- Get it the next time
                    // But <name>?<name> is always lexed as
                    // <name>, (op, ?), <name>
                    // Same with <name>! to indicate a method that
                    // modifies its target
                } else if (isEOLChar(ch)
                           && isMatch(styler, lengthDoc, i - 7, "__END__")) {
                    styler.ColourTo(i, SCE_RB_DATASECTION);
                    state = SCE_RB_DATASECTION;
                    // No need to handle this state -- we'll just move to the end
                    preferRE = false;
                } else {
					int wordStartPos = styler.GetStartSegment();
                    int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord);
                    switch (word_style) {
                        case SCE_RB_WORD:
                            preferRE = RE_CanFollowKeyword(prevWord);
							break;

                        case SCE_RB_WORD_DEMOTED:
                            preferRE = true;
							break;

                        case SCE_RB_IDENTIFIER:
                            if (isMatch(styler, lengthDoc, wordStartPos, "print")) {
                                preferRE = true;
                            } else if (isEOLChar(ch)) {
                                preferRE = true;
                            } else {
                                preferRE = false;
                            }
							break;
                        default:
                            preferRE = false;
                    }
                    if (ch == '.') {
                        // We might be redefining an operator-method
                        preferRE = false;
                    }
                    // And if it's the first
                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
                }
            }
        } else if (state == SCE_RB_NUMBER) {
            if (!is_real_number) {
                if (ch != '\\') {
                    styler.ColourTo(i, state);
                    state = SCE_RB_DEFAULT;
                    preferRE = false;
                } else if (strchr("\\ntrfvaebs", chNext)) {
                    // Terminal escape sequence -- handle it next time
                    // Nothing more to do this time through the loop
                } else if (chNext == 'C' || chNext == 'M') {
                    if (chNext2 != '-') {
                        // \C or \M ends the sequence -- handle it next time
                    } else {
                        // Move from abc?\C-x
                        //               ^
                        // to
                        //                 ^
                        i += 2;
                        ch = chNext2;
                        chNext = styler.SafeGetCharAt(i + 1);
                    }
                } else if (chNext == 'c') {
                    // Stay here, \c is a combining sequence
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                } else {
                    // ?\x, including ?\\ is final.
                    styler.ColourTo(i + 1, state);
                    state = SCE_RB_DEFAULT;
                    preferRE = false;
                    advance_char(i, ch, chNext, chNext2);
                }
            } else if (isSafeAlnumOrHigh(ch) || ch == '_') {
                // Keep going
            } else if (ch == '.' && chNext == '.') {
                ++numDots;
                styler.ColourTo(i - 1, state);
                redo_char(i, ch, chNext, chNext2, state); // pass by ref
            } else if (ch == '.' && ++numDots == 1) {
                // Keep going
            } else {
                styler.ColourTo(i - 1, state);
                redo_char(i, ch, chNext, chNext2, state); // pass by ref
                preferRE = false;
            }
        } else if (state == SCE_RB_COMMENTLINE) {
			if (isEOLChar(ch)) {
                styler.ColourTo(i - 1, state);
                state = SCE_RB_DEFAULT;
                // Use whatever setting we had going into the comment
            }
        } else if (state == SCE_RB_HERE_DELIM) {
            // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx
            // Slightly different: if we find an immediate '-',
            // the target can appear indented.

			if (HereDoc.State == 0) { // '<<' encountered
				HereDoc.State = 1;
                HereDoc.DelimiterLength = 0;
                if (ch == '-') {
                    HereDoc.CanBeIndented = true;
                    advance_char(i, ch, chNext, chNext2); // pass by ref
                } else {
                    HereDoc.CanBeIndented = false;
                }
                if (isEOLChar(ch)) {
                    // Bail out of doing a here doc if there's no target
                    state = SCE_RB_DEFAULT;
                    preferRE = false;
                } else {
                    HereDoc.Quote = ch;

                    if (ch == '\'' || ch == '"' || ch == '`') {
                        HereDoc.Quoted = true;
                        HereDoc.Delimiter[0] = '\0';
                    } else {
                        HereDoc.Quoted = false;
                        HereDoc.Delimiter[0] = ch;
                        HereDoc.Delimiter[1] = '\0';
                        HereDoc.DelimiterLength = 1;
                    }
                }
			} else if (HereDoc.State == 1) { // collect the delimiter
                if (isEOLChar(ch)) {
                    // End the quote now, and go back for more
                    styler.ColourTo(i - 1, state);
                    state = SCE_RB_DEFAULT;
                    i--;
                    chNext = ch;
                    preferRE = false;
                } else if (HereDoc.Quoted) {
					if (ch == HereDoc.Quote) { // closing quote => end of delimiter
						styler.ColourTo(i, state);
						state = SCE_RB_DEFAULT;
                        preferRE = false;
                    } else {
						if (ch == '\\' && !isEOLChar(chNext)) {
                            advance_char(i, ch, chNext, chNext2);
						}
						HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
						HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
                    }
                } else { // an unquoted here-doc delimiter
					if (isSafeAlnumOrHigh(ch) || ch == '_') {
						HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
						HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
					} else {
						styler.ColourTo(i - 1, state);
                        redo_char(i, ch, chNext, chNext2, state);
                        preferRE = false;
					}
                }
				if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
					styler.ColourTo(i - 1, state);
					state = SCE_RB_ERROR;
                    preferRE = false;
				}
            }
        } else if (state == SCE_RB_HERE_Q) {
            // Not needed: HereDoc.State == 2
            // Indentable here docs: look backwards
            // Non-indentable: look forwards, like in Perl
            //
            // Why: so we can quickly resolve things like <<-" abc"

            if (!HereDoc.CanBeIndented) {
                if (isEOLChar(chPrev)
                    && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) {
                    styler.ColourTo(i - 1, state);
                    i += HereDoc.DelimiterLength - 1;
                    chNext = styler.SafeGetCharAt(i + 1);
                    if (isEOLChar(chNext)) {
                        styler.ColourTo(i, SCE_RB_HERE_DELIM);
                        state = SCE_RB_DEFAULT;
                        HereDoc.State = 0;
                        preferRE = false;
                    }
                    // Otherwise we skipped through the here doc faster.
                }
            } else if (isEOLChar(chNext)
                       && lookingAtHereDocDelim(styler,
                                                i - HereDoc.DelimiterLength + 1,
                                                lengthDoc,
                                                HereDoc.Delimiter)) {
                styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state);
                styler.ColourTo(i, SCE_RB_HERE_DELIM);
                state = SCE_RB_DEFAULT;
                preferRE = false;
                HereDoc.State = 0;
            }
        } else if (state == SCE_RB_CLASS_VAR
                   || state == SCE_RB_INSTANCE_VAR
                   || state == SCE_RB_SYMBOL) {
            if (!isSafeWordcharOrHigh(ch)) {
                styler.ColourTo(i - 1, state);
                redo_char(i, ch, chNext, chNext2, state); // pass by ref
                preferRE = false;
            }
        } else if (state == SCE_RB_GLOBAL) {
            if (!isSafeWordcharOrHigh(ch)) {
                // handle special globals here as well
                if (chPrev == '$') {
                    if (ch == '-') {
                        // Include the next char, like $-a
                        advance_char(i, ch, chNext, chNext2);
                    }
                    styler.ColourTo(i, state);
                    state = SCE_RB_DEFAULT;
                } else {
                    styler.ColourTo(i - 1, state);
                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
                }
                preferRE = false;
            }
        } else if (state == SCE_RB_POD) {
            // PODs end with ^=end\s, -- any whitespace can follow =end
            if (strchr(" \t\n\r", ch) != NULL
                && i > 5
                && isEOLChar(styler[i - 5])
                && isMatch(styler, lengthDoc, i - 4, "=end")) {
                styler.ColourTo(i - 1, state);
                state = SCE_RB_DEFAULT;
                preferRE = false;
            }
        } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) {
            if (ch == '\\' && Quote.Up != '\\') {
                // Skip one
                advance_char(i, ch, chNext, chNext2);
            } else if (ch == Quote.Down) {
                Quote.Count--;
                if (Quote.Count == 0) {
                    // Include the options
                    while (isSafeAlpha(chNext)) {
                        i++;
						ch = chNext;
                        chNext = styler.SafeGetCharAt(i + 1);
                    }
                    styler.ColourTo(i, state);
                    state = SCE_RB_DEFAULT;
                    preferRE = false;
                }
            } else if (ch == Quote.Up) {
                // Only if close quoter != open quoter
                Quote.Count++;

            } else if (ch == '#' ) {
                if (chNext == '{'
                    && inner_string_count < INNER_STRINGS_MAX_COUNT) {
                    // process #{ ... }
                    styler.ColourTo(i - 1, state);
                    styler.ColourTo(i + 1, SCE_RB_OPERATOR);
                    enterInnerExpression(inner_string_types,
                                         inner_expn_brace_counts,
                                         inner_quotes,
                                         inner_string_count,
                                         state,
                                         brace_counts,
                                         Quote);
                    preferRE = true;
                    // Skip one
                    advance_char(i, ch, chNext, chNext2);
                } else {
                    //todo: distinguish comments from pound chars
                    // for now, handle as comment
                    styler.ColourTo(i - 1, state);
                    bool inEscape = false;
                    while (++i < lengthDoc) {
                        ch = styler.SafeGetCharAt(i);
                        if (ch == '\\') {
                            inEscape = true;
                        } else if (isEOLChar(ch)) {
                            // Comment inside a regex
                            styler.ColourTo(i - 1, SCE_RB_COMMENTLINE);
                            break;
                        } else if (inEscape) {
                            inEscape = false;  // don't look at char
                        } else if (ch == Quote.Down) {
                            // Have the regular handler deal with this
                            // to get trailing modifiers.
                            i--;
                            ch = styler[i];
                            break;
                        }
                    }
                    chNext = styler.SafeGetCharAt(i + 1);
                }
            }
        // Quotes of all kinds...
        } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ ||
                   state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW ||
                   state == SCE_RB_STRING || state == SCE_RB_CHARACTER ||
                   state == SCE_RB_BACKTICKS) {
            if (!Quote.Down && !isspacechar(ch)) {
                Quote.Open(ch);
            } else if (ch == '\\' && Quote.Up != '\\') {
                //Riddle me this: Is it safe to skip *every* escaped char?
                advance_char(i, ch, chNext, chNext2);
            } else if (ch == Quote.Down) {
                Quote.Count--;
                if (Quote.Count == 0) {
                    styler.ColourTo(i, state);
                    state = SCE_RB_DEFAULT;
                    preferRE = false;
                }
            } else if (ch == Quote.Up) {
                Quote.Count++;
            } else if (ch == '#' && chNext == '{'
                       && inner_string_count < INNER_STRINGS_MAX_COUNT
                       && state != SCE_RB_CHARACTER
                       && state != SCE_RB_STRING_Q) {
                // process #{ ... }
                styler.ColourTo(i - 1, state);
                styler.ColourTo(i + 1, SCE_RB_OPERATOR);
                enterInnerExpression(inner_string_types,
                                     inner_expn_brace_counts,
                                     inner_quotes,
                                     inner_string_count,
                                     state,
                                     brace_counts,
                                     Quote);
                preferRE = true;
                // Skip one
                advance_char(i, ch, chNext, chNext2);
            }
        }

        if (state == SCE_RB_ERROR) {
            break;
        }
        chPrev = ch;
    }
    if (state == SCE_RB_WORD) {
        // We've ended on a word, possibly at EOF, and need to
        // classify it.
        (void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord);
    } else {
        styler.ColourTo(lengthDoc - 1, state);
    }
}

// Helper functions for folding, disambiguation keywords
// Assert that there are no high-bit chars

static void getPrevWord(int pos,
                        char *prevWord,
                        Accessor &styler,
                        int word_state)
{
    int i;
    styler.Flush();
    for (i = pos - 1; i > 0; i--) {
        if (actual_style(styler.StyleAt(i)) != word_state) {
            i++;
            break;
        }
    }
    if (i < pos - MAX_KEYWORD_LENGTH) // overflow
        i = pos - MAX_KEYWORD_LENGTH;
    char *dst = prevWord;
    for (; i <= pos; i++) {
        *dst++ = styler[i];
    }
	*dst = 0;
}

static bool keywordIsAmbiguous(const char *prevWord)
{
    // Order from most likely used to least likely
    // Lots of ways to do a loop in Ruby besides 'while/until'
    if (!strcmp(prevWord, "if")
        || !strcmp(prevWord, "do")
        || !strcmp(prevWord, "while")
        || !strcmp(prevWord, "unless")
        || !strcmp(prevWord, "until")
        || !strcmp(prevWord, "for")) {
        return true;
    } else {
        return false;
    }
}

// Demote keywords in the following conditions:
// if, while, unless, until modify a statement
// do after a while or until, as a noise word (like then after if)

static bool keywordIsModifier(const char *word,
                              int pos,
                              Accessor &styler)
{
    if (word[0] == 'd' && word[1] == 'o' && !word[2]) {
        return keywordDoStartsLoop(pos, styler);
    }
    char ch, chPrev, chPrev2;
    int style = SCE_RB_DEFAULT;
	int lineStart = styler.GetLine(pos);
    int lineStartPosn = styler.LineStart(lineStart);
    // We want to step backwards until we don't care about the current
    // position. But first move lineStartPosn back behind any
    // continuations immediately above word.
    while (lineStartPosn > 0) {
        ch = styler[lineStartPosn-1];
        if (ch == '\n' || ch == '\r') {
            chPrev  = styler.SafeGetCharAt(lineStartPosn-2);
            chPrev2 = styler.SafeGetCharAt(lineStartPosn-3);
            lineStart = styler.GetLine(lineStartPosn-1);
            // If we find a continuation line, include it in our analysis.
            if (chPrev == '\\') {
                lineStartPosn = styler.LineStart(lineStart);
            } else if (ch == '\n' && chPrev == '\r' && chPrev2 == '\\') {
                lineStartPosn = styler.LineStart(lineStart);
            } else {
                break;
            }
        } else {
          break;
        }
    }

    styler.Flush();
    while (--pos >= lineStartPosn) {
        style = actual_style(styler.StyleAt(pos));
		if (style == SCE_RB_DEFAULT) {
			if (iswhitespace(ch = styler[pos])) {
				//continue
			} else if (ch == '\r' || ch == '\n') {
				// Scintilla's LineStart() and GetLine() routines aren't
				// platform-independent, so if we have text prepared with
				// a different system we can't rely on it.

                // Also, lineStartPosn may have been moved to more than one
                // line above word's line while pushing past continuations.
                chPrev = styler.SafeGetCharAt(pos - 1);
                chPrev2 = styler.SafeGetCharAt(pos - 2);
                if (chPrev == '\\') {
                    pos-=1;  // gloss over the "\\"
                    //continue
                } else if (ch == '\n' && chPrev == '\r' && chPrev2 == '\\') {
                    pos-=2;  // gloss over the "\\\r"
                    //continue
                } else {
				    return false;
                }
			}
		} else {
            break;
		}
    }
    if (pos < lineStartPosn) {
        return false;
    }
    // First things where the action is unambiguous
    switch (style) {
        case SCE_RB_DEFAULT:
        case SCE_RB_COMMENTLINE:
        case SCE_RB_POD:
        case SCE_RB_CLASSNAME:
        case SCE_RB_DEFNAME:
        case SCE_RB_MODULE_NAME:
            return false;
        case SCE_RB_OPERATOR:
            break;
        case SCE_RB_WORD:
            // Watch out for uses of 'else if'
            //XXX: Make a list of other keywords where 'if' isn't a modifier
            //     and can appear legitimately
            // Formulate this to avoid warnings from most compilers
            if (strcmp(word, "if") == 0) {
                char prevWord[MAX_KEYWORD_LENGTH + 1];
                getPrevWord(pos, prevWord, styler, SCE_RB_WORD);
                return strcmp(prevWord, "else") != 0;
            }
            return true;
        default:
            return true;
    }
    // Assume that if the keyword follows an operator,
    // usually it's a block assignment, like
    // a << if x then y else z

    ch = styler[pos];
    switch (ch) {
        case ')':
        case ']':
        case '}':
            return true;
        default:
            return false;
    }
}

#define WHILE_BACKWARDS "elihw"
#define UNTIL_BACKWARDS "litnu"
#define FOR_BACKWARDS "rof"

// Nothing fancy -- look to see if we follow a while/until somewhere
// on the current line

static bool keywordDoStartsLoop(int pos,
                                Accessor &styler)
{
    char ch;
    int style;
	int lineStart = styler.GetLine(pos);
    int lineStartPosn = styler.LineStart(lineStart);
    styler.Flush();
    while (--pos >= lineStartPosn) {
        style = actual_style(styler.StyleAt(pos));
		if (style == SCE_RB_DEFAULT) {
			if ((ch = styler[pos]) == '\r' || ch == '\n') {
				// Scintilla's LineStart() and GetLine() routines aren't
				// platform-independent, so if we have text prepared with
				// a different system we can't rely on it.
				return false;
			}
		} else if (style == SCE_RB_WORD) {
            // Check for while or until, but write the word in backwards
            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
            char *dst = prevWord;
            int wordLen = 0;
            int start_word;
            for (start_word = pos;
                 start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD;
                 start_word--) {
                if (++wordLen < MAX_KEYWORD_LENGTH) {
                    *dst++ = styler[start_word];
                }
            }
            *dst = 0;
            // Did we see our keyword?
            if (!strcmp(prevWord, WHILE_BACKWARDS)
                || !strcmp(prevWord, UNTIL_BACKWARDS)
                || !strcmp(prevWord, FOR_BACKWARDS)) {
                return true;
            }
            // We can move pos to the beginning of the keyword, and then
            // accept another decrement, as we can never have two contiguous
            // keywords:
            // word1 word2
            //           ^
            //        <-  move to start_word
            //      ^
            //      <- loop decrement
            //     ^  # pointing to end of word1 is fine
            pos = start_word;
        }
    }
    return false;
}

/*
 *  Folding Ruby
 *
 *  The language is quite complex to analyze without a full parse.
 *  For example, this line shouldn't affect fold level:
 *
 *   print "hello" if feeling_friendly?
 *
 *  Neither should this:
 *
 *   print "hello" \
 *      if feeling_friendly?
 *
 *
 *  But this should:
 *
 *   if feeling_friendly?  #++
 *     print "hello" \
 *     print "goodbye"
 *   end                   #--
 *
 *  So we cheat, by actually looking at the existing indentation
 *  levels for each line, and just echoing it back.  Like Python.
 *  Then if we get better at it, we'll take braces into consideration,
 *  which always affect folding levels.

 *  How the keywords should work:
 *  No effect:
 *  __FILE__ __LINE__ BEGIN END alias and
 *  defined? false in nil not or self super then
 *  true undef

 *  Always increment:
 *  begin  class def do for module when {
 *
 *  Always decrement:
 *  end }
 *
 *  Increment if these start a statement
 *  if unless until while -- do nothing if they're modifiers

 *  These end a block if there's no modifier, but don't bother
 *  break next redo retry return yield
 *
 *  These temporarily de-indent, but re-indent
 *  case else elsif ensure rescue
 *
 *  This means that the folder reflects indentation rather
 *  than setting it.  The language-service updates indentation
 *  when users type return and finishes entering de-denters.
 *
 *  Later offer to fold POD, here-docs, strings, and blocks of comments
 */

static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
                      WordList *[], Accessor &styler) {
	const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;

    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
                        false);
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent)
                                         & SC_FOLDLEVELNUMBERMASK
                                         & ~SC_FOLDLEVELBASE);
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
    bool buffer_ends_with_eol = false;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
        if (style == SCE_RB_COMMENTLINE) {
            if (foldComment && stylePrev != SCE_RB_COMMENTLINE) {
                if (chNext == '{') {
					levelCurrent++;
				} else if (chNext == '}' && levelCurrent > 0) {
					levelCurrent--;
				}
            }
        } else if (style == SCE_RB_OPERATOR) {
			if (strchr("[{(", ch)) {
				levelCurrent++;
			} else if (strchr(")}]", ch)) {
                // Don't decrement below 0
                if (levelCurrent > 0)
                    levelCurrent--;
			}
        } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) {
            // Look at the keyword on the left and decide what to do
            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
            prevWord[0] = 0;
            getPrevWord(i, prevWord, styler, SCE_RB_WORD);
            if (!strcmp(prevWord, "end")) {
                // Don't decrement below 0
                if (levelCurrent > 0)
                    levelCurrent--;
            } else if (   !strcmp(prevWord, "if")
                       || !strcmp(prevWord, "def")
                       || !strcmp(prevWord, "class")
                       || !strcmp(prevWord, "module")
                       || !strcmp(prevWord, "begin")
                       || !strcmp(prevWord, "case")
                       || !strcmp(prevWord, "do")
                       || !strcmp(prevWord, "while")
                       || !strcmp(prevWord, "unless")
                       || !strcmp(prevWord, "until")
                       || !strcmp(prevWord, "for")
                          ) {
				levelCurrent++;
            }
		} else if (style == SCE_RB_HERE_DELIM) {
			if (styler.SafeGetCharAt(i-2) == '<' && styler.SafeGetCharAt(i-1) == '<') {
				levelCurrent++;
			} else if (styleNext == SCE_RB_DEFAULT) {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
            styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE);
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
            buffer_ends_with_eol = true;
		} else if (!isspacechar(ch)) {
			visibleChars++;
            buffer_ends_with_eol = false;
        }
		stylePrev = style;
    }
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
    if (!buffer_ends_with_eol) {
        lineCurrent++;
        int new_lev = levelCurrent;
        if (visibleChars == 0 && foldCompact)
            new_lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				new_lev |= SC_FOLDLEVELHEADERFLAG;
            levelCurrent = new_lev;
    }
	styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE);
}

static const char * const rubyWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc, 6);

Added lexers/LexSML.cxx.































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexSML.cxx
 ** Lexer for SML.
 **/
// Copyright 2009 by James Moffatt and Yuzhou Xin
// Modified from LexCaml.cxx by Robert Roessler <robertr@rftp.com> Copyright 2005
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

inline int  issml(int c) {return isalnum(c) || c == '_';}
inline int issmlf(int c) {return isalpha(c) || c == '_';}
inline int issmld(int c) {return isdigit(c) || c == '_';}


#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void ColouriseSMLDoc(
	unsigned int startPos, int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler)
{
	StyleContext sc(startPos, length, initStyle, styler);
	int nesting = 0;
	if (sc.state < SCE_SML_STRING)
		sc.state = SCE_SML_DEFAULT;
	if (sc.state >= SCE_SML_COMMENT)
		nesting = (sc.state & 0x0f) - SCE_SML_COMMENT;

	int chBase = 0, chToken = 0, chLit = 0;
	WordList& keywords  = *keywordlists[0];
	WordList& keywords2 = *keywordlists[1];
	WordList& keywords3 = *keywordlists[2];
	const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);

	while (sc.More()) {
		int state2 = -1;
		int chColor = sc.currentPos - 1;
		bool advance = true;

		switch (sc.state & 0x0f) {
		case SCE_SML_DEFAULT:
			chToken = sc.currentPos;
			if (issmlf(sc.ch))
				state2 = SCE_SML_IDENTIFIER;
			else if (sc.Match('`') && issmlf(sc.chNext))
				state2 = SCE_SML_TAGNAME;
			else if (sc.Match('#')&&isdigit(sc.chNext))
					state2 = SCE_SML_LINENUM;
			else if (sc.Match('#','\"')){
					state2 = SCE_SML_CHAR,chLit = 0;
					sc.Forward();

				}
			else if (isdigit(sc.ch)) {
				state2 = SCE_SML_NUMBER, chBase = 10;
				if (sc.Match('0') && strchr("xX", sc.chNext))
					chBase = 16, sc.Forward();}
			else if (sc.Match('\"')&&sc.chPrev!='#')
				state2 = SCE_SML_STRING;
			else if (sc.Match('(', '*')){
				state2 = SCE_SML_COMMENT,
					sc.ch = ' ',
					sc.Forward();}
			else if (strchr("!~"
					"=<>@^+-*/"
					"()[];,:.#", sc.ch))
				state2 = SCE_SML_OPERATOR;
			break;

		case SCE_SML_IDENTIFIER:
			if (!(issml(sc.ch) || sc.Match('\''))) {
				const int n = sc.currentPos - chToken;
				if (n < 24) {
					char t[24];
					for (int i = -n; i < 0; i++)
						t[n + i] = static_cast<char>(sc.GetRelative(i));
					t[n] = '\0';
					if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD);
					else if (keywords2.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD2);
					else if (keywords3.InList(t))
						sc.ChangeState(SCE_SML_KEYWORD3);
				}
				state2 = SCE_SML_DEFAULT, advance = false;
			}
			break;

		case SCE_SML_TAGNAME:
			if (!(issml(sc.ch) || sc.Match('\'')))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_LINENUM:
			if (!isdigit(sc.ch))
				state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_OPERATOR: {
			const char* o = 0;
			if (issml(sc.ch) || isspace(sc.ch)
				|| (o = strchr(")]};,\'\"`#", sc.ch),o)
				|| !strchr("!$%&*+-./:<=>?@^|~", sc.ch)) {
				if (o && strchr(")]};,", sc.ch)) {
					if ((sc.Match(')') && sc.chPrev == '(')
						|| (sc.Match(']') && sc.chPrev == '['))
						sc.ChangeState(SCE_SML_KEYWORD);
					chColor++;
				} else
					advance = false;
				state2 = SCE_SML_DEFAULT;
			}
			break;
		}

		case SCE_SML_NUMBER:
			if (issmld(sc.ch) || IsADigit(sc.ch, chBase))
				break;
			if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
				&& (issmld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
				break;
			if (chBase == 10) {
				if (sc.Match('.') && issmld(sc.chPrev))
					break;
				if ((sc.Match('e') || sc.Match('E'))
					&& (issmld(sc.chPrev) || sc.chPrev == '.'))
					break;
				if ((sc.Match('+') || sc.Match('-'))
					&& (sc.chPrev == 'e' || sc.chPrev == 'E'))
					break;
			}
			state2 = SCE_SML_DEFAULT, advance = false;
			break;

		case SCE_SML_CHAR:
			if (sc.Match('\\')) {
				chLit = 1;
				if (sc.chPrev == '\\')
					sc.ch = ' ';
			} else if ((sc.Match('\"') && sc.chPrev != '\\') || sc.atLineEnd) {
				state2 = SCE_SML_DEFAULT;
				chLit = 1;
				if (sc.Match('\"'))
					chColor++;
				else
					sc.ChangeState(SCE_SML_IDENTIFIER);
			} else if (chLit < 1 && sc.currentPos - chToken >= 3)
				sc.ChangeState(SCE_SML_IDENTIFIER), advance = false;
			break;

		case SCE_SML_STRING:
			if (sc.Match('\\') && sc.chPrev == '\\')
				sc.ch = ' ';
			else if (sc.Match('\"') && sc.chPrev != '\\')
				state2 = SCE_SML_DEFAULT, chColor++;
			break;

		case SCE_SML_COMMENT:
		case SCE_SML_COMMENT1:
		case SCE_SML_COMMENT2:
		case SCE_SML_COMMENT3:
			if (sc.Match('(', '*'))
				state2 = sc.state + 1, chToken = sc.currentPos,
					sc.ch = ' ',
					sc.Forward(), nesting++;
			else if (sc.Match(')') && sc.chPrev == '*') {
				if (nesting)
					state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
				else
					state2 = SCE_SML_DEFAULT;
				chColor++;
			} else if (useMagic && sc.currentPos - chToken == 4
				&& sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
				sc.state |= 0x10;
			break;
		}

		if (state2 >= 0)
			styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
		if (advance)
			sc.Forward();
	}

	sc.Complete();
}

void FoldSMLDoc(
	unsigned int, int,
	int,
	WordList *[],
	Accessor &)
{
}

static const char * const SMLWordListDesc[] = {
	"Keywords",
	"Keywords2",
	"Keywords3",
	0
};

LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc);

Added lexers/LexSQL.cxx.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
//-*- coding: utf-8 -*-
// Scintilla source code edit control
/** @file LexSQL.cxx
 ** Lexer for SQL, including PL/SQL and SQL*Plus.
 ** Improved by Jérôme LAFORGE <jerome.laforge_AT_gmail_DOT_com> from 2010 to 2012.
 **/
// Copyright 1998-2012 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>
#include <vector>
#include <map>
#include <algorithm>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "SparseState.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(int ch, bool sqlAllowDottedWord) {
	if (!sqlAllowDottedWord)
		return (ch < 0x80) && (isalnum(ch) || ch == '_');
	else
		return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
}

static inline bool IsAWordStart(int ch) {
	return (ch < 0x80) && (isalpha(ch) || ch == '_');
}

static inline bool IsADoxygenChar(int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
	        ch == '\\' || ch == '&' || ch == '<' ||
	        ch == '>' || ch == '#' || ch == '{' ||
	        ch == '}' || ch == '[' || ch == ']');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	       (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+');
}


class SQLStates {
public :
	void Set(int lineNumber, unsigned short int sqlStatesLine) {
		sqlStatement.Set(lineNumber, sqlStatesLine);
	}

	unsigned short int IgnoreWhen (unsigned short int sqlStatesLine, bool enable) {
		if (enable)
			sqlStatesLine |= MASK_IGNORE_WHEN;
		else
			sqlStatesLine &= ~MASK_IGNORE_WHEN;

		return sqlStatesLine;
	}

	unsigned short int IntoCondition (unsigned short int sqlStatesLine, bool enable) {
		if (enable)
			sqlStatesLine |= MASK_INTO_CONDITION;
		else
			sqlStatesLine &= ~MASK_INTO_CONDITION;

		return sqlStatesLine;
	}

	unsigned short int IntoExceptionBlock (unsigned short int sqlStatesLine, bool enable) {
		if (enable)
			sqlStatesLine |= MASK_INTO_EXCEPTION;
		else
			sqlStatesLine &= ~MASK_INTO_EXCEPTION;

		return sqlStatesLine;
	}

	unsigned short int IntoDeclareBlock (unsigned short int sqlStatesLine, bool enable) {
		if (enable)
			sqlStatesLine |= MASK_INTO_DECLARE;
		else
			sqlStatesLine &= ~MASK_INTO_DECLARE;

		return sqlStatesLine;
	}

	unsigned short int IntoMergeStatement (unsigned short int sqlStatesLine, bool enable) {
		if (enable)
			sqlStatesLine |= MASK_MERGE_STATEMENT;
		else
			sqlStatesLine &= ~MASK_MERGE_STATEMENT;

		return sqlStatesLine;
	}

	unsigned short int CaseMergeWithoutWhenFound (unsigned short int sqlStatesLine, bool found) {
		if (found)
			sqlStatesLine |= MASK_CASE_MERGE_WITHOUT_WHEN_FOUND;
		else
			sqlStatesLine &= ~MASK_CASE_MERGE_WITHOUT_WHEN_FOUND;

		return sqlStatesLine;
	}
	unsigned short int IntoSelectStatementOrAssignment (unsigned short int sqlStatesLine, bool found) {
		if (found)
			sqlStatesLine |= MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT;
		else
			sqlStatesLine &= ~MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT;
		return sqlStatesLine;
	}

	unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) {
		if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) {
			sqlStatesLine++;
		}
		return sqlStatesLine;
	}

	unsigned short int EndCaseBlock (unsigned short int sqlStatesLine) {
		if ((sqlStatesLine & MASK_NESTED_CASES) > 0) {
			sqlStatesLine--;
		}
		return sqlStatesLine;
	}

	bool IsIgnoreWhen (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_IGNORE_WHEN) != 0;
	}

	bool IsIntoCondition (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_INTO_CONDITION) != 0;
	}

	bool IsIntoCaseBlock (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_NESTED_CASES) != 0;
	}

	bool IsIntoExceptionBlock (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0;
	}
	bool IsIntoSelectStatementOrAssignment (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT) != 0;
	}
	bool IsCaseMergeWithoutWhenFound (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_CASE_MERGE_WITHOUT_WHEN_FOUND) != 0;
	}

	bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_INTO_DECLARE) != 0;
	}

	bool IsIntoMergeStatement (unsigned short int sqlStatesLine) {
		return (sqlStatesLine & MASK_MERGE_STATEMENT) != 0;
	}

	unsigned short int ForLine(int lineNumber) {
		return sqlStatement.ValueAt(lineNumber);
	}

	SQLStates() {}

private :
	SparseState <unsigned short int> sqlStatement;
	enum {
		MASK_NESTED_CASES = 0x01FF,
		MASK_INTO_SELECT_STATEMENT_OR_ASSIGNEMENT = 0x0200,
		MASK_CASE_MERGE_WITHOUT_WHEN_FOUND = 0x0400,
		MASK_MERGE_STATEMENT = 0x0800,
		MASK_INTO_DECLARE = 0x1000,
		MASK_INTO_EXCEPTION = 0x2000,
		MASK_INTO_CONDITION = 0x4000,
		MASK_IGNORE_WHEN = 0x8000
	};
};

// Options used for LexerSQL
struct OptionsSQL {
	bool fold;
	bool foldAtElse;
	bool foldComment;
	bool foldCompact;
	bool foldOnlyBegin;
	bool sqlBackticksIdentifier;
	bool sqlNumbersignComment;
	bool sqlBackslashEscapes;
	bool sqlAllowDottedWord;
	OptionsSQL() {
		fold = false;
		foldAtElse = false;
		foldComment = false;
		foldCompact = false;
		foldOnlyBegin = false;
		sqlBackticksIdentifier = false;
		sqlNumbersignComment = false;
		sqlBackslashEscapes = false;
		sqlAllowDottedWord = false;
	}
};

static const char * const sqlWordListDesc[] = {
	"Keywords",
	"Database Objects",
	"PLDoc",
	"SQL*Plus",
	"User Keywords 1",
	"User Keywords 2",
	"User Keywords 3",
	"User Keywords 4",
	0
};

struct OptionSetSQL : public OptionSet<OptionsSQL> {
	OptionSetSQL() {
		DefineProperty("fold", &OptionsSQL::fold);

		DefineProperty("fold.sql.at.else", &OptionsSQL::foldAtElse,
		               "This option enables SQL folding on a \"ELSE\" and \"ELSIF\" line of an IF statement.");

		DefineProperty("fold.comment", &OptionsSQL::foldComment);

		DefineProperty("fold.compact", &OptionsSQL::foldCompact);

		DefineProperty("fold.sql.only.begin", &OptionsSQL::foldOnlyBegin);

		DefineProperty("lexer.sql.backticks.identifier", &OptionsSQL::sqlBackticksIdentifier);

		DefineProperty("lexer.sql.numbersign.comment", &OptionsSQL::sqlNumbersignComment,
		               "If \"lexer.sql.numbersign.comment\" property is set to 0 a line beginning with '#' will not be a comment.");

		DefineProperty("sql.backslash.escapes", &OptionsSQL::sqlBackslashEscapes,
		               "Enables backslash as an escape character in SQL.");

		DefineProperty("lexer.sql.allow.dotted.word", &OptionsSQL::sqlAllowDottedWord,
		               "Set to 1 to colourise recognized words with dots "
		               "(recommended for Oracle PL/SQL objects).");

		DefineWordListSets(sqlWordListDesc);
	}
};

class LexerSQL : public ILexer {
public :
	LexerSQL() {}

	virtual ~LexerSQL() {}

	int SCI_METHOD Version () const {
		return lvOriginal;
	}

	void SCI_METHOD Release() {
		delete this;
	}

	const char * SCI_METHOD PropertyNames() {
		return osSQL.PropertyNames();
	}

	int SCI_METHOD PropertyType(const char *name) {
		return osSQL.PropertyType(name);
	}

	const char * SCI_METHOD DescribeProperty(const char *name) {
		return osSQL.DescribeProperty(name);
	}

	int SCI_METHOD PropertySet(const char *key, const char *val) {
		if (osSQL.PropertySet(&options, key, val)) {
			return 0;
		}
		return -1;
	}

	const char * SCI_METHOD DescribeWordListSets() {
		return osSQL.DescribeWordListSets();
	}

	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex (unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);

	void * SCI_METHOD PrivateCall(int, void *) {
		return 0;
	}

	static ILexer *LexerFactorySQL() {
		return new LexerSQL();
	}
private:
	bool IsStreamCommentStyle(int style) {
		return style == SCE_SQL_COMMENT ||
		       style == SCE_SQL_COMMENTDOC ||
		       style == SCE_SQL_COMMENTDOCKEYWORD ||
		       style == SCE_SQL_COMMENTDOCKEYWORDERROR;
	}

	bool IsCommentStyle (int style) {
		switch (style) {
		case SCE_SQL_COMMENT :
		case SCE_SQL_COMMENTDOC :
		case SCE_SQL_COMMENTLINE :
		case SCE_SQL_COMMENTLINEDOC :
		case SCE_SQL_COMMENTDOCKEYWORD :
		case SCE_SQL_COMMENTDOCKEYWORDERROR :
			return true;
		default :
			return false;
		}
	}

	bool IsCommentLine (int line, LexAccessor &styler) {
		int pos = styler.LineStart(line);
		int eol_pos = styler.LineStart(line + 1) - 1;
		for (int i = pos; i + 1 < eol_pos; i++) {
			int style = styler.StyleAt(i);
			// MySQL needs -- comments to be followed by space or control char
			if (style == SCE_SQL_COMMENTLINE && styler.Match(i, "--"))
				return true;
			else if (!IsASpaceOrTab(styler[i]))
				return false;
		}
		return false;
	}

	OptionsSQL options;
	OptionSetSQL osSQL;
	SQLStates sqlStates;

	WordList keywords1;
	WordList keywords2;
	WordList kw_pldoc;
	WordList kw_sqlplus;
	WordList kw_user1;
	WordList kw_user2;
	WordList kw_user3;
	WordList kw_user4;
};

int SCI_METHOD LexerSQL::WordListSet(int n, const char *wl) {
	WordList *wordListN = 0;
	switch (n) {
	case 0:
		wordListN = &keywords1;
		break;
	case 1:
		wordListN = &keywords2;
		break;
	case 2:
		wordListN = &kw_pldoc;
		break;
	case 3:
		wordListN = &kw_sqlplus;
		break;
	case 4:
		wordListN = &kw_user1;
		break;
	case 5:
		wordListN = &kw_user2;
		break;
	case 6:
		wordListN = &kw_user3;
		break;
	case 7:
		wordListN = &kw_user4;
	}
	int firstModification = -1;
	if (wordListN) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*wordListN != wlNew) {
			wordListN->Set(wl);
			firstModification = 0;
		}
	}
	return firstModification;
}

void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	LexAccessor styler(pAccess);
	StyleContext sc(startPos, length, initStyle, styler);
	int styleBeforeDCKeyword = SCE_SQL_DEFAULT;
	int offset = 0;
	for (; sc.More(); sc.Forward(), offset++) {
		// Determine if the current state should terminate.
		switch (sc.state) {
		case SCE_SQL_OPERATOR:
			sc.SetState(SCE_SQL_DEFAULT);
			break;
		case SCE_SQL_NUMBER:
			// We stop the number definition on non-numerical non-dot non-eE non-sign char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_SQL_DEFAULT);
			}
			break;
		case SCE_SQL_IDENTIFIER:
			if (!IsAWordChar(sc.ch, options.sqlAllowDottedWord)) {
				int nextState = SCE_SQL_DEFAULT;
				char s[1000];
				sc.GetCurrentLowered(s, sizeof(s));
				if (keywords1.InList(s)) {
					sc.ChangeState(SCE_SQL_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_SQL_WORD2);
				} else if (kw_sqlplus.InListAbbreviated(s, '~')) {
					sc.ChangeState(SCE_SQL_SQLPLUS);
					if (strncmp(s, "rem", 3) == 0) {
						nextState = SCE_SQL_SQLPLUS_COMMENT;
					} else if (strncmp(s, "pro", 3) == 0) {
						nextState = SCE_SQL_SQLPLUS_PROMPT;
					}
				} else if (kw_user1.InList(s)) {
					sc.ChangeState(SCE_SQL_USER1);
				} else if (kw_user2.InList(s)) {
					sc.ChangeState(SCE_SQL_USER2);
				} else if (kw_user3.InList(s)) {
					sc.ChangeState(SCE_SQL_USER3);
				} else if (kw_user4.InList(s)) {
					sc.ChangeState(SCE_SQL_USER4);
				}
				sc.SetState(nextState);
			}
			break;
		case SCE_SQL_QUOTEDIDENTIFIER:
			if (sc.ch == 0x60) {
				if (sc.chNext == 0x60) {
					sc.Forward();	// Ignore it
				} else {
					sc.ForwardSetState(SCE_SQL_DEFAULT);
				}
			}
			break;
		case SCE_SQL_COMMENT:
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_SQL_DEFAULT);
			}
			break;
		case SCE_SQL_COMMENTDOC:
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_SQL_DEFAULT);
			} else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support
				// Verify that we have the conditions to mark a comment-doc-keyword
				if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
					styleBeforeDCKeyword = SCE_SQL_COMMENTDOC;
					sc.SetState(SCE_SQL_COMMENTDOCKEYWORD);
				}
			}
			break;
		case SCE_SQL_COMMENTLINE:
		case SCE_SQL_COMMENTLINEDOC:
		case SCE_SQL_SQLPLUS_COMMENT:
		case SCE_SQL_SQLPLUS_PROMPT:
			if (sc.atLineStart) {
				sc.SetState(SCE_SQL_DEFAULT);
			}
			break;
		case SCE_SQL_COMMENTDOCKEYWORD:
			if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) {
				sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
				sc.Forward();
				sc.ForwardSetState(SCE_SQL_DEFAULT);
			} else if (!IsADoxygenChar(sc.ch)) {
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) {
					sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
				}
				sc.SetState(styleBeforeDCKeyword);
			}
			break;
		case SCE_SQL_CHARACTER:
			if (options.sqlBackslashEscapes && sc.ch == '\\') {
				sc.Forward();
			} else if (sc.ch == '\'') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_SQL_DEFAULT);
				}
			}
			break;
		case SCE_SQL_STRING:
			if (sc.ch == '\\') {
				// Escape sequence
				sc.Forward();
			} else if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_SQL_DEFAULT);
				}
			}
			break;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_SQL_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_SQL_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_SQL_IDENTIFIER);
			} else if (sc.ch == 0x60 && options.sqlBackticksIdentifier) {
				sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Doxygen doc. style
					sc.SetState(SCE_SQL_COMMENTDOC);
				} else {
					sc.SetState(SCE_SQL_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('-', '-')) {
				// MySQL requires a space or control char after --
				// http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
				// Perhaps we should enforce that with proper property:
				//~ 			} else if (sc.Match("-- ")) {
				sc.SetState(SCE_SQL_COMMENTLINE);
			} else if (sc.ch == '#' && options.sqlNumbersignComment) {
				sc.SetState(SCE_SQL_COMMENTLINEDOC);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_SQL_CHARACTER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_SQL_STRING);
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_SQL_OPERATOR);
			}
		}
	}
	sc.Complete();
}

void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	if (!options.fold)
		return;
	LexAccessor styler(pAccess);
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;

	if (lineCurrent > 0) {
		// Backtrack to previous line in case need to fix its fold status for folding block of single-line comments (i.e. '--').
		lineCurrent -= 1;
		startPos = styler.LineStart(lineCurrent);

		if (lineCurrent > 0)
			levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
	}
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	bool endFound = false;
	bool isUnfoldingIgnored = false;
	// this statementFound flag avoids to fold when the statement is on only one line by ignoring ELSE or ELSIF
	// eg. "IF condition1 THEN ... ELSIF condition2 THEN ... ELSE ... END IF;"
	bool statementFound = false;
	unsigned short int sqlStatesCurrentLine = 0;
	if (!options.foldOnlyBegin) {
		sqlStatesCurrentLine = sqlStates.ForLine(lineCurrent);
	}
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (atEOL || (!IsCommentStyle(style) && ch == ';')) {
			if (endFound) {
				//Maybe this is the end of "EXCEPTION" BLOCK (eg. "BEGIN ... EXCEPTION ... END;")
				sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, false);
			}
			// set endFound and isUnfoldingIgnored to false if EOL is reached or ';' is found
			endFound = false;
			isUnfoldingIgnored = false;
		}
		if ((!IsCommentStyle(style) && ch == ';')) {
			if (sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine)) {
				// This is the end of "MERGE" statement.
				if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine))
					levelNext--;
				sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, false);
				levelNext--;
			}
			if (sqlStates.IsIntoSelectStatementOrAssignment(sqlStatesCurrentLine))
				sqlStatesCurrentLine = sqlStates.IntoSelectStatementOrAssignment(sqlStatesCurrentLine, false);
		}
		if (ch == ':' && chNext == '=' && !IsCommentStyle(style))
			sqlStatesCurrentLine = sqlStates.IntoSelectStatementOrAssignment(sqlStatesCurrentLine, true);

		if (options.foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (options.foldComment && (style == SCE_SQL_COMMENTLINE)) {
			// MySQL needs -- comments to be followed by space or control char
			if ((ch == '-') && (chNext == '-')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				char chNext3 = styler.SafeGetCharAt(i + 3);
				if (chNext2 == '{' || chNext3 == '{') {
					levelNext++;
				} else if (chNext2 == '}' || chNext3 == '}') {
					levelNext--;
				}
			}
		}
		// Fold block of single-line comments (i.e. '--').
		if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) {
			if (!IsCommentLine(lineCurrent - 1, styler) && IsCommentLine(lineCurrent + 1, styler))
				levelNext++;
			else if (IsCommentLine(lineCurrent - 1, styler) && !IsCommentLine(lineCurrent + 1, styler))
				levelNext--;
		}
		if (style == SCE_SQL_OPERATOR) {
			if (ch == '(') {
				if (levelCurrent > levelNext)
					levelCurrent--;
				levelNext++;
			} else if (ch == ')') {
				levelNext--;
			} else if ((!options.foldOnlyBegin) && ch == ';') {
				sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, false);
			}
		}
		// If new keyword (cannot trigger on elseif or nullif, does less tests)
		if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) {
			const int MAX_KW_LEN = 9;	// Maximum length of folding keywords
			char s[MAX_KW_LEN + 2];
			unsigned int j = 0;
			for (; j < MAX_KW_LEN + 1; j++) {
				if (!iswordchar(styler[i + j])) {
					break;
				}
				s[j] = static_cast<char>(tolower(styler[i + j]));
			}
			if (j == MAX_KW_LEN + 1) {
				// Keyword too long, don't test it
				s[0] = '\0';
			} else {
				s[j] = '\0';
			}
			if (!options.foldOnlyBegin &&
			        strcmp(s, "select") == 0) {
				sqlStatesCurrentLine = sqlStates.IntoSelectStatementOrAssignment(sqlStatesCurrentLine, true);
			} else if (strcmp(s, "if") == 0) {
				if (endFound) {
					endFound = false;
					if (options.foldOnlyBegin && !isUnfoldingIgnored) {
						// this end isn't for begin block, but for if block ("end if;")
						// so ignore previous "end" by increment levelNext.
						levelNext++;
					}
				} else {
					if (!options.foldOnlyBegin)
						sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);
					if (levelCurrent > levelNext) {
						// doesn't include this line into the folding block
						// because doesn't hide IF (eg "END; IF")
						levelCurrent = levelNext;
					}
				}
			} else if (!options.foldOnlyBegin &&
			           strcmp(s, "then") == 0 &&
			           sqlStates.IsIntoCondition(sqlStatesCurrentLine)) {
				sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, false);
				if (!options.foldOnlyBegin) {
					if (levelCurrent > levelNext) {
						levelCurrent = levelNext;
					}
					if (!statementFound)
						levelNext++;

					statementFound = true;
				} else if (levelCurrent > levelNext) {
					// doesn't include this line into the folding block
					// because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE")
					levelCurrent = levelNext;
				}
			} else if (strcmp(s, "loop") == 0 ||
			           strcmp(s, "case") == 0) {
				if (endFound) {
					endFound = false;
					if (options.foldOnlyBegin && !isUnfoldingIgnored) {
						// this end isn't for begin block, but for loop block ("end loop;") or case block ("end case;")
						// so ignore previous "end" by increment levelNext.
						levelNext++;
					}
					if ((!options.foldOnlyBegin) && strcmp(s, "case") == 0) {
						sqlStatesCurrentLine = sqlStates.EndCaseBlock(sqlStatesCurrentLine);
						if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine))
							levelNext--; //again for the "end case;" and block when
					}
				} else if (!options.foldOnlyBegin) {
					if (strcmp(s, "case") == 0) {
						sqlStatesCurrentLine = sqlStates.BeginCaseBlock(sqlStatesCurrentLine);
						sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true);
					}

					if (levelCurrent > levelNext)
						levelCurrent = levelNext;

					if (!statementFound)
						levelNext++;

					statementFound = true;
				} else if (levelCurrent > levelNext) {
					// doesn't include this line into the folding block
					// because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE")
					levelCurrent = levelNext;
				}
			} else if ((!options.foldOnlyBegin) && (
			               // folding for ELSE and ELSIF block only if foldAtElse is set
			               // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound)
			               options.foldAtElse && !statementFound) && strcmp(s, "elsif") == 0) {
				sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);
				levelCurrent--;
				levelNext--;
			} else if ((!options.foldOnlyBegin) && (
			               // folding for ELSE and ELSIF block only if foldAtElse is set
			               // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound)
			               options.foldAtElse && !statementFound) && strcmp(s, "else") == 0) {
				// prevent also ELSE is on the same line (eg. "ELSE ... END IF;")
				statementFound = true;
				if (sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine) && sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) {
					sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false);
					levelNext++;
				} else {
					// we are in same case "} ELSE {" in C language
					levelCurrent--;
				}
			} else if (strcmp(s, "begin") == 0) {
				levelNext++;
				sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false);
			} else if ((strcmp(s, "end") == 0) ||
			           // SQL Anywhere permits IF ... ELSE ... ENDIF
			           // will only be active if "endif" appears in the
			           // keyword list.
			           (strcmp(s, "endif") == 0)) {
				endFound = true;
				levelNext--;
				if (sqlStates.IsIntoSelectStatementOrAssignment(sqlStatesCurrentLine) && !sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine))
					levelNext--;
				if (levelNext < SC_FOLDLEVELBASE) {
					levelNext = SC_FOLDLEVELBASE;
					isUnfoldingIgnored = true;
				}
			} else if ((!options.foldOnlyBegin) &&
			           strcmp(s, "when") == 0 &&
			           !sqlStates.IsIgnoreWhen(sqlStatesCurrentLine) &&
			           !sqlStates.IsIntoExceptionBlock(sqlStatesCurrentLine) && (
			               sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine) ||
			               sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine)
			               )
			           ) {
				sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true);

				// Don't foldind when CASE and WHEN are on the same line (with flag statementFound) (eg. "CASE selector WHEN expression1 THEN sequence_of_statements1;\n")
				// and same way for MERGE statement.
				if (!statementFound) {
					if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) {
						levelCurrent--;
						levelNext--;
					}
					sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false);
				}
			} else if ((!options.foldOnlyBegin) && strcmp(s, "exit") == 0) {
				sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, true);
			} else if ((!options.foldOnlyBegin) && !sqlStates.IsIntoDeclareBlock(sqlStatesCurrentLine) && strcmp(s, "exception") == 0) {
				sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, true);
			} else if ((!options.foldOnlyBegin) &&
			           (strcmp(s, "declare") == 0 ||
			            strcmp(s, "function") == 0 ||
			            strcmp(s, "procedure") == 0 ||
			            strcmp(s, "package") == 0)) {
				sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, true);
			} else if ((!options.foldOnlyBegin) &&
			           strcmp(s, "merge") == 0) {
				sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, true);
				sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true);
				levelNext++;
				statementFound = true;
			}
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && options.foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			visibleChars = 0;
			statementFound = false;
			if (!options.foldOnlyBegin)
				sqlStates.Set(lineCurrent, sqlStatesCurrentLine);
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
}

LexerModule lmSQL(SCLEX_SQL, LexerSQL::LexerFactorySQL, "sql", sqlWordListDesc);

Added lexers/LexScriptol.cxx.























































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
// Scintilla source code edit control
/** @file LexScriptol.cxx
 ** Lexer for Scriptol.
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord)
{
    char s[100];
    bool wordIsNumber = isdigit(styler[start]) != 0;
    for (unsigned int i = 0; i < end - start + 1 && i < 30; i++)
     {
           s[i] = styler[start + i];
           s[i + 1] = '\0';
     }
    char chAttr = SCE_SCRIPTOL_IDENTIFIER;
    if (0 == strcmp(prevWord, "class"))       chAttr = SCE_SCRIPTOL_CLASSNAME;
    else if (wordIsNumber)                    chAttr = SCE_SCRIPTOL_NUMBER;
    else if (keywords.InList(s))              chAttr = SCE_SCRIPTOL_KEYWORD;
    else for (unsigned int i = 0; i < end - start + 1; i++)  // test dotted idents
    {
        if (styler[start + i] == '.')
        {
            styler.ColourTo(start + i - 1, chAttr);
            styler.ColourTo(start + i, SCE_SCRIPTOL_OPERATOR);
        }
    }
    styler.ColourTo(end, chAttr);
    strcpy(prevWord, s);
}

static bool IsSolComment(Accessor &styler, int pos, int len)
{
   if(len > 0)
   {
     char c = styler[pos];
     if(c == '`') return true;
     if(len > 1)
     {
        if(c == '/')
        {
          c = styler[pos + 1];
          if(c == '/') return true;
          if(c == '*') return true;
        }
     }
   }
   return false;
}

static bool IsSolStringStart(char ch)
{
    if (ch == '\'' || ch == '"')  return true;
    return false;
}

static bool IsSolWordStart(char ch)
{
    return (iswordchar(ch) && !IsSolStringStart(ch));
}


static int GetSolStringState(Accessor &styler, int i, int *nextIndex)
{
	char ch = styler.SafeGetCharAt(i);
	char chNext = styler.SafeGetCharAt(i + 1);

        if (ch != '\"' && ch != '\'')
        {
            *nextIndex = i + 1;
            return SCE_SCRIPTOL_DEFAULT;
	}
        // ch is either single or double quotes in string
        // code below seem non-sense but is here for future extensions
	if (ch == chNext && ch == styler.SafeGetCharAt(i + 2))
        {
          *nextIndex = i + 3;
          if(ch == '\"') return SCE_SCRIPTOL_TRIPLE;
          if(ch == '\'') return SCE_SCRIPTOL_TRIPLE;
          return SCE_SCRIPTOL_STRING;
	}
        else
        {
          *nextIndex = i + 1;
          if (ch == '"') return SCE_SCRIPTOL_STRING;
          else           return SCE_SCRIPTOL_STRING;
	}
}


static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle,
                            WordList *keywordlists[], Accessor &styler)
 {

	int lengthDoc = startPos + length;
        char stringType = '\"';

	if (startPos > 0)
        {
            int lineCurrent = styler.GetLine(startPos);
            if (lineCurrent > 0)
            {
              startPos = styler.LineStart(lineCurrent-1);
              if (startPos == 0) initStyle = SCE_SCRIPTOL_DEFAULT;
              else               initStyle = styler.StyleAt(startPos-1);
            }
	}

	styler.StartAt(startPos, 127);

	WordList &keywords = *keywordlists[0];

	int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
	char prevWord[200];
	prevWord[0] = '\0';
        if (length == 0)  return;

	int state = initStyle & 31;

	int nextIndex = 0;
        char chPrev  = ' ';
        char chPrev2 = ' ';
        char chNext  = styler[startPos];
	styler.StartSegment(startPos);
	bool atStartLine = true;
	int spaceFlags = 0;
	for (int i = startPos; i < lengthDoc; i++)
        {

         if (atStartLine)
         {
         char chBad = static_cast<char>(64);
         char chGood = static_cast<char>(0);
         char chFlags = chGood;

         if (whingeLevel == 1)
         {
             chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
         }
         else if (whingeLevel == 2)
         {
             chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
         }
         else if (whingeLevel == 3)
         {
             chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
         }
         else if (whingeLevel == 4)
         {
              chFlags = (spaceFlags & wsTab) ? chBad : chGood;
         }
         styler.SetFlags(chFlags, static_cast<char>(state));
         atStartLine = false;
       }

       char ch = chNext;
       chNext = styler.SafeGetCharAt(i + 1);

       if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc))
       {
          if ((state == SCE_SCRIPTOL_DEFAULT) ||
              (state == SCE_SCRIPTOL_TRIPLE) ||
              (state == SCE_SCRIPTOL_COMMENTBLOCK))
          {
              styler.ColourTo(i, state);
          }
          atStartLine = true;
        }

        if (styler.IsLeadByte(ch))
         {
             chNext = styler.SafeGetCharAt(i + 2);
             chPrev  = ' ';
             chPrev2 = ' ';
             i += 1;
             continue;
         }

        if (state == SCE_SCRIPTOL_STRINGEOL)
         {
             if (ch != '\r' && ch != '\n')
             {
                    styler.ColourTo(i - 1, state);
                    state = SCE_SCRIPTOL_DEFAULT;
             }
         }

        if (state == SCE_SCRIPTOL_DEFAULT)
         {
            if (IsSolWordStart(ch))
            {
                 styler.ColourTo(i - 1, state);
                 state = SCE_SCRIPTOL_KEYWORD;
            }
            else if (ch == '`')
            {
                styler.ColourTo(i - 1, state);
                state = SCE_SCRIPTOL_COMMENTLINE;
            }
            else if (ch == '/')
            {
                styler.ColourTo(i - 1, state);
                if(chNext == '/') state = SCE_SCRIPTOL_CSTYLE;
                if(chNext == '*') state = SCE_SCRIPTOL_COMMENTBLOCK;
            }

            else if (IsSolStringStart(ch))
            {
               styler.ColourTo(i - 1, state);
               state = GetSolStringState(styler, i, &nextIndex);
               if(state == SCE_SCRIPTOL_STRING)
               {
                 stringType = ch;
               }
               if (nextIndex != i + 1)
               {
                   i = nextIndex - 1;
                   ch = ' ';
                   chPrev = ' ';
                   chNext = styler.SafeGetCharAt(i + 1);
               }
           }
            else if (isoperator(ch))
            {
                 styler.ColourTo(i - 1, state);
                 styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR);
            }
          }
          else if (state == SCE_SCRIPTOL_KEYWORD)
          {
              if (!iswordchar(ch))
              {
                 ClassifyWordSol(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
                 state = SCE_SCRIPTOL_DEFAULT;
                 if (ch == '`')
                 {
                     state = chNext == '`' ? SCE_SCRIPTOL_PERSISTENT : SCE_SCRIPTOL_COMMENTLINE;
                 }
                 else if (IsSolStringStart(ch))
                 {
                    styler.ColourTo(i - 1, state);
                    state = GetSolStringState(styler, i, &nextIndex);
                    if (nextIndex != i + 1)
                    {
                       i = nextIndex - 1;
                       ch = ' ';
                       chPrev = ' ';
                       chNext = styler.SafeGetCharAt(i + 1);
                     }
                 }
                 else if (isoperator(ch))
                 {
                     styler.ColourTo(i, SCE_SCRIPTOL_OPERATOR);
                 }
             }
          }
          else
          {
            if (state == SCE_SCRIPTOL_COMMENTLINE ||
                state == SCE_SCRIPTOL_PERSISTENT ||
                state == SCE_SCRIPTOL_CSTYLE)
            {
                 if (ch == '\r' || ch == '\n')
                 {
                     styler.ColourTo(i - 1, state);
                     state = SCE_SCRIPTOL_DEFAULT;
                 }
            }
            else if(state == SCE_SCRIPTOL_COMMENTBLOCK)
            {
              if(chPrev == '*' && ch == '/')
              {
                styler.ColourTo(i, state);
                state = SCE_SCRIPTOL_DEFAULT;
              }
            }
            else if ((state == SCE_SCRIPTOL_STRING) ||
                     (state == SCE_SCRIPTOL_CHARACTER))
            {
               if ((ch == '\r' || ch == '\n') && (chPrev != '\\'))
                {
                    styler.ColourTo(i - 1, state);
                    state = SCE_SCRIPTOL_STRINGEOL;
                }
                else if (ch == '\\')
                {
                   if (chNext == '\"' || chNext == '\'' || chNext == '\\')
                   {
                        i++;
                        ch = chNext;
                        chNext = styler.SafeGetCharAt(i + 1);
                   }
                 }
                else if ((ch == '\"') || (ch == '\''))
                {
                    // must match the entered quote type
                    if(ch == stringType)
                    {
                      styler.ColourTo(i, state);
                      state = SCE_SCRIPTOL_DEFAULT;
                    }
                 }
             }
             else if (state == SCE_SCRIPTOL_TRIPLE)
             {
                if ((ch == '\'' && chPrev == '\'' && chPrev2 == '\'') ||
                    (ch == '\"' && chPrev == '\"' && chPrev2 == '\"'))
                 {
                    styler.ColourTo(i, state);
                    state = SCE_SCRIPTOL_DEFAULT;
                 }
             }

           }
          chPrev2 = chPrev;
          chPrev = ch;
	}
        if (state == SCE_SCRIPTOL_KEYWORD)
        {
            ClassifyWordSol(styler.GetStartSegment(),
                 lengthDoc-1, keywords, styler, prevWord);
	}
        else
        {
            styler.ColourTo(lengthDoc-1, state);
	}
}

static void FoldSolDoc(unsigned int startPos, int length, int initStyle,
						   WordList *[], Accessor &styler)
 {
	int lengthDoc = startPos + length;

	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0)
        {
          if (lineCurrent > 0)
          {
               lineCurrent--;
               startPos = styler.LineStart(lineCurrent);
               if (startPos == 0)
                    initStyle = SCE_SCRIPTOL_DEFAULT;
               else
                    initStyle = styler.StyleAt(startPos-1);
           }
	}
	int state = initStyle & 31;
	int spaceFlags = 0;
        int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment);
        if (state == SCE_SCRIPTOL_TRIPLE)
             indentCurrent |= SC_FOLDLEVELWHITEFLAG;
	char chNext = styler[startPos];
	for (int i = startPos; i < lengthDoc; i++)
         {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i) & 31;

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc))
                {
                   int lev = indentCurrent;
                   int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsSolComment);
                   if (style == SCE_SCRIPTOL_TRIPLE)
                        indentNext |= SC_FOLDLEVELWHITEFLAG;
                   if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG))
                    {
                        // Only non whitespace lines can be headers
                        if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
                        {
                              lev |= SC_FOLDLEVELHEADERFLAG;
                        }
                        else if (indentNext & SC_FOLDLEVELWHITEFLAG)
                        {
                             // Line after is blank so check the next - maybe should continue further?
                             int spaceFlags2 = 0;
                             int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsSolComment);
                             if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK))
                             {
                                   lev |= SC_FOLDLEVELHEADERFLAG;
                              }
                        }
                    }
                   indentCurrent = indentNext;
                   styler.SetLevel(lineCurrent, lev);
                   lineCurrent++;
		}
	}
}

LexerModule lmScriptol(SCLEX_SCRIPTOL, ColouriseSolDoc, "scriptol", FoldSolDoc);

Added lexers/LexSmalltalk.cxx.













































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
// Scintilla source code edit control
/** @file LexSmalltalk.cxx
 ** Lexer for Smalltalk language.
 ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
| lexTable classificationBlock charClasses |
charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
lexTable := ByteArray new: 128.
classificationBlock := [ :charClass :chars |
    | flag |
    flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
    chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].

classificationBlock
    value: #DecDigit value: '0123456789';
    value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    value: #Special value: '()[]{};.^:';
    value: #BinSel value: '~@%&*-+=|\/,<>?!';
    value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

((String new: 500) streamContents: [ :stream |
    stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
    lexTable keysAndValuesDo: [ :index :value |
        ((index - 1) rem: 16) == 0 ifTrue: [
            stream crLf; tab]
        ifFalse: [
            stream space].
        stream print: value.
        index ~= 256 ifTrue: [
            stream nextPut: $,]].
    stream crLf; nextPutAll: '};'; crLf.

    charClasses keysAndValuesDo: [ :index :name |
        stream
            crLf;
            nextPutAll: (
                ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
                    expandMacrosWith: name with: (1 bitShift: (index - 1)))
    ]]) edit
*/

// autogenerated {{{{

static int ClassificationTable[256] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
    16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
    0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
};

static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
// autogenerated }}}}

static inline bool isAlphaNumeric(int ch) {
    return isDecDigit(ch) || isLetter(ch);
}

static inline bool isDigitOfRadix(int ch, int radix)
{
    if (isDecDigit(ch))
        return (ch - '0') < radix;
    else if (!isUpper(ch))
        return false;
    else
        return (ch - 'A' + 10) < radix;
}

static inline void skipComment(StyleContext& sc)
{
    while (sc.More() && sc.ch != '\"')
        sc.Forward();
}

static inline void skipString(StyleContext& sc)
{
    while (sc.More()) {
        if (sc.ch == '\'') {
            if (sc.chNext != '\'')
                return;
            sc.Forward();
        }
        sc.Forward();
    }
}

static void handleHash(StyleContext& sc)
{
    if (isSpecial(sc.chNext)) {
        sc.SetState(SCE_ST_SPECIAL);
        return;
    }

    sc.SetState(SCE_ST_SYMBOL);
    sc.Forward();
    if (sc.ch == '\'') {
        sc.Forward();
        skipString(sc);
    }
    else {
        if (isLetter(sc.ch)) {
            while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
                sc.Forward();
        }
        else if (isBinSel(sc.ch)) {
            while (isBinSel(sc.chNext))
                sc.Forward();
        }
    }
}

static inline void handleSpecial(StyleContext& sc)
{
    if (sc.ch == ':' && sc.chNext == '=') {
        sc.SetState(SCE_ST_ASSIGN);
        sc.Forward();
    }
    else {
        if (sc.ch == '^')
            sc.SetState(SCE_ST_RETURN);
        else
            sc.SetState(SCE_ST_SPECIAL);
    }
}

static inline void skipInt(StyleContext& sc, int radix)
{
    while (isDigitOfRadix(sc.chNext, radix))
        sc.Forward();
}

static void handleNumeric(StyleContext& sc)
{
    char num[256];
    int nl;
    int radix;

    sc.SetState(SCE_ST_NUMBER);
    num[0] = static_cast<char>(sc.ch);
    nl = 1;
    while (isDecDigit(sc.chNext)) {
        num[nl++] = static_cast<char>(sc.chNext);
        sc.Forward();
        if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
            break;
    }
    if (sc.chNext == 'r') {
        num[nl] = 0;
        if (num[0] == '-')
            radix = atoi(num + 1);
        else
            radix = atoi(num);
        sc.Forward();
        if (sc.chNext == '-')
            sc.Forward();
        skipInt(sc, radix);
    }
    else
        radix = 10;
    if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
        return;
    sc.Forward();
    skipInt(sc, radix);
    if (sc.chNext == 's') {
        // ScaledDecimal
        sc.Forward();
        while (isDecDigit(sc.chNext))
            sc.Forward();
        return;
    }
    else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
        return;
    sc.Forward();
    if (sc.chNext == '+' || sc.chNext == '-')
        sc.Forward();
    skipInt(sc, radix);
}

static inline void handleBinSel(StyleContext& sc)
{
    sc.SetState(SCE_ST_BINARY);
    while (isBinSel(sc.chNext))
        sc.Forward();
}

static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
{
    char ident[256];
    int il;
    int state;
    bool doubleColonPresent;

    sc.SetState(SCE_ST_DEFAULT);

    ident[0] = static_cast<char>(sc.ch);
    il = 1;
    while (isAlphaNumeric(sc.chNext)) {
        ident[il++] = static_cast<char>(sc.chNext);
        sc.Forward();
        if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
            break;
    }

    if (sc.chNext == ':') {
        doubleColonPresent = true;
        ident[il++] = ':';
        sc.Forward();
    }
    else
        doubleColonPresent = false;
    ident[il] = 0;

    if (specialSelectorList->InList(ident))
            state = SCE_ST_SPEC_SEL;
    else if (doubleColonPresent)
            state = SCE_ST_KWSEND;
    else if (isUpper(ident[0]))
        state = SCE_ST_GLOBAL;
    else {
        if (!strcmp(ident, "self"))
            state = SCE_ST_SELF;
        else if (!strcmp(ident, "super"))
            state = SCE_ST_SUPER;
        else if (!strcmp(ident, "nil"))
            state = SCE_ST_NIL;
        else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
            state = SCE_ST_BOOL;
        else
            state = SCE_ST_DEFAULT;
    }

    sc.ChangeState(state);
}

static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler)
{
    StyleContext sc(startPos, length, initStyle, styler);

    if (initStyle == SCE_ST_COMMENT) {
        skipComment(sc);
        if (sc.More())
            sc.Forward();
    }
    else if (initStyle == SCE_ST_STRING) {
        skipString(sc);
        if (sc.More())
            sc.Forward();
    }

    for (; sc.More(); sc.Forward()) {
        int ch;

        ch = sc.ch;
        if (ch == '\"') {
            sc.SetState(SCE_ST_COMMENT);
            sc.Forward();
            skipComment(sc);
        }
        else if (ch == '\'') {
            sc.SetState(SCE_ST_STRING);
            sc.Forward();
            skipString(sc);
        }
        else if (ch == '#')
            handleHash(sc);
        else if (ch == '$') {
            sc.SetState(SCE_ST_CHARACTER);
            sc.Forward();
        }
        else if (isSpecial(ch))
            handleSpecial(sc);
        else if (isDecDigit(ch))
            handleNumeric(sc);
        else if (isLetter(ch))
            handleLetter(sc, wordLists[0]);
        else if (isBinSel(ch)) {
            if (ch == '-' && isDecDigit(sc.chNext))
                handleNumeric(sc);
            else
                handleBinSel(sc);
        }
        else
            sc.SetState(SCE_ST_DEFAULT);
    }
    sc.Complete();
}

static const char* const smalltalkWordListDesc[] = {
    "Special selectors",
    0
};

LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);

Added lexers/LexSorcus.cxx.

































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexSorcus.cxx
** Lexer for SORCUS installation files
** Written by Eugen Bitter and Christoph Baumann at SORCUS Computer, Heidelberg Germany
** Based on the ASM Lexer by The Black Horus
**/

// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


//each character a..z and A..Z + '_' can be part of a keyword
//additionally numbers that follow 'M' can be contained in a keyword
static inline bool IsSWordStart(const int ch, const int prev_ch)
{
    if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M')))
        return true;

    return false;
}


//only digits that are not preceded by 'M' count as a number
static inline bool IsSorcusNumber(const int ch, const int prev_ch)
{
    if ((isdigit(ch)) && (prev_ch != 'M'))
        return true;

    return false;
}


//only = is a valid operator
static inline bool IsSorcusOperator(const int ch)
{
    if (ch == '=')
        return true;

    return false;
}


static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                               Accessor &styler)
{

    WordList &Command = *keywordlists[0];
    WordList &Parameter = *keywordlists[1];
    WordList &Constant = *keywordlists[2];

    // Do not leak onto next line
    if (initStyle == SCE_SORCUS_STRINGEOL)
        initStyle = SCE_SORCUS_DEFAULT;

    StyleContext sc(startPos, length, initStyle, styler);

    for (; sc.More(); sc.Forward())
    {

        // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line
        if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING))
        {
            sc.SetState(SCE_SORCUS_STRING);
        }

        // Determine if the current state should terminate.
        if (sc.state == SCE_SORCUS_OPERATOR)
        {
            if (!IsSorcusOperator(sc.ch))
            {
                sc.SetState(SCE_SORCUS_DEFAULT);
            }
        }
        else if(sc.state == SCE_SORCUS_NUMBER)
        {
            if(!IsSorcusNumber(sc.ch, sc.chPrev))
            {
                sc.SetState(SCE_SORCUS_DEFAULT);
            }
        }
        else if (sc.state == SCE_SORCUS_IDENTIFIER)
        {
            if (!IsSWordStart(sc.ch, sc.chPrev))
            {
                char s[100];

                sc.GetCurrent(s, sizeof(s));

                if (Command.InList(s))
                {
                    sc.ChangeState(SCE_SORCUS_COMMAND);
                }
                else if (Parameter.InList(s))
                {
                    sc.ChangeState(SCE_SORCUS_PARAMETER);
                }
                else if (Constant.InList(s))
                {
                    sc.ChangeState(SCE_SORCUS_CONSTANT);
                }

                sc.SetState(SCE_SORCUS_DEFAULT);
            }
        }
        else if (sc.state == SCE_SORCUS_COMMENTLINE )
        {
            if (sc.atLineEnd)
            {
                sc.SetState(SCE_SORCUS_DEFAULT);
            }
        }
        else if (sc.state == SCE_SORCUS_STRING)
        {
            if (sc.ch == '\"')
            {
                sc.ForwardSetState(SCE_SORCUS_DEFAULT);
            }
            else if (sc.atLineEnd)
            {
                sc.ChangeState(SCE_SORCUS_STRINGEOL);
                sc.ForwardSetState(SCE_SORCUS_DEFAULT);
            }
        }

        // Determine if a new state should be entered.
        if (sc.state == SCE_SORCUS_DEFAULT)
        {
            if ((sc.ch == ';') || (sc.ch == '\''))
            {
                sc.SetState(SCE_SORCUS_COMMENTLINE);
            }
            else if (IsSWordStart(sc.ch, sc.chPrev))
            {
                sc.SetState(SCE_SORCUS_IDENTIFIER);
            }
            else if (sc.ch == '\"')
            {
                sc.SetState(SCE_SORCUS_STRING);
            }
            else if (IsSorcusOperator(sc.ch))
            {
                sc.SetState(SCE_SORCUS_OPERATOR);
            }
            else if (IsSorcusNumber(sc.ch, sc.chPrev))
            {
                sc.SetState(SCE_SORCUS_NUMBER);
            }
        }

    }
    sc.Complete();
}


static const char* const SorcusWordListDesc[] = {"Command","Parameter", "Constant", 0};

LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins", 0, SorcusWordListDesc);






























Added lexers/LexSpecman.cxx.









































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
// Scintilla source code edit control
/** @file LexSpecman.cxx
 ** Lexer for Specman E language.
 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
}

static inline bool IsANumberChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\'');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '`');
}

static void ColouriseSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler, bool caseSensitive) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_SN_STRINGEOL)
		initStyle = SCE_SN_CODE;

	int visibleChars = 0;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_SN_STRING)) {
			// Prevent SCE_SN_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_SN_STRING);
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_SN_OPERATOR) {
			sc.SetState(SCE_SN_CODE);
		} else if (sc.state == SCE_SN_NUMBER) {
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_SN_CODE);
			}
		} else if (sc.state == SCE_SN_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				if (caseSensitive) {
					sc.GetCurrent(s, sizeof(s));
				} else {
					sc.GetCurrentLowered(s, sizeof(s));
				}
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_SN_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_SN_WORD2);
				} else if (keywords3.InList(s)) {
                                        sc.ChangeState(SCE_SN_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_SN_USER);
				}
				sc.SetState(SCE_SN_CODE);
			}
		} else if (sc.state == SCE_SN_PREPROCESSOR) {
                        if (IsASpace(sc.ch)) {
                                sc.SetState(SCE_SN_CODE);
                        }
		} else if (sc.state == SCE_SN_DEFAULT) {
			if (sc.Match('<', '\'')) {
				sc.Forward();
				sc.ForwardSetState(SCE_SN_CODE);
			}
		} else if (sc.state == SCE_SN_COMMENTLINE || sc.state == SCE_SN_COMMENTLINEBANG) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_SN_CODE);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_SN_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_SN_CODE);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_SN_STRINGEOL);
				sc.ForwardSetState(SCE_SN_CODE);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_SN_SIGNAL) {
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_SN_STRINGEOL);
				sc.ForwardSetState(SCE_SN_CODE);
				visibleChars = 0;
			} else if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_SN_CODE);
			}
		} else if (sc.state == SCE_SN_REGEXTAG) {
			if (!IsADigit(sc.ch)) {
				sc.SetState(SCE_SN_CODE);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_SN_CODE) {
			if (sc.ch == '$' && IsADigit(sc.chNext)) {
				sc.SetState(SCE_SN_REGEXTAG);
                                sc.Forward();
			} else if (IsADigit(sc.ch)) {
                                sc.SetState(SCE_SN_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_SN_IDENTIFIER);
			} else if (sc.Match('\'', '>')) {
                                sc.SetState(SCE_SN_DEFAULT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("//!"))	// Nice to have a different comment style
					sc.SetState(SCE_SN_COMMENTLINEBANG);
				else
					sc.SetState(SCE_SN_COMMENTLINE);
			} else if (sc.Match('-', '-')) {
				if (sc.Match("--!"))	// Nice to have a different comment style
					sc.SetState(SCE_SN_COMMENTLINEBANG);
				else
					sc.SetState(SCE_SN_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_SN_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_SN_SIGNAL);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_SN_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_SN_CODE);
				}
			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@') {
				sc.SetState(SCE_SN_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}
	sc.Complete();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBoxSpecmanDoc(unsigned int startPos, int length, int,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		//int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && (style == SCE_SN_COMMENTLINE)) {
			if (((ch == '/') && (chNext == '/')) ||
                            ((ch == '-') && (chNext == '-'))) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelNext++;
				} else if (chNext2 == '}') {
					levelNext--;
				}
			}
		}
		if (style == SCE_SN_OPERATOR) {
			if (ch == '{') {
				// Measure the minimum before a '{' to allow
				// folding on "} else {"
				if (levelMinCurrent > levelNext) {
					levelMinCurrent = levelNext;
				}
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}

static void FoldSpecmanDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	FoldNoBoxSpecmanDoc(startPos, length, initStyle, styler);
}

static const char * const specmanWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "Sequence keywords and identifiers",
            "User defined keywords and identifiers",
            "Unused",
            0,
        };

static void ColouriseSpecmanDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                                     Accessor &styler) {
	ColouriseSpecmanDoc(startPos, length, initStyle, keywordlists, styler, true);
}


LexerModule lmSpecman(SCLEX_SPECMAN, ColouriseSpecmanDocSensitive, "specman", FoldSpecmanDoc, specmanWordLists);

Added lexers/LexSpice.cxx.















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexSpice.cxx
 ** Lexer for Spice
 **/
// Copyright 2006 by Fabien Proriol
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
 * Interface
 */

static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler);

static const char * const spiceWordListDesc[] = {
    "Keywords",        // SPICE command
    "Keywords2",    // SPICE functions
    "Keywords3",    // SPICE params
    0
};

LexerModule lmSpice(SCLEX_SPICE, ColouriseDocument, "spice", NULL, spiceWordListDesc);

/*
 * Implementation
 */

static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);

static inline bool IsDelimiterCharacter(int ch);
static inline bool IsNumberStartCharacter(int ch);
static inline bool IsNumberCharacter(int ch);
static inline bool IsSeparatorOrDelimiterCharacter(int ch);
static inline bool IsWordStartCharacter(int ch);
static inline bool IsWordCharacter(int ch);

static void ColouriseComment(StyleContext& sc, bool&) {
    sc.SetState(SCE_SPICE_COMMENTLINE);
    while (!sc.atLineEnd) {
        sc.Forward();
    }
}

static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = sc.Match (')');
    sc.SetState(SCE_SPICE_DELIMITER);
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
}

static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = true;
    std::string number;
    sc.SetState(SCE_SPICE_NUMBER);
    // Get all characters up to a delimiter or a separator, including points, but excluding
    // double points (ranges).
    while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
        number += static_cast<char>(sc.ch);
        sc.Forward();
    }
    // Special case: exponent with sign
    if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
            (sc.ch == '+' || sc.ch == '-')) {
        number += static_cast<char>(sc.ch);
        sc.Forward ();
        while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
            number += static_cast<char>(sc.ch);
            sc.Forward();
        }
    }
    sc.SetState(SCE_SPICE_DEFAULT);
}

static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
    sc.SetState(SCE_SPICE_DEFAULT);
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
}

static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = true;
    sc.SetState(SCE_SPICE_IDENTIFIER);
    std::string word;
    while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
        word += static_cast<char>(tolower(sc.ch));
        sc.Forward();
    }
    if (keywords.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    else if (keywords2.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD2);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    else if (keywords3.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD3);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    sc.SetState(SCE_SPICE_DEFAULT);
}

//
// ColouriseDocument
//
static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler) {
    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    StyleContext sc(startPos, length, initStyle, styler);
    int lineCurrent = styler.GetLine(startPos);
    bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
    while (sc.More()) {
        if (sc.atLineEnd) {
            // Go to the next line
            sc.Forward();
            lineCurrent++;
            // Remember the line state for future incremental lexing
            styler.SetLineState(lineCurrent, apostropheStartsAttribute);
            // Don't continue any styles on the next line
            sc.SetState(SCE_SPICE_DEFAULT);
        }
        // Comments
        if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
            ColouriseComment(sc, apostropheStartsAttribute);
        // Whitespace
        } else if (IsASpace(sc.ch)) {
            ColouriseWhiteSpace(sc, apostropheStartsAttribute);
        // Delimiters
        } else if (IsDelimiterCharacter(sc.ch)) {
            ColouriseDelimiter(sc, apostropheStartsAttribute);
        // Numbers
        } else if (IsADigit(sc.ch) || sc.ch == '#') {
            ColouriseNumber(sc, apostropheStartsAttribute);
        // Keywords or identifiers
        } else {
            ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
        }
    }
    sc.Complete();
}

static inline bool IsDelimiterCharacter(int ch) {
    switch (ch) {
    case '&':
    case '\'':
    case '(':
    case ')':
    case '*':
    case '+':
    case ',':
    case '-':
    case '.':
    case '/':
    case ':':
    case ';':
    case '<':
    case '=':
    case '>':
    case '|':
        return true;
    default:
        return false;
    }
}

static inline bool IsNumberCharacter(int ch) {
    return IsNumberStartCharacter(ch) ||
           ch == '_' ||
           ch == '.' ||
           ch == '#' ||
           (ch >= 'a' && ch <= 'f') ||
           (ch >= 'A' && ch <= 'F');
}

static inline bool IsNumberStartCharacter(int ch) {
    return IsADigit(ch);
}

static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
    return IsASpace(ch) || IsDelimiterCharacter(ch);
}

static inline bool IsWordCharacter(int ch) {
    return IsWordStartCharacter(ch) || IsADigit(ch);
}

static inline bool IsWordStartCharacter(int ch) {
    return (isascii(ch) && isalpha(ch)) || ch == '_';
}

Added lexers/LexTACL.cxx.

































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
// Scintilla source code edit control
/** @file LexTAL.cxx
 ** Lexer for TAL
 ** Based on LexPascal.cxx
 ** Written by Laurent le Tynevez
 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
 ** Updated by Rod Falck, Aug 2006 Converted to TACL
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

inline bool isTACLoperator(char ch)
	{
	return ch == '\'' || isoperator(ch);
	}

inline bool isTACLwordchar(char ch)
	{
	return ch == '#' || ch == '^' || ch == '|' || ch == '_' || iswordchar(ch);
	}

inline bool isTACLwordstart(char ch)
	{
	return ch == '#' || ch == '|' || ch == '_' || iswordstart(ch);
	}

static void getRange(unsigned int start,
		unsigned int end,
		Accessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_C_COMMENT ||
		style == SCE_C_COMMENTDOC ||
		style == SCE_C_COMMENTDOCKEYWORD ||
		style == SCE_C_COMMENTDOCKEYWORDERROR;
}

static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
	if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
		styler.ColourTo(end, SCE_C_REGEX);
	} else
		styler.ColourTo(end, attr);
}

// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
static int classifyWordTACL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
	int ret = 0;

	WordList& keywords = *keywordlists[0];
	WordList& builtins = *keywordlists[1];
	WordList& commands = *keywordlists[2];

	char s[100];
	getRange(start, end, styler, s, sizeof(s));

	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.')) {
		chAttr = SCE_C_NUMBER;
	}
	else {
		if (s[0] == '#' || keywords.InList(s)) {
			chAttr = SCE_C_WORD;

			if (strcmp(s, "asm") == 0) {
				ret = 2;
			}
			else if (strcmp(s, "end") == 0) {
				ret = -1;
			}
		}
		else if (s[0] == '|' || builtins.InList(s)) {
			chAttr = SCE_C_WORD2;
		}
		else if (commands.InList(s)) {
			chAttr = SCE_C_UUID;
		}
		else if (strcmp(s, "comment") == 0) {
			chAttr = SCE_C_COMMENTLINE;
			ret = 3;
		}
	}
	ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
	return ret;
}

static int classifyFoldPointTACL(const char* s) {
	int lev = 0;
	if (s[0] == '[')
		lev=1;
	else if (s[0] == ']')
		lev=-1;
	return lev;
}

static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	styler.StartAt(startPos);

	int state = initStyle;
	if (state == SCE_C_CHARACTER)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;

	bool bInClassDefinition;

	int currentLine = styler.GetLine(startPos);
	if (currentLine > 0) {
		styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
		bInClassDefinition = (styler.GetLineState(currentLine) == 1);
	} else {
		styler.SetLineState(currentLine, 0);
		bInClassDefinition = false;
	}

	bool bInAsm = (state == SCE_C_REGEX);
	if (bInAsm)
		state = SCE_C_DEFAULT;

	styler.StartSegment(startPos);
	int visibleChars = 0;
	unsigned int i;
	for (i = startPos; i < lengthDoc; i++) {
		char ch = chNext;

		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_CHARACTER) {
				ColourTo(styler, i, state, bInAsm);
				state = SCE_C_DEFAULT;
			}
			visibleChars = 0;
			currentLine++;
			styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
		}

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (isTACLwordstart(ch)) {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_IDENTIFIER;
			} else if (ch == '{') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENT;
			} else if (ch == '{' && chNext == '*') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENTDOC;
			} else if (ch == '=' && chNext == '=') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '"') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_STRING;
			} else if (ch == '?' && visibleChars == 0) {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_PREPROCESSOR;
			} else if (isTACLoperator(ch)) {
				ColourTo(styler, i-1, state, bInAsm);
				ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!isTACLwordchar(ch)) {
				int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);

				if(lStateChange == 1) {
					styler.SetLineState(currentLine, 1);
					bInClassDefinition = true;
				} else if(lStateChange == 2) {
					bInAsm = true;
				} else if(lStateChange == -1) {
					styler.SetLineState(currentLine, 0);
					bInClassDefinition = false;
					bInAsm = false;
				}

				if (lStateChange == 3) {
					 state = SCE_C_COMMENTLINE;
				}
				else {
					state = SCE_C_DEFAULT;
					chNext = styler.SafeGetCharAt(i + 1);
					if (ch == '{') {
						state = SCE_C_COMMENT;
					} else if (ch == '{' && chNext == '*') {
						ColourTo(styler, i-1, state, bInAsm);
						state = SCE_C_COMMENTDOC;
					} else if (ch == '=' && chNext == '=') {
						state = SCE_C_COMMENTLINE;
					} else if (ch == '"') {
						state = SCE_C_STRING;
					} else if (isTACLoperator(ch)) {
						ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
					}
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
					ColourTo(styler, i-1, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '}' || (ch == '\r' || ch == '\n') ) {
					ColourTo(styler, i, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '}' || (ch == '\r' || ch == '\n')) {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
							ColourTo(styler, i, state, bInAsm);
							state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					ColourTo(styler, i-1, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '"' || ch == '\r' || ch == '\n') {
					ColourTo(styler, i, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			}
		}
        if (!isspacechar(ch))
            visibleChars++;
		chPrev = ch;
	}

	// Process to end of document
	if (state == SCE_C_IDENTIFIER) {
		classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);
		}
	else
		ColourTo(styler, lengthDoc - 1, state, bInAsm);
}

static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	bool section = false;

	int lastStart = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR))
		{
			// Store last word start point.
			lastStart = i;
		}

		if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) {
			if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) {
				char s[100];
				getRange(lastStart, i, styler, s, sizeof(s));
				if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
					{
					section = true;
					levelCurrent = 1;
					levelPrev = 0;
					}
				else if (stylePrev == SCE_C_WORD)
					levelCurrent += classifyFoldPointTACL(s);
			}
		}

		if (style == SCE_C_OPERATOR) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}
		if (foldComment && (style == SCE_C_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelCurrent++;
				} else if (chNext2 == '}') {
					levelCurrent--;
				}
			}
		}

		if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
			if (ch == '{' && chNext == '$') {
				unsigned int j=i+2; // skip {$
				while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "region") || styler.Match(j, "if")) {
					levelCurrent++;
				} else if (styler.Match(j, "end")) {
					levelCurrent--;
				}
			}
		}

		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev | SC_FOLDLEVELBASE;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
			section = false;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const TACLWordListDesc[] = {
	"Builtins",
	"Labels",
	"Commands",
	0
};

LexerModule lmTACL(SCLEX_TACL, ColouriseTACLDoc, "TACL", FoldTACLDoc, TACLWordListDesc);

Added lexers/LexTADS3.cxx.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
// Scintilla source code edit control
/** @file LexTADS3.cxx
 ** Lexer for TADS3.
 **/
// Copyright 1998-2006 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

/*
 * TADS3 is a language designed by Michael J. Roberts for the writing of text
 * based games.  TADS comes from Text Adventure Development System.  It has good
 * support for the processing and outputting of formatted text and much of a
 * TADS program listing consists of strings.
 *
 * TADS has two types of strings, those enclosed in single quotes (') and those
 * enclosed in double quotes (").  These strings have different symantics and
 * can be given different highlighting if desired.
 *
 * There can be embedded within both types of strings html tags
 * ( <tag key=value> ), library directives ( <.directive> ), and message
 * parameters ( {The doctor's/his} ).
 *
 * Double quoted strings can also contain interpolated expressions
 * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ).  These expressions
 * may themselves contain single or double quoted strings, although the double
 * quoted strings may not contain interpolated expressions.
 *
 * These embedded constructs influence the output and formatting and are an
 * important part of a program and require highlighting.
 *
 * LINKS
 * http://www.tads.org/
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static const int T3_SINGLE_QUOTE = 1;
static const int T3_INT_EXPRESSION = 2;
static const int T3_INT_EXPRESSION_IN_TAG = 4;
static const int T3_HTML_SQUOTE = 8;

static inline bool IsEOL(const int ch, const int chNext) {
        return (ch == '\r' && chNext != '\n') || (ch == '\n');
}

/*
 *   Test the current character to see if it's the START of an EOL sequence;
 *   if so, skip ahead to the last character of the sequence and return true,
 *   and if not just return false.  There are a few places where we want to
 *   check to see if a newline sequence occurs at a particular point, but
 *   where a caller expects a subroutine to stop only upon reaching the END
 *   of a newline sequence (in particular, CR-LF on Windows).  That's why
 *   IsEOL() above only returns true on CR if the CR isn't followed by an LF
 *   - it doesn't want to admit that there's a newline until reaching the END
 *   of the sequence.  We meet both needs by saying that there's a newline
 *   when we see the CR in a CR-LF, but skipping the CR before returning so
 *   that the caller's caller will see that we've stopped at the LF.
 */
static inline bool IsEOLSkip(StyleContext &sc)
{
    /* test for CR-LF */
    if (sc.ch == '\r' && sc.chNext == '\n')
    {
        /* got CR-LF - skip the CR and indicate that we're at a newline */
        sc.Forward();
        return true;
    }

    /*
     *   in other cases, we have at most a 1-character newline, so do the
     *   normal IsEOL test
     */
    return IsEOL(sc.ch, sc.chNext);
}

static inline bool IsATADS3Operator(const int ch) {
        return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')'
                || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';'
                || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%'
                || ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|'
                || ch == '@' || ch == '&' || ch == '~';
}

static inline bool IsAWordChar(const int ch) {
        return isalnum(ch) || ch == '_';
}

static inline bool IsAWordStart(const int ch) {
        return isalpha(ch) || ch == '_';
}

static inline bool IsAHexDigit(const int ch) {
        int lch = tolower(ch);
        return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c'
                || lch == 'd' || lch == 'e' || lch == 'f';
}

static inline bool IsAnHTMLChar(int ch) {
        return isalnum(ch) || ch == '-' || ch == '_' || ch == '.';
}

static inline bool IsADirectiveChar(int ch) {
        return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/';
}

static inline bool IsANumberStart(StyleContext &sc) {
        return isdigit(sc.ch)
                || (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext));
}

inline static void ColouriseTADS3Operator(StyleContext &sc) {
        int initState = sc.state;
        int c = sc.ch;
        sc.SetState(c == '{' || c == '}' ? SCE_T3_BRACE : SCE_T3_OPERATOR);
        sc.ForwardSetState(initState);
}

static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) {
        int endState = sc.state;
        int chQuote = sc.ch;
        int chString = (lineState & T3_SINGLE_QUOTE) ? '\'' : '"';
        if (endState == SCE_T3_HTML_STRING) {
                if (lineState&T3_SINGLE_QUOTE) {
                        endState = SCE_T3_S_STRING;
                        chString = '\'';
                } else if (lineState&T3_INT_EXPRESSION) {
                        endState = SCE_T3_X_STRING;
                        chString = '"';
                } else {
                        endState = SCE_T3_HTML_DEFAULT;
                        chString = '"';
                }
                chQuote = (lineState & T3_HTML_SQUOTE) ? '\'' : '"';
        } else {
                sc.SetState(SCE_T3_HTML_STRING);
                sc.Forward();
        }
        if (chQuote == '"')
                lineState &= ~T3_HTML_SQUOTE;
        else
                lineState |= T3_HTML_SQUOTE;

        while (sc.More()) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                if (sc.ch == chQuote) {
                        sc.ForwardSetState(endState);
                        return;
                }
                if (sc.Match('\\', static_cast<char>(chQuote))) {
                        sc.Forward(2);
                        sc.SetState(endState);
                        return;
                }
                if (sc.ch == chString) {
                        sc.SetState(SCE_T3_DEFAULT);
                        return;
                }

                if (sc.Match('<', '<')) {
                        lineState |= T3_INT_EXPRESSION | T3_INT_EXPRESSION_IN_TAG;
                        sc.SetState(SCE_T3_X_DEFAULT);
                        sc.Forward(2);
                        return;
                }

                if (sc.Match('\\', static_cast<char>(chQuote))
                        || sc.Match('\\', static_cast<char>(chString))
                        || sc.Match('\\', '\\')) {
                        sc.Forward(2);
                } else {
                        sc.Forward();
                }
        }
}

static void ColouriseTADS3HTMLTagStart(StyleContext &sc) {
        sc.SetState(SCE_T3_HTML_TAG);
        sc.Forward();
        if (sc.ch == '/') {
                sc.Forward();
        }
        while (IsAnHTMLChar(sc.ch)) {
                sc.Forward();
        }
}

static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) {
        int endState = sc.state;
        int chQuote = '"';
        int chString = '\'';
        switch (endState) {
                case SCE_T3_S_STRING:
                        ColouriseTADS3HTMLTagStart(sc);
                        sc.SetState(SCE_T3_HTML_DEFAULT);
                        chQuote = '\'';
                        chString = '"';
                        break;
                case SCE_T3_D_STRING:
                case SCE_T3_X_STRING:
                        ColouriseTADS3HTMLTagStart(sc);
                        sc.SetState(SCE_T3_HTML_DEFAULT);
                        break;
                case SCE_T3_HTML_DEFAULT:
                        if (lineState&T3_SINGLE_QUOTE) {
                                endState = SCE_T3_S_STRING;
                                chQuote = '\'';
                                chString = '"';
                        } else if (lineState&T3_INT_EXPRESSION) {
                                endState = SCE_T3_X_STRING;
                        } else {
                                endState = SCE_T3_D_STRING;
                        }
                        break;
        }

        while (sc.More()) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                if (sc.Match('/', '>')) {
                        sc.SetState(SCE_T3_HTML_TAG);
                        sc.Forward(2);
                        sc.SetState(endState);
                        return;
                }
                if (sc.ch == '>') {
                        sc.SetState(SCE_T3_HTML_TAG);
                        sc.ForwardSetState(endState);
                        return;
                }
                if (sc.ch == chQuote) {
                        sc.SetState(endState);
                        return;
                }
                if (sc.Match('\\', static_cast<char>(chQuote))) {
                        sc.Forward();
                        ColouriseTADSHTMLString(sc, lineState);
                        if (sc.state == SCE_T3_X_DEFAULT)
                            break;
                } else if (sc.ch == chString) {
                        ColouriseTADSHTMLString(sc, lineState);
                } else if (sc.ch == '=') {
                        ColouriseTADS3Operator(sc);
                } else {
                        sc.Forward();
                }
        }
}

static void ColouriseTADS3Keyword(StyleContext &sc,
                                                        WordList *keywordlists[],       unsigned int endPos) {
        char s[250];
        WordList &keywords = *keywordlists[0];
        WordList &userwords1 = *keywordlists[1];
        WordList &userwords2 = *keywordlists[2];
        WordList &userwords3 = *keywordlists[3];
        int initState = sc.state;
        sc.SetState(SCE_T3_IDENTIFIER);
        while (sc.More() && (IsAWordChar(sc.ch))) {
                sc.Forward();
        }
        sc.GetCurrent(s, sizeof(s));
        if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) {
                // have to find if "in" is next
                int n = 1;
                while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n)))
                        n++;
                if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') {
                        sc.Forward(n+2);
                        sc.ChangeState(SCE_T3_KEYWORD);
                }
        } else if (keywords.InList(s)) {
                sc.ChangeState(SCE_T3_KEYWORD);
        } else if (userwords3.InList(s)) {
                sc.ChangeState(SCE_T3_USER3);
        } else if (userwords2.InList(s)) {
                sc.ChangeState(SCE_T3_USER2);
        } else if (userwords1.InList(s)) {
                sc.ChangeState(SCE_T3_USER1);
        }
        sc.SetState(initState);
}

static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) {
        int endState = sc.state;
        int chQuote = '"';
        switch (endState) {
                case SCE_T3_S_STRING:
                        sc.SetState(SCE_T3_MSG_PARAM);
                        sc.Forward();
                        chQuote = '\'';
                        break;
                case SCE_T3_D_STRING:
                case SCE_T3_X_STRING:
                        sc.SetState(SCE_T3_MSG_PARAM);
                        sc.Forward();
                        break;
                case SCE_T3_MSG_PARAM:
                        if (lineState&T3_SINGLE_QUOTE) {
                                endState = SCE_T3_S_STRING;
                                chQuote = '\'';
                        } else if (lineState&T3_INT_EXPRESSION) {
                                endState = SCE_T3_X_STRING;
                        } else {
                                endState = SCE_T3_D_STRING;
                        }
                        break;
        }
        while (sc.More() && sc.ch != '}' && sc.ch != chQuote) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                if (sc.ch == '\\') {
                        sc.Forward();
                }
                sc.Forward();
        }
        if (sc.ch == chQuote) {
                sc.SetState(endState);
        } else {
                sc.ForwardSetState(endState);
        }
}

static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) {
        int initState = sc.state;
        int chQuote = '"';
        switch (initState) {
                case SCE_T3_S_STRING:
                        sc.SetState(SCE_T3_LIB_DIRECTIVE);
                        sc.Forward(2);
                        chQuote = '\'';
                        break;
                case SCE_T3_D_STRING:
                        sc.SetState(SCE_T3_LIB_DIRECTIVE);
                        sc.Forward(2);
                        break;
                case SCE_T3_LIB_DIRECTIVE:
                        if (lineState&T3_SINGLE_QUOTE) {
                                initState = SCE_T3_S_STRING;
                                chQuote = '\'';
                        } else {
                                initState = SCE_T3_D_STRING;
                        }
                        break;
        }
        while (sc.More() && IsADirectiveChar(sc.ch)) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                sc.Forward();
        };
        if (sc.ch == '>' || !sc.More()) {
                sc.ForwardSetState(initState);
        } else if (sc.ch == chQuote) {
                sc.SetState(initState);
        } else {
                sc.ChangeState(initState);
                sc.Forward();
        }
}

static void ColouriseTADS3String(StyleContext &sc, int &lineState) {
        int chQuote = sc.ch;
        int endState = sc.state;
        switch (sc.state) {
                case SCE_T3_DEFAULT:
                case SCE_T3_X_DEFAULT:
                        if (chQuote == '"') {
                                if (sc.state == SCE_T3_DEFAULT) {
                                        sc.SetState(SCE_T3_D_STRING);
                                } else {
                                        sc.SetState(SCE_T3_X_STRING);
                                }
                                lineState &= ~T3_SINGLE_QUOTE;
                        } else {
                                sc.SetState(SCE_T3_S_STRING);
                                lineState |= T3_SINGLE_QUOTE;
                        }
                        sc.Forward();
                        break;
                case SCE_T3_S_STRING:
                        chQuote = '\'';
                        endState = lineState&T3_INT_EXPRESSION ?
                                SCE_T3_X_DEFAULT : SCE_T3_DEFAULT;
                        break;
                case SCE_T3_D_STRING:
                        chQuote = '"';
                        endState = SCE_T3_DEFAULT;
                        break;
                case SCE_T3_X_STRING:
                        chQuote = '"';
                        endState = SCE_T3_X_DEFAULT;
                        break;
        }
        while (sc.More()) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                if (sc.ch == chQuote) {
                        sc.ForwardSetState(endState);
                        return;
                }
                if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) {
                        lineState |= T3_INT_EXPRESSION;
                        sc.SetState(SCE_T3_X_DEFAULT);
                        sc.Forward(2);
                        return;
                }
                if (sc.Match('\\', static_cast<char>(chQuote))
                    || sc.Match('\\', '\\')) {
                        sc.Forward(2);
                } else if (sc.ch == '{') {
                        ColouriseTADS3MsgParam(sc, lineState);
                } else if (sc.Match('<', '.')) {
                        ColouriseTADS3LibDirective(sc, lineState);
                } else if (sc.ch == '<') {
                        ColouriseTADS3HTMLTag(sc, lineState);
                        if (sc.state == SCE_T3_X_DEFAULT)
                                return;
                } else {
                        sc.Forward();
                }
        }
}

static void ColouriseTADS3Comment(StyleContext &sc, int endState) {
        sc.SetState(SCE_T3_BLOCK_COMMENT);
        while (sc.More()) {
                if (IsEOL(sc.ch, sc.chNext)) {
                        return;
                }
                if (sc.Match('*', '/')) {
                        sc.Forward(2);
                        sc.SetState(endState);
                        return;
                }
                sc.Forward();
        }
}

static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) {
        sc.SetState(initState);
        while (sc.More()) {
                if (sc.ch == '\\') {
                        sc.Forward();
                        if (IsEOLSkip(sc)) {
                                        return;
                        }
                }
                if (IsEOL(sc.ch, sc.chNext)) {
                        sc.SetState(endState);
                        return;
                }
                sc.Forward();
        }
}

static void ColouriseTADS3Number(StyleContext &sc) {
        int endState = sc.state;
        bool inHexNumber = false;
        bool seenE = false;
        bool seenDot = sc.ch == '.';
        sc.SetState(SCE_T3_NUMBER);
        if (sc.More()) {
                sc.Forward();
        }
        if (sc.chPrev == '0' && tolower(sc.ch) == 'x') {
                inHexNumber = true;
                sc.Forward();
        }
        while (sc.More()) {
                if (inHexNumber) {
                        if (!IsAHexDigit(sc.ch)) {
                                break;
                        }
                } else if (!isdigit(sc.ch)) {
                        if (!seenE && tolower(sc.ch) == 'e') {
                                seenE = true;
                                seenDot = true;
                                if (sc.chNext == '+' || sc.chNext == '-') {
                                        sc.Forward();
                                }
                        } else if (!seenDot && sc.ch == '.') {
                                seenDot = true;
                        } else {
                                break;
                        }
                }
                sc.Forward();
        }
        sc.SetState(endState);
}

static void ColouriseTADS3Doc(unsigned int startPos, int length, int initStyle,
                                                           WordList *keywordlists[], Accessor &styler) {
        int visibleChars = 0;
        int bracketLevel = 0;
        int lineState = 0;
        unsigned int endPos = startPos + length;
        int lineCurrent = styler.GetLine(startPos);
        if (lineCurrent > 0) {
                lineState = styler.GetLineState(lineCurrent-1);
        }
        StyleContext sc(startPos, length, initStyle, styler);

        while (sc.More()) {

                if (IsEOL(sc.ch, sc.chNext)) {
                        styler.SetLineState(lineCurrent, lineState);
                        lineCurrent++;
                        visibleChars = 0;
                        sc.Forward();
                        if (sc.ch == '\n') {
                                sc.Forward();
                        }
                }

                switch(sc.state) {
                        case SCE_T3_PREPROCESSOR:
                        case SCE_T3_LINE_COMMENT:
                                ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ?
                                        SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
                                break;
                        case SCE_T3_S_STRING:
                        case SCE_T3_D_STRING:
                        case SCE_T3_X_STRING:
                                ColouriseTADS3String(sc, lineState);
                                visibleChars++;
                                break;
                        case SCE_T3_MSG_PARAM:
                                ColouriseTADS3MsgParam(sc, lineState);
                                break;
                        case SCE_T3_LIB_DIRECTIVE:
                                ColouriseTADS3LibDirective(sc, lineState);
                                break;
                        case SCE_T3_HTML_DEFAULT:
                                ColouriseTADS3HTMLTag(sc, lineState);
                                break;
                        case SCE_T3_HTML_STRING:
                                ColouriseTADSHTMLString(sc, lineState);
                                break;
                        case SCE_T3_BLOCK_COMMENT:
                                ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ?
                                        SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
                                break;
                        case SCE_T3_DEFAULT:
                        case SCE_T3_X_DEFAULT:
                                if (IsASpaceOrTab(sc.ch)) {
                                        sc.Forward();
                                } else if (sc.ch == '#' && visibleChars == 0) {
                                        ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state);
                                } else if (sc.Match('/', '*')) {
                                        ColouriseTADS3Comment(sc, sc.state);
                                        visibleChars++;
                                } else if (sc.Match('/', '/')) {
                                        ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state);
                                } else if (sc.ch == '"') {
                                        bracketLevel = 0;
                                        ColouriseTADS3String(sc, lineState);
                                        visibleChars++;
                                } else if (sc.ch == '\'') {
                                        ColouriseTADS3String(sc, lineState);
                                        visibleChars++;
                                } else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0
                                                   && sc.Match('>', '>')) {
                                        sc.Forward(2);
                                        sc.SetState(SCE_T3_D_STRING);
                                        if (lineState & T3_INT_EXPRESSION_IN_TAG)
                                                sc.SetState(SCE_T3_HTML_STRING);
                                        lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION
                                                       |T3_INT_EXPRESSION_IN_TAG);
                                } else if (IsATADS3Operator(sc.ch)) {
                                        if (sc.state == SCE_T3_X_DEFAULT) {
                                                if (sc.ch == '(') {
                                                        bracketLevel++;
                                                } else if (sc.ch == ')' && bracketLevel > 0) {
                                                        bracketLevel--;
                                                }
                                        }
                                        ColouriseTADS3Operator(sc);
                                        visibleChars++;
                                } else if (IsANumberStart(sc)) {
                                        ColouriseTADS3Number(sc);
                                        visibleChars++;
                                } else if (IsAWordStart(sc.ch)) {
                                        ColouriseTADS3Keyword(sc, keywordlists, endPos);
                                        visibleChars++;
                                } else if (sc.Match("...")) {
                                        sc.SetState(SCE_T3_IDENTIFIER);
                                        sc.Forward(3);
                                        sc.SetState(SCE_T3_DEFAULT);
                                } else {
                                        sc.Forward();
                                        visibleChars++;
                                }
                                break;
                        default:
                                sc.SetState(SCE_T3_DEFAULT);
                                sc.Forward();
                }
        }
        sc.Complete();
}

/*
 TADS3 has two styles of top level block (TLB). Eg

 // default style
 silverKey : Key 'small silver key' 'small silver key'
        "A small key glints in the sunlight. "
 ;

 and

 silverKey : Key {
        'small silver key'
        'small silver key'
        "A small key glints in the sunlight. "
 }

 Some constructs mandate one or the other, but usually the author has may choose
 either.

 T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
 seen and is also used to match the closing ';' of the default style.

 T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
 what characters may be seen without incrementing the block level.  The general
 pattern is identifier <punc> identifier, acceptable punctuation characters
 are ':', ',', '(' and ')'.  No attempt is made to ensure that punctuation
 characters are syntactically correct, eg parentheses match. A ')' always
 signifies the start of a block.  We just need to check if it is followed by a
 '{', in which case we let the brace handling code handle the folding level.

 expectingIdentifier == false && expectingIdentifier == false
 Before the start of a TLB.

 expectingIdentifier == true && expectingIdentifier == true
 Currently in an identifier.  Will accept identifier or punctuation.

 expectingIdentifier == true && expectingIdentifier == false
 Just seen a punctuation character & now waiting for an identifier to start.

 expectingIdentifier == false && expectingIdentifier == truee
 We were in an identifier and have seen space.  Now waiting to see a punctuation
 character

 Space, comments & preprocessor directives are always acceptable and are
 equivalent.
*/

static const int T3_SEENSTART = 1 << 12;
static const int T3_EXPECTINGIDENTIFIER = 1 << 13;
static const int T3_EXPECTINGPUNCTUATION = 1 << 14;

static inline bool IsStringTransition(int s1, int s2) {
        return s1 != s2
                && (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING
                        || (s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT))
                && s2 != SCE_T3_LIB_DIRECTIVE
                && s2 != SCE_T3_MSG_PARAM
                && s2 != SCE_T3_HTML_TAG
                && s2 != SCE_T3_HTML_STRING;
}

static inline bool IsATADS3Punctuation(const int ch) {
        return ch == ':' || ch == ',' || ch == '(' || ch == ')';
}

static inline bool IsAnIdentifier(const int style) {
        return style == SCE_T3_IDENTIFIER
                || style == SCE_T3_USER1
                || style == SCE_T3_USER2
                || style == SCE_T3_USER3;
}

static inline bool IsAnOperator(const int style) {
    return style == SCE_T3_OPERATOR || style == SCE_T3_BRACE;
}

static inline bool IsSpaceEquivalent(const int ch, const int style) {
        return isspace(ch)
                || style == SCE_T3_BLOCK_COMMENT
                || style == SCE_T3_LINE_COMMENT
                || style == SCE_T3_PREPROCESSOR;
}

static char peekAhead(unsigned int startPos, unsigned int endPos,
                                          Accessor &styler) {
        for (unsigned int i = startPos; i < endPos; i++) {
                int style = styler.StyleAt(i);
                char ch = styler[i];
                if (!IsSpaceEquivalent(ch, style)) {
                        if (IsAnIdentifier(style)) {
                                return 'a';
                        }
                        if (IsATADS3Punctuation(ch)) {
                                return ':';
                        }
                        if (ch == '{') {
                                return '{';
                        }
                        return '*';
                }
        }
        return ' ';
}

static void FoldTADS3Doc(unsigned int startPos, int length, int initStyle,
                            WordList *[], Accessor &styler) {
        unsigned int endPos = startPos + length;
        int lineCurrent = styler.GetLine(startPos);
        int levelCurrent = SC_FOLDLEVELBASE;
        if (lineCurrent > 0)
                levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
        int seenStart = levelCurrent & T3_SEENSTART;
        int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER;
        int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION;
        levelCurrent &= SC_FOLDLEVELNUMBERMASK;
        int levelMinCurrent = levelCurrent;
        int levelNext = levelCurrent;
        char chNext = styler[startPos];
        int styleNext = styler.StyleAt(startPos);
        int style = initStyle;
        char ch = chNext;
        int stylePrev = style;
        bool redo = false;
        for (unsigned int i = startPos; i < endPos; i++) {
                if (redo) {
                        redo = false;
                        i--;
                } else {
                        ch = chNext;
                        chNext = styler.SafeGetCharAt(i + 1);
                        stylePrev = style;
                        style = styleNext;
                        styleNext = styler.StyleAt(i + 1);
                }
                bool atEOL = IsEOL(ch, chNext);

                if (levelNext == SC_FOLDLEVELBASE) {
                        if (IsSpaceEquivalent(ch, style)) {
                                if (expectingPunctuation) {
                                        expectingIdentifier = 0;
                                }
                                if (style == SCE_T3_BLOCK_COMMENT) {
                                        levelNext++;
                                }
                        } else if (ch == '{') {
                                levelNext++;
                                seenStart = 0;
                        } else if (ch == '\'' || ch == '"' || ch == '[') {
                                levelNext++;
                                if (seenStart) {
                                        redo = true;
                                }
                        } else if (ch == ';') {
                                seenStart = 0;
                                expectingIdentifier = 0;
                                expectingPunctuation = 0;
                        } else if (expectingIdentifier && expectingPunctuation) {
                                if (IsATADS3Punctuation(ch)) {
                                        if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
                                                levelNext++;
                                        } else {
                                                expectingPunctuation = 0;
                                        }
                                } else if (!IsAnIdentifier(style)) {
                                        levelNext++;
                                }
                        } else if (expectingIdentifier && !expectingPunctuation) {
                                if (!IsAnIdentifier(style)) {
                                        levelNext++;
                                } else {
                                        expectingPunctuation = T3_EXPECTINGPUNCTUATION;
                                }
                        } else if (!expectingIdentifier && expectingPunctuation) {
                                if (!IsATADS3Punctuation(ch)) {
                                        levelNext++;
                                } else {
                                        if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
                                                levelNext++;
                                        } else {
                                                expectingIdentifier = T3_EXPECTINGIDENTIFIER;
                                                expectingPunctuation = 0;
                                        }
                                }
                        } else if (!expectingIdentifier && !expectingPunctuation) {
                                if (IsAnIdentifier(style)) {
                                        seenStart = T3_SEENSTART;
                                        expectingIdentifier = T3_EXPECTINGIDENTIFIER;
                                        expectingPunctuation = T3_EXPECTINGPUNCTUATION;
                                }
                        }

                        if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) {
                                expectingIdentifier = 0;
                                expectingPunctuation = 0;
                        }

                } else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart
                                   && ch == ';' && IsAnOperator(style)) {
                        levelNext--;
                        seenStart = 0;
                } else if (style == SCE_T3_BLOCK_COMMENT) {
                        if (stylePrev != SCE_T3_BLOCK_COMMENT) {
                                levelNext++;
                        } else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) {
                                // Comments don't end at end of line and the next character may be unstyled.
                                levelNext--;
                        }
                } else if (ch == '\'' || ch == '"') {
                        if (IsStringTransition(style, stylePrev)) {
                                if (levelMinCurrent > levelNext) {
                                        levelMinCurrent = levelNext;
                                }
                                levelNext++;
                        } else if (IsStringTransition(style, styleNext)) {
                                levelNext--;
                        }
                } else if (IsAnOperator(style)) {
                        if (ch == '{' || ch == '[') {
                                // Measure the minimum before a '{' to allow
                                // folding on "} else {"
                                if (levelMinCurrent > levelNext) {
                                        levelMinCurrent = levelNext;
                                }
                                levelNext++;
                        } else if (ch == '}' || ch == ']') {
                                levelNext--;
                        }
                }

                if (atEOL) {
                        if (seenStart && levelNext == SC_FOLDLEVELBASE) {
                                switch (peekAhead(i+1, endPos, styler)) {
                                        case ' ':
                                        case '{':
                                                break;
                                        case '*':
                                                levelNext++;
                                                break;
                                        case 'a':
                                                if (expectingPunctuation) {
                                                        levelNext++;
                                                }
                                                break;
                                        case ':':
                                                if (expectingIdentifier) {
                                                        levelNext++;
                                                }
                                                break;
                                }
                                if (levelNext != SC_FOLDLEVELBASE) {
                                        expectingIdentifier = 0;
                                        expectingPunctuation = 0;
                                }
                        }
                        int lev = levelMinCurrent | (levelNext | expectingIdentifier
                                | expectingPunctuation | seenStart) << 16;
                        if (levelMinCurrent < levelNext)
                                lev |= SC_FOLDLEVELHEADERFLAG;
                        if (lev != styler.LevelAt(lineCurrent)) {
                                styler.SetLevel(lineCurrent, lev);
                        }
                        lineCurrent++;
                        levelCurrent = levelNext;
                        levelMinCurrent = levelCurrent;
                }
        }
}

static const char * const tads3WordList[] = {
        "TADS3 Keywords",
        "User defined 1",
        "User defined 2",
        "User defined 3",
        0
};

LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList);

Added lexers/LexTAL.cxx.































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
// Scintilla source code edit control
/** @file LexTAL.cxx
 ** Lexer for TAL
 ** Based on LexPascal.cxx
 ** Written by Laurent le Tynevez
 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
 ** Updated by Rod Falck, Aug 2006 Converted to TAL
 **/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

inline bool isTALoperator(char ch)
	{
	return ch == '\'' || ch == '@' || ch == '#' || isoperator(ch);
	}

inline bool isTALwordchar(char ch)
	{
	return ch == '$' || ch == '^' || iswordchar(ch);
	}

inline bool isTALwordstart(char ch)
	{
	return ch == '$' || ch == '^' || iswordstart(ch);
	}

static void getRange(unsigned int start,
		unsigned int end,
		Accessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_C_COMMENT ||
		style == SCE_C_COMMENTDOC ||
		style == SCE_C_COMMENTDOCKEYWORD ||
		style == SCE_C_COMMENTDOCKEYWORDERROR;
}

static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) {
	if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) {
		styler.ColourTo(end, SCE_C_REGEX);
	} else
		styler.ColourTo(end, attr);
}

// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm"
static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInAsm) {
	int ret = 0;

	WordList& keywords = *keywordlists[0];
	WordList& builtins = *keywordlists[1];
	WordList& nonreserved_keywords = *keywordlists[2];

	char s[100];
	getRange(start, end, styler, s, sizeof(s));

	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.')) {
		chAttr = SCE_C_NUMBER;
	}
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;

			if (strcmp(s, "asm") == 0) {
				ret = 2;
			}
			else if (strcmp(s, "end") == 0) {
				ret = -1;
			}
		}
		else if (s[0] == '$' || builtins.InList(s)) {
			chAttr = SCE_C_WORD2;
		}
		else if (nonreserved_keywords.InList(s)) {
			chAttr = SCE_C_UUID;
		}
	}
	ColourTo(styler, end, chAttr, (bInAsm && ret != -1));
	return ret;
}

static int classifyFoldPointTAL(const char* s) {
	int lev = 0;
	if (!(isdigit(s[0]) || (s[0] == '.'))) {
		if (strcmp(s, "begin") == 0 ||
			strcmp(s, "block") == 0) {
			lev=1;
		} else if (strcmp(s, "end") == 0) {
			lev=-1;
		}
	}
	return lev;
}

static void ColouriseTALDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	styler.StartAt(startPos);

	int state = initStyle;
	if (state == SCE_C_CHARACTER)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;

	bool bInClassDefinition;

	int currentLine = styler.GetLine(startPos);
	if (currentLine > 0) {
		styler.SetLineState(currentLine, styler.GetLineState(currentLine-1));
		bInClassDefinition = (styler.GetLineState(currentLine) == 1);
	} else {
		styler.SetLineState(currentLine, 0);
		bInClassDefinition = false;
	}

	bool bInAsm = (state == SCE_C_REGEX);
	if (bInAsm)
		state = SCE_C_DEFAULT;

	styler.StartSegment(startPos);
	int visibleChars = 0;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;

		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_CHARACTER) {
				ColourTo(styler, i, state, bInAsm);
				state = SCE_C_DEFAULT;
			}
			visibleChars = 0;
			currentLine++;
			styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0));
		}

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (isTALwordstart(ch)) {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_IDENTIFIER;
			} else if (ch == '!' && chNext != '*') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENT;
			} else if (ch == '!' && chNext == '*') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENTDOC;
			} else if (ch == '-' && chNext == '-') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '"') {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_STRING;
			} else if (ch == '?' && visibleChars == 0) {
				ColourTo(styler, i-1, state, bInAsm);
				state = SCE_C_PREPROCESSOR;
			} else if (isTALoperator(ch)) {
				ColourTo(styler, i-1, state, bInAsm);
				ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!isTALwordchar(ch)) {
				int lStateChange = classifyWordTAL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm);

				if(lStateChange == 1) {
					styler.SetLineState(currentLine, 1);
					bInClassDefinition = true;
				} else if(lStateChange == 2) {
					bInAsm = true;
				} else if(lStateChange == -1) {
					styler.SetLineState(currentLine, 0);
					bInClassDefinition = false;
					bInAsm = false;
				}

				state = SCE_C_DEFAULT;
				chNext = styler.SafeGetCharAt(i + 1);
				if (ch == '!' && chNext != '*') {
					state = SCE_C_COMMENT;
				} else if (ch == '!' && chNext == '*') {
					ColourTo(styler, i-1, state, bInAsm);
					state = SCE_C_COMMENTDOC;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '"') {
					state = SCE_C_STRING;
				} else if (isTALoperator(ch)) {
					ColourTo(styler, i, SCE_C_OPERATOR, bInAsm);
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
					ColourTo(styler, i-1, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '!' || (ch == '\r' || ch == '\n') ) {
					ColourTo(styler, i, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '!' || (ch == '\r' || ch == '\n')) {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
							ColourTo(styler, i, state, bInAsm);
							state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					ColourTo(styler, i-1, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '"') {
					ColourTo(styler, i, state, bInAsm);
					state = SCE_C_DEFAULT;
				}
			}
		}
        if (!isspacechar(ch))
            visibleChars++;
		chPrev = ch;
	}
	ColourTo(styler, lengthDoc - 1, state, bInAsm);
}

static void FoldTALDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	bool was_end = false;
	bool section = false;

	int lastStart = 0;

	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_UUID || style == SCE_C_PREPROCESSOR))
		{
			// Store last word start point.
			lastStart = i;
		}

		if (stylePrev == SCE_C_WORD || style == SCE_C_UUID || stylePrev == SCE_C_PREPROCESSOR) {
			if(isTALwordchar(ch) && !isTALwordchar(chNext)) {
				char s[100];
				getRange(lastStart, i, styler, s, sizeof(s));
				if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0)
					{
					section = true;
					levelCurrent = 1;
					levelPrev = 0;
					}
				else if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_UUID)
					{
					if (strcmp(s, "block") == 0)
						{
						// block keyword is ignored immediately after end keyword
						if (!was_end)
							levelCurrent++;
						}
					else
						levelCurrent += classifyFoldPointTAL(s);
					if (strcmp(s, "end") == 0)
						{
						was_end = true;
						}
					else
						{
						was_end = false;
						}
					}
			}
		}

		if (foldComment && (style == SCE_C_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelCurrent++;
				} else if (chNext2 == '}') {
					levelCurrent--;
				}
			}
		}

		if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
			if (ch == '{' && chNext == '$') {
				unsigned int j=i+2; // skip {$
				while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "region") || styler.Match(j, "if")) {
					levelCurrent++;
				} else if (styler.Match(j, "end")) {
					levelCurrent--;
				}
			}
		}

		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelCurrent++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev | SC_FOLDLEVELBASE;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev || section) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
			section = false;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const TALWordListDesc[] = {
	"Keywords",
	"Builtins",
	0
};

LexerModule lmTAL(SCLEX_TAL, ColouriseTALDoc, "TAL", FoldTALDoc, TALWordListDesc);

Added lexers/LexTCL.cxx.





































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
// Scintilla source code edit control
/** @file LexTCL.cxx
 ** Lexer for TCL language.
 **/
// Copyright 1998-2001 by Andre Arpin <arpin@kingston.net>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
        (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 || (ch ==':' || isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	       (IsADigit(ch, 0x10) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+');
}

static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *keywordlists[], Accessor &styler) {
#define  isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT)
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool commentLevel = false;
    bool subBrace = false; // substitution begin with a brace ${.....}
	enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf,
        LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT;
	bool prevSlash = false;
	int currentLevel = 0;
    bool expected = 0;
    bool subParen = 0;

	int currentLine = styler.GetLine(startPos);
    if (currentLine > 0)
        currentLine--;
	length += startPos - styler.LineStart(currentLine);
	// make sure lines overlap
	startPos = styler.LineStart(currentLine);

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
    WordList &keywords8 = *keywordlists[7];
    WordList &keywords9 = *keywordlists[8];

	if (currentLine > 0) {
        int ls = styler.GetLineState(currentLine - 1);
		lineState = tLineState(ls & LS_MASK_STATE);
		expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED);
        subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY);
		currentLevel = styler.LevelAt(currentLine - 1) >> 17;
		commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1;
	} else
		styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG);
	bool visibleChars = false;

	int previousLevel = currentLevel;
    StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler);
	for (; ; sc.Forward()) {
next:
        if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac
            continue;
        bool atEnd = !sc.More();  // make sure we coloured the last word
        if (lineState != LS_DEFAULT) {
            sc.SetState(SCE_TCL_DEFAULT);
            if (lineState == LS_OPEN_COMMENT)
                sc.SetState(SCE_TCL_COMMENTLINE);
            else if (lineState == LS_OPEN_DOUBLE_QUOTE)
                sc.SetState(SCE_TCL_IN_QUOTE);
            else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#')))
                sc.SetState(SCE_TCL_COMMENT_BOX);
            lineState = LS_DEFAULT;
        }
        if (subBrace) { // ${ overrides every thing even \ except }
            if (sc.ch == '}') {
                subBrace = false;
                sc.SetState(SCE_TCL_OPERATOR);
                sc.ForwardSetState(SCE_TCL_DEFAULT);
                goto next;
            }
            else
                sc.SetState(SCE_TCL_SUB_BRACE);
            if (!sc.atLineEnd)
                continue;
        } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) {
            expected &= isspacechar(static_cast<unsigned char>(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#';
        } else if (sc.state == SCE_TCL_SUBSTITUTION) {
            switch(sc.ch) {
            case '(':
                subParen=true;
                sc.SetState(SCE_TCL_OPERATOR);
                sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
                continue;
            case ')':
                sc.SetState(SCE_TCL_OPERATOR);
                subParen=false;
                continue;
            case '$':
                continue;
            case ',':
                sc.SetState(SCE_TCL_OPERATOR);
                if (subParen)
                    sc.ForwardSetState(SCE_TCL_SUBSTITUTION);
                continue;
            default :
                // maybe spaces should be allowed ???
                if (!IsAWordChar(sc.ch)) { // probably the code is wrong
                    sc.SetState(SCE_TCL_DEFAULT);
                    subParen = 0;
                }
                break;
            }
        } else if (isComment(sc.state)) {
        } else if (!IsAWordChar(sc.ch)) {
            if ((sc.state == SCE_TCL_IDENTIFIER && expected) ||  sc.state == SCE_TCL_MODIFIER) {
                char w[100];
                char *s=w;
                sc.GetCurrent(w, sizeof(w));
                if (w[strlen(w)-1]=='\r')
                    w[strlen(w)-1]=0;
                while(*s == ':') // ignore leading : like in ::set a 10
                    ++s;
                bool quote = sc.state == SCE_TCL_IN_QUOTE;
                if (commentLevel  || expected) {
                    if (keywords.InList(s)) {
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD);
                    } else if (keywords2.InList(s)) {
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2);
                    } else if (keywords3.InList(s)) {
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3);
                    } else if (keywords4.InList(s)) {
                        sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4);
                    } else if (sc.GetRelative(-static_cast<int>(strlen(s))-1) == '{' &&
                        keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces
                            sc.ChangeState(SCE_TCL_EXPAND);
                    }
                    if (keywords6.InList(s)) {
                        sc.ChangeState(SCE_TCL_WORD5);
                    } else if (keywords7.InList(s)) {
                        sc.ChangeState(SCE_TCL_WORD6);
                    } else if (keywords8.InList(s)) {
                        sc.ChangeState(SCE_TCL_WORD7);
                    } else if (keywords9.InList(s)) {
                        sc.ChangeState(SCE_TCL_WORD8);
                    }
                }
                expected = false;
                sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT);
            } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) {
                sc.SetState(SCE_TCL_DEFAULT);
            }
        }
		if (atEnd)
			break;
        if (sc.atLineEnd) {
            lineState = LS_DEFAULT;
			currentLine = styler.GetLine(sc.currentPos);
			if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) {
				if (currentLevel == 0) {
					++currentLevel;
					commentLevel = true;
				}
			} else {
				if (visibleChars && commentLevel) {
					--currentLevel;
					--previousLevel;
					commentLevel = false;
				}
			}
			int flag = 0;
			if (!visibleChars)
				flag = SC_FOLDLEVELWHITEFLAG;
			if (currentLevel > previousLevel)
				flag = SC_FOLDLEVELHEADERFLAG;
			styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16));

			// Update the line state, so it can be seen by next line
			if (sc.state == SCE_TCL_IN_QUOTE)
				lineState = LS_OPEN_DOUBLE_QUOTE;
			else {
			     if (prevSlash) {
				    if (isComment(sc.state))
					    lineState = LS_OPEN_COMMENT;
                } else if (sc.state == SCE_TCL_COMMENT_BOX)
                    lineState = LS_COMMENT_BOX;
			}
            styler.SetLineState(currentLine,
                (subBrace ? LS_BRACE_ONLY : 0) |
                (expected ? LS_COMMAND_EXPECTED : 0)  | lineState);
            if (lineState == LS_COMMENT_BOX)
                sc.ForwardSetState(SCE_TCL_COMMENT_BOX);
            else if (lineState == LS_OPEN_DOUBLE_QUOTE)
                sc.ForwardSetState(SCE_TCL_IN_QUOTE);
            else
                sc.ForwardSetState(SCE_TCL_DEFAULT);
			prevSlash = false;
			previousLevel = currentLevel;
			goto next;
		}

		if (prevSlash) {
            prevSlash = false;
            if (sc.ch == '#' && IsANumberChar(sc.chNext))
                sc.ForwardSetState(SCE_TCL_NUMBER);
            continue;
		}
        prevSlash = sc.ch == '\\';
        if (isComment(sc.state))
            continue;
		if (sc.atLineStart) {
			visibleChars = false;
			if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state))
            {
				sc.SetState(SCE_TCL_DEFAULT);
                expected = IsAWordStart(sc.ch)|| isspacechar(static_cast<unsigned char>(sc.ch));
            }
		}

		switch (sc.state) {
		case SCE_TCL_NUMBER:
			if (!IsANumberChar(sc.ch))
				sc.SetState(SCE_TCL_DEFAULT);
			break;
		case SCE_TCL_IN_QUOTE:
			if (sc.ch == '"') {
				sc.ForwardSetState(SCE_TCL_DEFAULT);
				visibleChars = true; // necessary if a " is the first and only character on a line
				goto next;
			} else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') {
				sc.SetState(SCE_TCL_OPERATOR);
                expected = sc.ch == '[';
                sc.ForwardSetState(SCE_TCL_IN_QUOTE);
				goto next;
			}
            continue;
        case SCE_TCL_OPERATOR:
			sc.SetState(SCE_TCL_DEFAULT);
			break;
		}

		if (sc.ch == '#') {
			if (visibleChars) {
                if (sc.state != SCE_TCL_IN_QUOTE && expected)
					sc.SetState(SCE_TCL_COMMENT);
			} else {
                sc.SetState(SCE_TCL_COMMENTLINE);
                if (sc.chNext == '~')
                    sc.SetState(SCE_TCL_BLOCK_COMMENT);
                if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-'))
                        sc.SetState(SCE_TCL_COMMENT_BOX);
            }
        }

		if (!isspacechar(static_cast<unsigned char>(sc.ch))) {
			visibleChars = true;
		}

		if (sc.ch == '\\') {
			prevSlash = true;
			continue;
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_TCL_DEFAULT) {
            if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_TCL_IDENTIFIER);
			} else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) {
				sc.SetState(SCE_TCL_NUMBER);
			} else {
				switch (sc.ch) {
				case '\"':
					sc.SetState(SCE_TCL_IN_QUOTE);
					break;
				case '{':
					sc.SetState(SCE_TCL_OPERATOR);
					expected = true;
					++currentLevel;
					break;
				case '}':
					sc.SetState(SCE_TCL_OPERATOR);
					expected = true;
					--currentLevel;
					break;
				case '[':
                    expected = true;
				case ']':
				case '(':
				case ')':
					sc.SetState(SCE_TCL_OPERATOR);
					break;
				case ';':
                    expected = true;
					break;
                case '$':
                    subParen = 0;
                    if (sc.chNext != '{') {
                        sc.SetState(SCE_TCL_SUBSTITUTION);
                    }
                    else {
                        sc.SetState(SCE_TCL_OPERATOR);  // $
                        sc.Forward();  // {
                        sc.ForwardSetState(SCE_TCL_SUB_BRACE);
                        subBrace = true;
                    }
                    break;
                case '#':
                    if ((isspacechar(static_cast<unsigned char>(sc.chPrev))||
                            isoperator(static_cast<char>(sc.chPrev))) && IsADigit(sc.chNext,0x10))
                        sc.SetState(SCE_TCL_NUMBER);
                    break;
                case '-':
                    sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER);
                    break;
                default:
                    if (isoperator(static_cast<char>(sc.ch))) {
                        sc.SetState(SCE_TCL_OPERATOR);
                    }
				}
			}
		}
	}
	sc.Complete();
}

static const char * const tclWordListDesc[] = {
            "TCL Keywords",
            "TK Keywords",
            "iTCL Keywords",
            "tkCommands",
            "expand"
            "user1",
            "user2",
            "user3",
            "user4",
            0
        };

// this code supports folding in the colourizer
LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc);

Added lexers/LexTCMD.cxx.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
// Scintilla\ source code edit control
/** @file LexTCMD.cxx
 ** Lexer for Take Command / TCC batch scripts (.bat, .btm, .cmd).
 **/
// Written by Rex Conn (rconn [at] jpsoft [dot] com)
// based on the CMD lexer
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


static bool IsAlphabetic(int ch) {
	return isascii(ch) && isalpha(ch);
}

static inline bool AtEOL(Accessor &styler, unsigned int i) {
	return (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}

// Tests for BATCH Operators
static bool IsBOperator(char ch) {
	return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || (ch == '|') || (ch == '&') || (ch == '!') || (ch == '?') || (ch == '*') || (ch == '(') || (ch == ')');
}

// Tests for BATCH Separators
static bool IsBSeparator(char ch) {
	return (ch == '\\') || (ch == '.') || (ch == ';') || (ch == ' ') || (ch == '\t') || (ch == '[') || (ch == ']') || (ch == '\"') || (ch == '\'') || (ch == '/');
}

// Tests for Environment Variable symbol
static inline bool IsEnvironmentVar(char ch) {
	return isalpha(ch) || isdigit(ch) || (ch == '_') || (ch == '$');
}

// Find length of CMD FOR variable with modifier (%~...) or return 0
static unsigned int GetBatchVarLen( char *wordBuffer )
{
	int nLength = 0;
	if ( wordBuffer[0] == '%' ) {
		
		if ( wordBuffer[1] == '~' )
			nLength = 2;
		else if (( wordBuffer[1] == '%' ) && ( wordBuffer[2] == '~' ))
			nLength++;
		else
			return 0;

		for ( ; ( wordBuffer[nLength] ); nLength++ ) {

			switch ( toupper(wordBuffer[nLength]) ) {
			case 'A':
				// file attributes
			case 'D':
				// drive letter only
			case 'F':
				// fully qualified path name
			case 'N':
				// filename only
			case 'P':
				// path only
			case 'S':
				// short name
			case 'T':
				// date / time of file
			case 'X':
				// file extension only
			case 'Z':
				// file size
				break;
			default:
				return nLength;
			}
		}
	}

	return nLength;
}


static void ColouriseTCMDLine( char *lineBuffer, unsigned int lengthLine, unsigned int startLine, unsigned int endPos, WordList *keywordlists[], Accessor &styler)
{
	unsigned int offset = 0;	// Line Buffer Offset
	char wordBuffer[260];		// Word Buffer - large to catch long paths
	unsigned int wbl;			// Word Buffer Length
	unsigned int wbo;			// Word Buffer Offset - also Special Keyword Buffer Length
	WordList &keywords = *keywordlists[0];      // Internal Commands
//	WordList &keywords2 = *keywordlists[1];     // Aliases (optional)
	bool isDelayedExpansion = 1;				// !var!

	bool continueProcessing = true;	// Used to toggle Regular Keyword Checking
	// Special Keywords are those that allow certain characters without whitespace after the command
	// Examples are: cd. cd\ echo: echo. path=
	bool inString = false; // Used for processing while ""
	// Special Keyword Buffer used to determine if the first n characters is a Keyword
	char sKeywordBuffer[260];	// Special Keyword Buffer
	bool sKeywordFound;		// Exit Special Keyword for-loop if found

	// Skip leading whitespace
	while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
		offset++;
	}
	// Colorize Default Text
	styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT);

	if ( offset >= lengthLine )
		return;

	// Check for Fake Label (Comment) or Real Label - return if found
	if (lineBuffer[offset] == ':') {
		if (lineBuffer[offset + 1] == ':') {
			// Colorize Fake Label (Comment) - :: is the same as REM
			styler.ColourTo(endPos, SCE_TCMD_COMMENT);
		} else {
			// Colorize Real Label
			styler.ColourTo(endPos, SCE_TCMD_LABEL);
		}
		return;

	// Check for Comment - return if found
	} else if (( CompareNCaseInsensitive(lineBuffer+offset, "rem", 3) == 0 ) && (( lineBuffer[offset+3] == 0 ) || ( isspace(lineBuffer[offset+3] )))) {
			styler.ColourTo(endPos, SCE_TCMD_COMMENT);
			return;

	// Check for Drive Change (Drive Change is internal command) - return if found
	} else if ((IsAlphabetic(lineBuffer[offset])) &&
		(lineBuffer[offset + 1] == ':') &&
		((isspacechar(lineBuffer[offset + 2])) ||
		(((lineBuffer[offset + 2] == '\\')) &&
		(isspacechar(lineBuffer[offset + 3]))))) {
		// Colorize Regular Keyword
		styler.ColourTo(endPos, SCE_TCMD_WORD);
		return;
	}

	// Check for Hide Command (@ECHO OFF/ON)
	if (lineBuffer[offset] == '@') {
		styler.ColourTo(startLine + offset, SCE_TCMD_HIDE);
		offset++;
	}
	// Skip whitespace
	while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
		offset++;
	}

	// Read remainder of line word-at-a-time or remainder-of-word-at-a-time
	while (offset < lengthLine) {
		if (offset > startLine) {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT);
		}
		// Copy word from Line Buffer into Word Buffer
		wbl = 0;
		for (; offset < lengthLine && ( wbl < 260 ) && !isspacechar(lineBuffer[offset]); wbl++, offset++) {
			wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
		}
		wordBuffer[wbl] = '\0';
		wbo = 0;

		// Check for Separator
		if (IsBSeparator(wordBuffer[0])) {

			// Reset Offset to re-process remainder of word
			offset -= (wbl - 1);
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);

			if (wordBuffer[0] == '"')
				inString = !inString;

		// Check for Regular expression
		} else if (( wordBuffer[0] == ':' ) && ( wordBuffer[1] == ':' ) && (continueProcessing)) {

			// Colorize Regular exoressuin
			styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT);
			// No need to Reset Offset

		// Check for Labels in text (... :label)
		} else if (wordBuffer[0] == ':' && isspacechar(lineBuffer[offset - wbl - 1])) {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT);
			// Colorize Label
			styler.ColourTo(startLine + offset - 1, SCE_TCMD_CLABEL);
			// No need to Reset Offset
		// Check for delayed expansion Variable (!x...!)
		} else if (isDelayedExpansion && wordBuffer[0] == '!') {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT);
			wbo++;
			// Search to end of word for second !
			while ((wbo < wbl) && (wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}
			if (wordBuffer[wbo] == '!') {
				wbo++;
				// Colorize Environment Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_EXPANSION);
			} else {
				wbo = 1;
				// Colorize Symbol
				styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_DEFAULT);
			}

			// Reset Offset to re-process remainder of word
			offset -= (wbl - wbo);

		// Check for Regular Keyword in list
		} else if ((keywords.InList(wordBuffer)) &&	(!inString) && (continueProcessing)) {

			// ECHO, PATH, and PROMPT require no further Regular Keyword Checking
			if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echos") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echoerr") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echoserr") == 0) ||
			  (CompareCaseInsensitive(wordBuffer, "path") == 0) ||
			  (CompareCaseInsensitive(wordBuffer, "prompt") == 0)) {
				continueProcessing = false;
			}

			// Colorize Regular keyword
			styler.ColourTo(startLine + offset - 1, SCE_TCMD_WORD);
			// No need to Reset Offset

		} else if ((wordBuffer[0] != '%') && (wordBuffer[0] != '!') && (!IsBOperator(wordBuffer[0])) &&	(!inString) && (continueProcessing)) {

			// a few commands accept "illegal" syntax -- cd\, echo., etc.
			sscanf( wordBuffer, "%[^.<>|&=\\/]", sKeywordBuffer );
			sKeywordFound = false;

			if ((CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echos") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echoerr") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "echoserr") == 0) || 
			  (CompareCaseInsensitive(sKeywordBuffer, "cd") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "path") == 0) ||
			  (CompareCaseInsensitive(sKeywordBuffer, "prompt") == 0)) {

				// no further Regular Keyword Checking
				continueProcessing = false;
				sKeywordFound = true;
				wbo = (unsigned int)strlen( sKeywordBuffer );

				// Colorize Special Keyword as Regular Keyword
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_WORD);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);
			}

			// Check for Default Text
			if (!sKeywordFound) {
				wbo = 0;
				// Read up to %, Operator or Separator
				while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!isDelayedExpansion || wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) &&	(!IsBSeparator(wordBuffer[wbo]))) {
					wbo++;
				}
				// Colorize Default Text
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_DEFAULT);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);
			}

		// Check for Argument  (%n), Environment Variable (%x...%) or Local Variable (%%a)
		} else if (wordBuffer[0] == '%') {
			unsigned int varlen;
			unsigned int n = 1;
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT);
			wbo++;

			// check for %[nn] syntax
			if ( wordBuffer[1] == '[' ) {
				n++;
				while ((n < wbl) && (wordBuffer[n] != ']')) {
					n++;
				}
				if ( wordBuffer[n] == ']' )
					n++;
				goto ColorizeArg;
			}

			// Search to end of word for second % or to the first terminator (can be a long path)
			while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}

			// Check for Argument (%n) or (%*)
			if (((isdigit(wordBuffer[1])) || (wordBuffer[1] == '*')) && (wordBuffer[wbo] != '%')) {
				while (( wordBuffer[n] ) && ( strchr( "%0123456789*#$", wordBuffer[n] ) != NULL ))
					n++;
ColorizeArg:
				// Colorize Argument
				styler.ColourTo(startLine + offset - 1 - (wbl - n), SCE_TCMD_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - n);

			// Check for Variable with modifiers (%~...)
			} else if ((varlen = GetBatchVarLen(wordBuffer)) != 0) {

				// Colorize Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - varlen), SCE_TCMD_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - varlen);

			// Check for Environment Variable (%x...%)
			} else if (( wordBuffer[1] ) && ( wordBuffer[1] != '%')) {
				if ( wordBuffer[wbo] == '%' )
					wbo++;

				// Colorize Environment Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_ENVIRONMENT);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - wbo);

			// Check for Local Variable (%%a)
			} else if (	(wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] != '%') && (!IsBOperator(wordBuffer[2])) && (!IsBSeparator(wordBuffer[2]))) {

				n = 2;
				while (( wordBuffer[n] ) && (!IsBOperator(wordBuffer[n])) && (!IsBSeparator(wordBuffer[n])))
					n++;

				// Colorize Local Variable
				styler.ColourTo(startLine + offset - 1 - (wbl - n), SCE_TCMD_IDENTIFIER);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - n);

			// Check for %%
			} else if ((wbl > 1) && (wordBuffer[1] == '%')) {

				// Colorize Symbols
				styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_TCMD_DEFAULT);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 2);
			} else {

				// Colorize Symbol
				styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_DEFAULT);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
			}

		// Check for Operator
		} else if (IsBOperator(wordBuffer[0])) {
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT);

			// Check for Pipe, compound, or conditional Operator
			if ((wordBuffer[0] == '|') || (wordBuffer[0] == '&')) {

				// Colorize Pipe Operator
				styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_OPERATOR);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
				continueProcessing = true;

			// Check for Other Operator
			} else {
				// Check for > Operator
				if ((wordBuffer[0] == '>') || (wordBuffer[0] == '<')) {
					// Turn Keyword and External Command / Program checking back on
					continueProcessing = true;
				}
				// Colorize Other Operator
				if (!inString || !(wordBuffer[0] == '(' || wordBuffer[0] == ')'))
					styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_OPERATOR);
				// Reset Offset to re-process remainder of word
				offset -= (wbl - 1);
			}

		// Check for Default Text
		} else {
			// Read up to %, Operator or Separator
			while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!isDelayedExpansion || wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) &&	(!IsBSeparator(wordBuffer[wbo]))) {
				wbo++;
			}
			// Colorize Default Text
			styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_DEFAULT);
			// Reset Offset to re-process remainder of word
			offset -= (wbl - wbo);
		}

		// Skip whitespace - nothing happens if Offset was Reset
		while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
			offset++;
		}
	}
	// Colorize Default Text for remainder of line - currently not lexed
	styler.ColourTo(endPos, SCE_TCMD_DEFAULT);
}

static void ColouriseTCMDDoc( unsigned int startPos, int length, int /*initStyle*/, WordList *keywordlists[], Accessor &styler )
{
	char lineBuffer[16384];

	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	unsigned int startLine = startPos;
	for (unsigned int i = startPos; i < startPos + length; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColouriseTCMDLine(lineBuffer, linePos, startLine, i, keywordlists, styler);
			linePos = 0;
			startLine = i + 1;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		lineBuffer[linePos] = '\0';
		ColouriseTCMDLine(lineBuffer, linePos, startLine, startPos + length - 1, keywordlists, styler);
	}
}

// Convert string to upper case
static void StrUpr(char *s) {
	while (*s) {
		*s = MakeUpperCase(*s);
		s++;
	}
}

// Folding support (for DO, IFF, SWITCH, TEXT, and command groups)
static void FoldTCMDDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
	int line = styler.GetLine(startPos);
	int level = styler.LevelAt(line);
	int levelIndent = 0;
	unsigned int endPos = startPos + length;
	char s[16];

    char chPrev = styler.SafeGetCharAt(startPos - 1);

	// Scan for ( and )
	for (unsigned int i = startPos; i < endPos; i++) {

		int c = styler.SafeGetCharAt(i, '\n');
		int style = styler.StyleAt(i);
        bool bLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0;

		if (style == SCE_TCMD_OPERATOR) {
			// CheckFoldPoint
			if (c == '(') {
				levelIndent += 1;
			} else if (c == ')') {
				levelIndent -= 1;
			}
		}

        if (( bLineStart ) && ( style == SCE_TCMD_WORD )) {
            for (unsigned int j = 0; j < 10; j++) {
                if (!iswordchar(styler[i + j])) {
                    break;
                }
                s[j] = styler[i + j];
                s[j + 1] = '\0';
            }

			StrUpr( s );
            if ((strcmp(s, "DO") == 0) || (strcmp(s, "IFF") == 0) || (strcmp(s, "SWITCH") == 0) || (strcmp(s, "TEXT") == 0)) {
                levelIndent++;
            } else if ((strcmp(s, "ENDDO") == 0) || (strcmp(s, "ENDIFF") == 0) || (strcmp(s, "ENDSWITCH") == 0) || (strcmp(s, "ENDTEXT") == 0)) {
                levelIndent--;
            }
        }

		if (c == '\n') { // line end
				if (levelIndent > 0) {
						level |= SC_FOLDLEVELHEADERFLAG;
				}
				if (level != styler.LevelAt(line))
						styler.SetLevel(line, level);
				level += levelIndent;
				if ((level & SC_FOLDLEVELNUMBERMASK) < SC_FOLDLEVELBASE)
						level = SC_FOLDLEVELBASE;
				line++;
				// reset state
				levelIndent = 0;
				level &= ~SC_FOLDLEVELHEADERFLAG;
				level &= ~SC_FOLDLEVELWHITEFLAG;
		}

		chPrev = c;
	}
}

static const char *const tcmdWordListDesc[] = {
	"Internal Commands",
	"Aliases",
	0
};

LexerModule lmTCMD(SCLEX_TCMD, ColouriseTCMDDoc, "tcmd", FoldTCMDDoc, tcmdWordListDesc);

Added lexers/LexTeX.cxx.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
// Scintilla source code edit control

// File: LexTeX.cxx - general context conformant tex coloring scheme
// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
// Version: September 28, 2003

// Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// This lexer is derived from the one written for the texwork environment (1999++) which in
// turn is inspired on texedit (1991++) which finds its roots in wdt (1986).

// If you run into strange boundary cases, just tell me and I'll look into it.


// TeX Folding code added by instanton (soft_share@126.com) with borrowed code from VisualTeX source by Alex Romanenko.
// Version: June 22, 2007

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// val SCE_TEX_DEFAULT = 0
// val SCE_TEX_SPECIAL = 1
// val SCE_TEX_GROUP   = 2
// val SCE_TEX_SYMBOL  = 3
// val SCE_TEX_COMMAND = 4
// val SCE_TEX_TEXT    = 5

// Definitions in SciTEGlobal.properties:
//
// TeX Highlighting
//
// # Default
// style.tex.0=fore:#7F7F00
// # Special
// style.tex.1=fore:#007F7F
// # Group
// style.tex.2=fore:#880000
// # Symbol
// style.tex.3=fore:#7F7F00
// # Command
// style.tex.4=fore:#008800
// # Text
// style.tex.5=fore:#000000

// lexer.tex.interface.default=0
// lexer.tex.comment.process=0

// todo: lexer.tex.auto.if

// Auxiliary functions:

static inline bool endOfLine(Accessor &styler, unsigned int i) {
	return
      (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
}

static inline bool isTeXzero(int ch) {
	return
      (ch == '%') ;
}

static inline bool isTeXone(int ch) {
	return
      (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') ||
      (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') ||
      (ch == '"') ;
}

static inline bool isTeXtwo(int ch) {
	return
      (ch == '{') || (ch == '}') || (ch == '$') ;
}

static inline bool isTeXthree(int ch) {
	return
      (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') ||
      (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') ||
      (ch == '/') || (ch == '|') || (ch == '%') ;
}

static inline bool isTeXfour(int ch) {
	return
      (ch == '\\') ;
}

static inline bool isTeXfive(int ch) {
	return
      ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
      (ch == '@') || (ch == '!') || (ch == '?') ;
}

static inline bool isTeXsix(int ch) {
	return
      (ch == ' ') ;
}

static inline bool isTeXseven(int ch) {
	return
      (ch == '^') ;
}

// Interface determination

static int CheckTeXInterface(
    unsigned int startPos,
    int length,
    Accessor &styler,
	int defaultInterface) {

    char lineBuffer[1024] ;
	unsigned int linePos = 0 ;

    // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)...

    if (styler.SafeGetCharAt(0) == '%') {
        for (unsigned int i = 0; i < startPos + length; i++) {
            lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
            if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
                lineBuffer[linePos] = '\0';
                if (strstr(lineBuffer, "interface=all")) {
                    return 0 ;
				} else if (strstr(lineBuffer, "interface=tex")) {
                    return 1 ;
                } else if (strstr(lineBuffer, "interface=nl")) {
                    return 2 ;
                } else if (strstr(lineBuffer, "interface=en")) {
                    return 3 ;
                } else if (strstr(lineBuffer, "interface=de")) {
                    return 4 ;
                } else if (strstr(lineBuffer, "interface=cz")) {
                    return 5 ;
                } else if (strstr(lineBuffer, "interface=it")) {
                    return 6 ;
                } else if (strstr(lineBuffer, "interface=ro")) {
                    return 7 ;
                } else if (strstr(lineBuffer, "interface=latex")) {
					// we will move latex cum suis up to 91+ when more keyword lists are supported
                    return 8 ;
				} else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
					// better would be to limit the search to just one line
					return 3 ;
                } else {
                    return defaultInterface ;
                }
            }
		}
    }

    return defaultInterface ;
}

static void ColouriseTeXDoc(
    unsigned int startPos,
    int length,
    int,
    WordList *keywordlists[],
    Accessor &styler) {

	styler.StartAt(startPos) ;
	styler.StartSegment(startPos) ;

	bool processComment   = styler.GetPropertyInt("lexer.tex.comment.process",   0) == 1 ;
	bool useKeywords      = styler.GetPropertyInt("lexer.tex.use.keywords",      1) == 1 ;
	bool autoIf           = styler.GetPropertyInt("lexer.tex.auto.if",           1) == 1 ;
	int  defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ;

	char key[100] ;
	int  k ;
	bool newifDone = false ;
	bool inComment = false ;

	int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ;

    if (currentInterface == 0) {
        useKeywords = false ;
        currentInterface = 1 ;
    }

    WordList &keywords = *keywordlists[currentInterface-1] ;

	StyleContext sc(startPos, length, SCE_TEX_TEXT, styler);

	bool going = sc.More() ; // needed because of a fuzzy end of file state

	for (; going; sc.Forward()) {

		if (! sc.More()) { going = false ; } // we need to go one behind the end of text

		if (inComment) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_TEX_TEXT) ;
				newifDone = false ;
				inComment = false ;
			}
		} else {
			if (! isTeXfive(sc.ch)) {
				if (sc.state == SCE_TEX_COMMAND) {
					if (sc.LengthCurrent() == 1) { // \<noncstoken>
						if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) {
							sc.Forward(2) ; // \^^ and \^^<token>
						}
						sc.ForwardSetState(SCE_TEX_TEXT) ;
					} else {
						sc.GetCurrent(key, sizeof(key)-1) ;
						k = static_cast<int>(strlen(key)) ;
						memmove(key,key+1,k) ; // shift left over escape token
						key[k] = '\0' ;
						k-- ;
						if (! keywords || ! useKeywords) {
							sc.SetState(SCE_TEX_COMMAND) ;
							newifDone = false ;
						} else if (k == 1) { //\<cstoken>
							sc.SetState(SCE_TEX_COMMAND) ;
							newifDone = false ;
						} else if (keywords.InList(key)) {
    						sc.SetState(SCE_TEX_COMMAND) ;
							newifDone = autoIf && (strcmp(key,"newif") == 0) ;
						} else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) {
	    					sc.SetState(SCE_TEX_COMMAND) ;
						} else {
							sc.ChangeState(SCE_TEX_TEXT) ;
							sc.SetState(SCE_TEX_TEXT) ;
							newifDone = false ;
						}
					}
				}
				if (isTeXzero(sc.ch)) {
					sc.SetState(SCE_TEX_SYMBOL);

					if (!endOfLine(styler,sc.currentPos + 1))
						sc.ForwardSetState(SCE_TEX_DEFAULT) ;

					inComment = ! processComment ;
					newifDone = false ;
				} else if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) {
					sc.SetState(SCE_TEX_TEXT) ;
					sc.ForwardSetState(SCE_TEX_TEXT) ;
				} else if (isTeXone(sc.ch)) {
					sc.SetState(SCE_TEX_SPECIAL) ;
					newifDone = false ;
				} else if (isTeXtwo(sc.ch)) {
					sc.SetState(SCE_TEX_GROUP) ;
					newifDone = false ;
				} else if (isTeXthree(sc.ch)) {
					sc.SetState(SCE_TEX_SYMBOL) ;
					newifDone = false ;
				} else if (isTeXfour(sc.ch)) {
					sc.SetState(SCE_TEX_COMMAND) ;
				} else if (isTeXsix(sc.ch)) {
					sc.SetState(SCE_TEX_TEXT) ;
				} else if (sc.atLineEnd) {
					sc.SetState(SCE_TEX_TEXT) ;
					newifDone = false ;
					inComment = false ;
				} else {
					sc.SetState(SCE_TEX_TEXT) ;
				}
			} else if (sc.state != SCE_TEX_COMMAND) {
				sc.SetState(SCE_TEX_TEXT) ;
			}
		}
	}
	sc.ChangeState(SCE_TEX_TEXT) ;
	sc.Complete();

}


static inline bool isNumber(int ch) {
	return
      (ch == '0') || (ch == '1') || (ch == '2') ||
      (ch == '3') || (ch == '4') || (ch == '5') ||
      (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9');
}

static inline bool isWordChar(int ch) {
	return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'));
}

static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command)
{
  int length=0;
  char ch=styler.SafeGetCharAt(pos+1);

  if(ch==',' || ch==':' || ch==';' || ch=='%'){
      command[0]=ch;
      command[1]=0;
	  return 1;
  }

  // find end
     while(isWordChar(ch) && !isNumber(ch) && ch!='_' && ch!='.' && length<100){
          command[length]=ch;
          length++;
          ch=styler.SafeGetCharAt(pos+length+1);
     }

  command[length]='\0';
  if(!length) return 0;
  return length+1;
}

static int classifyFoldPointTeXPaired(const char* s) {
	int lev=0;
	if (!(isdigit(s[0]) || (s[0] == '.'))){
		if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0||
			strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0||
			strcmp(s,"title")==0||strncmp(s,"start",5)==0||strncmp(s,"Start",5)==0||
			strcmp(s,"documentclass")==0||strncmp(s,"if",2)==0
			)
			lev=1;
		if (strcmp(s, "end")==0||strcmp(s,"FoldStop")==0||
			strcmp(s,"maketitle")==0||strcmp(s,"protect")==0||
			strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0||
			strcmp(s,"fi")==0
			)
		lev=-1;
	}
	return lev;
}

static int classifyFoldPointTeXUnpaired(const char* s) {
	int lev=0;
	if (!(isdigit(s[0]) || (s[0] == '.'))){
		if (strcmp(s,"part")==0||
			strcmp(s,"chapter")==0||
			strcmp(s,"section")==0||
			strcmp(s,"subsection")==0||
			strcmp(s,"subsubsection")==0||
			strcmp(s,"CJKfamily")==0||
			strcmp(s,"appendix")==0||
			strcmp(s,"Topic")==0||strcmp(s,"topic")==0||
			strcmp(s,"subject")==0||strcmp(s,"subsubject")==0||
			strcmp(s,"def")==0||strcmp(s,"gdef")==0||strcmp(s,"edef")==0||
			strcmp(s,"xdef")==0||strcmp(s,"framed")==0||
			strcmp(s,"frame")==0||
			strcmp(s,"foilhead")==0||strcmp(s,"overlays")==0||strcmp(s,"slide")==0
			){
			    lev=1;
			}
	}
	return lev;
}

static bool IsTeXCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;

	int startpos = pos;

	while (startpos<eol_pos){
		char ch = styler[startpos];
		if (ch!='%' && ch!=' ') return false;
		else if (ch=='%') return true;
		startpos++;
	}

	return false;
}

// FoldTeXDoc: borrowed from VisualTeX with modifications

static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
{
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos+length;
	int visibleChars=0;
	int lineCurrent=styler.GetLine(startPos);
	int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent=levelPrev;
	char chNext=styler[startPos];
	char buffer[100]="";

	for (unsigned int i=startPos; i < endPos; i++) {
		char ch=chNext;
		chNext=styler.SafeGetCharAt(i+1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

        if(ch=='\\') {
            ParseTeXCommand(i, styler, buffer);
			levelCurrent += classifyFoldPointTeXPaired(buffer)+classifyFoldPointTeXUnpaired(buffer);
		}

		if (levelCurrent > SC_FOLDLEVELBASE && ((ch == '\r' || ch=='\n') && (chNext == '\\'))) {
            ParseTeXCommand(i+1, styler, buffer);
			levelCurrent -= classifyFoldPointTeXUnpaired(buffer);
		}

	char chNext2;
	char chNext3;
	char chNext4;
	char chNext5;
	chNext2=styler.SafeGetCharAt(i+2);
	chNext3=styler.SafeGetCharAt(i+3);
	chNext4=styler.SafeGetCharAt(i+4);
	chNext5=styler.SafeGetCharAt(i+5);

	bool atEOfold = (ch == '%') &&
			(chNext == '%') && (chNext2=='}') &&
				(chNext3=='}')&& (chNext4=='-')&& (chNext5=='-');

	bool atBOfold = (ch == '%') &&
			(chNext == '%') && (chNext2=='-') &&
				(chNext3=='-')&& (chNext4=='{')&& (chNext5=='{');

	if(atBOfold){
		levelCurrent+=1;
	}

	if(atEOfold){
		levelCurrent-=1;
	}

	if(ch=='\\' && chNext=='['){
		levelCurrent+=1;
	}

	if(ch=='\\' && chNext==']'){
		levelCurrent-=1;
	}

	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;

	if (foldComment && atEOL && IsTeXCommentLine(lineCurrent, styler))
        {
            if (lineCurrent==0 && IsTeXCommentLine(lineCurrent + 1, styler)
				)
                levelCurrent++;
            else if (lineCurrent!=0 && !IsTeXCommentLine(lineCurrent - 1, styler)
               && IsTeXCommentLine(lineCurrent + 1, styler)
				)
                levelCurrent++;
            else if (lineCurrent!=0 && IsTeXCommentLine(lineCurrent - 1, styler) &&
                     !IsTeXCommentLine(lineCurrent+1, styler))
                levelCurrent--;
        }

//---------------------------------------------------------------------------------------------

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}

		if (!isspacechar(ch))
			visibleChars++;
	}

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}




static const char * const texWordListDesc[] = {
    "TeX, eTeX, pdfTeX, Omega",
    "ConTeXt Dutch",
    "ConTeXt English",
    "ConTeXt German",
    "ConTeXt Czech",
    "ConTeXt Italian",
    "ConTeXt Romanian",
	0,
} ;

LexerModule lmTeX(SCLEX_TEX,   ColouriseTeXDoc, "tex", FoldTexDoc, texWordListDesc);

Added lexers/LexTxt2tags.cxx.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
/******************************************************************
 *  LexTxt2tags.cxx
 *
 *  A simple Txt2tags lexer for scintilla.
 *
 *
 *  Adapted by Eric Forgeot
 *  Based on the LexMarkdown.cxx by Jon Strait - jstrait@moonloop.net
 *
 *  What could be improved:
 *   - Verbatim lines could be like for raw lines : when there is no space between the ``` and the following text, the first letter should be colored so the user would understand there must be a space for a valid tag.
 *   - marks such as bold, italic, strikeout, underline should begin to be highlighted only when they are closed and valid.
 *   - verbatim and raw area should be highlighted too.
 *
 *  The License.txt file describes the conditions under which this
 *  software may be distributed.
 *
 *****************************************************************/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif



static inline bool IsNewline(const int ch) {
    return (ch == '\n' || ch == '\r');
}

// True if can follow ch down to the end with possibly trailing whitespace
static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) {
    unsigned int i = 0;
    while (sc.GetRelative(++i) == ch)
        ;
    // Skip over whitespace
    while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
        ++i;
    if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
        sc.Forward(i);
        sc.ChangeState(state);
        sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
        return true;
    }
    else return false;
}

// Does the previous line have more than spaces and tabs?
static bool HasPrevLineContent(StyleContext &sc) {
    int i = 0;
    // Go back to the previous newline
    while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i)))
        ;
    while (--i + sc.currentPos) {
        if (IsNewline(sc.GetRelative(i)))
            break;
        if (!IsASpaceOrTab(sc.GetRelative(i)))
            return true;
    }
    return false;
}

// Separator line
static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) {
    int c, count = 1;
    unsigned int i = 0;
    while (++i) {
        c = sc.GetRelative(i);
        if (c == sc.ch)
            ++count;
        // hit a terminating character
        else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) {
            // Are we a valid HRULE
            if ((IsNewline(c) || sc.currentPos + i == endPos) &&
                    count >= 20 && !HasPrevLineContent(sc)) {
                sc.SetState(SCE_TXT2TAGS_HRULE);
                sc.Forward(i);
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
                return true;
            }
            else {
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
		return false;
            }
        }
    }
    return false;
}

static void ColorizeTxt2tagsDoc(unsigned int startPos, int length, int initStyle,
                               WordList **, Accessor &styler) {
    unsigned int endPos = startPos + length;
    int precharCount = 0;
    // Don't advance on a new loop iteration and retry at the same position.
    // Useful in the corner case of having to start at the beginning file position
    // in the default state.
    bool freezeCursor = false;

    StyleContext sc(startPos, length, initStyle, styler);

    while (sc.More()) {
        // Skip past escaped characters
        if (sc.ch == '\\') {
            sc.Forward();
            continue;
        }

        // A blockquotes resets the line semantics
        if (sc.state == SCE_TXT2TAGS_BLOCKQUOTE){
            sc.Forward(2);
            sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
        }
        // An option colors the whole line
        if (sc.state == SCE_TXT2TAGS_OPTION){
            FollowToLineEnd('%', SCE_TXT2TAGS_OPTION, endPos, sc);
        }
        if (sc.state == SCE_TXT2TAGS_POSTPROC){
            FollowToLineEnd('%', SCE_TXT2TAGS_POSTPROC, endPos, sc);
        }
        if (sc.state == SCE_TXT2TAGS_PREPROC){
            FollowToLineEnd('%', SCE_TXT2TAGS_PREPROC, endPos, sc);
        }
        // A comment colors the whole line
        if (sc.state == SCE_TXT2TAGS_COMMENT){
            FollowToLineEnd('%', SCE_TXT2TAGS_COMMENT, endPos, sc);
        }
        // Conditional state-based actions
        if (sc.state == SCE_TXT2TAGS_CODE2) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.Match("``") && sc.GetRelative(-2) != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }
        }
        // Table
        else if (sc.state == SCE_TXT2TAGS_CODE) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.ch == '|' && sc.chPrev != ' ')
                sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT);
        }
        // Strong
        else if (sc.state == SCE_TXT2TAGS_STRONG1) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.Match("**") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }
        }
        // Emphasis
        else if (sc.state == SCE_TXT2TAGS_EM1) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.Match("//") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT);
           }
        }
        // Underline
        else if (sc.state == SCE_TXT2TAGS_EM2) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.Match("__") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT);
           }
        }
        // codeblock
        else if (sc.state == SCE_TXT2TAGS_CODEBK) {
                if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.atLineStart && sc.Match("```")) {
                int i = 1;
                while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos)
                    i++;
                sc.Forward(i);
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }
        }
        // strikeout
        else if (sc.state == SCE_TXT2TAGS_STRIKEOUT) {
        if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            if (sc.Match("--") && sc.chPrev != ' ') {
                sc.Forward(2);
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }
        }
        // Headers
        else if (sc.state == SCE_TXT2TAGS_LINE_BEGIN) {
            if (sc.Match("======"))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER6);
                sc.Forward();
                }
            else if (sc.Match("====="))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER5);
                sc.Forward();
                }
            else if (sc.Match("===="))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER4);
                sc.Forward();
                }
            else if (sc.Match("==="))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER3);
                sc.Forward();
                }
                //SetStateAndZoom(SCE_TXT2TAGS_HEADER3, 3, '=', sc);
            else if (sc.Match("==")) {
                sc.SetState(SCE_TXT2TAGS_HEADER2);
                sc.Forward();
                }
                //SetStateAndZoom(SCE_TXT2TAGS_HEADER2, 2, '=', sc);
            else if (sc.Match("=")) {
                // Catch the special case of an unordered list
                if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
                    precharCount = 0;
                    sc.SetState(SCE_TXT2TAGS_PRECHAR);
                }
                else
                    {
                    sc.SetState(SCE_TXT2TAGS_HEADER1);
                    sc.Forward();
                    }
                    //SetStateAndZoom(SCE_TXT2TAGS_HEADER1, 1, '=', sc);
            }

            // Numbered title
            else if (sc.Match("++++++"))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER6);
                sc.Forward();
                }
            else if (sc.Match("+++++"))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER5);
                sc.Forward();
                }
            else if (sc.Match("++++"))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER4);
                sc.Forward();
                }
            else if (sc.Match("+++"))
                {
                sc.SetState(SCE_TXT2TAGS_HEADER3);
                sc.Forward();
                }
                //SetStateAndZoom(SCE_TXT2TAGS_HEADER3, 3, '+', sc);
            else if (sc.Match("++")) {
                sc.SetState(SCE_TXT2TAGS_HEADER2);
                sc.Forward();
                }
                //SetStateAndZoom(SCE_TXT2TAGS_HEADER2, 2, '+', sc);
            else if (sc.Match("+")) {
                // Catch the special case of an unordered list
                if (sc.chNext == ' ' && IsASpaceOrTab(sc.GetRelative(1))) {
                 //    if (IsNewline(sc.ch)) {
                     	//precharCount = 0;
                //		sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
                		//sc.SetState(SCE_TXT2TAGS_PRECHAR);
				//	}
                //    else {
                //    precharCount = 0;
                    sc.SetState(SCE_TXT2TAGS_OLIST_ITEM);
                    sc.Forward(2);
                    sc.SetState(SCE_TXT2TAGS_DEFAULT);
               //     sc.SetState(SCE_TXT2TAGS_PRECHAR);
				//	}
                }
                else
                    {
                    sc.SetState(SCE_TXT2TAGS_HEADER1);
                    sc.Forward();
                    }
            }


            // Codeblock
            else if (sc.Match("```")) {
                if (!HasPrevLineContent(sc))
              //  if (!FollowToLineEnd(sc))
                    sc.SetState(SCE_TXT2TAGS_CODEBK);
                else
                    sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }

            // Preproc
            else if (sc.Match("%!preproc")) {
                sc.SetState(SCE_TXT2TAGS_PREPROC);
            }
            // Postproc
            else if (sc.Match("%!postproc")) {
                sc.SetState(SCE_TXT2TAGS_POSTPROC);
            }
            // Option
            else if (sc.Match("%!")) {
                sc.SetState(SCE_TXT2TAGS_OPTION);
            }

             // Comment
            else if (sc.ch == '%') {
                sc.SetState(SCE_TXT2TAGS_COMMENT);
            }
            // list
            else if (sc.ch == '-') {
                    precharCount = 0;
                    sc.SetState(SCE_TXT2TAGS_PRECHAR);
            }
            // def list
            else if (sc.ch == ':') {
                    precharCount = 0;
                   sc.SetState(SCE_TXT2TAGS_OLIST_ITEM);
                   sc.Forward(1);
                   sc.SetState(SCE_TXT2TAGS_PRECHAR);
            }
            else if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
            else {
                precharCount = 0;
                sc.SetState(SCE_TXT2TAGS_PRECHAR);
            }
        }

        // The header lasts until the newline
        else if (sc.state == SCE_TXT2TAGS_HEADER1 || sc.state == SCE_TXT2TAGS_HEADER2 ||
                sc.state == SCE_TXT2TAGS_HEADER3 || sc.state == SCE_TXT2TAGS_HEADER4 ||
                sc.state == SCE_TXT2TAGS_HEADER5 || sc.state == SCE_TXT2TAGS_HEADER6) {
            if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
        }

        // New state only within the initial whitespace
        if (sc.state == SCE_TXT2TAGS_PRECHAR) {
            // Blockquote
            if (sc.Match("\"\"\"") && precharCount < 5){

                sc.SetState(SCE_TXT2TAGS_BLOCKQUOTE);
                sc.Forward(1);
                }
            /*
            // Begin of code block
            else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4))
                sc.SetState(SCE_TXT2TAGS_CODEBK);
            */
            // HRule - Total of 20 or more hyphens, asterisks, or underscores
            // on a line by themselves
            else if ((sc.ch == '-' ) && IsValidHrule(endPos, sc))
                ;
            // Unordered list
            else if ((sc.ch == '-') && IsASpaceOrTab(sc.chNext)) {
                sc.SetState(SCE_TXT2TAGS_ULIST_ITEM);
                sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT);
            }
            // Ordered list
            else if (IsADigit(sc.ch)) {
                int digitCount = 0;
                while (IsADigit(sc.GetRelative(++digitCount)))
                    ;
                if (sc.GetRelative(digitCount) == '.' &&
                        IsASpaceOrTab(sc.GetRelative(digitCount + 1))) {
                    sc.SetState(SCE_TXT2TAGS_OLIST_ITEM);
                    sc.Forward(digitCount + 1);
                    sc.SetState(SCE_TXT2TAGS_DEFAULT);
                }
            }
            // Alternate Ordered list
            else if (sc.ch == '+' && sc.chNext == ' ' && IsASpaceOrTab(sc.GetRelative(2))) {
            //    sc.SetState(SCE_TXT2TAGS_OLIST_ITEM);
            //    sc.Forward(2);
             //   sc.SetState(SCE_TXT2TAGS_DEFAULT);
            }
            else if (sc.ch != ' ' || precharCount > 2)
                sc.SetState(SCE_TXT2TAGS_DEFAULT);
            else
                ++precharCount;
        }

        // New state anywhere in doc
        if (sc.state == SCE_TXT2TAGS_DEFAULT) {
         //   if (sc.atLineStart && sc.ch == '#') {
         //       sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
         //       freezeCursor = true;
         //   }
            // Links and Images
            if (sc.Match("![") || sc.ch == '[') {
                int i = 0, j = 0, k = 0;
                int len = endPos - sc.currentPos;
                while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
                    ;
                if (sc.GetRelative(i) == ']') {
                    j = i;
                    if (sc.GetRelative(++i) == '(') {
                        while (i < len && (sc.GetRelative(++i) != '(' || sc.GetRelative(i - 1) == '\\'))
                            ;
                        if (sc.GetRelative(i) == '(')
                            k = i;
                    }

                    else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') {
                        while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
                            ;
                        if (sc.GetRelative(i) == ']')
                            k = i;
                    }
                }
                // At least a link text
                if (j) {
                    sc.SetState(SCE_TXT2TAGS_LINK);
                    sc.Forward(j);
                    // Also has a URL or reference portion
                    if (k)
                        sc.Forward(k - j);
                    sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT);
                }
            }
            // Code - also a special case for alternate inside spacing
            if (sc.Match("``") && sc.GetRelative(3) != ' ') {
                sc.SetState(SCE_TXT2TAGS_CODE2);
                sc.Forward();
            }
            else if (sc.ch == '|' && sc.GetRelative(3) != ' ') {
                sc.SetState(SCE_TXT2TAGS_CODE);
            }
            // Strong
            else if (sc.Match("**") && sc.GetRelative(2) != ' ') {
                sc.SetState(SCE_TXT2TAGS_STRONG1);
                sc.Forward();
           }
            // Emphasis
            else if (sc.Match("//") && sc.GetRelative(2) != ' ') {
                sc.SetState(SCE_TXT2TAGS_EM1);
                sc.Forward();
            }
            else if (sc.Match("__") && sc.GetRelative(2) != ' ') {
                sc.SetState(SCE_TXT2TAGS_EM2);
                sc.Forward();
            }
            // Strikeout
            else if (sc.Match("--") && sc.GetRelative(2) != ' ') {
                sc.SetState(SCE_TXT2TAGS_STRIKEOUT);
                sc.Forward();
            }

            // Beginning of line
            else if (IsNewline(sc.ch))
                sc.SetState(SCE_TXT2TAGS_LINE_BEGIN);
        }
        // Advance if not holding back the cursor for this iteration.
        if (!freezeCursor)
            sc.Forward();
        freezeCursor = false;
    }
    sc.Complete();
}

LexerModule lmTxt2tags(SCLEX_TXT2TAGS, ColorizeTxt2tagsDoc, "txt2tags");


Added lexers/LexVB.cxx.































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
// Scintilla source code edit control
/** @file LexVB.cxx
 ** Lexer for Visual Basic and VBScript.
 **/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Internal state, highlighted as number
#define SCE_B_FILENUMBER SCE_B_DEFAULT+100


static bool IsVBComment(Accessor &styler, int pos, int len) {
	return len > 0 && styler[pos] == '\'';
}

static inline bool IsTypeCharacter(int ch) {
	return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
}

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
             ch == '.' || ch == '-' || ch == '+');
}

static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler, bool vbScriptSyntax) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	styler.StartAt(startPos);

	int visibleChars = 0;
	int fileNbDigits = 0;

	// Do not leak onto next line
	if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) {
		initStyle = SCE_B_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.state == SCE_B_OPERATOR) {
			sc.SetState(SCE_B_DEFAULT);
		} else if (sc.state == SCE_B_IDENTIFIER) {
			if (!IsAWordChar(sc.ch)) {
				// In Basic (except VBScript), a variable name or a function name
				// can end with a special character indicating the type of the value
				// held or returned.
				bool skipType = false;
				if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) {
					sc.Forward();	// Skip it
					skipType = true;
				}
				if (sc.ch == ']') {
					sc.Forward();
				}
				char s[100];
				sc.GetCurrentLowered(s, sizeof(s));
				if (skipType) {
					s[strlen(s) - 1] = '\0';
				}
				if (strcmp(s, "rem") == 0) {
					sc.ChangeState(SCE_B_COMMENT);
				} else {
					if (keywords.InList(s)) {
						sc.ChangeState(SCE_B_KEYWORD);
					} else if (keywords2.InList(s)) {
						sc.ChangeState(SCE_B_KEYWORD2);
					} else if (keywords3.InList(s)) {
						sc.ChangeState(SCE_B_KEYWORD3);
					} else if (keywords4.InList(s)) {
						sc.ChangeState(SCE_B_KEYWORD4);
					}	// Else, it is really an identifier...
					sc.SetState(SCE_B_DEFAULT);
				}
			}
		} else if (sc.state == SCE_B_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign char
			// Also accepts A-F for hex. numbers
			if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) {
				sc.SetState(SCE_B_DEFAULT);
			}
		} else if (sc.state == SCE_B_STRING) {
			// VB doubles quotes to preserve them, so just end this string
			// state now as a following quote will start again
			if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					if (tolower(sc.chNext) == 'c') {
						sc.Forward();
					}
					sc.ForwardSetState(SCE_B_DEFAULT);
				}
			} else if (sc.atLineEnd) {
				visibleChars = 0;
				sc.ChangeState(SCE_B_STRINGEOL);
				sc.ForwardSetState(SCE_B_DEFAULT);
			}
		} else if (sc.state == SCE_B_COMMENT) {
			if (sc.atLineEnd) {
				visibleChars = 0;
				sc.ForwardSetState(SCE_B_DEFAULT);
			}
		} else if (sc.state == SCE_B_PREPROCESSOR) {
			if (sc.atLineEnd) {
				visibleChars = 0;
				sc.ForwardSetState(SCE_B_DEFAULT);
			}
		} else if (sc.state == SCE_B_FILENUMBER) {
			if (IsADigit(sc.ch)) {
				fileNbDigits++;
				if (fileNbDigits > 3) {
					sc.ChangeState(SCE_B_DATE);
				}
			} else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') {
				// Regular uses: Close #1; Put #1, ...; Get #1, ... etc.
				// Too bad if date is format #27, Oct, 2003# or something like that...
				// Use regular number state
				sc.ChangeState(SCE_B_NUMBER);
				sc.SetState(SCE_B_DEFAULT);
			} else if (sc.ch == '#') {
				sc.ChangeState(SCE_B_DATE);
				sc.ForwardSetState(SCE_B_DEFAULT);
			} else {
				sc.ChangeState(SCE_B_DATE);
			}
			if (sc.state != SCE_B_FILENUMBER) {
				fileNbDigits = 0;
			}
		} else if (sc.state == SCE_B_DATE) {
			if (sc.atLineEnd) {
				visibleChars = 0;
				sc.ChangeState(SCE_B_STRINGEOL);
				sc.ForwardSetState(SCE_B_DEFAULT);
			} else if (sc.ch == '#') {
				sc.ForwardSetState(SCE_B_DEFAULT);
			}
		}

		if (sc.state == SCE_B_DEFAULT) {
			if (sc.ch == '\'') {
				sc.SetState(SCE_B_COMMENT);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_B_STRING);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_B_PREPROCESSOR);
			} else if (sc.ch == '#') {
				// It can be a date literal, ending with #, or a file number, from 1 to 511
				// The date literal depends on the locale, so anything can go between #'s.
				// Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc.
				// So we set the FILENUMBER state, and switch to DATE if it isn't a file number
				sc.SetState(SCE_B_FILENUMBER);
			} else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
				// Hexadecimal number
				sc.SetState(SCE_B_NUMBER);
				sc.Forward();
			} else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
				// Octal number
				sc.SetState(SCE_B_NUMBER);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_B_NUMBER);
			} else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
				sc.SetState(SCE_B_IDENTIFIER);
			} else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {	// Integer division
				sc.SetState(SCE_B_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			visibleChars = 0;
		}
		if (!IsASpace(sc.ch)) {
			visibleChars++;
		}
	}

	if (sc.state == SCE_B_IDENTIFIER && !IsAWordChar(sc.ch)) {
		// In Basic (except VBScript), a variable name or a function name
		// can end with a special character indicating the type of the value
		// held or returned.
		bool skipType = false;
		if (!vbScriptSyntax && IsTypeCharacter(sc.ch)) {
			sc.Forward();	// Skip it
			skipType = true;
		}
		if (sc.ch == ']') {
			sc.Forward();
		}
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));
		if (skipType) {
			s[strlen(s) - 1] = '\0';
		}
		if (strcmp(s, "rem") == 0) {
			sc.ChangeState(SCE_B_COMMENT);
		} else {
			if (keywords.InList(s)) {
				sc.ChangeState(SCE_B_KEYWORD);
			} else if (keywords2.InList(s)) {
				sc.ChangeState(SCE_B_KEYWORD2);
			} else if (keywords3.InList(s)) {
				sc.ChangeState(SCE_B_KEYWORD3);
			} else if (keywords4.InList(s)) {
				sc.ChangeState(SCE_B_KEYWORD4);
			}	// Else, it is really an identifier...
			sc.SetState(SCE_B_DEFAULT);
		}
	}

	sc.Complete();
}

static void FoldVBDoc(unsigned int startPos, int length, int,
						   WordList *[], Accessor &styler) {
	int endPos = startPos + length;

	// Backtrack to previous line in case need to fix its fold status
	int lineCurrent = styler.GetLine(startPos);
	if (startPos > 0) {
		if (lineCurrent > 0) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent);
		}
	}
	int spaceFlags = 0;
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsVBComment);
	char chNext = styler[startPos];
	for (int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
			int lev = indentCurrent;
			int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsVBComment);
			if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
				// Only non whitespace lines can be headers
				if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
					lev |= SC_FOLDLEVELHEADERFLAG;
				} else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
					// Line after is blank so check the next - maybe should continue further?
					int spaceFlags2 = 0;
					int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsVBComment);
					if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
						lev |= SC_FOLDLEVELHEADERFLAG;
					}
				}
			}
			indentCurrent = indentNext;
			styler.SetLevel(lineCurrent, lev);
			lineCurrent++;
		}
	}
}

static void ColouriseVBNetDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler) {
	ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, false);
}

static void ColouriseVBScriptDoc(unsigned int startPos, int length, int initStyle,
                           WordList *keywordlists[], Accessor &styler) {
	ColouriseVBDoc(startPos, length, initStyle, keywordlists, styler, true);
}

static const char * const vbWordListDesc[] = {
	"Keywords",
	"user1",
	"user2",
	"user3",
	0
};

LexerModule lmVB(SCLEX_VB, ColouriseVBNetDoc, "vb", FoldVBDoc, vbWordListDesc);
LexerModule lmVBScript(SCLEX_VBSCRIPT, ColouriseVBScriptDoc, "vbscript", FoldVBDoc, vbWordListDesc);

Added lexers/LexVHDL.cxx.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
// Scintilla source code edit control
/** @file LexVHDL.cxx
 ** Lexer for VHDL
 ** Written by Phil Reid,
 ** Based on:
 **  - The Verilog Lexer by Avi Yegudin
 **  - The Fortran Lexer by Chuan-jian Shen
 **  - The C++ lexer by Neil Hodgson
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void ColouriseVHDLDoc(
  unsigned int startPos,
  int length,
  int initStyle,
  WordList *keywordlists[],
  Accessor &styler);


/***************************************/
static inline bool IsAWordChar(const int ch) {
  return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' );
}

/***************************************/
static inline bool IsAWordStart(const int ch) {
  return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

/***************************************/
inline bool IsABlank(unsigned int ch) {
    return (ch == ' ') || (ch == 0x09) || (ch == 0x0b) ;
}

/***************************************/
static void ColouriseVHDLDoc(
  unsigned int startPos,
  int length,
  int initStyle,
  WordList *keywordlists[],
  Accessor &styler)
{
  WordList &Keywords   = *keywordlists[0];
  WordList &Operators  = *keywordlists[1];
  WordList &Attributes = *keywordlists[2];
  WordList &Functions  = *keywordlists[3];
  WordList &Packages   = *keywordlists[4];
  WordList &Types      = *keywordlists[5];
  WordList &User       = *keywordlists[6];

  StyleContext sc(startPos, length, initStyle, styler);

  for (; sc.More(); sc.Forward())
  {

    // Determine if the current state should terminate.
    if (sc.state == SCE_VHDL_OPERATOR) {
      sc.SetState(SCE_VHDL_DEFAULT);
    } else if (sc.state == SCE_VHDL_NUMBER) {
      if (!IsAWordChar(sc.ch) && (sc.ch != '#')) {
        sc.SetState(SCE_VHDL_DEFAULT);
      }
    } else if (sc.state == SCE_VHDL_IDENTIFIER) {
      if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
        char s[100];
        sc.GetCurrentLowered(s, sizeof(s));
        if (Keywords.InList(s)) {
          sc.ChangeState(SCE_VHDL_KEYWORD);
        } else if (Operators.InList(s)) {
          sc.ChangeState(SCE_VHDL_STDOPERATOR);
        } else if (Attributes.InList(s)) {
          sc.ChangeState(SCE_VHDL_ATTRIBUTE);
        } else if (Functions.InList(s)) {
          sc.ChangeState(SCE_VHDL_STDFUNCTION);
        } else if (Packages.InList(s)) {
          sc.ChangeState(SCE_VHDL_STDPACKAGE);
        } else if (Types.InList(s)) {
          sc.ChangeState(SCE_VHDL_STDTYPE);
        } else if (User.InList(s)) {
          sc.ChangeState(SCE_VHDL_USERWORD);
        }
        sc.SetState(SCE_VHDL_DEFAULT);
      }
    } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_VHDL_COMMENTLINEBANG) {
      if (sc.atLineEnd) {
        sc.SetState(SCE_VHDL_DEFAULT);
      }
    } else if (sc.state == SCE_VHDL_STRING) {
      if (sc.ch == '\\') {
        if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
          sc.Forward();
        }
      } else if (sc.ch == '\"') {
        sc.ForwardSetState(SCE_VHDL_DEFAULT);
      } else if (sc.atLineEnd) {
        sc.ChangeState(SCE_VHDL_STRINGEOL);
        sc.ForwardSetState(SCE_VHDL_DEFAULT);
      }
    }

    // Determine if a new state should be entered.
    if (sc.state == SCE_VHDL_DEFAULT) {
      if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
        sc.SetState(SCE_VHDL_NUMBER);
      } else if (IsAWordStart(sc.ch)) {
        sc.SetState(SCE_VHDL_IDENTIFIER);
      } else if (sc.Match('-', '-')) {
        if (sc.Match("--!"))  // Nice to have a different comment style
          sc.SetState(SCE_VHDL_COMMENTLINEBANG);
        else
          sc.SetState(SCE_VHDL_COMMENT);
      } else if (sc.ch == '\"') {
        sc.SetState(SCE_VHDL_STRING);
      } else if (isoperator(static_cast<char>(sc.ch))) {
        sc.SetState(SCE_VHDL_OPERATOR);
      }
    }
  }
  sc.Complete();
}
//=============================================================================
static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eol_pos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eol_pos; i++) {
		char ch = styler[i];
		char chNext = styler[i+1];
		if ((ch == '-') && (chNext == '-'))
			return true;
		else if (ch != ' ' && ch != '\t')
			return false;
	}
	return false;
}

//=============================================================================
// Folding the code
static void FoldNoBoxVHDLDoc(
  unsigned int startPos,
  int length,
  int,
  Accessor &styler)
{
  // Decided it would be smarter to have the lexer have all keywords included. Therefore I
  // don't check if the style for the keywords that I use to adjust the levels.
  char words[] =
    "architecture begin case component else elsif end entity generate loop package process record then "
    "procedure function when";
  WordList keywords;
  keywords.Set(words);

  bool foldComment      = styler.GetPropertyInt("fold.comment", 1) != 0;
  bool foldCompact      = styler.GetPropertyInt("fold.compact", 1) != 0;
  bool foldAtElse       = styler.GetPropertyInt("fold.at.else", 1) != 0;
  bool foldAtBegin      = styler.GetPropertyInt("fold.at.Begin", 1) != 0;
  bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0;
  //bool foldAtWhen       = styler.GetPropertyInt("fold.at.When", 1) != 0;  //< fold at when in case statements

  int  visibleChars     = 0;
  unsigned int endPos   = startPos + length;

  int lineCurrent       = styler.GetLine(startPos);
  int levelCurrent      = SC_FOLDLEVELBASE;
  if(lineCurrent > 0)
    levelCurrent        = styler.LevelAt(lineCurrent-1) >> 16;
  //int levelMinCurrent   = levelCurrent;
  int levelMinCurrentElse = levelCurrent;   //< Used for folding at 'else'
  int levelMinCurrentBegin = levelCurrent;  //< Used for folding at 'begin'
  int levelNext         = levelCurrent;

  /***************************************/
  int lastStart         = 0;
  char prevWord[32]     = "";

  /***************************************/
  // Find prev word
  // The logic for going up or down a level depends on a the previous keyword
  // This code could be cleaned up.
  int end = 0;
  unsigned int j;
  for(j = startPos; j>0; j--)
  {
    char ch       = styler.SafeGetCharAt(j);
    char chPrev   = styler.SafeGetCharAt(j-1);
    int style     = styler.StyleAt(j);
    int stylePrev = styler.StyleAt(j-1);
    if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING))
    {
      if(IsAWordChar(chPrev) && !IsAWordChar(ch))
      {
        end = j-1;
      }
    }
    if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
    {
      if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0))
      {
        char s[32];
        unsigned int k;
        for(k=0; (k<31 ) && (k<end-j+1 ); k++) {
          s[k] = static_cast<char>(tolower(styler[j+k]));
        }
        s[k] = '\0';

        if(keywords.InList(s)) {
          strcpy(prevWord, s);
          break;
        }
      }
    }
  }
  for(j=j+static_cast<unsigned int>(strlen(prevWord)); j<endPos; j++)
  {
    char ch       = styler.SafeGetCharAt(j);
    int style     = styler.StyleAt(j);
    if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
    {
      if((ch == ';') && (strcmp(prevWord, "end") == 0))
      {
        strcpy(prevWord, ";");
      }
    }
  }

  char  chNext          = styler[startPos];
  char  chPrev          = '\0';
  char  chNextNonBlank;
  int   styleNext       = styler.StyleAt(startPos);
  //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent);

  /***************************************/
  for (unsigned int i = startPos; i < endPos; i++)
  {
    char ch         = chNext;
    chNext          = styler.SafeGetCharAt(i + 1);
    chPrev          = styler.SafeGetCharAt(i - 1);
    chNextNonBlank  = chNext;
    unsigned int j  = i+1;
    while(IsABlank(chNextNonBlank) && j<endPos)
    {
      j ++ ;
      chNextNonBlank = styler.SafeGetCharAt(j);
    }
    int style           = styleNext;
    styleNext       = styler.StyleAt(i + 1);
    bool atEOL      = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
    {
      if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler))
      {
        levelNext++;
      }
      else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler))
      {
        levelNext--;
      }
    }

    if ((style == SCE_VHDL_OPERATOR) && foldAtParenthese)
    {
      if(ch == '(') {
        levelNext++;
      } else if (ch == ')') {
        levelNext--;
      }
    }

    if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING))
    {
      if((ch == ';') && (strcmp(prevWord, "end") == 0))
      {
        strcpy(prevWord, ";");
      }

      if(!IsAWordChar(chPrev) && IsAWordStart(ch))
      {
        lastStart = i;
      }

      if(iswordchar(ch) && !iswordchar(chNext)) {
        char s[32];
        unsigned int k;
        for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) {
          s[k] = static_cast<char>(tolower(styler[lastStart+k]));
        }
        s[k] = '\0';

        if(keywords.InList(s))
        {
          if (
            strcmp(s, "architecture") == 0  ||
            strcmp(s, "case") == 0          ||
            strcmp(s, "component") == 0     ||
            strcmp(s, "entity") == 0        ||
            strcmp(s, "generate") == 0      ||
            strcmp(s, "loop") == 0          ||
            strcmp(s, "package") ==0        ||
            strcmp(s, "process") == 0       ||
            strcmp(s, "record") == 0        ||
            strcmp(s, "then") == 0)
          {
            if (strcmp(prevWord, "end") != 0)
            {
              if (levelMinCurrentElse > levelNext) {
                levelMinCurrentElse = levelNext;
              }
              levelNext++;
            }
          } else if (
            strcmp(s, "procedure") == 0     ||
            strcmp(s, "function") == 0)
          {
            if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc.
            { // This code checks to see if the procedure / function is a definition within a "package"
              // rather than the actual code in the body.
              int BracketLevel = 0;
              for(int j=i+1; j<styler.Length(); j++)
              {
                int LocalStyle = styler.StyleAt(j);
                char LocalCh = styler.SafeGetCharAt(j);
                if(LocalCh == '(') BracketLevel++;
                if(LocalCh == ')') BracketLevel--;
                if(
                  (BracketLevel == 0) &&
                  (LocalStyle != SCE_VHDL_COMMENT) &&
                  (LocalStyle != SCE_VHDL_STRING) &&
                  !iswordchar(styler.SafeGetCharAt(j-1)) &&
                  styler.Match(j, "is") &&
                  !iswordchar(styler.SafeGetCharAt(j+2)))
                {
                  if (levelMinCurrentElse > levelNext) {
                    levelMinCurrentElse = levelNext;
                  }
                  levelNext++;
                  break;
                }
                if((BracketLevel == 0) && (LocalCh == ';'))
                {
                  break;
                }
              }
            }

          } else if (strcmp(s, "end") == 0) {
            levelNext--;
          }  else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly
            levelNext--;
          } else if (strcmp(s, "else") == 0) {
            if(strcmp(prevWord, "when") != 0)  // ignore a <= x when y else z;
            {
              levelMinCurrentElse = levelNext - 1;  // VHDL else is all on its own so just dec. the min level
            }
          } else if(
            ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) ||
            ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) ||
            ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0)))
          {
            levelMinCurrentBegin = levelNext - 1;
          }
          //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent);
          strcpy(prevWord, s);
        }
      }
    }
    if (atEOL) {
      int levelUse = levelCurrent;

      if (foldAtElse && (levelMinCurrentElse < levelUse)) {
        levelUse = levelMinCurrentElse;
      }
      if (foldAtBegin && (levelMinCurrentBegin < levelUse)) {
        levelUse = levelMinCurrentBegin;
      }
      int lev = levelUse | levelNext << 16;
      if (visibleChars == 0 && foldCompact)
        lev |= SC_FOLDLEVELWHITEFLAG;

      if (levelUse < levelNext)
        lev |= SC_FOLDLEVELHEADERFLAG;
      if (lev != styler.LevelAt(lineCurrent)) {
        styler.SetLevel(lineCurrent, lev);
      }
      //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
      lineCurrent++;
      levelCurrent = levelNext;
      //levelMinCurrent = levelCurrent;
      levelMinCurrentElse = levelCurrent;
      levelMinCurrentBegin = levelCurrent;
      visibleChars = 0;
    }
    /***************************************/
    if (!isspacechar(ch)) visibleChars++;
  }

  /***************************************/
//  Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent);
}

//=============================================================================
static void FoldVHDLDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
  FoldNoBoxVHDLDoc(startPos, length, initStyle, styler);
}

//=============================================================================
static const char * const VHDLWordLists[] = {
            "Keywords",
            "Operators",
            "Attributes",
            "Standard Functions",
            "Standard Packages",
            "Standard Types",
            "User Words",
            0,
        };


LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLists);


// Keyword:
//    access after alias all architecture array assert attribute begin block body buffer bus case component
//    configuration constant disconnect downto else elsif end entity exit file for function generate generic
//    group guarded if impure in inertial inout is label library linkage literal loop map new next null of
//    on open others out package port postponed procedure process pure range record register reject report
//    return select severity shared signal subtype then to transport type unaffected units until use variable
//    wait when while with
//
// Operators:
//    abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor
//
// Attributes:
//    left right low high ascending image value pos val succ pred leftof rightof base range reverse_range
//    length delayed stable quiet transaction event active last_event last_active last_value driving
//    driving_value simple_name path_name instance_name
//
// Std Functions:
//    now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector
//    to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left
//    rotate_right resize to_integer to_unsigned to_signed std_match to_01
//
// Std Packages:
//    std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed
//    std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives
//    vital_timing
//
// Std Types:
//    boolean bit character severity_level integer real time delay_length natural positive string bit_vector
//    file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic
//    std_logic_vector X01 X01Z UX01 UX01Z unsigned signed
//

Added lexers/LexVerilog.cxx.



















































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
// Scintilla source code edit control
/** @file LexVerilog.cxx
 ** Lexer for Verilog.
 ** Written by Avi Yegudin, based on C++ lexer by Neil Hodgson
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$');
}

static inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
}

static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];

	// Do not leak onto next line
	if (initStyle == SCE_V_STRINGEOL)
		initStyle = SCE_V_DEFAULT;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
			// Prevent SCE_V_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_V_STRING);
		}

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_V_OPERATOR) {
			sc.SetState(SCE_V_DEFAULT);
		} else if (sc.state == SCE_V_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
                                sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_V_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_V_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_V_WORD3);
                                } else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_V_USER);
				}
				sc.SetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_PREPROCESSOR) {
                        if (!IsAWordChar(sc.ch)) {
                                sc.SetState(SCE_V_DEFAULT);
                        }
		} else if (sc.state == SCE_V_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		} else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
			if (sc.atLineStart) {
				sc.SetState(SCE_V_DEFAULT);
			}
                } else if (sc.state == SCE_V_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_V_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_V_STRINGEOL);
				sc.ForwardSetState(SCE_V_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_V_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_V_NUMBER);
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_V_IDENTIFIER);
			} else if (sc.Match('/', '*')) {
                                sc.SetState(SCE_V_COMMENT);
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("//!"))	// Nice to have a different comment style
					sc.SetState(SCE_V_COMMENTLINEBANG);
				else
					sc.SetState(SCE_V_COMMENTLINE);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_V_STRING);
			} else if (sc.ch == '`') {
				sc.SetState(SCE_V_PREPROCESSOR);
				// Skip whitespace between ` and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_V_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
				sc.SetState(SCE_V_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static bool IsStreamCommentStyle(int style) {
	return style == SCE_V_COMMENT;
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	int eolPos = styler.LineStart(line + 1) - 1;
	for (int i = pos; i < eolPos; i++) {
		char ch = styler[i];
		char chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		if (ch == '/' && chNext == '/' &&
		   (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) {
			return true;
		} else if (!IsASpaceOrTab(ch)) {
			return false;
		}
	}
	return false;
}
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
        // Verilog specific folding options:
        // fold_at_module -
        //      Generally used methodology in verilog code is
        //      one module per file, so folding at module definition is useless.
        // fold_at_brace/parenthese -
        //      Folding of long port lists can be convenient.
	bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
	bool foldAtBrace  = 1;
	bool foldAtParenthese  = 1;

	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelCurrent = SC_FOLDLEVELBASE;
	if (lineCurrent > 0)
		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
	int levelMinCurrent = levelCurrent;
	int levelNext = levelCurrent;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment && IsStreamCommentStyle(style)) {
			if (!IsStreamCommentStyle(stylePrev)) {
				levelNext++;
			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelNext--;
			}
		}
		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
		{
			if (!IsCommentLine(lineCurrent - 1, styler)
			    && IsCommentLine(lineCurrent + 1, styler))
				levelNext++;
			else if (IsCommentLine(lineCurrent - 1, styler)
			         && !IsCommentLine(lineCurrent+1, styler))
				levelNext--;
		}
		if (foldComment && (style == SCE_V_COMMENTLINE)) {
			if ((ch == '/') && (chNext == '/')) {
				char chNext2 = styler.SafeGetCharAt(i + 2);
				if (chNext2 == '{') {
					levelNext++;
				} else if (chNext2 == '}') {
					levelNext--;
				}
			}
		}
		if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
			if (ch == '`') {
				unsigned int j = i + 1;
				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
					j++;
				}
				if (styler.Match(j, "if")) {
					levelNext++;
				} else if (styler.Match(j, "end")) {
					levelNext--;
				}
			}
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtParenthese) {
			if (ch == '(') {
				levelNext++;
			} else if (ch == ')') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_OPERATOR) {
                    if (foldAtBrace) {
			if (ch == '{') {
				levelNext++;
			} else if (ch == '}') {
				levelNext--;
			}
                    }
		}
                if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
                        unsigned int j = i;
                        if (styler.Match(j, "case") ||
                            styler.Match(j, "casex") ||
                            styler.Match(j, "casez") ||
                            styler.Match(j, "class") ||
                            styler.Match(j, "function") ||
                            styler.Match(j, "generate") ||
                            styler.Match(j, "covergroup") ||
                            styler.Match(j, "package") ||
                            styler.Match(j, "primitive") ||
                            styler.Match(j, "program") ||
                            styler.Match(j, "sequence") ||
                            styler.Match(j, "specify") ||
                            styler.Match(j, "table") ||
                            styler.Match(j, "task") ||
                            styler.Match(j, "fork") ||
                            (styler.Match(j, "module") && foldAtModule) ||
                            styler.Match(j, "begin")) {
                                levelNext++;
                        } else if (styler.Match(j, "endcase") ||
                                   styler.Match(j, "endclass") ||
                                   styler.Match(j, "endfunction") ||
                                   styler.Match(j, "endgenerate") ||
                                   styler.Match(j, "endgroup") ||
                                   styler.Match(j, "endpackage") ||
                                   styler.Match(j, "endprimitive") ||
                                   styler.Match(j, "endprogram") ||
                                   styler.Match(j, "endsequence") ||
                                   styler.Match(j, "endspecify") ||
                                   styler.Match(j, "endtable") ||
                                   styler.Match(j, "endtask") ||
                                   styler.Match(j, "join") ||
                                   styler.Match(j, "join_any") ||
                                   styler.Match(j, "join_none") ||
                                   (styler.Match(j, "endmodule") && foldAtModule) ||
                                   (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
                                levelNext--;
                        }
		}
		if (atEOL) {
			int levelUse = levelCurrent;
			if (foldAtElse) {
				levelUse = levelMinCurrent;
			}
			int lev = levelUse | levelNext << 16;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if (levelUse < levelNext)
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelCurrent = levelNext;
			levelMinCurrent = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
}

static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
}

static const char * const verilogWordLists[] = {
            "Primary keywords and identifiers",
            "Secondary keywords and identifiers",
            "System Tasks",
            "User defined tasks and identifiers",
            "Unused",
            0,
        };


LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);

Added lexers/LexVisualProlog.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
// Scintilla source code edit control
/** @file LexVisualProlog.cxx
** Lexer for Visual Prolog.
**/
// Author Thomas Linder Puls, Prolog Development Denter A/S, http://www.visual-prolog.com
// Based on Lexer for C++, C, Java, and JavaScript.
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif

#include <string>
#include <vector>
#include <map>
#include <algorithm>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Options used for LexerVisualProlog
struct OptionsVisualProlog {
    OptionsVisualProlog() {
    }
};

static const char *const visualPrologWordLists[] = {
    "Major keywords (class, predicates, ...)",
    "Minor keywords (if, then, try, ...)",
    "Directive keywords without the '#' (include, requires, ...)",
    "Documentation keywords without the '@' (short, detail, ...)",
    0,
};

struct OptionSetVisualProlog : public OptionSet<OptionsVisualProlog> {
    OptionSetVisualProlog() {
        DefineWordListSets(visualPrologWordLists);
    }
};

class LexerVisualProlog : public ILexer {
    WordList majorKeywords;
    WordList minorKeywords;
    WordList directiveKeywords;
    WordList docKeywords;
    OptionsVisualProlog options;
    OptionSetVisualProlog osVisualProlog;
public:
    LexerVisualProlog() {
    }
    virtual ~LexerVisualProlog() {
    }
    void SCI_METHOD Release() {
        delete this;
    }
    int SCI_METHOD Version() const {
        return lvOriginal;
    }
    const char * SCI_METHOD PropertyNames() {
        return osVisualProlog.PropertyNames();
    }
    int SCI_METHOD PropertyType(const char *name) {
        return osVisualProlog.PropertyType(name);
    }
    const char * SCI_METHOD DescribeProperty(const char *name) {
        return osVisualProlog.DescribeProperty(name);
    }
    int SCI_METHOD PropertySet(const char *key, const char *val);
    const char * SCI_METHOD DescribeWordListSets() {
        return osVisualProlog.DescribeWordListSets();
    }
    int SCI_METHOD WordListSet(int n, const char *wl);
    void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
    void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);

    void * SCI_METHOD PrivateCall(int, void *) {
        return 0;
    }

    static ILexer *LexerFactoryVisualProlog() {
        return new LexerVisualProlog();
    }
};

int SCI_METHOD LexerVisualProlog::PropertySet(const char *key, const char *val) {
    if (osVisualProlog.PropertySet(&options, key, val)) {
        return 0;
    }
    return -1;
}

int SCI_METHOD LexerVisualProlog::WordListSet(int n, const char *wl) {
    WordList *wordListN = 0;
    switch (n) {
    case 0:
        wordListN = &majorKeywords;
        break;
    case 1:
        wordListN = &minorKeywords;
        break;
    case 2:
        wordListN = &directiveKeywords;
        break;
    case 3:
        wordListN = &docKeywords;
        break;
    }
    int firstModification = -1;
    if (wordListN) {
        WordList wlNew;
        wlNew.Set(wl);
        if (*wordListN != wlNew) {
            wordListN->Set(wl);
            firstModification = 0;
        }
    }
    return firstModification;
}

// Functor used to truncate history
struct After {
    int line;
    After(int line_) : line(line_) {}
};

// Look ahead to see which colour "end" should have (takes colour after the following keyword)
static void endLookAhead(char s[], LexAccessor &styler, int start, CharacterSet &setIdentifier) {
    char ch = styler.SafeGetCharAt(start, '\n');
    while (' ' == ch) {
        start++;
        ch = styler.SafeGetCharAt(start, '\n');
    }
    int i = 0;
    while (i < 100 && setIdentifier.Contains(ch)){
        s[i] = ch;
        i++;
        ch = styler.SafeGetCharAt(start + i, '\n');
    }
    s[i] = '\0';
}

static void forwardEscapeLiteral(StyleContext &sc, int OwnChar, int EscapeState) {
    sc.Forward();
    if (sc.ch == OwnChar || sc.ch == '\\' || sc.ch == 'n' || sc.ch == 'l' || sc.ch == 'r' || sc.ch == 't') {
        sc.ChangeState(EscapeState);
    } else if (sc.ch == 'u') {
        if (IsADigit(sc.chNext, 16)) {
            sc.Forward();
            if (IsADigit(sc.chNext, 16)) {
                sc.Forward();
                if (IsADigit(sc.chNext, 16)) {
                    sc.Forward();
                    if (IsADigit(sc.chNext, 16)) {
                        sc.Forward();
                        sc.ChangeState(EscapeState);
                    }
                }
            }
        }
    }
}

void SCI_METHOD LexerVisualProlog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
    LexAccessor styler(pAccess);

    CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");

    CharacterSet setLowerStart(CharacterSet::setLower);
    CharacterSet setVariableStart(CharacterSet::setUpper);
    CharacterSet setIdentifier(CharacterSet::setAlphaNum, "_", 0x80, true);

    int styleBeforeDocKeyword = SCE_VISUALPROLOG_DEFAULT;

    int currentLine = styler.GetLine(startPos);

    int nestLevel = 0;
    if (currentLine >= 1)
    {
        nestLevel = styler.GetLineState(currentLine - 1);
    }

    StyleContext sc(startPos, length, initStyle, styler, 0x7f);

    // Truncate ppDefineHistory before current line

    for (; sc.More(); sc.Forward()) {

        if (sc.atLineEnd) {
            // Update the line state, so it can be seen by next line
            styler.SetLineState(currentLine, nestLevel);
            currentLine++;
        }

        if (sc.atLineStart) {
            if ((sc.state == SCE_VISUALPROLOG_STRING) || (sc.state == SCE_VISUALPROLOG_CHARACTER)) {
                // Prevent SCE_VISUALPROLOG_STRING_EOL from leaking back to previous line which
                // ends with a line continuation by locking in the state upto this position.
                sc.SetState(sc.state);
            }
        }

        const bool atLineEndBeforeSwitch = sc.atLineEnd;

        // Determine if the current state should terminate.
        switch (sc.state) {
        case SCE_VISUALPROLOG_OPERATOR:
            sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            break;
        case SCE_VISUALPROLOG_NUMBER:
            // We accept almost anything because of hex. and number suffixes
            if (!(setIdentifier.Contains(sc.ch) || (sc.ch == '.') || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_IDENTIFIER:
            if (!setIdentifier.Contains(sc.ch)) {
                char s[1000];
                sc.GetCurrent(s, sizeof(s));
                if (0 == strcmp(s, "end")) {
                    endLookAhead(s, styler, sc.currentPos, setIdentifier);
                }
                if (majorKeywords.InList(s)) {
                    sc.ChangeState(SCE_VISUALPROLOG_KEY_MAJOR);
                } else if (minorKeywords.InList(s)) {
                    sc.ChangeState(SCE_VISUALPROLOG_KEY_MINOR);
                }
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_VARIABLE:
        case SCE_VISUALPROLOG_ANONYMOUS:
            if (!setIdentifier.Contains(sc.ch)) {
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_KEY_DIRECTIVE:
            if (!setLowerStart.Contains(sc.ch)) {
                char s[1000];
                sc.GetCurrent(s, sizeof(s));
                if (!directiveKeywords.InList(s+1)) {
                    sc.ChangeState(SCE_VISUALPROLOG_IDENTIFIER);
                }
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_COMMENT_BLOCK:
            if (sc.Match('*', '/')) {
                sc.Forward();
                nestLevel--;
                int nextState = (nestLevel == 0) ? SCE_VISUALPROLOG_DEFAULT : SCE_VISUALPROLOG_COMMENT_BLOCK;
                sc.ForwardSetState(nextState);
            } else if (sc.Match('/', '*')) {
                sc.Forward();
                nestLevel++;
            } else if (sc.ch == '%') {
                sc.SetState(SCE_VISUALPROLOG_COMMENT_LINE);
            } else if (sc.ch == '@') {
                styleBeforeDocKeyword = sc.state;
                sc.SetState(SCE_VISUALPROLOG_COMMENT_KEY_ERROR);
            }
            break;
        case SCE_VISUALPROLOG_COMMENT_LINE:
            if (sc.atLineEnd) {
                int nextState = (nestLevel == 0) ? SCE_VISUALPROLOG_DEFAULT : SCE_VISUALPROLOG_COMMENT_BLOCK;
                sc.SetState(nextState);
            } else if (sc.ch == '@') {
                styleBeforeDocKeyword = sc.state;
                sc.SetState(SCE_VISUALPROLOG_COMMENT_KEY_ERROR);
            }
            break;
        case SCE_VISUALPROLOG_COMMENT_KEY_ERROR:
            if (!setDoxygen.Contains(sc.ch)) {
                char s[1000];
                sc.GetCurrent(s, sizeof(s));
                if (docKeywords.InList(s+1)) {
                    sc.ChangeState(SCE_VISUALPROLOG_COMMENT_KEY);
                }
                sc.SetState(styleBeforeDocKeyword);
            }
            if (SCE_VISUALPROLOG_COMMENT_LINE == styleBeforeDocKeyword && sc.atLineStart) {
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            } else if (SCE_VISUALPROLOG_COMMENT_BLOCK == styleBeforeDocKeyword && sc.atLineStart) {
                sc.SetState(SCE_VISUALPROLOG_COMMENT_BLOCK);
            }
            break;
        case SCE_VISUALPROLOG_STRING_ESCAPE:
        case SCE_VISUALPROLOG_STRING_ESCAPE_ERROR:
            // return to SCE_VISUALPROLOG_STRING and treat as such (fall-through)
            sc.SetState(SCE_VISUALPROLOG_STRING);
        case SCE_VISUALPROLOG_STRING:
            if (sc.atLineEnd) {
                sc.SetState(SCE_VISUALPROLOG_STRING_EOL_OPEN);
            } else if (sc.ch == '"') {
                sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT);
            } else if (sc.ch == '\\') {
                sc.SetState(SCE_VISUALPROLOG_STRING_ESCAPE_ERROR);
                forwardEscapeLiteral(sc, '"', SCE_VISUALPROLOG_STRING_ESCAPE);
            }
            break;
        case SCE_VISUALPROLOG_CHARACTER_TOO_MANY:
            if (sc.atLineStart) {
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            } else if (sc.ch == '\'') {
                sc.SetState(SCE_VISUALPROLOG_CHARACTER);
                sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_CHARACTER:
            if (sc.atLineEnd) {
                sc.SetState(SCE_VISUALPROLOG_STRING_EOL_OPEN);  // reuse STRING_EOL_OPEN for this
            } else if (sc.ch == '\'') {
                sc.SetState(SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR);
                sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT);
            } else {
                if (sc.ch == '\\') {
                    sc.SetState(SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR);
                    forwardEscapeLiteral(sc, '\'', SCE_VISUALPROLOG_CHARACTER);
                } 
                sc.ForwardSetState(SCE_VISUALPROLOG_CHARACTER);
                if (sc.ch == '\'') {
                    sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT);
                } else {
                    sc.SetState(SCE_VISUALPROLOG_CHARACTER_TOO_MANY);
                }
            }
            break;
        case SCE_VISUALPROLOG_STRING_EOL_OPEN:
            if (sc.atLineStart) {
                sc.SetState(SCE_VISUALPROLOG_DEFAULT);
            }
            break;
        case SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL:
        case SCE_VISUALPROLOG_STRING_VERBATIM_EOL:
            // return to SCE_VISUALPROLOG_STRING_VERBATIM and treat as such (fall-through)
            sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM);
        case SCE_VISUALPROLOG_STRING_VERBATIM:
            if (sc.atLineEnd) {
                sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM_EOL);
            } else if (sc.ch == '\"') {
                if (sc.chNext == '\"') {
                    sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL);
                    sc.Forward();
                } else {
                    sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT);
                }
            }
            break;
        }

        if (sc.atLineEnd && !atLineEndBeforeSwitch) {
            // State exit processing consumed characters up to end of line.
            currentLine++;
        }

        // Determine if a new state should be entered.
        if (sc.state == SCE_VISUALPROLOG_DEFAULT) {
            if (sc.Match('@', '\"')) {
                sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM);
                sc.Forward();
            } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
                sc.SetState(SCE_VISUALPROLOG_NUMBER);
            } else if (setLowerStart.Contains(sc.ch)) {
                sc.SetState(SCE_VISUALPROLOG_IDENTIFIER);
            } else if (setVariableStart.Contains(sc.ch)) {
                sc.SetState(SCE_VISUALPROLOG_VARIABLE);
            } else if (sc.ch == '_') {
                sc.SetState(SCE_VISUALPROLOG_ANONYMOUS);
            } else if (sc.Match('/', '*')) {
                sc.SetState(SCE_VISUALPROLOG_COMMENT_BLOCK);
                nestLevel = 1;
                sc.Forward();	// Eat the * so it isn't used for the end of the comment
            } else if (sc.ch == '%') {
                sc.SetState(SCE_VISUALPROLOG_COMMENT_LINE);
            } else if (sc.ch == '\"') {
                sc.SetState(SCE_VISUALPROLOG_STRING);
            } else if (sc.ch == '\'') {
                sc.SetState(SCE_VISUALPROLOG_CHARACTER);
            } else if (sc.ch == '#') {
                sc.SetState(SCE_VISUALPROLOG_KEY_DIRECTIVE);
            } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '\\') {
                sc.SetState(SCE_VISUALPROLOG_OPERATOR);
            }
        }

    }
    sc.Complete();
    styler.Flush();
}

// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".

void SCI_METHOD LexerVisualProlog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {

    LexAccessor styler(pAccess);

    unsigned int endPos = startPos + length;
    int visibleChars = 0;
    int currentLine = styler.GetLine(startPos);
    int levelCurrent = SC_FOLDLEVELBASE;
    if (currentLine > 0)
        levelCurrent = styler.LevelAt(currentLine-1) >> 16;
    int levelMinCurrent = levelCurrent;
    int levelNext = levelCurrent;
    char chNext = styler[startPos];
    int styleNext = styler.StyleAt(startPos);
    int style = initStyle;
    for (unsigned int i = startPos; i < endPos; i++) {
        char ch = chNext;
        chNext = styler.SafeGetCharAt(i + 1);
        style = styleNext;
        styleNext = styler.StyleAt(i + 1);
        bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
        if (style == SCE_VISUALPROLOG_OPERATOR) {
            if (ch == '{') {
                // Measure the minimum before a '{' to allow
                // folding on "} else {"
                if (levelMinCurrent > levelNext) {
                    levelMinCurrent = levelNext;
                }
                levelNext++;
            } else if (ch == '}') {
                levelNext--;
            }
        }
        if (!IsASpace(ch))
            visibleChars++;
        if (atEOL || (i == endPos-1)) {
            int levelUse = levelCurrent;
            int lev = levelUse | levelNext << 16;
            if (levelUse < levelNext)
                lev |= SC_FOLDLEVELHEADERFLAG;
            if (lev != styler.LevelAt(currentLine)) {
                styler.SetLevel(currentLine, lev);
            }
            currentLine++;
            levelCurrent = levelNext;
            levelMinCurrent = levelCurrent;
            if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
                // There is an empty line at end of file so give it same level and empty
                styler.SetLevel(currentLine, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
            }
            visibleChars = 0;
        }
    }
}

LexerModule lmVisualProlog(SCLEX_VISUALPROLOG, LexerVisualProlog::LexerFactoryVisualProlog, "visualprolog", visualPrologWordLists);

Added lexers/LexYAML.cxx.



























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// Scintilla source code edit control
/** @file LexYAML.cxx
 ** Lexer for YAML.
 **/
// Copyright 2003- by Sean O'Dell <sean@celsoft.com>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static const char * const yamlWordListDesc[] = {
	"Keywords",
	0
};

static inline bool AtEOL(Accessor &styler, unsigned int i) {
	return (styler[i] == '\n') ||
		((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}

static unsigned int SpaceCount(char* lineBuffer) {
	if (lineBuffer == NULL)
		return 0;

	char* headBuffer = lineBuffer;

	while (*headBuffer == ' ')
		headBuffer++;

	return headBuffer - lineBuffer;
}

#define YAML_STATE_BITSIZE 16
#define YAML_STATE_MASK			(0xFFFF0000)
#define YAML_STATE_DOCUMENT		(1 << YAML_STATE_BITSIZE)
#define YAML_STATE_VALUE			(2 << YAML_STATE_BITSIZE)
#define YAML_STATE_COMMENT		(3 << YAML_STATE_BITSIZE)
#define YAML_STATE_TEXT_PARENT	(4 << YAML_STATE_BITSIZE)
#define YAML_STATE_TEXT			(5 << YAML_STATE_BITSIZE)

static void ColouriseYAMLLine(
	char *lineBuffer,
	unsigned int currentLine,
	unsigned int lengthLine,
	unsigned int startLine,
	unsigned int endPos,
	WordList &keywords,
	Accessor &styler) {

	unsigned int i = 0;
	bool bInQuotes = false;
	unsigned int indentAmount = SpaceCount(lineBuffer);

	if (currentLine > 0) {
		int parentLineState = styler.GetLineState(currentLine - 1);

		if ((parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT || (parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT_PARENT) {
			unsigned int parentIndentAmount = parentLineState&(~YAML_STATE_MASK);
			if (indentAmount > parentIndentAmount) {
				styler.SetLineState(currentLine, YAML_STATE_TEXT | parentIndentAmount);
				styler.ColourTo(endPos, SCE_YAML_TEXT);
				return;
			}
		}
	}
	styler.SetLineState(currentLine, 0);
	if (strncmp(lineBuffer, "---", 3) == 0) {	// Document marker
		styler.SetLineState(currentLine, YAML_STATE_DOCUMENT);
		styler.ColourTo(endPos, SCE_YAML_DOCUMENT);
		return;
	}
	// Skip initial spaces
	while ((i < lengthLine) && lineBuffer[i] == ' ') { // YAML always uses space, never TABS or anything else
		i++;
	}
	if (lineBuffer[i] == '\t') { // if we skipped all spaces, and we are NOT inside a text block, this is wrong
		styler.ColourTo(endPos, SCE_YAML_ERROR);
		return;
	}
	if (lineBuffer[i] == '#') {	// Comment
		styler.SetLineState(currentLine, YAML_STATE_COMMENT);
		styler.ColourTo(endPos, SCE_YAML_COMMENT);
		return;
	}
	while (i < lengthLine) {
		if (lineBuffer[i] == '\'' || lineBuffer[i] == '\"') {
			bInQuotes = !bInQuotes;
		} else if (lineBuffer[i] == ':' && !bInQuotes) {
			styler.ColourTo(startLine + i - 1, SCE_YAML_IDENTIFIER);
			styler.ColourTo(startLine + i, SCE_YAML_OPERATOR);
			// Non-folding scalar
			i++;
			while ((i < lengthLine) && isspacechar(lineBuffer[i]))
				i++;
			unsigned int endValue = lengthLine - 1;
			while ((endValue >= i) && isspacechar(lineBuffer[endValue]))
				endValue--;
			lineBuffer[endValue + 1] = '\0';
			if (lineBuffer[i] == '|' || lineBuffer[i] == '>') {
				i++;
				if (lineBuffer[i] == '+' || lineBuffer[i] == '-')
					i++;
				while ((i < lengthLine) && isspacechar(lineBuffer[i]))
					i++;
				if (lineBuffer[i] == '\0') {
					styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
					styler.ColourTo(endPos, SCE_YAML_DEFAULT);
					return;
				} else if (lineBuffer[i] == '#') {
					styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
					styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
					styler.ColourTo(endPos, SCE_YAML_COMMENT);
					return;
				} else {
					styler.ColourTo(endPos, SCE_YAML_ERROR);
					return;
				}
			} else if (lineBuffer[i] == '#') {
				styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
				styler.ColourTo(endPos, SCE_YAML_COMMENT);
				return;
			}
			styler.SetLineState(currentLine, YAML_STATE_VALUE);
			if (lineBuffer[i] == '&' || lineBuffer[i] == '*') {
				styler.ColourTo(endPos, SCE_YAML_REFERENCE);
				return;
			}
			if (keywords.InList(&lineBuffer[i])) { // Convertible value (true/false, etc.)
				styler.ColourTo(endPos, SCE_YAML_KEYWORD);
				return;
			} else {
				unsigned int i2 = i;
				while ((i < lengthLine) && lineBuffer[i]) {
					if (!(isascii(lineBuffer[i]) && isdigit(lineBuffer[i])) && lineBuffer[i] != '-' && lineBuffer[i] != '.' && lineBuffer[i] != ',') {
						styler.ColourTo(endPos, SCE_YAML_DEFAULT);
						return;
					}
					i++;
				}
				if (i > i2) {
					styler.ColourTo(endPos, SCE_YAML_NUMBER);
					return;
				}
			}
			break; // shouldn't get here, but just in case, the rest of the line is coloured the default
		}
		i++;
	}
	styler.ColourTo(endPos, SCE_YAML_DEFAULT);
}

static void ColouriseYAMLDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
	char lineBuffer[1024] = "";
	styler.StartAt(startPos);
	styler.StartSegment(startPos);
	unsigned int linePos = 0;
	unsigned int startLine = startPos;
	unsigned int endPos = startPos + length;
	unsigned int maxPos = styler.Length();
	unsigned int lineCurrent = styler.GetLine(startPos);

	for (unsigned int i = startPos; i < maxPos && i < endPos; i++) {
		lineBuffer[linePos++] = styler[i];
		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
			// End of line (or of line buffer) met, colourise it
			lineBuffer[linePos] = '\0';
			ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, i, *keywordLists[0], styler);
			linePos = 0;
			startLine = i + 1;
			lineCurrent++;
		}
	}
	if (linePos > 0) {	// Last line does not have ending characters
		ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, startPos + length - 1, *keywordLists[0], styler);
	}
}

static bool IsCommentLine(int line, Accessor &styler) {
	int pos = styler.LineStart(line);
	if (styler[pos] == '#')
		return true;
	return false;
}

static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unused*/,
                      WordList *[], Accessor &styler) {
	const int maxPos = startPos + length;
	const int maxLines = styler.GetLine(maxPos - 1);             // Requested last line
	const int docLines = styler.GetLine(styler.Length() - 1);  // Available last line
	const bool foldComment = styler.GetPropertyInt("fold.comment.yaml") != 0;

	// Backtrack to previous non-blank line so we can determine indent level
	// for any white space lines
	// and so we can fix any preceding fold level (which is why we go back
	// at least one line in all cases)
	int spaceFlags = 0;
	int lineCurrent = styler.GetLine(startPos);
	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
	while (lineCurrent > 0) {
		lineCurrent--;
		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
		        (!IsCommentLine(lineCurrent, styler)))
			break;
	}
	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;

	// Set up initial loop state
	int prevComment = 0;
	if (lineCurrent >= 1)
		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);

	// Process all characters to end of requested range
	// or comment that hangs over the end of the range.  Cap processing in all cases
	// to end of document (in case of unclosed comment at end).
	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) {

		// Gather info
		int lev = indentCurrent;
		int lineNext = lineCurrent + 1;
		int indentNext = indentCurrent;
		if (lineNext <= docLines) {
			// Information about next line is only available if not at end of document
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
	}
		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
		                           IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
		const int comment_continue = (comment && prevComment);
		if (!comment)
			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
		if (indentNext & SC_FOLDLEVELWHITEFLAG)
			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;

		if (comment_start) {
			// Place fold point at start of a block of comments
			lev |= SC_FOLDLEVELHEADERFLAG;
		} else if (comment_continue) {
			// Add level to rest of lines in the block
			lev = lev + 1;
		}

		// Skip past any blank lines for next indent level info; we skip also
		// comments (all comments, not just those starting in column 0)
		// which effectively folds them into surrounding code rather
		// than screwing up folding.

		while ((lineNext < docLines) &&
		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {

			lineNext++;
			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
		}

		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
		const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments);

		// Now set all the indent levels on the lines we skipped
		// Do this from end to start.  Once we encounter one line
		// which is indented more than the line after the end of
		// the comment-block, use the level of the block before

		int skipLine = lineNext;
		int skipLevel = levelAfterComments;

		while (--skipLine > lineCurrent) {
			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);

			if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
				skipLevel = levelBeforeComments;

			int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;

			styler.SetLevel(skipLine, skipLevel | whiteFlag);
		}

		// Set fold header on non-comment line
		if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
				lev |= SC_FOLDLEVELHEADERFLAG;
		}

		// Keep track of block comment state of previous line
		prevComment = comment_start || comment_continue;

		// Set fold level for this line and move to next line
		styler.SetLevel(lineCurrent, lev);
		indentCurrent = indentNext;
		lineCurrent = lineNext;
	}

	// NOTE: Cannot set level of last line here because indentCurrent doesn't have
	// header flag set; the loop above is crafted to take care of this case!
	//styler.SetLevel(lineCurrent, indentCurrent);
}

LexerModule lmYAML(SCLEX_YAML, ColouriseYAMLDoc, "yaml", FoldYAMLDoc, yamlWordListDesc);

Added lexlib/Accessor.cxx.































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

Accessor::Accessor(IDocument *pAccess_, PropSetSimple *pprops_) : LexAccessor(pAccess_), pprops(pprops_) {
}

int Accessor::GetPropertyInt(const char *key, int defaultValue) {
	return pprops->GetInt(key, defaultValue);
}

int Accessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
	int end = Length();
	int spaceFlags = 0;

	// Determines the indentation level of the current line and also checks for consistent
	// indentation compared to the previous line.
	// Indentation is judged consistent when the indentation whitespace of each line lines
	// the same or the indentation of one line is a prefix of the other.

	int pos = LineStart(line);
	char ch = (*this)[pos];
	int indent = 0;
	bool inPrevPrefix = line > 0;
	int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
	while ((ch == ' ' || ch == '\t') && (pos < end)) {
		if (inPrevPrefix) {
			char chPrev = (*this)[posPrev++];
			if (chPrev == ' ' || chPrev == '\t') {
				if (chPrev != ch)
					spaceFlags |= wsInconsistent;
			} else {
				inPrevPrefix = false;
			}
		}
		if (ch == ' ') {
			spaceFlags |= wsSpace;
			indent++;
		} else {	// Tab
			spaceFlags |= wsTab;
			if (spaceFlags & wsSpace)
				spaceFlags |= wsSpaceTab;
			indent = (indent / 8 + 1) * 8;
		}
		ch = (*this)[++pos];
	}

	*flags = spaceFlags;
	indent += SC_FOLDLEVELBASE;
	// if completely empty line or the start of a comment...
	if ((LineStart(line) == Length()) || (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ||
			(pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)))
		return indent | SC_FOLDLEVELWHITEFLAG;
	else
		return indent;
}

Added lexlib/Accessor.h.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Accessor.h
 ** Interfaces between Scintilla and lexers.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef ACCESSOR_H
#define ACCESSOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};

class Accessor;
class WordList;
class PropSetSimple;

typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len);

class Accessor : public LexAccessor {
public:
	PropSetSimple *pprops;
	Accessor(IDocument *pAccess_, PropSetSimple *pprops_);
	int GetPropertyInt(const char *, int defaultValue=0);
	int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/CharacterSet.cxx.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CharacterSet.cxx
 ** Simple case functions for ASCII.
 ** Lexer infrastructure.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <assert.h>

#include "CharacterSet.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

int CompareCaseInsensitive(const char *a, const char *b) {
	while (*a && *b) {
		if (*a != *b) {
			char upperA = MakeUpperCase(*a);
			char upperB = MakeUpperCase(*b);
			if (upperA != upperB)
				return upperA - upperB;
		}
		a++;
		b++;
	}
	// Either *a or *b is nul
	return *a - *b;
}

int CompareNCaseInsensitive(const char *a, const char *b, size_t len) {
	while (*a && *b && len) {
		if (*a != *b) {
			char upperA = MakeUpperCase(*a);
			char upperB = MakeUpperCase(*b);
			if (upperA != upperB)
				return upperA - upperB;
		}
		a++;
		b++;
		len--;
	}
	if (len == 0)
		return 0;
	else
		// Either *a or *b is nul
		return *a - *b;
}

#ifdef SCI_NAMESPACE
}
#endif

Added lexlib/CharacterSet.h.



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CharacterSet.h
 ** Encapsulates a set of characters. Used to test if a character is within a set.
 **/
// Copyright 2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CHARACTERSET_H
#define CHARACTERSET_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class CharacterSet {
	int size;
	bool valueAfter;
	bool *bset;
public:
	enum setBase {
		setNone=0,
		setLower=1,
		setUpper=2,
		setDigits=4,
		setAlpha=setLower|setUpper,
		setAlphaNum=setAlpha|setDigits
	};
	CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) {
		size = size_;
		valueAfter = valueAfter_;
		bset = new bool[size];
		for (int i=0; i < size; i++) {
			bset[i] = false;
		}
		AddString(initialSet);
		if (base & setLower)
			AddString("abcdefghijklmnopqrstuvwxyz");
		if (base & setUpper)
			AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
		if (base & setDigits)
			AddString("0123456789");
	}
	CharacterSet(const CharacterSet &other) {
		size = other.size;
		valueAfter = other.valueAfter;
		bset = new bool[size];
		for (int i=0; i < size; i++) {
			bset[i] = other.bset[i];
		}
	}
	~CharacterSet() {
		delete []bset;
		bset = 0;
		size = 0;
	}
	CharacterSet &operator=(const CharacterSet &other) {
		if (this != &other) {
			bool *bsetNew = new bool[other.size];
			for (int i=0; i < other.size; i++) {
				bsetNew[i] = other.bset[i];
			}
			delete []bset;
			size = other.size;
			valueAfter = other.valueAfter;
			bset = bsetNew;
		}
		return *this;
	}
	void Add(int val) {
		assert(val >= 0);
		assert(val < size);
		bset[val] = true;
	}
	void AddString(const char *setToAdd) {
		for (const char *cp=setToAdd; *cp; cp++) {
			int val = static_cast<unsigned char>(*cp);
			assert(val >= 0);
			assert(val < size);
			bset[val] = true;
		}
	}
	bool Contains(int val) const {
		assert(val >= 0);
		if (val < 0) return false;
		return (val < size) ? bset[val] : valueAfter;
	}
};

// Functions for classifying characters

inline bool IsASpace(int ch) {
    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
}

inline bool IsASpaceOrTab(int ch) {
	return (ch == ' ') || (ch == '\t');
}

inline bool IsADigit(int ch) {
	return (ch >= '0') && (ch <= '9');
}

inline bool IsADigit(int ch, int base) {
	if (base <= 10) {
		return (ch >= '0') && (ch < '0' + base);
	} else {
		return ((ch >= '0') && (ch <= '9')) ||
		       ((ch >= 'A') && (ch < 'A' + base - 10)) ||
		       ((ch >= 'a') && (ch < 'a' + base - 10));
	}
}

inline bool IsASCII(int ch) {
	return (ch >= 0) && (ch < 0x80);
}

inline bool IsLowerCase(int ch) {
	return (ch >= 'a') && (ch <= 'z');
}

inline bool IsUpperCase(int ch) {
	return (ch >= 'A') && (ch <= 'Z');
}

inline bool IsAlphaNumeric(int ch) {
	return
		((ch >= '0') && (ch <= '9')) ||
		((ch >= 'a') && (ch <= 'z')) ||
		((ch >= 'A') && (ch <= 'Z'));
}

/**
 * Check if a character is a space.
 * This is ASCII specific but is safe with chars >= 0x80.
 */
inline bool isspacechar(int ch) {
    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
}

inline bool iswordchar(int ch) {
	return IsAlphaNumeric(ch) || ch == '.' || ch == '_';
}

inline bool iswordstart(int ch) {
	return IsAlphaNumeric(ch) || ch == '_';
}

inline bool isoperator(int ch) {
	if (IsAlphaNumeric(ch))
		return false;
	if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
	        ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
	        ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
	        ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
	        ch == '?' || ch == '!' || ch == '.' || ch == '~')
		return true;
	return false;
}

// Simple case functions for ASCII.

inline char MakeUpperCase(char ch) {
	if (ch < 'a' || ch > 'z')
		return ch;
	else
		return static_cast<char>(ch - 'a' + 'A');
}

int CompareCaseInsensitive(const char *a, const char *b);
int CompareNCaseInsensitive(const char *a, const char *b, size_t len);

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/LexAccessor.h.

































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexAccessor.h
 ** Interfaces between Scintilla and lexers.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LEXACCESSOR_H
#define LEXACCESSOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

enum EncodingType { enc8bit, encUnicode, encDBCS };

class LexAccessor {
private:
	IDocument *pAccess;
	enum {extremePosition=0x7FFFFFFF};
	/** @a bufferSize is a trade off between time taken to copy the characters
	 * and retrieval overhead.
	 * @a slopSize positions the buffer before the desired position
	 * in case there is some backtracking. */
	enum {bufferSize=4000, slopSize=bufferSize/8};
	char buf[bufferSize+1];
	int startPos;
	int endPos;
	int codePage;
	enum EncodingType encodingType;
	int lenDoc;
	int mask;
	char styleBuf[bufferSize];
	int validLen;
	char chFlags;
	char chWhile;
	unsigned int startSeg;
	int startPosStyling;
	int documentVersion;

	void Fill(int position) {
		startPos = position - slopSize;
		if (startPos + bufferSize > lenDoc)
			startPos = lenDoc - bufferSize;
		if (startPos < 0)
			startPos = 0;
		endPos = startPos + bufferSize;
		if (endPos > lenDoc)
			endPos = lenDoc;

		pAccess->GetCharRange(buf, startPos, endPos-startPos);
		buf[endPos-startPos] = '\0';
	}

public:
	LexAccessor(IDocument *pAccess_) :
		pAccess(pAccess_), startPos(extremePosition), endPos(0),
		codePage(pAccess->CodePage()), 
		encodingType(enc8bit),
		lenDoc(pAccess->Length()),
		mask(127), validLen(0), chFlags(0), chWhile(0),
		startSeg(0), startPosStyling(0), 
		documentVersion(pAccess->Version()) {
		switch (codePage) {
		case 65001:
			encodingType = encUnicode;
			break;
		case 932:
		case 936:
		case 949:
		case 950:
		case 1361:
			encodingType = encDBCS;
		}
	}
	char operator[](int position) {
		if (position < startPos || position >= endPos) {
			Fill(position);
		}
		return buf[position - startPos];
	}
	/** Safe version of operator[], returning a defined value for invalid position. */
	char SafeGetCharAt(int position, char chDefault=' ') {
		if (position < startPos || position >= endPos) {
			Fill(position);
			if (position < startPos || position >= endPos) {
				// Position is outside range of document
				return chDefault;
			}
		}
		return buf[position - startPos];
	}
	bool IsLeadByte(char ch) {
		return pAccess->IsDBCSLeadByte(ch);
	}
	EncodingType Encoding() const {
		return encodingType;
	}
	bool Match(int pos, const char *s) {
		for (int i=0; *s; i++) {
			if (*s != SafeGetCharAt(pos+i))
				return false;
			s++;
		}
		return true;
	}
	char StyleAt(int position) {
		return static_cast<char>(pAccess->StyleAt(position) & mask);
	}
	int GetLine(int position) {
		return pAccess->LineFromPosition(position);
	}
	int LineStart(int line) {
		return pAccess->LineStart(line);
	}
	int LineEnd(int line) {
		if (documentVersion >= dvLineEnd) {
			return (static_cast<IDocumentWithLineEnd *>(pAccess))->LineEnd(line);
		} else {
			// Old interface means only '\r', '\n' and '\r\n' line ends.
			int startNext = pAccess->LineStart(line+1);
			char chLineEnd = SafeGetCharAt(startNext-1);
			if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2)  == '\r'))
				return startNext - 2;
			else
				return startNext - 1;
		}
	}
	int LevelAt(int line) {
		return pAccess->GetLevel(line);
	}
	int Length() const {
		return lenDoc;
	}
	void Flush() {
		startPos = extremePosition;
		if (validLen > 0) {
			pAccess->SetStyles(validLen, styleBuf);
			startPosStyling += validLen;
			validLen = 0;
		}
	}
	int GetLineState(int line) {
		return pAccess->GetLineState(line);
	}
	int SetLineState(int line, int state) {
		return pAccess->SetLineState(line, state);
	}
	// Style setting
	void StartAt(unsigned int start, char chMask=31) {
		// Store the mask specified for use with StyleAt.
		mask = chMask;
		pAccess->StartStyling(start, chMask);
		startPosStyling = start;
	}
	void SetFlags(char chFlags_, char chWhile_) {
		chFlags = chFlags_;
		chWhile = chWhile_;
	}
	unsigned int GetStartSegment() const {
		return startSeg;
	}
	void StartSegment(unsigned int pos) {
		startSeg = pos;
	}
	void ColourTo(unsigned int pos, int chAttr) {
		// Only perform styling if non empty range
		if (pos != startSeg - 1) {
			assert(pos >= startSeg);
			if (pos < startSeg) {
				return;
			}

			if (validLen + (pos - startSeg + 1) >= bufferSize)
				Flush();
			if (validLen + (pos - startSeg + 1) >= bufferSize) {
				// Too big for buffer so send directly
				pAccess->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
			} else {
				if (chAttr != chWhile)
					chFlags = 0;
				chAttr = static_cast<char>(chAttr | chFlags);
				for (unsigned int i = startSeg; i <= pos; i++) {
					assert((startPosStyling + validLen) < Length());
					styleBuf[validLen++] = static_cast<char>(chAttr);
				}
			}
		}
		startSeg = pos+1;
	}
	void SetLevel(int line, int level) {
		pAccess->SetLevel(line, level);
	}
	void IndicatorFill(int start, int end, int indicator, int value) {
		pAccess->DecorationSetCurrentIndicator(indicator);
		pAccess->DecorationFillRange(start, value, end - start);
	}

	void ChangeLexerState(int start, int end) {
		pAccess->ChangeLexerState(start, end);
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/LexerBase.cxx.

























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerBase.cxx
 ** A simple lexer with no state.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerBase::LexerBase() {
	for (int wl = 0; wl < numWordLists; wl++)
		keyWordLists[wl] = new WordList;
	keyWordLists[numWordLists] = 0;
}

LexerBase::~LexerBase() {
	for (int wl = 0; wl < numWordLists; wl++) {
		delete keyWordLists[wl];
		keyWordLists[wl] = 0;
	}
	keyWordLists[numWordLists] = 0;
}

void SCI_METHOD LexerBase::Release() {
	delete this;
}

int SCI_METHOD LexerBase::Version() const {
	return lvOriginal;
}

const char * SCI_METHOD LexerBase::PropertyNames() {
	return "";
}

int SCI_METHOD LexerBase::PropertyType(const char *) {
	return SC_TYPE_BOOLEAN;
}

const char * SCI_METHOD LexerBase::DescribeProperty(const char *) {
	return "";
}

int SCI_METHOD LexerBase::PropertySet(const char *key, const char *val) {
	const char *valOld = props.Get(key);
	if (strcmp(val, valOld) != 0) {
		props.Set(key, val);
		return 0;
	} else {
		return -1;
	}
}

const char * SCI_METHOD LexerBase::DescribeWordListSets() {
	return "";
}

int SCI_METHOD LexerBase::WordListSet(int n, const char *wl) {
	if (n < numWordLists) {
		WordList wlNew;
		wlNew.Set(wl);
		if (*keyWordLists[n] != wlNew) {
			keyWordLists[n]->Set(wl);
			return 0;
		}
	}
	return -1;
}

void * SCI_METHOD LexerBase::PrivateCall(int, void *) {
	return 0;
}

Added lexlib/LexerBase.h.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerBase.h
 ** A simple lexer with no state.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LEXERBASE_H
#define LEXERBASE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

// A simple lexer with no state
class LexerBase : public ILexer {
protected:
	PropSetSimple props;
	enum {numWordLists=KEYWORDSET_MAX+1};
	WordList *keyWordLists[numWordLists+1];
public:
	LexerBase();
	virtual ~LexerBase();
	void SCI_METHOD Release();
	int SCI_METHOD Version() const;
	const char * SCI_METHOD PropertyNames();
	int SCI_METHOD PropertyType(const char *name);
	const char * SCI_METHOD DescribeProperty(const char *name);
	int SCI_METHOD PropertySet(const char *key, const char *val);
	const char * SCI_METHOD DescribeWordListSets();
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
	void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
	void * SCI_METHOD PrivateCall(int operation, void *pointer);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/LexerModule.cxx.



















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerModule.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerSimple.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerModule::LexerModule(int language_,
	LexerFunction fnLexer_,
	const char *languageName_,
	LexerFunction fnFolder_,
        const char *const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(fnLexer_),
	fnFolder(fnFolder_),
	fnFactory(0),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

LexerModule::LexerModule(int language_,
	LexerFactoryFunction fnFactory_,
	const char *languageName_,
	const char * const wordListDescriptions_[],
	int styleBits_) :
	language(language_),
	fnLexer(0),
	fnFolder(0),
	fnFactory(fnFactory_),
	wordListDescriptions(wordListDescriptions_),
	styleBits(styleBits_),
	languageName(languageName_) {
}

int LexerModule::GetNumWordLists() const {
	if (wordListDescriptions == NULL) {
		return -1;
	} else {
		int numWordLists = 0;

		while (wordListDescriptions[numWordLists]) {
			++numWordLists;
		}

		return numWordLists;
	}
}

const char *LexerModule::GetWordListDescription(int index) const {
	static const char *emptyStr = "";

	assert(index < GetNumWordLists());
	if (index >= GetNumWordLists()) {
		return emptyStr;
	} else {
		return wordListDescriptions[index];
 	}
}

int LexerModule::GetStyleBitsNeeded() const {
	return styleBits;
}

ILexer *LexerModule::Create() const {
	if (fnFactory)
		return fnFactory();
	else
		return new LexerSimple(this);
}

void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnLexer)
		fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
}

void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
	  WordList *keywordlists[], Accessor &styler) const {
	if (fnFolder) {
		int lineCurrent = styler.GetLine(startPos);
		// Move back one line in case deletion wrecked current line fold state
		if (lineCurrent > 0) {
			lineCurrent--;
			int newStartPos = styler.LineStart(lineCurrent);
			lengthDoc += startPos - newStartPos;
			startPos = newStartPos;
			initStyle = 0;
			if (startPos > 0) {
				initStyle = styler.StyleAt(startPos - 1);
			}
		}
		fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
	}
}

Added lexlib/LexerModule.h.





































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerModule.h
 ** Colourise for particular languages.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LEXERMODULE_H
#define LEXERMODULE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class Accessor;
class WordList;

typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle,
                  WordList *keywordlists[], Accessor &styler);
typedef ILexer *(*LexerFactoryFunction)();

/**
 * A LexerModule is responsible for lexing and folding a particular language.
 * The class maintains a list of LexerModules which can be searched to find a
 * module appropriate to a particular language.
 */
class LexerModule {
protected:
	int language;
	LexerFunction fnLexer;
	LexerFunction fnFolder;
	LexerFactoryFunction fnFactory;
	const char * const * wordListDescriptions;
	int styleBits;

public:
	const char *languageName;
	LexerModule(int language_,
		LexerFunction fnLexer_,
		const char *languageName_=0,
		LexerFunction fnFolder_=0,
		const char * const wordListDescriptions_[] = NULL,
		int styleBits_=5);
	LexerModule(int language_,
		LexerFactoryFunction fnFactory_,
		const char *languageName_,
		const char * const wordListDescriptions_[] = NULL,
		int styleBits_=8);
	virtual ~LexerModule() {
	}
	int GetLanguage() const { return language; }

	// -1 is returned if no WordList information is available
	int GetNumWordLists() const;
	const char *GetWordListDescription(int index) const;

	int GetStyleBitsNeeded() const;

	ILexer *Create() const;

	virtual void Lex(unsigned int startPos, int length, int initStyle,
                  WordList *keywordlists[], Accessor &styler) const;
	virtual void Fold(unsigned int startPos, int length, int initStyle,
                  WordList *keywordlists[], Accessor &styler) const;

	friend class Catalogue;
};

inline int Maximum(int a, int b) {
	return (a > b) ? a : b;
}

// Shut up annoying Visual C++ warnings:
#ifdef _MSC_VER
#pragma warning(disable: 4244 4309 4514 4710)
#endif

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/LexerNoExceptions.cxx.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerNoExceptions.cxx
 ** A simple lexer with no state which does not throw exceptions so can be used in an external lexer.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerNoExceptions.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

int SCI_METHOD LexerNoExceptions::PropertySet(const char *key, const char *val) {
	try {
		return LexerBase::PropertySet(key, val);
	} catch (...) {
		// Should not throw into caller as may be compiled with different compiler or options
	}
	return -1;
}

int SCI_METHOD LexerNoExceptions::WordListSet(int n, const char *wl) {
	try {
		return LexerBase::WordListSet(n, wl);
	} catch (...) {
		// Should not throw into caller as may be compiled with different compiler or options
	}
	return -1;
}

void SCI_METHOD LexerNoExceptions::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	try {
		Accessor astyler(pAccess, &props);
		Lexer(startPos, length, initStyle, pAccess, astyler);
		astyler.Flush();
	} catch (...) {
		// Should not throw into caller as may be compiled with different compiler or options
		pAccess->SetErrorStatus(SC_STATUS_FAILURE);
	}
}
void SCI_METHOD LexerNoExceptions::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
	try {
		Accessor astyler(pAccess, &props);
		Folder(startPos, length, initStyle, pAccess, astyler);
		astyler.Flush();
	} catch (...) {
		// Should not throw into caller as may be compiled with different compiler or options
		pAccess->SetErrorStatus(SC_STATUS_FAILURE);
	}
}

Added lexlib/LexerNoExceptions.h.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerNoExceptions.h
 ** A simple lexer with no state.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LexerNoExceptions_H
#define LexerNoExceptions_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

// A simple lexer with no state
class LexerNoExceptions : public LexerBase {
public:
	// TODO Also need to prevent exceptions in constructor and destructor
	int SCI_METHOD PropertySet(const char *key, const char *val);
	int SCI_METHOD WordListSet(int n, const char *wl);
	void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *);

	virtual void Lexer(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0;
	virtual void Folder(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/LexerSimple.cxx.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerSimple.cxx
 ** A simple lexer with no state.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "PropSetSimple.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerSimple.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerSimple::LexerSimple(const LexerModule *module_) : module(module_) {
	for (int wl = 0; wl < module->GetNumWordLists(); wl++) {
		if (!wordLists.empty())
			wordLists += "\n";
		wordLists += module->GetWordListDescription(wl);
	}
}

const char * SCI_METHOD LexerSimple::DescribeWordListSets() {
	return wordLists.c_str();
}

void SCI_METHOD LexerSimple::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) {
	Accessor astyler(pAccess, &props);
	module->Lex(startPos, lengthDoc, initStyle, keyWordLists, astyler);
	astyler.Flush();
}

void SCI_METHOD LexerSimple::Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) {
	if (props.GetInt("fold")) {
		Accessor astyler(pAccess, &props);
		module->Fold(startPos, lengthDoc, initStyle, keyWordLists, astyler);
		astyler.Flush();
	}
}

Added lexlib/LexerSimple.h.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LexerSimple.h
 ** A simple lexer with no state.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LEXERSIMPLE_H
#define LEXERSIMPLE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

// A simple lexer with no state
class LexerSimple : public LexerBase {
	const LexerModule *module;
	std::string wordLists;
public:
	LexerSimple(const LexerModule *module_);
	const char * SCI_METHOD DescribeWordListSets();
	void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
	void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/OptionSet.h.





























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file OptionSet.h
 ** Manage descriptive information about an options struct for a lexer.
 ** Hold the names, positions, and descriptions of boolean, integer and string options and
 ** allow setting options and retrieving metadata about the options.
 **/
// Copyright 2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef OPTIONSET_H
#define OPTIONSET_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

template <typename T>
class OptionSet {
	typedef T Target;
	typedef bool T::*plcob;
	typedef int T::*plcoi;
	typedef std::string T::*plcos;
	struct Option {
		int opType;
		union {
			plcob pb;
			plcoi pi;
			plcos ps;
		};
		std::string description;
		Option() :
			opType(SC_TYPE_BOOLEAN), pb(0), description("") {
		}
		Option(plcob pb_, std::string description_="") :
			opType(SC_TYPE_BOOLEAN), pb(pb_), description(description_) {
		}
		Option(plcoi pi_, std::string description_) :
			opType(SC_TYPE_INTEGER), pi(pi_), description(description_) {
		}
		Option(plcos ps_, std::string description_) :
			opType(SC_TYPE_STRING), ps(ps_), description(description_) {
		}
		bool Set(T *base, const char *val) {
			switch (opType) {
			case SC_TYPE_BOOLEAN: {
					bool option = atoi(val) != 0;
					if ((*base).*pb != option) {
						(*base).*pb = option;
						return true;
					}
					break;
				}
			case SC_TYPE_INTEGER: {
					int option = atoi(val);
					if ((*base).*pi != option) {
						(*base).*pi = option;
						return true;
					}
					break;
				}
			case SC_TYPE_STRING: {
					if ((*base).*ps != val) {
						(*base).*ps = val;
						return true;
					}
					break;
				}
			}
			return false;
		}
	};
	typedef std::map<std::string, Option> OptionMap;
	OptionMap nameToDef;
	std::string names;
	std::string wordLists;

	void AppendName(const char *name) {
		if (!names.empty())
			names += "\n";
		names += name;
	}
public:
	virtual ~OptionSet() {
	}
	void DefineProperty(const char *name, plcob pb, std::string description="") {
		nameToDef[name] = Option(pb, description);
		AppendName(name);
	}
	void DefineProperty(const char *name, plcoi pi, std::string description="") {
		nameToDef[name] = Option(pi, description);
		AppendName(name);
	}
	void DefineProperty(const char *name, plcos ps, std::string description="") {
		nameToDef[name] = Option(ps, description);
		AppendName(name);
	}
	const char *PropertyNames() {
		return names.c_str();
	}
	int PropertyType(const char *name) {
		typename OptionMap::iterator it = nameToDef.find(name);
		if (it != nameToDef.end()) {
			return it->second.opType;
		}
		return SC_TYPE_BOOLEAN;
	}
	const char *DescribeProperty(const char *name) {
		typename OptionMap::iterator it = nameToDef.find(name);
		if (it != nameToDef.end()) {
			return it->second.description.c_str();
		}
		return "";
	}

	bool PropertySet(T *base, const char *name, const char *val) {
		typename OptionMap::iterator it = nameToDef.find(name);
		if (it != nameToDef.end()) {
			return it->second.Set(base, val);
		}
		return false;
	}

	void DefineWordListSets(const char * const wordListDescriptions[]) {
		if (wordListDescriptions) {
			for (size_t wl = 0; wordListDescriptions[wl]; wl++) {
				if (!wordLists.empty())
					wordLists += "\n";
				wordLists += wordListDescriptions[wl];
			}
		}
	}

	const char *DescribeWordListSets() {
		return wordLists.c_str();
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/PropSetSimple.cxx.





















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// SciTE - Scintilla based Text Editor
/** @file PropSetSimple.cxx
 ** A Java style properties file module.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

// Maintain a dictionary of properties

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#ifdef _MSC_VER
// Visual C++ doesn't like unreachable code in its own headers.
#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702)
#endif

#include <string>
#include <map>

#include "PropSetSimple.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

typedef std::map<std::string, std::string> mapss;

PropSetSimple::PropSetSimple() {
	mapss *props = new mapss;
	impl = static_cast<void *>(props);
}

PropSetSimple::~PropSetSimple() {
	mapss *props = static_cast<mapss *>(impl);
	delete props;
	impl = 0;
}

void PropSetSimple::Set(const char *key, const char *val, int lenKey, int lenVal) {
	mapss *props = static_cast<mapss *>(impl);
	if (!*key)	// Empty keys are not supported
		return;
	if (lenKey == -1)
		lenKey = static_cast<int>(strlen(key));
	if (lenVal == -1)
		lenVal = static_cast<int>(strlen(val));
	(*props)[std::string(key, lenKey)] = std::string(val, lenVal);
}

static bool IsASpaceCharacter(unsigned int ch) {
    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
}

void PropSetSimple::Set(const char *keyVal) {
	while (IsASpaceCharacter(*keyVal))
		keyVal++;
	const char *endVal = keyVal;
	while (*endVal && (*endVal != '\n'))
		endVal++;
	const char *eqAt = strchr(keyVal, '=');
	if (eqAt) {
		Set(keyVal, eqAt + 1, static_cast<int>(eqAt-keyVal), 
			static_cast<int>(endVal - eqAt - 1));
	} else if (*keyVal) {	// No '=' so assume '=1'
		Set(keyVal, "1", static_cast<int>(endVal-keyVal), 1);
	}
}

void PropSetSimple::SetMultiple(const char *s) {
	const char *eol = strchr(s, '\n');
	while (eol) {
		Set(s);
		s = eol + 1;
		eol = strchr(s, '\n');
	}
	Set(s);
}

const char *PropSetSimple::Get(const char *key) const {
	mapss *props = static_cast<mapss *>(impl);
	mapss::const_iterator keyPos = props->find(std::string(key));
	if (keyPos != props->end()) {
		return keyPos->second.c_str();
	} else {
		return "";
	}
}

// There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
// A solution is to keep a stack of variables that have been expanded, so that
// recursive expansions can be skipped.  For now I'll just use the C++ stack
// for that, through a recursive function and a simple chain of pointers.

struct VarChain {
	VarChain(const char *var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}

	bool contains(const char *testVar) const {
		return (var && (0 == strcmp(var, testVar)))
			|| (link && link->contains(testVar));
	}

	const char *var;
	const VarChain *link;
};

static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, int maxExpands, const VarChain &blankVars) {
	size_t varStart = withVars.find("$(");
	while ((varStart != std::string::npos) && (maxExpands > 0)) {
		size_t varEnd = withVars.find(")", varStart+2);
		if (varEnd == std::string::npos) {
			break;
		}

		// For consistency, when we see '$(ab$(cde))', expand the inner variable first,
		// regardless whether there is actually a degenerate variable named 'ab$(cde'.
		size_t innerVarStart = withVars.find("$(", varStart+2);
		while ((innerVarStart != std::string::npos) && (innerVarStart > varStart) && (innerVarStart < varEnd)) {
			varStart = innerVarStart;
			innerVarStart = withVars.find("$(", varStart+2);
		}

		std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
		std::string val = props.Get(var.c_str());

		if (blankVars.contains(var.c_str())) {
			val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
		}

		if (--maxExpands >= 0) {
			maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
		}

		withVars.erase(varStart, varEnd-varStart+1);
		withVars.insert(varStart, val.c_str(), val.length());

		varStart = withVars.find("$(");
	}

	return maxExpands;
}

char *PropSetSimple::Expanded(const char *key) const {
	std::string val = Get(key);
	ExpandAllInPlace(*this, val, 100, VarChain(key));
	char *ret = new char [val.size() + 1];
	strcpy(ret, val.c_str());
	return ret;
}

int PropSetSimple::GetExpanded(const char *key, char *result) const {
	char *val = Expanded(key);
	const int n = static_cast<int>(strlen(val));
	if (result) {
		strcpy(result, val);
	}
	delete []val;
	return n;	// Not including NUL
}

int PropSetSimple::GetInt(const char *key, int defaultValue) const {
	char *val = Expanded(key);
	if (val) {
		int retVal = val[0] ? atoi(val) : defaultValue;
		delete []val;
		return retVal;
	}
	return defaultValue;
}

Added lexlib/PropSetSimple.h.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file PropSetSimple.h
 ** A basic string to string map.
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef PROPSETSIMPLE_H
#define PROPSETSIMPLE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class PropSetSimple {
	void *impl;
	void Set(const char *keyVal);
public:
	PropSetSimple();
	virtual ~PropSetSimple();
	void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1);
	void SetMultiple(const char *);
	const char *Get(const char *key) const;
	char *Expanded(const char *key) const;
	int GetExpanded(const char *key, char *result) const;
	int GetInt(const char *key, int defaultValue=0) const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/SparseState.h.





























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file SparseState.h
 ** Hold lexer state that may change rarely.
 ** This is often per-line state such as whether a particular type of section has been entered.
 ** A state continues until it is changed.
 **/
// Copyright 2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SPARSESTATE_H
#define SPARSESTATE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

template <typename T>
class SparseState {
	struct State {
		int position;
		T value;
		State(int position_, T value_) : position(position_), value(value_) {
		}
		inline bool operator<(const State &other) const {
			return position < other.position;
		}
		inline bool operator==(const State &other) const {
			return (position == other.position) && (value == other.value);
		}
	};
	int positionFirst;
	typedef std::vector<State> stateVector;
	stateVector states;

	typename stateVector::iterator Find(int position) {
		State searchValue(position, T());
		return std::lower_bound(states.begin(), states.end(), searchValue);
	}

public:
	SparseState(int positionFirst_=-1) {
		positionFirst = positionFirst_;
	}
	void Set(int position, T value) {
		Delete(position);
		if (states.empty() || (value != states[states.size()-1].value)) {
			states.push_back(State(position, value));
		}
	}
	T ValueAt(int position) {
		if (states.empty())
			return T();
		if (position < states[0].position)
			return T();
		typename stateVector::iterator low = Find(position);
		if (low == states.end()) {
			return states[states.size()-1].value;
		} else {
			if (low->position > position) {
				--low;
			}
			return low->value;
		}
	}
	bool Delete(int position) {
		typename stateVector::iterator low = Find(position);
		if (low != states.end()) {
			states.erase(low, states.end());
			return true;
		}
		return false;
	}
	size_t size() const {
		return states.size();
	}

	// Returns true if Merge caused a significant change
	bool Merge(const SparseState<T> &other, int ignoreAfter) {
		// Changes caused beyond ignoreAfter are not significant
		Delete(ignoreAfter+1);

		bool different = true;
		bool changed = false;
		typename stateVector::iterator low = Find(other.positionFirst);
		if (static_cast<size_t>(states.end() - low) == other.states.size()) {
			// Same number in other as after positionFirst in this
			different = !std::equal(low, states.end(), other.states.begin());
		}
		if (different) {
			if (low != states.end()) {
				states.erase(low, states.end());
				changed = true;
			}
			typename stateVector::const_iterator startOther = other.states.begin();
			if (!states.empty() && !other.states.empty() && states.back().value == startOther->value)
				++startOther;
			if (startOther != other.states.end()) {
				states.insert(states.end(), startOther, other.states.end());
				changed = true;
			}
		}
		return changed;
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/StyleContext.cxx.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file StyleContext.cxx
 ** Lexer infrastructure.
 **/
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// This file is in the public domain.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <assert.h>

#include "ILexer.h"

#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static void getRange(unsigned int start,
		unsigned int end,
		LexAccessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = styler[start + i];
		i++;
	}
	s[i] = '\0';
}

void StyleContext::GetCurrent(char *s, unsigned int len) {
	getRange(styler.GetStartSegment(), currentPos - 1, styler, s, len);
}

static void getRangeLowered(unsigned int start,
		unsigned int end,
		LexAccessor &styler,
		char *s,
		unsigned int len) {
	unsigned int i = 0;
	while ((i < end - start + 1) && (i < len-1)) {
		s[i] = static_cast<char>(tolower(styler[start + i]));
		i++;
	}
	s[i] = '\0';
}

void StyleContext::GetCurrentLowered(char *s, unsigned int len) {
	getRangeLowered(styler.GetStartSegment(), currentPos - 1, styler, s, len);
}

Added lexlib/StyleContext.h.



























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file StyleContext.cxx
 ** Lexer infrastructure.
 **/
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// This file is in the public domain.

#ifndef STYLECONTEXT_H
#define STYLECONTEXT_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

static inline int MakeLowerCase(int ch) {
	if (ch < 'A' || ch > 'Z')
		return ch;
	else
		return ch - 'A' + 'a';
}

inline int UnicodeCodePoint(const unsigned char *us) {
	if (us[0] < 0xC2) {
		return us[0];
	} else if (us[0] < 0xE0) {
		return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
	} else if (us[0] < 0xF0) {
		return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
	} else if (us[0] < 0xF5) {
		return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
	}
	return us[0];
}

inline int BytesInUnicodeCodePoint(int codePoint) {
	if (codePoint < 0x80)
		return 1;
	else if (codePoint < 0x800)
		return 2;
	else if (codePoint < 0x10000)
		return 3;
	else
		return 4;
}

// All languages handled so far can treat all characters >= 0x80 as one class
// which just continues the current token or starts an identifier if in default.
// DBCS treated specially as the second character can be < 0x80 and hence
// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
class StyleContext {
	LexAccessor &styler;
	unsigned int endPos;
	StyleContext &operator=(const StyleContext &);

	void GetNextChar(unsigned int pos) {
		chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1));
		if (styler.Encoding() == encUnicode) {
			if (chNext >= 0x80) {
				unsigned char bytes[4] = { static_cast<unsigned char>(chNext), 0, 0, 0 };
				for (int trail=1; trail<3; trail++) {
					bytes[trail] = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1+trail));
					if (!((bytes[trail] >= 0x80) && (bytes[trail] < 0xc0))) {
						bytes[trail] = 0;
						break;
					}
				}
				chNext = UnicodeCodePoint(bytes);
			}
		} else if (styler.Encoding() == encDBCS) {
			if (styler.IsLeadByte(static_cast<char>(chNext))) {
				chNext = chNext << 8;
				chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2));
			}
		}
		// End of line?
		// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win)
		// or on LF alone (Unix). Avoid triggering two times on Dos/Win.
		if (lineStartNext < styler.Length())
			atLineEnd = static_cast<int>(pos) >= (lineStartNext-1);
		else // Last line
			atLineEnd = static_cast<int>(pos) >= lineStartNext;
	}

public:
	unsigned int currentPos;
	int currentLine;
	int lineStartNext;
	bool atLineStart;
	bool atLineEnd;
	int state;
	int chPrev;
	int ch;
	int chNext;

	StyleContext(unsigned int startPos, unsigned int length,
                        int initStyle, LexAccessor &styler_, char chMask=31) :
		styler(styler_),
		endPos(startPos + length),
		currentPos(startPos),
		currentLine(-1),
		lineStartNext(-1),
		atLineEnd(false),
		state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
		chPrev(0),
		ch(0),
		chNext(0) {
		styler.StartAt(startPos, chMask);
		styler.StartSegment(startPos);
		currentLine = styler.GetLine(startPos);
		lineStartNext = styler.LineStart(currentLine+1);
		atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
		unsigned int pos = currentPos;
		ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
		if (styler.Encoding() == encUnicode) {
			// Get the current char
			GetNextChar(pos-1);
			ch = chNext;
			pos += BytesInUnicodeCodePoint(ch) - 1;
		} else if (styler.Encoding() == encDBCS) {
			if (styler.IsLeadByte(static_cast<char>(ch))) {
				pos++;
				ch = ch << 8;
				ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos));
			}
		}
		GetNextChar(pos);
	}
	void Complete() {
		styler.ColourTo(currentPos - 1, state);
		styler.Flush();
	}
	bool More() const {
		return currentPos < endPos;
	}
	void Forward() {
		if (currentPos < endPos) {
			atLineStart = atLineEnd;
			if (atLineStart) {
				currentLine++;
				lineStartNext = styler.LineStart(currentLine+1);
			}
			chPrev = ch;
			if (styler.Encoding() == encUnicode) {
				currentPos += BytesInUnicodeCodePoint(ch);
			} else if (styler.Encoding() == encDBCS) {
				currentPos++;
				if (ch >= 0x100)
					currentPos++;
			} else {
				currentPos++;
			}
			ch = chNext;
			if (styler.Encoding() == encUnicode) {
				GetNextChar(currentPos + BytesInUnicodeCodePoint(ch)-1);
			} else if (styler.Encoding() == encDBCS) {
				GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
			} else {
				GetNextChar(currentPos);
			}
		} else {
			atLineStart = false;
			chPrev = ' ';
			ch = ' ';
			chNext = ' ';
			atLineEnd = true;
		}
	}
	void Forward(int nb) {
		for (int i = 0; i < nb; i++) {
			Forward();
		}
	}
	void ChangeState(int state_) {
		state = state_;
	}
	void SetState(int state_) {
		styler.ColourTo(currentPos - 1, state);
		state = state_;
	}
	void ForwardSetState(int state_) {
		Forward();
		styler.ColourTo(currentPos - 1, state);
		state = state_;
	}
	int LengthCurrent() {
		return currentPos - styler.GetStartSegment();
	}
	int GetRelative(int n) {
		return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
	}
	bool Match(char ch0) const {
		return ch == static_cast<unsigned char>(ch0);
	}
	bool Match(char ch0, char ch1) const {
		return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1));
	}
	bool Match(const char *s) {
		if (ch != static_cast<unsigned char>(*s))
			return false;
		s++;
		if (!*s)
			return true;
		if (chNext != static_cast<unsigned char>(*s))
			return false;
		s++;
		for (int n=2; *s; n++) {
			if (*s != styler.SafeGetCharAt(currentPos+n))
				return false;
			s++;
		}
		return true;
	}
	bool MatchIgnoreCase(const char *s) {
		if (MakeLowerCase(ch) != static_cast<unsigned char>(*s))
			return false;
		s++;
		if (MakeLowerCase(chNext) != static_cast<unsigned char>(*s))
			return false;
		s++;
		for (int n=2; *s; n++) {
			if (static_cast<unsigned char>(*s) !=
				MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
				return false;
			s++;
		}
		return true;
	}
	// Non-inline
	void GetCurrent(char *s, unsigned int len);
	void GetCurrentLowered(char *s, unsigned int len);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/SubStyles.h.





































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file SubStyles.h
 ** Manage substyles for a lexer.
 **/
// Copyright 2012 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SUBSTYLES_H
#define SUBSTYLES_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class WordClassifier {
	int firstStyle;
	int lenStyles;
	std::map<std::string, int> wordToStyle;

public:

	WordClassifier() : firstStyle(0), lenStyles(0) {
	}

	void Allocate(int firstStyle_, int lenStyles_) {
		firstStyle = firstStyle_;
		lenStyles = lenStyles_;
		wordToStyle.clear();
	}

	int Start() const {
		return firstStyle;
	}

	int Length() const {
		return lenStyles;
	}

	void Clear() {
		firstStyle = 0;
		lenStyles = 0;
		wordToStyle.clear();
	}

	int ValueFor(const std::string &s) const {
		std::map<std::string, int>::const_iterator it = wordToStyle.find(s);
		if (it != wordToStyle.end())
			return it->second;
		else
			return -1;
	}

	bool IncludesStyle(int style) const {
		return (style >= firstStyle) && (style < (firstStyle + lenStyles));
	}

	void SetIdentifiers(int style, const char *identifiers) {
		while (*identifiers) {
			const char *cpSpace = identifiers;
			while (*cpSpace && *cpSpace != ' ')
				cpSpace++;
			std::string word(identifiers, cpSpace - identifiers);
			wordToStyle[word] = style;
			identifiers = cpSpace;
			if (*identifiers)
				identifiers++;
		}
	}
};

class SubStyles {
	int classifications;
	const char *baseStyles;
	int styleFirst;
	int stylesAvailable;
	int secondaryDistance;
	int allocated;
	std::vector<WordClassifier> classifiers;

	int BlockFromBaseStyle(int baseStyle) const {
		for (int b=0; b < classifications; b++) {
			if (baseStyle == baseStyles[b])
				return b;
		}
		return -1;
	}

	int BlockFromStyle(int style) const {
		int b = 0;
		for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) {
			if (it->IncludesStyle(style))
				return b;
			b++;
		}
		return -1;
	}

public:

	SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) :
		classifications(0),
		baseStyles(baseStyles_),
		styleFirst(styleFirst_),
		stylesAvailable(stylesAvailable_),
		secondaryDistance(secondaryDistance_),
		allocated(0) {
		while (baseStyles[classifications]) {
			classifications++;
			classifiers.push_back(WordClassifier());
		}
	}

	int Allocate(int styleBase, int numberStyles) {
		int block = BlockFromBaseStyle(styleBase);
		if (block >= 0) {
			if ((allocated + numberStyles) > stylesAvailable)
				return -1;
			int startBlock = styleFirst + allocated;
			allocated += numberStyles;
			classifiers[block].Allocate(startBlock, numberStyles);
			return startBlock;
		} else {
			return -1;
		}
	}

	int Start(int styleBase) {
		int block = BlockFromBaseStyle(styleBase);
		return (block >= 0) ? classifiers[block].Start() : -1;
	}

	int Length(int styleBase) {
		int block = BlockFromBaseStyle(styleBase);
		return (block >= 0) ? classifiers[block].Length() : 0;
	}

	int DistanceToSecondaryStyles() const {
		return secondaryDistance;
	}

	void SetIdentifiers(int style, const char *identifiers) {
		int block = BlockFromStyle(style);
		if (block >= 0)
			classifiers[block].SetIdentifiers(style, identifiers);
	}

	void Free() {
		allocated = 0;
		for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it)
			it->Clear();
	}

	const WordClassifier &Classifier(int baseStyle) const {
		return classifiers[BlockFromBaseStyle(baseStyle)];
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added lexlib/WordList.cxx.























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include <algorithm>

#include "WordList.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/**
 * Creates an array that points into each word in the string and puts \0 terminators
 * after each word.
 */
static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) {
	int prev = '\n';
	int words = 0;
	// For rapid determination of whether a character is a separator, build
	// a look up table.
	bool wordSeparator[256];
	for (int i=0; i<256; i++) {
		wordSeparator[i] = false;
	}
	wordSeparator['\r'] = true;
	wordSeparator['\n'] = true;
	if (!onlyLineEnds) {
		wordSeparator[' '] = true;
		wordSeparator['\t'] = true;
	}
	for (int j = 0; wordlist[j]; j++) {
		int curr = static_cast<unsigned char>(wordlist[j]);
		if (!wordSeparator[curr] && wordSeparator[prev])
			words++;
		prev = curr;
	}
	char **keywords = new char *[words + 1];
	if (keywords) {
		words = 0;
		prev = '\0';
		size_t slen = strlen(wordlist);
		for (size_t k = 0; k < slen; k++) {
			if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
				if (!prev) {
					keywords[words] = &wordlist[k];
					words++;
				}
			} else {
				wordlist[k] = '\0';
			}
			prev = wordlist[k];
		}
		keywords[words] = &wordlist[slen];
		*len = words;
	} else {
		*len = 0;
	}
	return keywords;
}

bool WordList::operator!=(const WordList &other) const {
	if (len != other.len)
		return true;
	for (int i=0; i<len; i++) {
		if (strcmp(words[i], other.words[i]) != 0)
			return true;
	}
	return false;
}

void WordList::Clear() {
	if (words) {
		delete []list;
		delete []words;
	}
	words = 0;
	list = 0;
	len = 0;
}

#ifdef _MSC_VER

static bool cmpWords(const char *a, const char *b) {
	return strcmp(a, b) == -1;
}

#else

static int cmpWords(const void *a, const void *b) {
	return strcmp(*static_cast<const char * const *>(a), *static_cast<const char * const *>(b));
}

static void SortWordList(char **words, unsigned int len) {
	qsort(reinterpret_cast<void *>(words), len, sizeof(*words), cmpWords);
}

#endif

void WordList::Set(const char *s) {
	Clear();
	list = new char[strlen(s) + 1];
	strcpy(list, s);
	words = ArrayFromWordList(list, &len, onlyLineEnds);
#ifdef _MSC_VER
	std::sort(words, words + len, cmpWords);
#else
	SortWordList(words, len);
#endif
	for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
		starts[k] = -1;
	for (int l = len - 1; l >= 0; l--) {
		unsigned char indexChar = words[l][0];
		starts[indexChar] = l;
	}
}

/** Check whether a string is in the list.
 * List elements are either exact matches or prefixes.
 * Prefix elements start with '^' and match all strings that start with the rest of the element
 * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
 */
bool WordList::InList(const char *s) const {
	if (0 == words)
		return false;
	unsigned char firstChar = s[0];
	int j = starts[firstChar];
	if (j >= 0) {
		while (static_cast<unsigned char>(words[j][0]) == firstChar) {
			if (s[1] == words[j][1]) {
				const char *a = words[j] + 1;
				const char *b = s + 1;
				while (*a && *a == *b) {
					a++;
					b++;
				}
				if (!*a && !*b)
					return true;
			}
			j++;
		}
	}
	j = starts['^'];
	if (j >= 0) {
		while (words[j][0] == '^') {
			const char *a = words[j] + 1;
			const char *b = s;
			while (*a && *a == *b) {
				a++;
				b++;
			}
			if (!*a)
				return true;
			j++;
		}
	}
	return false;
}

/** similar to InList, but word s can be a substring of keyword.
 * eg. the keyword define is defined as def~ine. This means the word must start
 * with def to be a keyword, but also defi, defin and define are valid.
 * The marker is ~ in this case.
 */
bool WordList::InListAbbreviated(const char *s, const char marker) const {
	if (0 == words)
		return false;
	unsigned char firstChar = s[0];
	int j = starts[firstChar];
	if (j >= 0) {
		while (static_cast<unsigned char>(words[j][0]) == firstChar) {
			bool isSubword = false;
			int start = 1;
			if (words[j][1] == marker) {
				isSubword = true;
				start++;
			}
			if (s[1] == words[j][start]) {
				const char *a = words[j] + start;
				const char *b = s + 1;
				while (*a && *a == *b) {
					a++;
					if (*a == marker) {
						isSubword = true;
						a++;
					}
					b++;
				}
				if ((!*a || isSubword) && !*b)
					return true;
			}
			j++;
		}
	}
	j = starts['^'];
	if (j >= 0) {
		while (words[j][0] == '^') {
			const char *a = words[j] + 1;
			const char *b = s;
			while (*a && *a == *b) {
				a++;
				b++;
			}
			if (!*a)
				return true;
			j++;
		}
	}
	return false;
}

Added lexlib/WordList.h.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file WordList.h
 ** Hold a list of words.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef WORDLIST_H
#define WORDLIST_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class WordList {
public:
	// Each word contains at least one character - a empty word acts as sentinel at the end.
	char **words;
	char *list;
	int len;
	bool onlyLineEnds;	///< Delimited by any white space or only line ends
	int starts[256];
	WordList(bool onlyLineEnds_ = false) :
		words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_)
		{}
	~WordList() { Clear(); }
	operator bool() const { return len ? true : false; }
	bool operator!=(const WordList &other) const;
	void Clear();
	void Set(const char *s);
	bool InList(const char *s) const;
	bool InListAbbreviated(const char *s, const char marker) const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added qt/README.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
README for building of Scintilla on Qt

There are three different Scintilla libraries that can be produced:

	ScintillaEditBase
A basic widget callable from C++ which is small and can be used just as is 
or with higher level functionality added.

	ScintillaEdit
A more complete C++ widget with a method for every Scintilla API and a
secondary API allowing direct access to document objects.

	ScintillaEditPy
A Python callable version of ScintillaEdit using the PySide bindings.

	Building a library

ScintillaEditBase can be built without performing any generation steps.
The ScintillaEditBase/ScintillaEditBase.pro project can be loaded into 
Qt Creator and the "Build All" command performed.
Alternatively, run "qmake" to build make files and then use the platform
make to build. Most commonly, use "make" on Unix and "nmake"
on Windows.

ScintillaEdit requires a generation command be run first. From the 
ScintillaEdit directory:

python WidgetGen.py

After the generation command has run, the ScintillaEdit.h and
ScintillaEdit.cpp files will have been populated with the Scintilla API
methods. 
To build, use Qt Creator or qmake and make as for ScintillaEditBase.

ScintillaEditPy is more complex and instructions are found in 
ScintillaEditPy/README.

Added qt/ScintillaEdit/ScintillaDocument.cpp.





























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// ScintillaDocument.cpp
// Wrapper for Scintilla document object so it can be manipulated independently.
// Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware

#include <vector>
#include <map>

#include "ScintillaDocument.h"

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"

class WatcherHelper : public DocWatcher {
	ScintillaDocument *owner;
public:
	WatcherHelper(ScintillaDocument *owner_);
	virtual ~WatcherHelper();

	void NotifyModifyAttempt(Document *doc, void *userData);
	void NotifySavePoint(Document *doc, void *userData, bool atSavePoint);
	void NotifyModified(Document *doc, DocModification mh, void *userData);
	void NotifyDeleted(Document *doc, void *userData);
	void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
	void NotifyLexerChanged(Document *doc, void *userData);
	void NotifyErrorOccurred(Document *doc, void *userData, int status);
};

WatcherHelper::WatcherHelper(ScintillaDocument *owner_) : owner(owner_) {
}

WatcherHelper::~WatcherHelper() {
}

void WatcherHelper::NotifyModifyAttempt(Document *, void *) {
	owner->emit_modify_attempt();
}

void WatcherHelper::NotifySavePoint(Document *, void *, bool atSavePoint) {
	owner->emit_save_point(atSavePoint);
}

void WatcherHelper::NotifyModified(Document *, DocModification mh, void *) {
    int length = mh.length;
    if (!mh.text)
        length = 0;
    QByteArray ba = QByteArray::fromRawData(mh.text, length);
    owner->emit_modified(mh.position, mh.modificationType, ba, length,
        mh.linesAdded, mh.line, mh.foldLevelNow, mh.foldLevelPrev);
}

void WatcherHelper::NotifyDeleted(Document *, void *) {
}

void WatcherHelper::NotifyStyleNeeded(Document *, void *, int endPos) {
	owner->emit_style_needed(endPos);
}

void WatcherHelper::NotifyLexerChanged(Document *, void *) {
    owner->emit_lexer_changed();
}

void WatcherHelper::NotifyErrorOccurred(Document *, void *, int status) {
    owner->emit_error_occurred(status);
}

ScintillaDocument::ScintillaDocument(QObject *parent, void *pdoc_) :
    QObject(parent), pdoc(pdoc_), docWatcher(0) {
    if (!pdoc) {
        pdoc = new Document();
    }
    docWatcher = new WatcherHelper(this);
    ((Document *)pdoc)->AddRef();
    ((Document *)pdoc)->AddWatcher(docWatcher, pdoc);
}

ScintillaDocument::~ScintillaDocument() {
    Document *doc = static_cast<Document *>(pdoc);
    if (doc) {
        doc->RemoveWatcher(docWatcher, doc);
        doc->Release();
    }
    pdoc = NULL;
    delete docWatcher;
    docWatcher = NULL;
}

void *ScintillaDocument::pointer() {
	return pdoc;
}

int ScintillaDocument::line_from_position(int pos) {
    return ((Document *)pdoc)->LineFromPosition(pos);
}

bool ScintillaDocument::is_cr_lf(int pos) {
    return ((Document *)pdoc)->IsCrLf(pos);
}

bool ScintillaDocument::delete_chars(int pos, int len) {
    return ((Document *)pdoc)->DeleteChars(pos, len);
}

int ScintillaDocument::undo() {
    return ((Document *)pdoc)->Undo();
}

int ScintillaDocument::redo() {
    return ((Document *)pdoc)->Redo();
}

bool ScintillaDocument::can_undo() {
    return ((Document *)pdoc)->CanUndo();
}

bool ScintillaDocument::can_redo() {
    return ((Document *)pdoc)->CanRedo();
}

void ScintillaDocument::delete_undo_history() {
    ((Document *)pdoc)->DeleteUndoHistory();
}

bool ScintillaDocument::set_undo_collection(bool collect_undo) {
    return ((Document *)pdoc)->SetUndoCollection(collect_undo);
}

bool ScintillaDocument::is_collecting_undo() {
    return ((Document *)pdoc)->IsCollectingUndo();
}

void ScintillaDocument::begin_undo_action() {
    ((Document *)pdoc)->BeginUndoAction();
}

void ScintillaDocument::end_undo_action() {
    ((Document *)pdoc)->EndUndoAction();
}

void ScintillaDocument::set_save_point() {
    ((Document *)pdoc)->SetSavePoint();
}

bool ScintillaDocument::is_save_point() {
    return ((Document *)pdoc)->IsSavePoint();
}

void ScintillaDocument::set_read_only(bool read_only) {
    ((Document *)pdoc)->SetReadOnly(read_only);
}

bool ScintillaDocument::is_read_only() {
    return ((Document *)pdoc)->IsReadOnly();
}

void ScintillaDocument::insert_string(int position, QByteArray &str) {
    ((Document *)pdoc)->InsertString(position, str.data(), str.size());
}

QByteArray ScintillaDocument::get_char_range(int position, int length) {
    Document *doc = (Document *)pdoc;

    if (position < 0 || length <= 0 || position + length > doc->Length())
        return QByteArray();

    QByteArray ba(length, '\0');
    doc->GetCharRange(ba.data(), position, length);
    return ba;
}

char ScintillaDocument::style_at(int position) {
    return ((Document *)pdoc)->StyleAt(position);
}

int ScintillaDocument::line_start(int lineno) {
    return ((Document *)pdoc)->LineStart(lineno);
}

int ScintillaDocument::line_end(int lineno) {
    return ((Document *)pdoc)->LineEnd(lineno);
}

int ScintillaDocument::line_end_position(int pos) {
    return ((Document *)pdoc)->LineEndPosition(pos);
}

int ScintillaDocument::length() {
    return ((Document *)pdoc)->Length();
}

int ScintillaDocument::lines_total() {
    return ((Document *)pdoc)->LinesTotal();
}

void ScintillaDocument::start_styling(int position, char flags) {
    ((Document *)pdoc)->StartStyling(position, flags);
}

bool ScintillaDocument::set_style_for(int length, char style) {
    return ((Document *)pdoc)->SetStyleFor(length, style);
}

int ScintillaDocument::get_end_styled() {
    return ((Document *)pdoc)->GetEndStyled();
}

void ScintillaDocument::ensure_styled_to(int position) {
    ((Document *)pdoc)->EnsureStyledTo(position);
}

void ScintillaDocument::set_current_indicator(int indic) {
    ((Document *)pdoc)->decorations.SetCurrentIndicator(indic);
}

void ScintillaDocument::decoration_fill_range(int position, int value, int fillLength) {
    ((Document *)pdoc)->DecorationFillRange(position, value, fillLength);
}

int ScintillaDocument::decorations_value_at(int indic, int position) {
    return ((Document *)pdoc)->decorations.ValueAt(indic, position);
}

int ScintillaDocument::decorations_start(int indic, int position) {
    return ((Document *)pdoc)->decorations.Start(indic, position);
}

int ScintillaDocument::decorations_end(int indic, int position) {
    return ((Document *)pdoc)->decorations.End(indic, position);
}

int ScintillaDocument::get_code_page() {
    return ((Document *)pdoc)->CodePage();
}

void ScintillaDocument::set_code_page(int code_page) {
    ((Document *)pdoc)->dbcsCodePage = code_page;
}

int ScintillaDocument::move_position_outside_char(int pos, int move_dir, bool check_line_end) {
    return ((Document *)pdoc)->MovePositionOutsideChar(pos, move_dir, check_line_end);
}

// Signal emitters

void ScintillaDocument::emit_modify_attempt() {
    emit modify_attempt();
}

void ScintillaDocument::emit_save_point(bool atSavePoint) {
    emit save_point(atSavePoint);
}

void ScintillaDocument::emit_modified(int position, int modification_type, const QByteArray& text, int length,
    int linesAdded, int line, int foldLevelNow, int foldLevelPrev) {
    emit modified(position, modification_type, text, length,
        linesAdded, line, foldLevelNow, foldLevelPrev);
}

void ScintillaDocument::emit_style_needed(int pos) {
    emit style_needed(pos);
}

void ScintillaDocument::emit_lexer_changed() {
    emit lexer_changed();
}

void ScintillaDocument::emit_error_occurred(int status) {
    emit error_occurred(status);
}

Added qt/ScintillaEdit/ScintillaDocument.h.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// ScintillaDocument.h
// Wrapper for Scintilla document object so it can be manipulated independently.
// Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware

#ifndef SCINTILLADOCUMENT_H
#define SCINTILLADOCUMENT_H

#include <QObject>

class WatcherHelper;

#ifndef EXPORT_IMPORT_API
#ifdef WIN32
#ifdef MAKING_LIBRARY
#define EXPORT_IMPORT_API __declspec(dllexport)
#else
// Defining dllimport upsets moc
#define EXPORT_IMPORT_API __declspec(dllimport)
//#define EXPORT_IMPORT_API
#endif
#else
#define EXPORT_IMPORT_API
#endif
#endif

class EXPORT_IMPORT_API ScintillaDocument : public QObject
{
    Q_OBJECT

    void *pdoc;
    WatcherHelper *docWatcher;

public:
    explicit ScintillaDocument(QObject *parent = 0, void *pdoc_=0);
    virtual ~ScintillaDocument();
    void *pointer();

    int line_from_position(int pos);
    bool is_cr_lf(int pos);
    bool delete_chars(int pos, int len);
    int undo();
    int redo();
    bool can_undo();
    bool can_redo();
    void delete_undo_history();
    bool set_undo_collection(bool collect_undo);
    bool is_collecting_undo();
    void begin_undo_action();
    void end_undo_action();
    void set_save_point();
    bool is_save_point();
    void set_read_only(bool read_only);
    bool is_read_only();
    void insert_string(int position, QByteArray &str);
    QByteArray get_char_range(int position, int length);
    char style_at(int position);
    int line_start(int lineno);
    int line_end(int lineno);
    int line_end_position(int pos);
    int length();
    int lines_total();
    void start_styling(int position, char flags);
    bool set_style_for(int length, char style);
    int get_end_styled();
    void ensure_styled_to(int position);
    void set_current_indicator(int indic);
    void decoration_fill_range(int position, int value, int fillLength);
    int decorations_value_at(int indic, int position);
    int decorations_start(int indic, int position);
    int decorations_end(int indic, int position);
    int get_code_page();
    void set_code_page(int code_page);
    int move_position_outside_char(int pos, int move_dir, bool check_line_end);

private:
    void emit_modify_attempt();
    void emit_save_point(bool atSavePoint);
    void emit_modified(int position, int modification_type, const QByteArray& text, int length,
	int linesAdded, int line, int foldLevelNow, int foldLevelPrev);
    void emit_style_needed(int pos);
    void emit_lexer_changed();
    void emit_error_occurred(int status);

signals:
    void modify_attempt();
    void save_point(bool atSavePoint);
    void modified(int position, int modification_type, const QByteArray& text, int length,
	int linesAdded, int line, int foldLevelNow, int foldLevelPrev);
    void style_needed(int pos);
    void lexer_changed();
    void error_occurred(int status);

    friend class WatcherHelper;

};

#endif // SCINTILLADOCUMENT_H

Added qt/ScintillaEdit/ScintillaEdit.cpp.template.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// ScintillaEdit.cpp
// Extended version of ScintillaEditBase with a method for each API
// Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware

#include "ScintillaEdit.h"

ScintillaEdit::ScintillaEdit(QWidget *parent) : ScintillaEditBase(parent) {
}

ScintillaEdit::~ScintillaEdit() {
}

QByteArray ScintillaEdit::TextReturner(int message, uptr_t wParam) const {
    int length = send(message, wParam, 0);
    QByteArray ba(length, '\0');
    send(message, wParam, (sptr_t)ba.data());
    // Remove extra NULs
    if (ba.size() > 0 && ba.at(ba.size()-1) == 0)
        ba.chop(1);
    return ba;
}

QPair<int, int>ScintillaEdit::find_text(int flags, const char *text, int cpMin, int cpMax) {
    struct TextToFind ft = {{0, 0}, 0, {0, 0}};
    ft.chrg.cpMin = cpMin;
    ft.chrg.cpMax = cpMax;
    ft.chrgText.cpMin = cpMin;
    ft.chrgText.cpMax = cpMax;
    ft.lpstrText = const_cast<char *>(text);

    send(SCI_FINDTEXT, flags, (uptr_t) (&ft));

    return QPair<int,int>(ft.chrgText.cpMin, ft.chrgText.cpMax);
}

QByteArray ScintillaEdit::get_text_range(int start, int end) {
    if (start > end)
        start = end;

    int length = end-start;
    QByteArray ba(length+1, '\0');
    struct TextRange tr = {{start, end}, ba.data()};

    length = send(SCI_GETTEXTRANGE, 0, (sptr_t)&tr);
    ba.chop(1); // Remove extra NUL

    return ba;
}

ScintillaDocument *ScintillaEdit::get_doc() {
    return new ScintillaDocument(0, (void *)send(SCI_GETDOCPOINTER, 0, 0));
}

void ScintillaEdit::set_doc(ScintillaDocument *pdoc_) {
    send(SCI_SETDOCPOINTER, 0, (sptr_t)(pdoc_->pointer()));
}

/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */

Added qt/ScintillaEdit/ScintillaEdit.h.template.































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// ScintillaEdit.h
// Extended version of ScintillaEditBase with a method for each API
// Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware

#ifndef SCINTILLAEDIT_H
#define SCINTILLAEDIT_H

#include <QPair>

#include "ScintillaEditBase.h"
#include "ScintillaDocument.h"

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

#ifndef EXPORT_IMPORT_API
#ifdef WIN32
#ifdef MAKING_LIBRARY
#define EXPORT_IMPORT_API __declspec(dllexport)
#else
// Defining dllimport upsets moc
#define EXPORT_IMPORT_API __declspec(dllimport)
//#define EXPORT_IMPORT_API
#endif
#else
#define EXPORT_IMPORT_API
#endif
#endif

class EXPORT_IMPORT_API ScintillaEdit : public ScintillaEditBase {
	Q_OBJECT

public:
	ScintillaEdit(QWidget *parent = 0);
	virtual ~ScintillaEdit();

	QByteArray TextReturner(int message, uptr_t wParam) const;

	QPair<int, int>find_text(int flags, const char *text, int cpMin, int cpMax);
	QByteArray get_text_range(int start, int end);
        ScintillaDocument *get_doc();
        void set_doc(ScintillaDocument *pdoc_);

	// Same as previous two methods but with Qt style names
	QPair<int, int>findText(int flags, const char *text, int cpMin, int cpMax) {
		return find_text(flags, text, cpMin, cpMax);
	}

	QByteArray textRange(int start, int end) {
		return get_text_range(start, end);
	}

/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */

};

#ifdef SCI_NAMESPACE
}
#endif

#endif /* SCINTILLAEDIT_H */

Added qt/ScintillaEdit/ScintillaEdit.pro.

















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#-------------------------------------------------
#
# Project created by QtCreator 2011-05-05T12:41:23
#
#-------------------------------------------------

QT       += core gui

TARGET = ScintillaEdit
TEMPLATE = lib
CONFIG += lib_bundle

VERSION = 3.3.0

SOURCES += \
    ScintillaEdit.cpp \
    ScintillaDocument.cpp \
    ../ScintillaEditBase/PlatQt.cpp \
    ../ScintillaEditBase/ScintillaQt.cpp \
    ../ScintillaEditBase/ScintillaEditBase.cpp \
    ../../src/XPM.cxx \
    ../../src/ViewStyle.cxx \
    ../../src/UniConversion.cxx \
    ../../src/Style.cxx \
    ../../src/Selection.cxx \
    ../../src/ScintillaBase.cxx \
    ../../src/RunStyles.cxx \
    ../../src/RESearch.cxx \
    ../../src/PositionCache.cxx \
    ../../src/PerLine.cxx \
    ../../src/LineMarker.cxx \
    ../../src/KeyMap.cxx \
    ../../src/Indicator.cxx \
    ../../src/ExternalLexer.cxx \
    ../../src/Editor.cxx \
    ../../src/Document.cxx \
    ../../src/Decoration.cxx \
    ../../src/ContractionState.cxx \
    ../../src/CharClassify.cxx \
    ../../src/CellBuffer.cxx \
    ../../src/Catalogue.cxx \
    ../../src/CallTip.cxx \
    ../../src/AutoComplete.cxx \
    ../../lexlib/WordList.cxx \
    ../../lexlib/StyleContext.cxx \
    ../../lexlib/PropSetSimple.cxx \
    ../../lexlib/LexerSimple.cxx \
    ../../lexlib/LexerNoExceptions.cxx \
    ../../lexlib/LexerModule.cxx \
    ../../lexlib/LexerBase.cxx \
    ../../lexlib/CharacterSet.cxx \
    ../../lexlib/Accessor.cxx \
    ../../lexers/*.cxx

HEADERS  += \
    ScintillaEdit.h \
    ScintillaDocument.h \
    ../ScintillaEditBase/ScintillaEditBase.h \
    ../ScintillaEditBase/ScintillaQt.h

OTHER_FILES +=

INCLUDEPATH += ../ScintillaEditBase ../../include ../../src ../../lexlib

DEFINES += SCINTILLA_QT=1 MAKING_LIBRARY=1 SCI_LEXER=1 _CRT_SECURE_NO_DEPRECATE=1

DESTDIR = ../../bin
DLLDESTDIR = ../../bin

macx {
	QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/
}

Added qt/ScintillaEdit/WidgetGen.py.





















































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/usr/bin/env python
# WidgetGen.py - regenerate the ScintillaWidgetCpp.cpp and ScintillaWidgetCpp.h files
# Check that API includes all gtkscintilla2 functions

import sys
import os
import getopt

scintillaDirectory = "../.."
scintillaIncludeDirectory = os.path.join(scintillaDirectory, "include")
sys.path.append(scintillaIncludeDirectory)
import Face

def Contains(s,sub):
	return s.find(sub) != -1

def underscoreName(s):
	# Name conversion fixes to match gtkscintilla2
	irregular = ['WS', 'EOL', 'AutoC', 'KeyWords', 'BackSpace', 'UnIndents', 'RE', 'RGBA']
	for word in irregular:
		replacement = word[0] + word[1:].lower()
		s = s.replace(word, replacement)

	out = ""
	for c in s:
		if c.isupper():
			if out:
				out += "_"
			out += c.lower()
		else:
			out += c
	return out

def normalisedName(s, options, role=None):
	if options["qtStyle"]:
		if role == "get":
			s = s.replace("Get", "")
		return s[0].lower() + s[1:]
	else:
		return underscoreName(s)

typeAliases = {
	"position": "int",
	"colour": "int",
	"keymod": "int",
	"string": "const char *",
	"stringresult": "const char *",
	"cells": "const char *",
}

def cppAlias(s):
	if s in typeAliases:
		return typeAliases[s]
	else:
		return s

understoodTypes = ["", "void", "int", "bool", "position",
	"colour", "keymod", "string", "stringresult", "cells"]

def checkTypes(name, v):
	understandAllTypes = True
	if v["ReturnType"] not in understoodTypes:
		#~ print("Do not understand", v["ReturnType"], "for", name)
		understandAllTypes = False
	if v["Param1Type"] not in understoodTypes:
		#~ print("Do not understand", v["Param1Type"], "for", name)
		understandAllTypes = False
	if v["Param2Type"] not in understoodTypes:
		#~ print("Do not understand", v["Param2Type"], "for", name)
		understandAllTypes = False
	return understandAllTypes

def arguments(v, stringResult, options):
	ret = ""
	p1Type = cppAlias(v["Param1Type"])
	if p1Type:
		ret = ret + p1Type + " " + normalisedName(v["Param1Name"], options)
	p2Type = cppAlias(v["Param2Type"])
	if p2Type and not stringResult:
		if p1Type:
			ret = ret + ", "
		ret = ret + p2Type + " " + normalisedName(v["Param2Name"], options)
	return ret

def printPyFile(f,out, options):
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["val"]:
				out.write(name + "=" + v["Value"] + "\n")
			if feat in ["evt"]:
				out.write("SCN_" + name.upper() + "=" + v["Value"] + "\n")

def printHFile(f,out, options):
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["fun", "get", "set"]:
				if checkTypes(name, v):
					constDeclarator = " const" if feat == "get" else ""
					returnType = cppAlias(v["ReturnType"])
					stringResult = v["Param2Type"] == "stringresult"
					if stringResult:
						returnType = "QByteArray"
					out.write("\t" + returnType + " " + normalisedName(name, options, feat) + "(")
					out.write(arguments(v, stringResult, options))
					out.write(")" + constDeclarator + ";\n")

def methodNames(f, options):
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["fun", "get", "set"]:
				if checkTypes(name, v):
					yield normalisedName(name, options)

def printCPPFile(f,out, options):
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["fun", "get", "set"]:
				if checkTypes(name, v):
					constDeclarator = " const" if feat == "get" else ""
					featureDefineName = "SCI_" + name.upper()
					returnType = cppAlias(v["ReturnType"])
					stringResult = v["Param2Type"] == "stringresult"
					if stringResult:
						returnType = "QByteArray"
					returnStatement = ""
					if returnType != "void":
						returnStatement = "return "
					out.write(returnType + " ScintillaEdit::" + normalisedName(name, options, feat) + "(")
					out.write(arguments(v, stringResult, options))
					out.write(")" + constDeclarator + " {\n")
					if stringResult:
						out.write("    " + returnStatement + "TextReturner(" + featureDefineName + ", ")
						if "*" in cppAlias(v["Param1Type"]):
							out.write("(uptr_t)")
						if v["Param1Name"]:
							out.write(normalisedName(v["Param1Name"], options))
						else:
							out.write("0")
						out.write(");\n")
					else:
						out.write("    " + returnStatement + "send(" + featureDefineName + ", ")
						if "*" in cppAlias(v["Param1Type"]):
							out.write("(uptr_t)")
						if v["Param1Name"]:
							out.write(normalisedName(v["Param1Name"], options))
						else:
							out.write("0")
						out.write(", ")
						if "*" in cppAlias(v["Param2Type"]):
							out.write("(sptr_t)")
						if v["Param2Name"]:
							out.write(normalisedName(v["Param2Name"], options))
						else:
							out.write("0")
						out.write(");\n")
					out.write("}\n")
					out.write("\n")

def CopyWithInsertion(input, output, genfn, definition, options):
	copying = 1
	for line in input.readlines():
		if copying:
			output.write(line)
		if "/* ++Autogenerated" in line or "# ++Autogenerated" in line or "<!-- ++Autogenerated" in line:
			copying = 0
			genfn(definition, output, options)
		# ~~ form needed as XML comments can not contain --
		if "/* --Autogenerated" in line or "# --Autogenerated" in line or "<!-- ~~Autogenerated" in line:
			copying = 1
			output.write(line)

def contents(filename):
	with open(filename, "U") as f:
		t = f.read()
		return t

def Generate(templateFile, destinationFile, genfn, definition, options):
	inText = contents(templateFile)
	try:
		currentText = contents(destinationFile)
	except IOError:
		currentText = ""
	tempname = "WidgetGen.tmp"
	with open(tempname, "w") as out:
		with open(templateFile, "U") as hfile:
			CopyWithInsertion(hfile, out, genfn, definition, options)
	outText = contents(tempname)
	if currentText == outText:
		os.unlink(tempname)
	else:
		try:
			os.unlink(destinationFile)
		except OSError:
			# Will see failure if file does not yet exist
			pass
		os.rename(tempname, destinationFile)

def gtkNames():
	# The full path on my machine: should be altered for anyone else
	p = "C:/Users/Neil/Downloads/wingide-source-4.0.1-1/wingide-source-4.0.1-1/external/gtkscintilla2/gtkscintilla.c"
	with open(p) as f:
		for l in f.readlines():
			if "gtk_scintilla_" in l:
				name = l.split()[1][14:]
				if '(' in name:
					name = name.split('(')[0]
					yield name

def usage():
	print("WidgetGen.py [-c|--clean][-h|--help][-u|--underscore-names]")
	print("")
	print("Generate full APIs for ScintillaEdit class and ScintillaConstants.py.")
	print("")
	print("options:")
	print("")
	print("-c --clean remove all generated code from files")
	print("-h --help  display this text")
	print("-u --underscore-names  use method_names consistent with GTK+ standards")

def readInterface(cleanGenerated):
	f = Face.Face()
	if not cleanGenerated:
		f.ReadFromFile("../../include/Scintilla.iface")
	return f

def main(argv):
	# Using local path for gtkscintilla2 so don't default to checking
	checkGTK = False
	cleanGenerated = False
	qtStyleInterface = True
	# The --gtk-check option checks for full coverage of the gtkscintilla2 API but
	# depends on a particular directory so is not mentioned in --help.
	opts, args = getopt.getopt(argv, "hcgu", ["help", "clean", "gtk-check", "underscore-names"])
	for opt, arg in opts:
		if opt in ("-h", "--help"):
			usage()
			sys.exit()
		elif opt in ("-c", "--clean"):
			cleanGenerated = True
		elif opt in ("-g", "--gtk-check"):
			checkGTK = True
		elif opt in ("-u", "--underscore-names"):
			qtStyleInterface = False

	options = {"qtStyle": qtStyleInterface}
	f = readInterface(cleanGenerated)
	try:
		Generate("ScintillaEdit.cpp.template", "ScintillaEdit.cpp", printCPPFile, f, options)
		Generate("ScintillaEdit.h.template", "ScintillaEdit.h", printHFile, f, options)
		Generate("../ScintillaEditPy/ScintillaConstants.py.template",
			"../ScintillaEditPy/ScintillaConstants.py",
			printPyFile, f, options)
		if checkGTK:
			names = set(methodNames(f))
			#~ print("\n".join(names))
			namesGtk = set(gtkNames())
			for name in namesGtk:
				if name not in names:
					print(name, "not found in Qt version")
			for name in names:
				if name not in namesGtk:
					print(name, "not found in GTK+ version")
	except:
		raise

	if cleanGenerated:
		for file in ["ScintillaEdit.cpp", "ScintillaEdit.h", "../ScintillaEditPy/ScintillaConstants.py"]:
			try:
				os.remove(file)
			except OSError:
				pass
		
if __name__ == "__main__":
	main(sys.argv[1:])

Added qt/ScintillaEdit/WidgetGen.pyc.

cannot compute difference between binary files

Added qt/ScintillaEditBase/Notes.txt.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Issues with Scintilla for Qt

Qt reports character descenders are 1 pixel shorter than they really are.
There is a tweak in the code to add a pixel in. This may have to be reviewed for Qt 5.
There's a comment in the Qt code for Windows:
       // ### we substract 1 to even out the historical +1 in QFontMetrics's
       // ### height=asc+desc+1 equation. Fix in Qt5.

The clocks used aren't great. QTime is a time since midnight clock so wraps around and
is only accurate to, at best, milliseconds.

On OS X drawing text into a pixmap moves it around 1 pixel to the right compared to drawing
it directly onto a window. Buffered drawing turned off by default to avoid this.
Reported as QTBUG-19483.

Only one QPainter can be active on any widget at a time. Scintilla only draws into one
widget but reenters for measurement.

Added qt/ScintillaEditBase/PlatQt.cpp.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// Scintilla platform layer for Qt

#include "PlatQt.h"
#include "Scintilla.h"
#include "FontQuality.h"

#include <QApplication>
#include <QFont>
#include <QColor>
#include <QRect>
#include <QPaintDevice>
#include <QPaintEngine>
#include <QWidget>
#include <QPixmap>
#include <QPainter>
#include <QMenu>
#include <QAction>
#include <QTime>
#include <QMessageBox>
#include <QTextCodec>
#include <QListWidget>
#include <QVarLengthArray>
#include <QScrollBar>
#include <QDesktopWidget>
#include <QTextLayout>
#include <QTextLine>
#include <QLibrary>
#include <cstdio>

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

//----------------------------------------------------------------------

// Convert from a Scintilla characterSet value to a Qt codec name.
const char *CharacterSetID(int characterSet)
{
	switch (characterSet) {
		//case SC_CHARSET_ANSI:
		//	return "";
	case SC_CHARSET_DEFAULT:
		return "ISO 8859-1";
	case SC_CHARSET_BALTIC:
		return "ISO 8859-13";
	case SC_CHARSET_CHINESEBIG5:
		return "Big5";
	case SC_CHARSET_EASTEUROPE:
		return "ISO 8859-2";
	case SC_CHARSET_GB2312:
		return "GB18030-0";
	case SC_CHARSET_GREEK:
		return "ISO 8859-7";
	case SC_CHARSET_HANGUL:
		return "CP949";
	case SC_CHARSET_MAC:
		return "Apple Roman";
		//case SC_CHARSET_OEM:
		//	return "ASCII";
	case SC_CHARSET_RUSSIAN:
		return "KOI8-R";
	case SC_CHARSET_CYRILLIC:
		return "Windows-1251";
	case SC_CHARSET_SHIFTJIS:
		return "Shift-JIS";
		//case SC_CHARSET_SYMBOL:
		//        return "";
	case SC_CHARSET_TURKISH:
		return "ISO 8859-9";
		//case SC_CHARSET_JOHAB:
		//        return "CP1361";
	case SC_CHARSET_HEBREW:
		return "ISO 8859-8";
	case SC_CHARSET_ARABIC:
		return "ISO 8859-6";
	case SC_CHARSET_VIETNAMESE:
		return "Windows-1258";
	case SC_CHARSET_THAI:
		return "TIS-620";
	case SC_CHARSET_8859_15:
		return "ISO 8859-15";
	default:
		return "ISO 8859-1";
	}
}

class FontAndCharacterSet {
public:
	int characterSet;
	QFont *pfont;
	FontAndCharacterSet(int characterSet_, QFont *pfont):
		characterSet(characterSet_), pfont(pfont) {
	}
	~FontAndCharacterSet() {
		delete pfont;
		pfont = 0;
	}
};

static int FontCharacterSet(Font &f)
{
	return reinterpret_cast<FontAndCharacterSet *>(f.GetID())->characterSet;
}

static QFont *FontPointer(Font &f)
{
	return reinterpret_cast<FontAndCharacterSet *>(f.GetID())->pfont;
}

Font::Font() : fid(0) {}

Font::~Font()
{
	delete reinterpret_cast<FontAndCharacterSet *>(fid);
	fid = 0;
}

static QFont::StyleStrategy ChooseStrategy(int eff)
{
	switch (eff) {
		case SC_EFF_QUALITY_DEFAULT:         return QFont::PreferDefault;
		case SC_EFF_QUALITY_NON_ANTIALIASED: return QFont::NoAntialias;
		case SC_EFF_QUALITY_ANTIALIASED:     return QFont::PreferAntialias;
		case SC_EFF_QUALITY_LCD_OPTIMIZED:   return QFont::PreferAntialias;
		default:                             return QFont::PreferDefault;
	}
}

void Font::Create(const FontParameters &fp)
{
	Release();

	QFont *font = new QFont;
	font->setStyleStrategy(ChooseStrategy(fp.extraFontFlag));
	font->setFamily(QString::fromUtf8(fp.faceName));
	font->setPointSize(fp.size);
	font->setBold(fp.weight > 500);
	font->setItalic(fp.italic);

	fid = new FontAndCharacterSet(fp.characterSet, font);
}

void Font::Release()
{
	if (fid)
		delete reinterpret_cast<FontAndCharacterSet *>(fid);

	fid = 0;
}


SurfaceImpl::SurfaceImpl()
: device(0), painter(0), deviceOwned(false), painterOwned(false), x(0), y(0),
	  unicodeMode(false), codePage(0), codecName(0), codec(0)
{}

SurfaceImpl::~SurfaceImpl()
{
	Release();
}

void SurfaceImpl::Init(WindowID wid)
{
	Release();
	device = static_cast<QWidget *>(wid);
}

void SurfaceImpl::Init(SurfaceID sid, WindowID /*wid*/)
{
	Release();
	device = static_cast<QPaintDevice *>(sid);
}

void SurfaceImpl::InitPixMap(int width,
        int height,
        Surface * /*surface*/,
        WindowID /*wid*/)
{
	Release();
	if (width < 1) width = 1;
	if (height < 1) height = 1;
	deviceOwned = true;
	device = new QPixmap(width, height);
}

void SurfaceImpl::Release()
{
	if (painterOwned && painter) {
		delete painter;
	}

	if (deviceOwned && device) {
		delete device;
	}

	device = 0;
	painter = 0;
	deviceOwned = false;
	painterOwned = false;
}

bool SurfaceImpl::Initialised()
{
	return device != 0;
}

void SurfaceImpl::PenColour(ColourDesired fore)
{
	QPen penOutline(QColorFromCA(fore));
	penOutline.setCapStyle(Qt::FlatCap);
	GetPainter()->setPen(penOutline);
}

void SurfaceImpl::BrushColour(ColourDesired back)
{
	GetPainter()->setBrush(QBrush(QColorFromCA(back)));
}

void SurfaceImpl::SetCodec(Font &font)
{
	if (font.GetID()) {
		const char *csid = "UTF-8";
		if (!unicodeMode)
			csid = CharacterSetID(FontCharacterSet(font));
		if (csid != codecName) {
			codecName = csid;
			codec = QTextCodec::codecForName(csid);
		}
	}
}

void SurfaceImpl::SetFont(Font &font)
{
	if (font.GetID()) {
		GetPainter()->setFont(*FontPointer(font));
		SetCodec(font);
	}
}

int SurfaceImpl::LogPixelsY()
{
	return device->logicalDpiY();
}

int SurfaceImpl::DeviceHeightFont(int points)
{
	return points;
}

void SurfaceImpl::MoveTo(int x_, int y_)
{
	x = x_;
	y = y_;
}

void SurfaceImpl::LineTo(int x_, int y_)
{
	QLineF line(x, y, x_, y_);
	GetPainter()->drawLine(line);
	x = x_;
	y = y_;
}

void SurfaceImpl::Polygon(Point *pts,
                          int npts,
                          ColourDesired fore,
                          ColourDesired back)
{
	PenColour(fore);
	BrushColour(back);

	QPoint *qpts = new QPoint[npts];
	for (int i = 0; i < npts; i++) {
		qpts[i] = QPoint(pts[i].x, pts[i].y);
	}

	GetPainter()->drawPolygon(qpts, npts);
	delete [] qpts;
}

void SurfaceImpl::RectangleDraw(PRectangle rc,
                                ColourDesired fore,
                                ColourDesired back)
{
	PenColour(fore);
	BrushColour(back);
	QRect rect = QRect(rc.left, rc.top, rc.Width() - 1, rc.Height() - 1);
	GetPainter()->drawRect(rect);
}

void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back)
{
	BrushColour(back);
	GetPainter()->setPen(Qt::NoPen);
	GetPainter()->drawRect(QRectFromPRect(rc));
}

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern)
{
	// Tile pattern over rectangle
	SurfaceImpl *surface = static_cast<SurfaceImpl *>(&surfacePattern);
	// Currently assumes 8x8 pattern
	int widthPat = 8;
	int heightPat = 8;
	for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
		int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
		for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
			int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
			QRect source(0, 0, widthx, heighty);
			QRect target(xTile, yTile, widthx, heighty);
			QPixmap *pixmap = static_cast<QPixmap *>(surface->GetPaintDevice());
			GetPainter()->drawPixmap(target, *pixmap, source);
		}
	}
}

void SurfaceImpl::RoundedRectangle(PRectangle rc,
                                   ColourDesired fore,
                                   ColourDesired back)
{
	PenColour(fore);
	BrushColour(back);
	GetPainter()->drawRoundRect(QRectFromPRect(rc));
}

void SurfaceImpl::AlphaRectangle(PRectangle rc,
                                 int cornerSize,
                                 ColourDesired fill,
                                 int alphaFill,
                                 ColourDesired outline,
                                 int alphaOutline,
                                 int /*flags*/)
{
	QColor qOutline = QColorFromCA(outline);
	qOutline.setAlpha(alphaOutline);
	GetPainter()->setPen(QPen(qOutline));

	QColor qFill = QColorFromCA(fill);
	qFill.setAlpha(alphaFill);
	GetPainter()->setBrush(QBrush(qFill));

	// A radius of 1 shows no curve so add 1
	qreal radius = cornerSize+1;
	QRect rect(rc.left, rc.top, rc.Width() - 1, rc.Height() - 1);
	GetPainter()->drawRoundedRect(rect, radius, radius);
}

static std::vector<unsigned char> ImageByteSwapped(int width, int height, const unsigned char *pixelsImage)
{
	// Input is RGBA, but Format_ARGB32 is BGRA, so swap the red bytes and blue bytes
	size_t bytes = width * height * 4;
	std::vector<unsigned char> imageBytes(pixelsImage, pixelsImage+bytes);
	for (size_t i=0; i<bytes; i+=4)
		std::swap(imageBytes[i], imageBytes[i+2]);
	return imageBytes;
}

void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage)
{
	std::vector<unsigned char> imageBytes = ImageByteSwapped(width, height, pixelsImage);
	QImage image(&imageBytes[0], width, height, QImage::Format_ARGB32);
	QPoint pt(rc.left, rc.top);
	GetPainter()->drawImage(pt, image);
}

void SurfaceImpl::Ellipse(PRectangle rc,
                          ColourDesired fore,
                          ColourDesired back)
{
	PenColour(fore);
	BrushColour(back);
	GetPainter()->drawEllipse(QRectFromPRect(rc));
}

void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource)
{
	SurfaceImpl *source = static_cast<SurfaceImpl *>(&surfaceSource);
	QPixmap *pixmap = static_cast<QPixmap *>(source->GetPaintDevice());

	GetPainter()->drawPixmap(rc.left, rc.top, *pixmap, from.x, from.y, -1, -1);
}

void SurfaceImpl::DrawTextNoClip(PRectangle rc,
                                 Font &font,
                                 XYPOSITION ybase,
                                 const char *s,
                                 int len,
                                 ColourDesired fore,
                                 ColourDesired back)
{
	SetFont(font);
	PenColour(fore);

	GetPainter()->setBackground(QColorFromCA(back));
	GetPainter()->setBackgroundMode(Qt::OpaqueMode);
	QString su = codec->toUnicode(s, len);
	GetPainter()->drawText(QPointF(rc.left, ybase), su);
}

void SurfaceImpl::DrawTextClipped(PRectangle rc,
                                  Font &font,
                                  XYPOSITION ybase,
                                  const char *s,
                                  int len,
                                  ColourDesired fore,
                                  ColourDesired back)
{
	SetClip(rc);
	DrawTextNoClip(rc, font, ybase, s, len, fore, back);
	GetPainter()->setClipping(false);
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc,
                                      Font &font,
                                      XYPOSITION ybase,
                                      const char *s,
                                      int len,
        ColourDesired fore)
{
	SetFont(font);
	PenColour(fore);

	GetPainter()->setBackgroundMode(Qt::TransparentMode);
	QString su = codec->toUnicode(s, len);
	GetPainter()->drawText(QPointF(rc.left, ybase), su);
}

void SurfaceImpl::SetClip(PRectangle rc)
{
	GetPainter()->setClipRect(QRectFromPRect(rc));
}

static size_t utf8LengthFromLead(unsigned char uch)
{
	if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
		return 4;
	} else if (uch >= (0x80 + 0x40 + 0x20)) {
		return 3;
	} else if (uch >= (0x80)) {
		return 2;
	} else {
		return 1;
	}
}

void SurfaceImpl::MeasureWidths(Font &font,
                                const char *s,
                                int len,
                                XYPOSITION *positions)
{
	if (!font.GetID())
		return;
	SetCodec(font);
	QString su = codec->toUnicode(s, len);
	QTextLayout tlay(su, *FontPointer(font));
	tlay.beginLayout();
	QTextLine tl = tlay.createLine();
	tlay.endLayout();
	if (unicodeMode) {
		int fit = su.size();
		int ui=0;
		const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
		int i=0;
		while (ui<fit) {
			size_t lenChar = utf8LengthFromLead(us[i]);
			size_t codeUnits = (lenChar < 4) ? 1 : 2;
			qreal xPosition = tl.cursorToX(ui+codeUnits);
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = qRound(xPosition);
			}
			ui += codeUnits;
		}
		int lastPos = 0;
		if (i > 0)
			lastPos = positions[i-1];
		while (i<len) {
			positions[i++] = lastPos;
		}
	} else if (codePage) {
		// DBCS
		int ui = 0;
		for (int i=0; i<len;) {
			size_t lenChar = Platform::IsDBCSLeadByte(codePage, s[i]) ? 2 : 1;
			qreal xPosition = tl.cursorToX(ui+1);
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = qRound(xPosition);
			}
			ui++;
		}
	} else {
		// Single byte encoding
		for (int i=0; i<len; i++) {
			positions[i] = qRound(tl.cursorToX(i+1));
		}
	}
}

XYPOSITION SurfaceImpl::WidthText(Font &font, const char *s, int len)
{
	QFontMetrics metrics(*FontPointer(font), device);
	SetCodec(font);
	QString string = codec->toUnicode(s, len);
	return metrics.width(string);
}

XYPOSITION SurfaceImpl::WidthChar(Font &font, char ch)
{
	QFontMetrics metrics(*FontPointer(font), device);
	return metrics.width(ch);
}

XYPOSITION SurfaceImpl::Ascent(Font &font)
{
	QFontMetrics metrics(*FontPointer(font), device);
	return metrics.ascent();
}

XYPOSITION SurfaceImpl::Descent(Font &font)
{
	QFontMetrics metrics(*FontPointer(font), device);
	// Qt returns 1 less than true descent
	// See: QFontEngineWin::descent which says:
	// ### we substract 1 to even out the historical +1 in QFontMetrics's
	// ### height=asc+desc+1 equation. Fix in Qt5.
	return metrics.descent() + 1;
}

XYPOSITION SurfaceImpl::InternalLeading(Font & /* font */)
{
	return 0;
}

XYPOSITION SurfaceImpl::ExternalLeading(Font &font)
{
	QFontMetrics metrics(*FontPointer(font), device);
	return metrics.leading();
}

XYPOSITION SurfaceImpl::Height(Font &font)
{
	QFontMetrics metrics(*FontPointer(font), device);
	return metrics.height();
}

XYPOSITION SurfaceImpl::AverageCharWidth(Font &font)
{
	QFontMetrics metrics(*FontPointer(font), device);
	return metrics.averageCharWidth();
}

void SurfaceImpl::FlushCachedState()
{
	if (device->paintingActive()) {
		GetPainter()->setPen(QPen());
		GetPainter()->setBrush(QBrush());
	}
}

void SurfaceImpl::SetUnicodeMode(bool unicodeMode_)
{
	unicodeMode=unicodeMode_;
}

void SurfaceImpl::SetDBCSMode(int codePage_)
{
	codePage = codePage_;
}

QPaintDevice *SurfaceImpl::GetPaintDevice()
{
	return device;
}

QPainter *SurfaceImpl::GetPainter()
{
	Q_ASSERT(device);

	if (painter == 0) {
		if (device->paintingActive()) {
			painter = device->paintEngine()->painter();
		} else {
			painterOwned = true;
			painter = new QPainter(device);
		}

		// Set text antialiasing unconditionally.
		// The font's style strategy will override.
		painter->setRenderHint(QPainter::TextAntialiasing, true);
	}

	return painter;
}

Surface *Surface::Allocate(int)
{
	return new SurfaceImpl;
}


//----------------------------------------------------------------------

namespace {
QWidget *window(WindowID wid)
{
	return static_cast<QWidget *>(wid);
}
}

Window::~Window() {}

void Window::Destroy()
{
	if (wid)
		delete window(wid);

	wid = 0;
}

bool Window::HasFocus()
{
	return wid ? window(wid)->hasFocus() : false;
}

PRectangle Window::GetPosition()
{
	// Before any size allocated pretend its 1000 wide so not scrolled
	return wid ? PRectFromQRect(window(wid)->frameGeometry()) : PRectangle(0, 0, 1000, 1000);
}

void Window::SetPosition(PRectangle rc)
{
	if (wid)
		window(wid)->setGeometry(QRectFromPRect(rc));
}

void Window::SetPositionRelative(PRectangle rc, Window relativeTo)
{
	QPoint oPos = window(relativeTo.wid)->mapToGlobal(QPoint(0,0));
	int ox = oPos.x();
	int oy = oPos.y();
	ox += rc.left;
	if (ox < 0)
		ox = 0;
	oy += rc.top;
	if (oy < 0)
		oy = 0;

	QDesktopWidget *desktop = QApplication::desktop();
	QRect rectDesk = desktop->availableGeometry(window(wid));
	/* do some corrections to fit into screen */
	int sizex = rc.right - rc.left;
	int sizey = rc.bottom - rc.top;
	int screenWidth = rectDesk.width();
	int screenHeight = rectDesk.height();
	if (sizex > screenWidth)
		ox = 0; /* the best we can do */
	else if (ox + sizex > screenWidth)
		ox = screenWidth - sizex;
	if (oy + sizey > screenHeight)
		oy = screenHeight - sizey;

	Q_ASSERT(wid);
	window(wid)->move(ox, oy);
	window(wid)->resize(sizex, sizey);
}

PRectangle Window::GetClientPosition()
{
	// The client position is the window position
	return GetPosition();
}

void Window::Show(bool show)
{
	if (wid)
		window(wid)->setVisible(show);
}

void Window::InvalidateAll()
{
	if (wid)
		window(wid)->update();
}

void Window::InvalidateRectangle(PRectangle rc)
{
	if (wid)
		window(wid)->update(QRectFromPRect(rc));
}

void Window::SetFont(Font &font)
{
	if (wid)
		window(wid)->setFont(*FontPointer(font));
}

void Window::SetCursor(Cursor curs)
{
	if (wid) {
		Qt::CursorShape shape;

		switch (curs) {
			case cursorText:  shape = Qt::IBeamCursor;        break;
			case cursorArrow: shape = Qt::ArrowCursor;        break;
			case cursorUp:    shape = Qt::UpArrowCursor;      break;
			case cursorWait:  shape = Qt::WaitCursor;         break;
			case cursorHoriz: shape = Qt::SizeHorCursor;      break;
			case cursorVert:  shape = Qt::SizeVerCursor;      break;
			case cursorHand:  shape = Qt::PointingHandCursor; break;
			default:          shape = Qt::ArrowCursor;        break;
		}

		QCursor cursor = QCursor(shape);

		if (curs != cursorLast) {
			window(wid)->setCursor(cursor);
			cursorLast = curs;
		}
	}
}

void Window::SetTitle(const char *s)
{
	if (wid)
		window(wid)->setWindowTitle(s);
}

/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
   window coordinates */
PRectangle Window::GetMonitorRect(Point pt)
{
	QPoint originGlobal = window(wid)->mapToGlobal(QPoint(0, 0));
	QPoint posGlobal = window(wid)->mapToGlobal(QPoint(pt.x, pt.y));
	QDesktopWidget *desktop = QApplication::desktop();
	QRect rectScreen = desktop->availableGeometry(posGlobal);
	rectScreen.moveLeft(-originGlobal.x());
	rectScreen.moveTop(-originGlobal.y());
	return PRectangle(rectScreen.left(), rectScreen.top(),
	        rectScreen.right(), rectScreen.bottom());
}


//----------------------------------------------------------------------

class ListBoxImpl : public ListBox {
public:
	ListBoxImpl();
	~ListBoxImpl();

	virtual void SetFont(Font &font);
	virtual void Create(Window &parent, int ctrlID, Point location,
						int lineHeight, bool unicodeMode, int technology);
	virtual void SetAverageCharWidth(int width);
	virtual void SetVisibleRows(int rows);
	virtual int GetVisibleRows() const;
	virtual PRectangle GetDesiredRect();
	virtual int CaretFromEdge();
	virtual void Clear();
	virtual void Append(char *s, int type = -1);
	virtual int Length();
	virtual void Select(int n);
	virtual int GetSelection();
	virtual int Find(const char *prefix);
	virtual void GetValue(int n, char *value, int len);
	virtual void RegisterImage(int type, const char *xpmData);
	virtual void RegisterRGBAImage(int type, int width, int height,
		const unsigned char *pixelsImage);
	virtual void ClearRegisteredImages();
	virtual void SetDoubleClickAction(CallBackAction action, void *data);
	virtual void SetList(const char *list, char separator, char typesep);
private:
	bool unicodeMode;
	int visibleRows;
	QMap<int,QPixmap> images;
};

class ListWidget : public QListWidget {
public:
	ListWidget(QWidget *parent);
	virtual ~ListWidget();

	void setDoubleClickAction(CallBackAction action, void *data);

protected:
	virtual void mouseDoubleClickEvent(QMouseEvent *event);
	virtual QStyleOptionViewItem viewOptions() const;

private:
	CallBackAction doubleClickAction;
	void *doubleClickActionData;
};


ListBoxImpl::ListBoxImpl()
: unicodeMode(false), visibleRows(5)
{}

ListBoxImpl::~ListBoxImpl() {}

void ListBoxImpl::Create(Window &parent,
                         int /*ctrlID*/,
                         Point location,
                         int /*lineHeight*/,
                         bool unicodeMode_,
			 int)
{
	unicodeMode = unicodeMode_;

	QWidget *qparent = static_cast<QWidget *>(parent.GetID());
	ListWidget *list = new ListWidget(qparent);

#if defined(Q_OS_WIN)
	// On Windows, Qt::ToolTip causes a crash when the list is clicked on
	// so Qt::Tool is used.
	list->setParent(0, Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
#else
	// On OS X, Qt::Tool takes focus so main window loses focus so
	// keyboard stops working. Qt::ToolTip works but its only really
	// documented for tooltips.
	// On Linux / X this setting allows clicking on list items.
	list->setParent(0, Qt::ToolTip | Qt::FramelessWindowHint);
#endif
	list->setAttribute(Qt::WA_ShowWithoutActivating);
	list->setFocusPolicy(Qt::NoFocus);
	list->setUniformItemSizes(true);
	list->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	list->move(location.x, location.y);

	wid = list;
}

void ListBoxImpl::SetFont(Font &font)
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	list->setFont(*FontPointer(font));
}

void ListBoxImpl::SetAverageCharWidth(int /*width*/) {}

void ListBoxImpl::SetVisibleRows(int rows)
{
	visibleRows = rows;
}

int ListBoxImpl::GetVisibleRows() const
{
	return visibleRows;
}

PRectangle ListBoxImpl::GetDesiredRect()
{
	ListWidget *list = static_cast<ListWidget *>(wid);

	int rows = Length();
	if (rows == 0 || rows > visibleRows) {
		rows = visibleRows;
	}
	int rowHeight = list->sizeHintForRow(0);
	int height = (rows * rowHeight) + (2 * list->frameWidth());

	QStyle *style = QApplication::style();
	int width = list->sizeHintForColumn(0) + (2 * list->frameWidth());
	if (Length() > rows) {
		width += style->pixelMetric(QStyle::PM_ScrollBarExtent);
	}

	return PRectangle(0, 0, width, height);
}

int ListBoxImpl::CaretFromEdge()
{
	ListWidget *list = static_cast<ListWidget *>(wid);

	int maxIconWidth = 0;
	foreach (QPixmap im, images) {
		if (maxIconWidth < im.width())
			maxIconWidth = im.width();
	}

	// The '7' is from trial and error on Windows - there may be
	// a better programmatic way to find any padding factors.
	return maxIconWidth  + (2 * list->frameWidth()) + 7;
}

void ListBoxImpl::Clear()
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	list->clear();
}

void ListBoxImpl::Append(char *s, int type)
{
	ListWidget *list = static_cast<ListWidget *>(wid);

	QString str = unicodeMode ? QString::fromUtf8(s) : QString::fromLocal8Bit(s);
	QIcon icon;
	if (type >= 0) {
		Q_ASSERT(images.contains(type));
		icon = images.value(type);
	}
	new QListWidgetItem(icon, str, list);
}

int ListBoxImpl::Length()
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	return list->count();
}

void ListBoxImpl::Select(int n)
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	list->setCurrentRow(n);
}

int ListBoxImpl::GetSelection()
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	return list->currentRow();
}

int ListBoxImpl::Find(const char *prefix)
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	QString sPrefix = unicodeMode ? QString::fromUtf8(prefix) : QString::fromLocal8Bit(prefix);
	QList<QListWidgetItem *> ms = list->findItems(sPrefix, Qt::MatchStartsWith);

	int result = -1;
	if (!ms.isEmpty()) {
		result = list->row(ms.first());
	}

	return result;
}

void ListBoxImpl::GetValue(int n, char *value, int len)
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	QListWidgetItem *item = list->item(n);
	QString str = item->data(Qt::DisplayRole).toString();
	QByteArray bytes = unicodeMode ? str.toUtf8() : str.toLocal8Bit();

	strncpy(value, bytes.constData(), len);
	value[len-1] = '\0';
}

void ListBoxImpl::RegisterImage(int type, const char *xpmData)
{
	images[type] = QPixmap(reinterpret_cast<const char * const *>(xpmData));
}

void ListBoxImpl::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage)
{
	std::vector<unsigned char> imageBytes = ImageByteSwapped(width, height, pixelsImage);
	QImage image(&imageBytes[0], width, height, QImage::Format_ARGB32);
	images[type] = QPixmap::fromImage(image);
}

void ListBoxImpl::ClearRegisteredImages()
{
	images.clear();
}

void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data)
{
	ListWidget *list = static_cast<ListWidget *>(wid);
	list->setDoubleClickAction(action, data);
}

void ListBoxImpl::SetList(const char *list, char separator, char typesep)
{
	// This method is *not* platform dependent.
	// It is borrowed from the GTK implementation.
	Clear();
	int count = strlen(list) + 1;
	char *words = new char[count];
	if (words) {
		memcpy(words, list, count);
		char *startword = words;
		char *numword = NULL;
		int i = 0;
		for (; words[i]; i++) {
			if (words[i] == separator) {
				words[i] = '\0';
				if (numword)
					*numword = '\0';
				Append(startword, numword?atoi(numword + 1):-1);
				startword = words + i + 1;
				numword = NULL;
			} else if (words[i] == typesep) {
				numword = words + i;
			}
		}
		if (startword) {
			if (numword)
				*numword = '\0';
			Append(startword, numword?atoi(numword + 1):-1);
		}
		delete []words;
	}
}

ListBox::ListBox() {}

ListBox::~ListBox() {}

ListBox *ListBox::Allocate()
{
	return new ListBoxImpl();
}

ListWidget::ListWidget(QWidget *parent)
: QListWidget(parent), doubleClickAction(0), doubleClickActionData(0)
{}

ListWidget::~ListWidget() {}

void ListWidget::setDoubleClickAction(CallBackAction action, void *data)
{
	doubleClickAction = action;
	doubleClickActionData = data;
}

void ListWidget::mouseDoubleClickEvent(QMouseEvent * /* event */)
{
	if (doubleClickAction != 0) {
		doubleClickAction(doubleClickActionData);
	}
}

QStyleOptionViewItem ListWidget::viewOptions() const
{
	QStyleOptionViewItem result = QListWidget::viewOptions();
	result.state |= QStyle::State_Active;
	return result;
}

//----------------------------------------------------------------------

Menu::Menu() : mid(0) {}

void Menu::CreatePopUp()
{
	Destroy();
	mid = new QMenu();
}

void Menu::Destroy()
{
	if (mid) {
		QMenu *menu = static_cast<QMenu *>(mid);
		delete menu;
	}
	mid = 0;
}

void Menu::Show(Point pt, Window & /*w*/)
{
	QMenu *menu = static_cast<QMenu *>(mid);
	menu->exec(QPoint(pt.x, pt.y));
	Destroy();
}

//----------------------------------------------------------------------

class DynamicLibraryImpl : public DynamicLibrary {
protected:
	QLibrary *lib;
public:
	DynamicLibraryImpl(const char *modulePath) {
		QString path = QString::fromUtf8(modulePath);
		lib = new QLibrary(path);
	}

	virtual ~DynamicLibraryImpl() {
		if (lib)
			lib->unload();
		lib = 0;
	}

	virtual Function FindFunction(const char *name) {
		if (lib) {
			void *fnAddress = lib->resolve(name);
			return static_cast<Function>(fnAddress);
		}
		return NULL;
	}

	virtual bool IsValid() {
		return lib != NULL;
	}
};

DynamicLibrary *DynamicLibrary::Load(const char *modulePath)
{
	return static_cast<DynamicLibrary *>(new DynamicLibraryImpl(modulePath));
}

ColourDesired Platform::Chrome()
{
	QColor c(Qt::gray);
	return ColourDesired(c.red(), c.green(), c.blue());
}

ColourDesired Platform::ChromeHighlight()
{
	QColor c(Qt::lightGray);
	return ColourDesired(c.red(), c.green(), c.blue());
}

const char *Platform::DefaultFont()
{
	static char fontNameDefault[200] = "";
	if (!fontNameDefault[0]) {
		QFont font = QApplication::font();
		strcpy(fontNameDefault, font.family().toAscii());
	}
	return fontNameDefault;
}

int Platform::DefaultFontSize()
{
	QFont font = QApplication::font();
	return font.pointSize();
}

unsigned int Platform::DoubleClickTime()
{
	return QApplication::doubleClickInterval();
}

bool Platform::MouseButtonBounce()
{
	return false;
}

bool Platform::IsKeyDown(int /*key*/)
{
	return false;
}

long Platform::SendScintilla(WindowID /*w*/,
                             unsigned int /*msg*/,
                             unsigned long /*wParam*/,
                             long /*lParam*/)
{
	return 0;
}

long Platform::SendScintillaPointer(WindowID /*w*/,
                                    unsigned int /*msg*/,
                                    unsigned long /*wParam*/,
                                    void * /*lParam*/)
{
	return 0;
}

int Platform::Minimum(int a, int b)
{
	return qMin(a, b);
}

int Platform::Maximum(int a, int b)
{
	return qMax(a, b);
}

int Platform::Clamp(int val, int minVal, int maxVal)
{
	return qBound(minVal, val, maxVal);
}

void Platform::DebugDisplay(const char *s)
{
	qWarning("Scintilla: %s", s);
}

void Platform::DebugPrintf(const char *format, ...)
{
	char buffer[2000];
	va_list pArguments;
	va_start(pArguments, format);
	vsprintf(buffer, format, pArguments);
	va_end(pArguments);
	Platform::DebugDisplay(buffer);
}

bool Platform::ShowAssertionPopUps(bool /*assertionPopUps*/)
{
	return false;
}

void Platform::Assert(const char *c, const char *file, int line)
{
	char buffer[2000];
	sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
	if (Platform::ShowAssertionPopUps(false)) {
		QMessageBox mb("Assertion Failure", buffer, QMessageBox::NoIcon,
			QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton);
		mb.exec();
	} else {
		strcat(buffer, "\n");
		Platform::DebugDisplay(buffer);
	}
}


bool Platform::IsDBCSLeadByte(int codePage, char ch)
{
	// Byte ranges found in Wikipedia articles with relevant search strings in each case
	unsigned char uch = static_cast<unsigned char>(ch);
	switch (codePage) {
	case 932:
		// Shift_jis
		return ((uch >= 0x81) && (uch <= 0x9F)) ||
		       ((uch >= 0xE0) && (uch <= 0xEF));
	case 936:
		// GBK
		return (uch >= 0x81) && (uch <= 0xFE);
	case 949:
		// Korean Wansung KS C-5601-1987
		return (uch >= 0x81) && (uch <= 0xFE);
	case 950:
		// Big5
		return (uch >= 0x81) && (uch <= 0xFE);
	case 1361:
		// Korean Johab KS C-5601-1992
		return
		    ((uch >= 0x84) && (uch <= 0xD3)) ||
		    ((uch >= 0xD8) && (uch <= 0xDE)) ||
		    ((uch >= 0xE0) && (uch <= 0xF9));
	}
	return false;
}

int Platform::DBCSCharLength(int codePage, const char *s)
{
	if (codePage == 932 || codePage == 936 || codePage == 949 ||
	        codePage == 950 || codePage == 1361) {
		return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1;
	} else {
		return 1;
	}
}

int Platform::DBCSCharMaxLength()
{
	return 2;
}


//----------------------------------------------------------------------

static QTime timer;

ElapsedTime::ElapsedTime()
{
	timer.start();
}

double ElapsedTime::Duration(bool reset)
{
	double result = timer.elapsed();
	if (reset) {
		timer.restart();
	}
	result /= 1000.0;
	return result;
}

#ifdef SCI_NAMESPACE
}
#endif

Added qt/ScintillaEditBase/PlatQt.h.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// Scintilla platform layer for Qt

#ifndef PLATQT_H
#define PLATQT_H

#include "Platform.h"

#include <QPaintDevice>
#include <QPainter>
#include <QHash>

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

const char *CharacterSetID(int characterSet);

inline QColor QColorFromCA(ColourDesired ca)
{
	long c = ca.AsLong();
	return QColor(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
}

inline QRect QRectFromPRect(PRectangle pr)
{
	return QRect(pr.left, pr.top, pr.Width(), pr.Height());
}

inline PRectangle PRectFromQRect(QRect qr)
{
	return PRectangle(qr.x(), qr.y(), qr.x() + qr.width(), qr.y() + qr.height());
}

inline Point PointFromQPoint(QPoint qp)
{
	return Point(qp.x(), qp.y());
}

class SurfaceImpl : public Surface {
private:
	QPaintDevice *device;
	QPainter *painter;
	bool deviceOwned;
	bool painterOwned;
	float x, y;
	bool unicodeMode;
	int codePage;
	const char *codecName;
	QTextCodec *codec;

public:
	SurfaceImpl();
	virtual ~SurfaceImpl();

	virtual void Init(WindowID wid);
	virtual void Init(SurfaceID sid, WindowID wid);
	virtual void InitPixMap(int width, int height,
		Surface *surface, WindowID wid);

	virtual void Release();
	virtual bool Initialised();
	virtual void PenColour(ColourDesired fore);
	virtual int LogPixelsY();
	virtual int DeviceHeightFont(int points);
	virtual void MoveTo(int x, int y);
	virtual void LineTo(int x, int y);
	virtual void Polygon(Point *pts, int npts, ColourDesired fore,
		ColourDesired back);
	virtual void RectangleDraw(PRectangle rc, ColourDesired fore,
		ColourDesired back);
	virtual void FillRectangle(PRectangle rc, ColourDesired back);
	virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
	virtual void RoundedRectangle(PRectangle rc, ColourDesired fore,
		ColourDesired back);
	virtual void AlphaRectangle(PRectangle rc, int corner, ColourDesired fill,
		int alphaFill, ColourDesired outline, int alphaOutline, int flags);
	virtual void DrawRGBAImage(PRectangle rc, int width, int height,
		const unsigned char *pixelsImage);
	virtual void Ellipse(PRectangle rc, ColourDesired fore,
		ColourDesired back);
	virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);

	virtual void DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
		const char *s, int len, ColourDesired fore, ColourDesired back);
	virtual void DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
		const char *s, int len, ColourDesired fore, ColourDesired back);
	virtual void DrawTextTransparent(PRectangle rc, Font &font, XYPOSITION ybase,
		const char *s, int len, ColourDesired fore);
	virtual void MeasureWidths(Font &font, const char *s, int len,
		XYPOSITION *positions);
	virtual XYPOSITION WidthText(Font &font, const char *s, int len);
	virtual XYPOSITION WidthChar(Font &font, char ch);
	virtual XYPOSITION Ascent(Font &font);
	virtual XYPOSITION Descent(Font &font);
	virtual XYPOSITION InternalLeading(Font &font);
	virtual XYPOSITION ExternalLeading(Font &font);
	virtual XYPOSITION Height(Font &font);
	virtual XYPOSITION AverageCharWidth(Font &font);

	virtual void SetClip(PRectangle rc);
	virtual void FlushCachedState();

	virtual void SetUnicodeMode(bool unicodeMode);
	virtual void SetDBCSMode(int codePage);

	void BrushColour(ColourDesired back);
	void SetCodec(Font &font);
	void SetFont(Font &font);

	QPaintDevice *GetPaintDevice();
	void SetPainter(QPainter *painter);
	QPainter *GetPainter();
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added qt/ScintillaEditBase/ScintillaEditBase.cpp.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// ScintillaEditBase.cpp - Qt widget that wraps ScintillaQt and provides events and scrolling

#include "ScintillaEditBase.h"
#include "ScintillaQt.h"
#include "PlatQt.h"

#include <QApplication>
#include <QInputContext>
#include <QPainter>
#include <QScrollBar>
#include <QTextFormat>
#include <QVarLengthArray>

#define INDIC_INPUTMETHOD 24

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

ScintillaEditBase::ScintillaEditBase(QWidget *parent)
: QAbstractScrollArea(parent), sqt(0), preeditPos(-1), wheelDelta(0)
{
	sqt = new ScintillaQt(this);

	time.start();

	// Set Qt defaults.
	setAcceptDrops(true);
	setMouseTracking(true);
	setAutoFillBackground(false);
	setFrameStyle(QFrame::NoFrame);
	setFocusPolicy(Qt::StrongFocus);
	setAttribute(Qt::WA_StaticContents);
	setAttribute(Qt::WA_OpaquePaintEvent);
	setAttribute(Qt::WA_KeyCompression);
	setAttribute(Qt::WA_InputMethodEnabled);

	connect(sqt, SIGNAL(notifyParent(SCNotification)),
	        this, SLOT(notifyParent(SCNotification)));

	// Connect scroll bars.
	connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
	        this, SLOT(scrollVertical(int)));
	connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
	        this, SLOT(scrollHorizontal(int)));

	// Connect pass-through signals.
	connect(sqt, SIGNAL(horizontalRangeChanged(int,int)),
	        this, SIGNAL(horizontalRangeChanged(int,int)));
	connect(sqt, SIGNAL(verticalRangeChanged(int,int)),
	        this, SIGNAL(verticalRangeChanged(int,int)));
	connect(sqt, SIGNAL(horizontalScrolled(int)),
	        this, SIGNAL(horizontalScrolled(int)));
	connect(sqt, SIGNAL(verticalScrolled(int)),
	        this, SIGNAL(verticalScrolled(int)));

	connect(sqt, SIGNAL(notifyChange()),
	        this, SIGNAL(notifyChange()));

	connect(sqt, SIGNAL(command(uptr_t, sptr_t)),
	        this, SLOT(event_command(uptr_t, sptr_t)));

	connect(sqt, SIGNAL(aboutToCopy(QMimeData *)),
	        this, SIGNAL(aboutToCopy(QMimeData *)));
}

ScintillaEditBase::~ScintillaEditBase() {}

sptr_t ScintillaEditBase::send(
	unsigned int iMessage,
	uptr_t wParam,
	sptr_t lParam) const
{
	return sqt->WndProc(iMessage, wParam, lParam);
}

sptr_t ScintillaEditBase::sends(
    unsigned int iMessage,
    uptr_t wParam,
    const char *s) const
{
	return sqt->WndProc(iMessage, wParam, (sptr_t)s);
}

void ScintillaEditBase::scrollHorizontal(int value)
{
	sqt->HorizontalScrollTo(value);
}

void ScintillaEditBase::scrollVertical(int value)
{
	sqt->ScrollTo(value);
}

bool ScintillaEditBase::event(QEvent *event)
{
	bool result = false;

	if (event->type() == QEvent::KeyPress) {
		// Circumvent the tab focus convention.
		keyPressEvent(static_cast<QKeyEvent *>(event));
		result = event->isAccepted();
	} else {
		result = QAbstractScrollArea::event(event);
	}

	return result;
}

void ScintillaEditBase::paintEvent(QPaintEvent *event)
{
	sqt->PartialPaint(PRectFromQRect(event->rect()));
}

void ScintillaEditBase::wheelEvent(QWheelEvent *event)
{
	if (event->orientation() == Qt::Horizontal) {
		if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
			event->ignore();
		else
			QAbstractScrollArea::wheelEvent(event);
	} else {
		if (event->modifiers() & Qt::ControlModifier) {
			// Zoom! We play with the font sizes in the styles.
			// Number of steps/line is ignored, we just care if sizing up or down
			if (event->delta() > 0) {
				sqt->KeyCommand(SCI_ZOOMIN);
			} else {
				sqt->KeyCommand(SCI_ZOOMOUT);
			}
		} else {
			// Ignore wheel events when the scroll bars are disabled.
			if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
				event->ignore();
			} else {
				// Scroll
				QAbstractScrollArea::wheelEvent(event);
			}
		}
	}
}

void ScintillaEditBase::focusInEvent(QFocusEvent *event)
{
	sqt->SetFocusState(true);
	emit updateUi();

	QAbstractScrollArea::focusInEvent(event);
}

void ScintillaEditBase::focusOutEvent(QFocusEvent *event)
{
	sqt->SetFocusState(false);

	QAbstractScrollArea::focusOutEvent(event);
}

void ScintillaEditBase::resizeEvent(QResizeEvent *)
{
	sqt->ChangeSize();
	emit resized();
}

void ScintillaEditBase::keyPressEvent(QKeyEvent *event)
{
	// All keystrokes containing the meta modifier are
	// assumed to be shortcuts not handled by scintilla.
	if (event->modifiers() & Qt::MetaModifier) {
		QAbstractScrollArea::keyPressEvent(event);
		emit keyPressed(event);
		return;
	}

	int key = 0;
	switch (event->key()) {
		case Qt::Key_Down:          key = SCK_DOWN;     break;
		case Qt::Key_Up:            key = SCK_UP;       break;
		case Qt::Key_Left:          key = SCK_LEFT;     break;
		case Qt::Key_Right:         key = SCK_RIGHT;    break;
		case Qt::Key_Home:          key = SCK_HOME;     break;
		case Qt::Key_End:           key = SCK_END;      break;
		case Qt::Key_PageUp:        key = SCK_PRIOR;    break;
		case Qt::Key_PageDown:      key = SCK_NEXT;     break;
		case Qt::Key_Delete:        key = SCK_DELETE;   break;
		case Qt::Key_Insert:        key = SCK_INSERT;   break;
		case Qt::Key_Escape:        key = SCK_ESCAPE;   break;
		case Qt::Key_Backspace:     key = SCK_BACK;     break;
		case Qt::Key_Plus:          key = SCK_ADD;      break;
		case Qt::Key_Minus:         key = SCK_SUBTRACT; break;
		case Qt::Key_Backtab:       // fall through
		case Qt::Key_Tab:           key = SCK_TAB;      break;
		case Qt::Key_Enter:         // fall through
		case Qt::Key_Return:        key = SCK_RETURN;   break;
		case Qt::Key_Control:       key = 0;            break;
		case Qt::Key_Alt:           key = 0;            break;
		case Qt::Key_Shift:         key = 0;            break;
		case Qt::Key_Meta:          key = 0;            break;
		default:                    key = event->key(); break;
	}

	bool shift = event->modifiers() & Qt::ShiftModifier;
	bool ctrl  = event->modifiers() & Qt::ControlModifier;
	bool alt   = event->modifiers() & Qt::AltModifier;

	bool consumed = false;
	bool added = sqt->KeyDown(key, shift, ctrl, alt, &consumed) != 0;
	if (!consumed)
		consumed = added;

	if (!consumed) {
		// Don't insert text if the control key was pressed unless
		// it was pressed in conjunction with alt for AltGr emulation.
		bool input = (!ctrl || alt);

		// Additionally, on non-mac platforms, don't insert text
		// if the alt key was pressed unless control is also present.
		// On mac alt can be used to insert special characters.
#ifndef Q_WS_MAC
		input &= (!alt || ctrl);
#endif

		QString text = event->text();
		if (input && !text.isEmpty() && text[0].isPrint()) {
			QByteArray utext = sqt->BytesForDocument(text);
			sqt->AddCharUTF(utext.data(), utext.size());
		} else {
			event->ignore();
		}
	}

	emit keyPressed(event);
}

static int modifierTranslated(int sciModifier)
{
	switch (sciModifier) {
		case SCMOD_SHIFT:
			return Qt::ShiftModifier;
		case SCMOD_CTRL:
			return Qt::ControlModifier;
		case SCMOD_ALT:
			return Qt::AltModifier;
		case SCMOD_SUPER:
			return Qt::MetaModifier;
		default:
			return 0;
	}
}

void ScintillaEditBase::mousePressEvent(QMouseEvent *event)
{
	Point pos = PointFromQPoint(event->pos());

	emit buttonPressed(event);

	if (event->button() == Qt::MidButton &&
	    QApplication::clipboard()->supportsSelection()) {
		SelectionPosition selPos = sqt->SPositionFromLocation(
					pos, false, false, sqt->UserVirtualSpace());
		sqt->sel.Clear();
		sqt->SetSelection(selPos, selPos);
		sqt->PasteFromMode(QClipboard::Selection);
		return;
	}

	bool button = event->button() == Qt::LeftButton;

	if (button) {
		bool shift = event->modifiers() & Qt::ShiftModifier;
		bool ctrl  = event->modifiers() & Qt::ControlModifier;
#ifdef Q_WS_X11
		// On X allow choice of rectangular modifier since most window
		// managers grab alt + click for moving windows.
		bool alt   = event->modifiers() & modifierTranslated(sqt->rectangularSelectionModifier);
#else
		bool alt   = event->modifiers() & Qt::AltModifier;
#endif

		sqt->ButtonDown(pos, time.elapsed(), shift, ctrl, alt);
	}
}

void ScintillaEditBase::mouseReleaseEvent(QMouseEvent *event)
{
	Point point = PointFromQPoint(event->pos());
	bool ctrl  = event->modifiers() & Qt::ControlModifier;
	if (event->button() == Qt::LeftButton)
		sqt->ButtonUp(point, time.elapsed(), ctrl);

	int pos = send(SCI_POSITIONFROMPOINT, point.x, point.y);
	int line = send(SCI_LINEFROMPOSITION, pos);
	int modifiers = event->modifiers();

	emit textAreaClicked(line, modifiers);
	emit buttonReleased(event);
}

void ScintillaEditBase::mouseDoubleClickEvent(QMouseEvent *event)
{
	// Scintilla does its own double-click detection.
	mousePressEvent(event);
}

void ScintillaEditBase::mouseMoveEvent(QMouseEvent *event)
{
	Point pos = PointFromQPoint(event->pos());
	sqt->ButtonMove(pos);
}

void ScintillaEditBase::contextMenuEvent(QContextMenuEvent *event)
{
	Point pos = PointFromQPoint(event->globalPos());
	Point pt = PointFromQPoint(event->pos());
	if (!sqt->PointInSelection(pt))
		sqt->SetEmptySelection(sqt->PositionFromLocation(pt));
	sqt->ContextMenu(pos);
}

void ScintillaEditBase::dragEnterEvent(QDragEnterEvent *event)
{
	if (event->mimeData()->hasText()) {
		event->acceptProposedAction();

		Point point = PointFromQPoint(event->pos());
		sqt->DragEnter(point);
	} else {
		event->ignore();
	}
}

void ScintillaEditBase::dragLeaveEvent(QDragLeaveEvent * /* event */)
{
	sqt->DragLeave();
}

void ScintillaEditBase::dragMoveEvent(QDragMoveEvent *event)
{
	if (event->mimeData()->hasText()) {
		event->acceptProposedAction();

		Point point = PointFromQPoint(event->pos());
		sqt->DragMove(point);
	} else {
		event->ignore();
	}
}

void ScintillaEditBase::dropEvent(QDropEvent *event)
{
	if (event->mimeData()->hasText()) {
		event->acceptProposedAction();

		Point point = PointFromQPoint(event->pos());
		bool move = (event->source() == this &&
                 event->proposedAction() == Qt::MoveAction);
		sqt->Drop(point, event->mimeData(), move);
	} else {
		event->ignore();
	}
}

void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
{
	// Clear the current selection.
	sqt->ClearSelection();
	if (preeditPos >= 0)
		sqt->SetSelection(preeditPos, preeditPos);

	// Insert the commit string.
	if (!event->commitString().isEmpty() || event->replacementLength()) {
		// Select the text to be removed.
		int commitPos = send(SCI_GETCURRENTPOS);
		int start = commitPos + event->replacementStart();
		int end = start + event->replacementLength();
		sqt->SetSelection(start, end);

		// Replace the selection with the commit string.
		QByteArray commitBytes = sqt->BytesForDocument(event->commitString());
		char *commitData = commitBytes.data();
		sqt->AddCharUTF(commitData, strlen(commitData));
	}

	// Select the previous preedit string.
	int pos = send(SCI_GETCURRENTPOS);
	int length = sqt->BytesForDocument(preeditString).length();
	sqt->SetSelection(pos, pos + length);

	// Replace the selection with the new preedit string.
	QByteArray bytes = sqt->BytesForDocument(event->preeditString());
	char *data = bytes.data();
	bool recording = sqt->recordingMacro;
	sqt->recordingMacro = false;
	send(SCI_SETUNDOCOLLECTION, false);
	sqt->AddCharUTF(data, strlen(data));
	send(SCI_SETUNDOCOLLECTION, true);
	sqt->recordingMacro = recording;
	sqt->SetSelection(pos, pos);

	// Store the state of the current preedit string.
	preeditString = event->preeditString();
	preeditPos = !preeditString.isEmpty() ? send(SCI_GETCURRENTPOS) : -1;

	if (!preeditString.isEmpty()) {
		// Apply attributes to the preedit string.
		int indicNum = 0;
		sqt->ShowCaretAtCurrentPosition();
		foreach (QInputMethodEvent::Attribute a, event->attributes()) {
			QString prefix = preeditString.left(a.start);
			QByteArray prefixBytes = sqt->BytesForDocument(prefix);
			int prefixLength = prefixBytes.length();
			int caretPos = preeditPos + prefixLength;

			if (a.type == QInputMethodEvent::Cursor) {
				sqt->SetSelection(caretPos, caretPos);
				if (!a.length)
					sqt->DropCaret();

			} else if (a.type == QInputMethodEvent::TextFormat) {
				Q_ASSERT(a.value.canConvert(QVariant::TextFormat));
				QTextFormat format = a.value.value<QTextFormat>();
				Q_ASSERT(format.isCharFormat());
				QTextCharFormat charFormat = format.toCharFormat();

				QString sub = preeditString.mid(a.start, a.length);
				QByteArray subBytes = sqt->BytesForDocument(sub);
				int subLength = subBytes.length();

				if (charFormat.underlineStyle() != QTextCharFormat::NoUnderline) {
					// Set temporary indicator for underline style.
					QColor uc = charFormat.underlineColor();
					int style = INDIC_PLAIN;
					if (charFormat.underlineStyle() == QTextCharFormat::DashUnderline)
						style = INDIC_DASH;
					send(SCI_INDICSETSTYLE, INDIC_INPUTMETHOD + indicNum, style);
					send(SCI_INDICSETFORE, INDIC_INPUTMETHOD + indicNum, uc.rgb());
					send(SCI_SETINDICATORCURRENT, INDIC_INPUTMETHOD + indicNum);
					send(SCI_INDICATORFILLRANGE, caretPos, subLength);
					indicNum++;
				}
			}
		}
	}
}

QVariant ScintillaEditBase::inputMethodQuery(Qt::InputMethodQuery query) const
{
	int pos = send(SCI_GETCURRENTPOS);
	int line = send(SCI_LINEFROMPOSITION, pos);

	switch (query) {
		case Qt::ImMicroFocus:
		{
			int startPos = (preeditPos >= 0) ? preeditPos : pos;
			Point pt = sqt->LocationFromPosition(startPos);
			int width = send(SCI_GETCARETWIDTH);
			int height = send(SCI_TEXTHEIGHT, line);
			return QRect(pt.x, pt.y, width, height);
		}

		case Qt::ImFont:
		{
			char fontName[64];
			int style = send(SCI_GETSTYLEAT, pos);
			int len = send(SCI_STYLEGETFONT, style, (sptr_t)fontName);
			int size = send(SCI_STYLEGETSIZE, style);
			bool italic = send(SCI_STYLEGETITALIC, style);
			int weight = send(SCI_STYLEGETBOLD, style) ? QFont::Bold : -1;
			return QFont(QString::fromUtf8(fontName, len), size, weight, italic);
		}

		case Qt::ImCursorPosition:
		{
			int paraStart = sqt->pdoc->ParaUp(pos);
			return pos - paraStart;
		}

		case Qt::ImSurroundingText:
		{
			int paraStart = sqt->pdoc->ParaUp(pos);
			int paraEnd = sqt->pdoc->ParaDown(pos);
			QVarLengthArray<char,1024> buffer(paraEnd - paraStart + 1);

			Sci_CharacterRange charRange;
			charRange.cpMin = paraStart;
			charRange.cpMax = paraEnd;

			Sci_TextRange textRange;
			textRange.chrg = charRange;
			textRange.lpstrText = buffer.data();

			send(SCI_GETTEXTRANGE, 0, (sptr_t)&textRange);

			return sqt->StringFromDocument(buffer.constData());
		}

		case Qt::ImCurrentSelection:
		{
			QVarLengthArray<char,1024> buffer(send(SCI_GETSELTEXT));
			send(SCI_GETSELTEXT, 0, (sptr_t)buffer.data());

			return sqt->StringFromDocument(buffer.constData());
		}

		default:
			return QVariant();
	}
}

void ScintillaEditBase::notifyParent(SCNotification scn)
{
	emit notify(&scn);
	switch (scn.nmhdr.code) {
		case SCN_STYLENEEDED:
			emit styleNeeded(scn.position);
			break;

		case SCN_CHARADDED:
			emit charAdded(scn.ch);
			break;

		case SCN_SAVEPOINTREACHED:
			emit savePointChanged(false);
			break;

		case SCN_SAVEPOINTLEFT:
			emit savePointChanged(true);
			break;

		case SCN_MODIFYATTEMPTRO:
			emit modifyAttemptReadOnly();
			break;

		case SCN_KEY:
			emit key(scn.ch);
			break;

		case SCN_DOUBLECLICK:
			emit doubleClick(scn.position, scn.line);
			break;

		case SCN_UPDATEUI:
			emit updateUi();
			break;

		case SCN_MODIFIED:
		{
			bool added = scn.modificationType & SC_MOD_INSERTTEXT;
			bool deleted = scn.modificationType & SC_MOD_DELETETEXT;

			int length = send(SCI_GETTEXTLENGTH);
			bool firstLineAdded = (added && length == 1) ||
			                      (deleted && length == 0);

			if (scn.linesAdded != 0) {
				emit linesAdded(scn.linesAdded);
			} else if (firstLineAdded) {
				emit linesAdded(added ? 1 : -1);
			}

			const QByteArray bytes = QByteArray::fromRawData(scn.text, scn.length);
			emit modified(scn.modificationType, scn.position, scn.length,
			              scn.linesAdded, bytes, scn.line,
			              scn.foldLevelNow, scn.foldLevelPrev);
			break;
		}

		case SCN_MACRORECORD:
			emit macroRecord(scn.message, scn.wParam, scn.lParam);
			break;

		case SCN_MARGINCLICK:
			emit marginClicked(scn.position, scn.modifiers, scn.margin);
			break;

		case SCN_NEEDSHOWN:
			emit needShown(scn.position, scn.length);
			break;

		case SCN_PAINTED:
			emit painted();
			break;

		case SCN_USERLISTSELECTION:
			emit userListSelection();
			break;

		case SCN_URIDROPPED:
			emit uriDropped();
			break;

		case SCN_DWELLSTART:
			emit dwellStart(scn.x, scn.y);
			break;

		case SCN_DWELLEND:
			emit dwellEnd(scn.x, scn.y);
			break;

		case SCN_ZOOM:
			emit zoom(send(SCI_GETZOOM));
			break;

		case SCN_HOTSPOTCLICK:
			emit hotSpotClick(scn.position, scn.modifiers);
			break;

		case SCN_HOTSPOTDOUBLECLICK:
			emit hotSpotDoubleClick(scn.position, scn.modifiers);
			break;

		case SCN_CALLTIPCLICK:
			emit callTipClick();
			break;

		case SCN_AUTOCSELECTION:
			emit autoCompleteSelection(scn.lParam, QString::fromUtf8(scn.text));
			break;

		case SCN_AUTOCCANCELLED:
			emit autoCompleteCancelled();
			break;

		default:
			return;
	}
}

void ScintillaEditBase::event_command(uptr_t wParam, sptr_t lParam)
{
	emit command(wParam, lParam);
}

Added qt/ScintillaEditBase/ScintillaEditBase.h.

















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// ScintillaWidget.h - Qt widget that wraps ScintillaQt and provides events and scrolling


#ifndef SCINTILLAEDITBASE_H
#define SCINTILLAEDITBASE_H

#include "Platform.h"
#include "Scintilla.h"

#include <QAbstractScrollArea>
#include <QMimeData>
#include <QTime>

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class ScintillaQt;
class SurfaceImpl;
struct SCNotification;

#ifdef WIN32
#ifdef MAKING_LIBRARY
#define EXPORT_IMPORT_API __declspec(dllexport)
#else
// Defining dllimport upsets moc
#define EXPORT_IMPORT_API __declspec(dllimport)
//#define EXPORT_IMPORT_API
#endif
#else
#define EXPORT_IMPORT_API
#endif

class EXPORT_IMPORT_API ScintillaEditBase : public QAbstractScrollArea {
	Q_OBJECT

public:
	ScintillaEditBase(QWidget *parent = 0);
	virtual ~ScintillaEditBase();

	virtual sptr_t send(
		unsigned int iMessage,
		uptr_t wParam = 0,
		sptr_t lParam = 0) const;

	virtual sptr_t sends(
		unsigned int iMessage,
		uptr_t wParam = 0,
		const char *s = 0) const;

public slots:
	// Scroll events coming from GUI to be sent to Scintilla.
	void scrollHorizontal(int value);
	void scrollVertical(int value);

	// Emit Scintilla notifications as signals.
	void notifyParent(SCNotification scn);
	void event_command(uptr_t wParam, sptr_t lParam);

signals:
	void horizontalScrolled(int value);
	void verticalScrolled(int value);
	void horizontalRangeChanged(int max, int page);
	void verticalRangeChanged(int max, int page);
	void notifyChange();
	void linesAdded(int linesAdded);

	// Clients can use this hook to add additional
	// formats (e.g. rich text) to the MIME data.
	void aboutToCopy(QMimeData *data);

	// Scintilla Notifications
	void styleNeeded(int position);
	void charAdded(int ch);
	void savePointChanged(bool dirty);
	void modifyAttemptReadOnly();
	void key(int key);
	void doubleClick(int position, int line);
	void updateUi();
	void modified(int type, int position, int length, int linesAdded,
	              const QByteArray &text, int line, int foldNow, int foldPrev);
	void macroRecord(int message, uptr_t wParam, sptr_t lParam);
	void marginClicked(int position, int modifiers, int margin);
	void textAreaClicked(int line, int modifiers);
	void needShown(int position, int length);
	void painted();
	void userListSelection(); // Wants some args.
	void uriDropped();        // Wants some args.
	void dwellStart(int x, int y);
	void dwellEnd(int x, int y);
	void zoom(int zoom);
	void hotSpotClick(int position, int modifiers);
	void hotSpotDoubleClick(int position, int modifiers);
	void callTipClick();
	void autoCompleteSelection(int position, const QString &text);
	void autoCompleteCancelled();

	// Base notifications for compatibility with other Scintilla implementations
	void notify(SCNotification *pscn);
	void command(uptr_t wParam, sptr_t lParam);

	// GUI event notifications needed under Qt
	void buttonPressed(QMouseEvent *event);
	void buttonReleased(QMouseEvent *event);
	void keyPressed(QKeyEvent *event);
	void resized();

protected:
	virtual bool event(QEvent *event);
	virtual void paintEvent(QPaintEvent *event);
	virtual void wheelEvent(QWheelEvent *event);
	virtual void focusInEvent(QFocusEvent *event);
	virtual void focusOutEvent(QFocusEvent *event);
	virtual void resizeEvent(QResizeEvent *event);
	virtual void keyPressEvent(QKeyEvent *event);
	virtual void mousePressEvent(QMouseEvent *event);
	virtual void mouseReleaseEvent(QMouseEvent *event);
	virtual void mouseDoubleClickEvent(QMouseEvent *event);
	virtual void mouseMoveEvent(QMouseEvent *event);
	virtual void contextMenuEvent(QContextMenuEvent *event);
	virtual void dragEnterEvent(QDragEnterEvent *event);
	virtual void dragLeaveEvent(QDragLeaveEvent *event);
	virtual void dragMoveEvent(QDragMoveEvent *event);
	virtual void dropEvent(QDropEvent *event);
	virtual void inputMethodEvent(QInputMethodEvent *event);
	virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
	virtual void scrollContentsBy(int, int) {}

private:
	ScintillaQt *sqt;

	QTime time;

	int preeditPos;
	QString preeditString;

	int wheelDelta;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif /* SCINTILLAEDITBASE_H */

Added qt/ScintillaEditBase/ScintillaEditBase.pro.































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#-------------------------------------------------
#
# Project created by QtCreator 2011-05-05T12:41:23
#
#-------------------------------------------------

QT       += core gui

TARGET = ScintillaEditBase
TEMPLATE = lib
CONFIG += lib_bundle

VERSION = 3.3.0

SOURCES += \
    PlatQt.cpp \
    ScintillaQt.cpp \
    ScintillaEditBase.cpp \
    ../../src/XPM.cxx \
    ../../src/ViewStyle.cxx \
    ../../src/UniConversion.cxx \
    ../../src/Style.cxx \
    ../../src/Selection.cxx \
    ../../src/ScintillaBase.cxx \
    ../../src/RunStyles.cxx \
    ../../src/RESearch.cxx \
    ../../src/PositionCache.cxx \
    ../../src/PerLine.cxx \
    ../../src/LineMarker.cxx \
    ../../src/KeyMap.cxx \
    ../../src/Indicator.cxx \
    ../../src/ExternalLexer.cxx \
    ../../src/Editor.cxx \
    ../../src/Document.cxx \
    ../../src/Decoration.cxx \
    ../../src/ContractionState.cxx \
    ../../src/CharClassify.cxx \
    ../../src/CellBuffer.cxx \
    ../../src/Catalogue.cxx \
    ../../src/CallTip.cxx \
    ../../src/AutoComplete.cxx \
    ../../lexlib/WordList.cxx \
    ../../lexlib/StyleContext.cxx \
    ../../lexlib/PropSetSimple.cxx \
    ../../lexlib/LexerSimple.cxx \
    ../../lexlib/LexerNoExceptions.cxx \
    ../../lexlib/LexerModule.cxx \
    ../../lexlib/LexerBase.cxx \
    ../../lexlib/CharacterSet.cxx \
    ../../lexlib/Accessor.cxx \
    ../../lexers/*.cxx

HEADERS  += \
    PlatQt.h \
    ScintillaQt.h \
    ScintillaEditBase.h \
    ../../src/XPM.h \
    ../../src/ViewStyle.h \
    ../../src/UniConversion.h \
    ../../src/SVector.h \
    ../../src/Style.h \
    ../../src/SplitVector.h \
    ../../src/Selection.h \
    ../../src/ScintillaBase.h \
    ../../src/RunStyles.h \
    ../../src/RESearch.h \
    ../../src/PositionCache.h \
    ../../src/PerLine.h \
    ../../src/Partitioning.h \
    ../../src/LineMarker.h \
    ../../src/KeyMap.h \
    ../../src/Indicator.h \
    ../../src/FontQuality.h \
    ../../src/ExternalLexer.h \
    ../../src/Editor.h \
    ../../src/Document.h \
    ../../src/Decoration.h \
    ../../src/ContractionState.h \
    ../../src/CharClassify.h \
    ../../src/CellBuffer.h \
    ../../src/Catalogue.h \
    ../../src/CallTip.h \
    ../../src/AutoComplete.h \
    ../../include/Scintilla.h \
    ../../include/SciLexer.h \
    ../../include/Platform.h \
    ../../include/ILexer.h \
    ../../lexlib/WordList.h \
    ../../lexlib/StyleContext.h \
    ../../lexlib/SparseState.h \
    ../../lexlib/PropSetSimple.h \
    ../../lexlib/OptionSet.h \
    ../../lexlib/LexerSimple.h \
    ../../lexlib/LexerNoExceptions.h \
    ../../lexlib/LexerModule.h \
    ../../lexlib/LexerBase.h \
    ../../lexlib/LexAccessor.h \
    ../../lexlib/CharacterSet.h \
    ../../lexlib/Accessor.h

OTHER_FILES +=

INCLUDEPATH += ../../include ../../src ../../lexlib

DEFINES += SCINTILLA_QT=1 MAKING_LIBRARY=1 SCI_LEXER=1 _CRT_SECURE_NO_DEPRECATE=1

DESTDIR = ../../bin

macx {
	QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/
}

Added qt/ScintillaEditBase/ScintillaQt.cpp.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// ScintillaQt.cpp - Qt specific subclass of ScintillaBase

#include "PlatQt.h"
#include "ScintillaQt.h"
#ifdef SCI_LEXER
#include "LexerModule.h"
#include "ExternalLexer.h"
#endif

#include <QApplication>
#include <QDrag>
#include <QInputContext>
#include <QMimeData>
#include <QMenu>
#include <QScrollBar>
#include <QTimer>
#include <QTextCodec>

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif


ScintillaQt::ScintillaQt(QAbstractScrollArea *parent)
: QObject(parent), scrollArea(parent), vMax(0),  hMax(0), vPage(0), hPage(0),
 haveMouseCapture(false), dragWasDropped(false)
{

	wMain = scrollArea->viewport();

	// On OS X drawing text into a pixmap moves it around 1 pixel to
	// the right compared to drawing it directly onto a window.
	// Buffered drawing turned off by default to avoid this.
	WndProc(SCI_SETBUFFEREDDRAW, false, 0);

	Initialise();
}

ScintillaQt::~ScintillaQt()
{
	SetTicking(false);
}

void ScintillaQt::tick()
{
	Tick();
}

void ScintillaQt::execCommand(QAction *action)
{
	int command = action->data().toInt();
	Command(command);
}

#if defined(Q_OS_WIN)
static const QString sMSDEVColumnSelect("MSDEVColumnSelect");
static const QString sWrappedMSDEVColumnSelect("application/x-qt-windows-mime;value=\"MSDEVColumnSelect\"");
#elif defined(Q_OS_MAC)
static const QString sScintillaRecPboardType("com.scintilla.utf16-plain-text.rectangular");
static const QString sScintillaRecMimeType("text/x-scintilla.utf16-plain-text.rectangular");
#else
// Linux
static const QString sMimeRectangularMarker("text/x-rectangular-marker");
#endif

#ifdef Q_OS_MAC

class ScintillaRectangularMime : public QMacPasteboardMime {
public:
	ScintillaRectangularMime() : QMacPasteboardMime(MIME_ALL) {
	}

	QString convertorName() {
		return QString("ScintillaRectangularMime");
	}

	bool canConvert(const QString &mime, QString flav) {
		return mimeFor(flav) == mime;
	}

	QString mimeFor(QString flav) {
		if (flav == sScintillaRecPboardType)
			return sScintillaRecMimeType;
		return QString();
	}

	QString flavorFor(const QString &mime) {
		if (mime == sScintillaRecMimeType)
			return sScintillaRecPboardType;
		return QString();
	}

	QVariant convertToMime(const QString & /* mime */, QList<QByteArray> data, QString /* flav */) {
		QByteArray all;
		foreach (QByteArray i, data) {
			all += i;
		}
		return QVariant(all);
	}

	QList<QByteArray> convertFromMime(const QString & /* mime */, QVariant data, QString /* flav */) {
		QByteArray a = data.toByteArray();
		QList<QByteArray> l;
		l.append(a);
		return l;
	}

};

// The Mime object registers itself but only want one for all Scintilla instances.
// Should delete at exit to help memory leak detection but that would be extra work
// and, since the clipboard exists after last Scintilla instance, may be complex.
static ScintillaRectangularMime *singletonMime = 0;

#endif

void ScintillaQt::Initialise()
{
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
	rectangularSelectionModifier = SCMOD_ALT;
#else
	rectangularSelectionModifier = SCMOD_CTRL;
#endif

#ifdef Q_OS_MAC
	if (!singletonMime) {
		singletonMime = new ScintillaRectangularMime();

		QStringList slTypes(sScintillaRecPboardType);
		qRegisterDraggedTypes(slTypes);
	}
#endif

	connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
		this, SLOT(SelectionChanged()));
}

void ScintillaQt::Finalise()
{
	SetTicking(false);
	ScintillaBase::Finalise();
}

void ScintillaQt::SelectionChanged()
{
	bool nowPrimary = QApplication::clipboard()->ownsSelection();
	if (nowPrimary != primarySelection) {
		primarySelection = nowPrimary;
		Redraw();
	}
}

bool ScintillaQt::DragThreshold(Point ptStart, Point ptNow)
{
	int xMove = abs(ptStart.x - ptNow.x);
	int yMove = abs(ptStart.y - ptNow.y);
	return (xMove > QApplication::startDragDistance()) ||
		(yMove > QApplication::startDragDistance());
}

static QString StringFromSelectedText(const SelectionText &selectedText)
{
	if (selectedText.codePage == SC_CP_UTF8) {
		return QString::fromUtf8(selectedText.s, selectedText.len-1);
	} else {
		QTextCodec *codec = QTextCodec::codecForName(
				CharacterSetID(selectedText.characterSet));
		return codec->toUnicode(selectedText.s, selectedText.len-1);
	}
}

static void AddRectangularToMime(QMimeData *mimeData, QString su)
{
#if defined(Q_OS_WIN)
	// Add an empty marker
	mimeData->setData(sMSDEVColumnSelect, QByteArray());
#elif defined(Q_OS_MAC)
	// OS X gets marker + data to work with other implementations.
	// Don't understand how this works but it does - the
	// clipboard format is supposed to be UTF-16, not UTF-8.
	mimeData->setData(sScintillaRecMimeType, su.toUtf8());
#else
	Q_UNUSED(su);
	// Linux
	// Add an empty marker
	mimeData->setData(sMimeRectangularMarker, QByteArray());
#endif
}

static bool IsRectangularInMime(const QMimeData *mimeData)
{
	QStringList formats = mimeData->formats();
	for (int i = 0; i < formats.size(); ++i) {
#if defined(Q_OS_WIN)
		// Windows rectangular markers
		// If rectangular copies made by this application, see base name.
		if (formats[i] == sMSDEVColumnSelect)
			return true;
		// Otherwise see wrapped name.
		if (formats[i] == sWrappedMSDEVColumnSelect)
			return true;
#elif defined(Q_OS_MAC)
		if (formats[i] == sScintillaRecMimeType)
			return true;
#else
		// Linux
		if (formats[i] == sMimeRectangularMarker)
			return true;
#endif
	}
	return false;
}

bool ScintillaQt::ValidCodePage(int codePage) const
{
	return codePage == 0
	|| codePage == SC_CP_UTF8
	|| codePage == 932
	|| codePage == 936
	|| codePage == 949
	|| codePage == 950
	|| codePage == 1361;
}


void ScintillaQt::ScrollText(int linesToMove)
{
	int dy = vs.lineHeight * (linesToMove);
	scrollArea->viewport()->scroll(0, dy);
}

void ScintillaQt::SetVerticalScrollPos()
{
	scrollArea->verticalScrollBar()->setValue(topLine);
	emit verticalScrolled(topLine);
}

void ScintillaQt::SetHorizontalScrollPos()
{
	scrollArea->horizontalScrollBar()->setValue(xOffset);
	emit horizontalScrolled(xOffset);
}

bool ScintillaQt::ModifyScrollBars(int nMax, int nPage)
{
	bool modified = false;

	int vNewPage = nPage;
	int vNewMax = nMax - vNewPage + 1;
	if (vMax != vNewMax || vPage != vNewPage) {
		vMax = vNewMax;
		vPage = vNewPage;
		modified = true;

		scrollArea->verticalScrollBar()->setMaximum(vMax);
		scrollArea->verticalScrollBar()->setPageStep(vPage);
		emit verticalRangeChanged(vMax, vPage);
	}

	int hNewPage = GetTextRectangle().Width();
	int hNewMax = (scrollWidth > hNewPage) ? scrollWidth - hNewPage : 0;
	int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
	if (hMax != hNewMax || hPage != hNewPage ||
	    scrollArea->horizontalScrollBar()->singleStep() != charWidth) {
		hMax = hNewMax;
		hPage = hNewPage;
		modified = true;

		scrollArea->horizontalScrollBar()->setMaximum(hMax);
		scrollArea->horizontalScrollBar()->setPageStep(hPage);
		scrollArea->horizontalScrollBar()->setSingleStep(charWidth);
		emit horizontalRangeChanged(hMax, hPage);
	}

	return modified;
}

void ScintillaQt::ReconfigureScrollBars()
{
	if (verticalScrollBarVisible) {
		scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	} else {
		scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	}

	if (horizontalScrollBarVisible && (wrapState == eWrapNone)) {
		scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	} else {
		scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	}
}

void ScintillaQt::CopyToModeClipboard(const SelectionText &selectedText, QClipboard::Mode clipboardMode_)
{
	QClipboard *clipboard = QApplication::clipboard();
	clipboard->clear(clipboardMode_);
	QString su = StringFromSelectedText(selectedText);
	QMimeData *mimeData = new QMimeData();
	mimeData->setText(su);
	if (selectedText.rectangular) {
		AddRectangularToMime(mimeData, su);
	}

	// Allow client code to add additional data (e.g rich text).
	emit aboutToCopy(mimeData);

	clipboard->setMimeData(mimeData, clipboardMode_);
}

void ScintillaQt::Copy()
{
	if (!sel.Empty()) {
		SelectionText st;
		CopySelectionRange(&st);
		CopyToClipboard(st);
	}
}

void ScintillaQt::CopyToClipboard(const SelectionText &selectedText)
{
	CopyToModeClipboard(selectedText, QClipboard::Clipboard);
}

void ScintillaQt::PasteFromMode(QClipboard::Mode clipboardMode_)
{
	QClipboard *clipboard = QApplication::clipboard();
	const QMimeData *mimeData = clipboard->mimeData(clipboardMode_);
	bool isRectangular = IsRectangularInMime(mimeData);
	QString text = clipboard->text(clipboardMode_);
	QByteArray utext = BytesForDocument(text);
	int len = utext.length();
	char *dest = Document::TransformLineEnds(&len, utext, len, pdoc->eolMode);
	SelectionText selText;
	selText.Set(dest, len, pdoc->dbcsCodePage, CharacterSetOfDocument(), isRectangular, false);

	UndoGroup ug(pdoc);
	ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
	SelectionPosition selStart = sel.IsRectangular() ?
		sel.Rectangular().Start() :
		sel.Range(sel.Main()).Start();
	if (selText.rectangular) {
		PasteRectangular(selStart, selText.s, selText.len);
	} else {
		InsertPaste(selStart, selText.s, selText.len);
	}
	EnsureCaretVisible();
}

void ScintillaQt::Paste()
{
	PasteFromMode(QClipboard::Clipboard);
}

void ScintillaQt::ClaimSelection()
{
	if (QApplication::clipboard()->supportsSelection()) {
		// X Windows has a 'primary selection' as well as the clipboard.
		// Whenever the user selects some text, we become the primary selection
		if (!sel.Empty()) {
			primarySelection = true;
			SelectionText st;
			CopySelectionRange(&st);
			CopyToModeClipboard(st, QClipboard::Selection);
		} else {
			primarySelection = false;
		}
	}
}

void ScintillaQt::NotifyChange()
{
	emit notifyChange();
	emit command(
			Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE),
			reinterpret_cast<sptr_t>(wMain.GetID()));
}

void ScintillaQt::NotifyFocus(bool focus)
{
	emit command(
			Platform::LongFromTwoShorts
					(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
			reinterpret_cast<sptr_t>(wMain.GetID()));
}

void ScintillaQt::NotifyParent(SCNotification scn)
{
	scn.nmhdr.hwndFrom = wMain.GetID();
	scn.nmhdr.idFrom = GetCtrlID();
	emit notifyParent(scn);
}

void ScintillaQt::SetTicking(bool on)
{
	QTimer *qTimer;
	if (timer.ticking != on) {
		timer.ticking = on;
		if (timer.ticking) {
			qTimer = new QTimer;
			connect(qTimer, SIGNAL(timeout()), this, SLOT(tick()));
			qTimer->start(timer.tickSize);
			timer.tickerID = qTimer;
		} else {
			qTimer = static_cast<QTimer *>(timer.tickerID);
			qTimer->stop();
			disconnect(qTimer, SIGNAL(timeout()), 0, 0);
			delete qTimer;
			timer.tickerID = 0;
		}
	}
	timer.ticksToWait = caret.period;
}

void ScintillaQt::onIdle()
{
	bool continueIdling = Idle();
	if (!continueIdling) {
		SetIdle(false);
	}
}

bool ScintillaQt::SetIdle(bool on)
{
	QTimer *qIdle;
	if (on) {
		// Start idler, if it's not running.
		if (!idler.state) {
			idler.state = true;
			qIdle = new QTimer;
			connect(qIdle, SIGNAL(timeout()), this, SLOT(onIdle()));
			qIdle->start(0);
			idler.idlerID = qIdle;
		}
	} else {
		// Stop idler, if it's running
		if (idler.state) {
			idler.state = false;
			qIdle = static_cast<QTimer *>(idler.idlerID);
			qIdle->stop();
			disconnect(qIdle, SIGNAL(timeout()), 0, 0);
			delete qIdle;
			idler.idlerID = 0;
		}
	}
	return true;
}

int ScintillaQt::CharacterSetOfDocument() const
{
	return vs.styles[STYLE_DEFAULT].characterSet;
}

const char *ScintillaQt::CharacterSetIDOfDocument() const
{
	return CharacterSetID(CharacterSetOfDocument());
}

QString ScintillaQt::StringFromDocument(const char *s) const
{
	if (IsUnicodeMode()) {
		return QString::fromUtf8(s);
	} else {
		QTextCodec *codec = QTextCodec::codecForName(
				CharacterSetID(CharacterSetOfDocument()));
		return codec->toUnicode(s);
	}
}

QByteArray ScintillaQt::BytesForDocument(const QString &text) const
{
	if (IsUnicodeMode()) {
		return text.toUtf8();
	} else {
		QTextCodec *codec = QTextCodec::codecForName(
				CharacterSetID(CharacterSetOfDocument()));
		return codec->fromUnicode(text);
	}
}


class CaseFolderUTF8 : public CaseFolderTable {
public:
	CaseFolderUTF8() {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
			QString su = QString::fromUtf8(mixed, lenMixed);
			QString suFolded = su.toCaseFolded();
			QByteArray bytesFolded = suFolded.toUtf8();
			if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
				memcpy(folded, bytesFolded,  bytesFolded.length());
				return bytesFolded.length();
			} else {
				folded[0] = '\0';
				return 0;
			}
		}
	}
};

class CaseFolderDBCS : public CaseFolderTable {
	QTextCodec *codec;
public:
	CaseFolderDBCS(QTextCodec *codec_) : codec(codec_) {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else if (codec) {
			QString su = codec->toUnicode(mixed, lenMixed);
			QString suFolded = su.toCaseFolded();
			QByteArray bytesFolded = codec->fromUnicode(suFolded);

			if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
				memcpy(folded, bytesFolded,  bytesFolded.length());
				return bytesFolded.length();
			}
		}
		// Something failed so return a single NUL byte
		folded[0] = '\0';
		return 1;
	}
};

CaseFolder *ScintillaQt::CaseFolderForEncoding()
{
	if (pdoc->dbcsCodePage == SC_CP_UTF8) {
		return new CaseFolderUTF8();
	} else {
		const char *charSetBuffer = CharacterSetIDOfDocument();
		if (charSetBuffer) {
			if (pdoc->dbcsCodePage == 0) {
				CaseFolderTable *pcf = new CaseFolderTable();
				pcf->StandardASCII();
				QTextCodec *codec = QTextCodec::codecForName(charSetBuffer);
				// Only for single byte encodings
				for (int i=0x80; i<0x100; i++) {
					char sCharacter[2] = "A";
					sCharacter[0] = i;
					QString su = codec->toUnicode(sCharacter, 1);
					QString suFolded = su.toCaseFolded();
					QByteArray bytesFolded = codec->fromUnicode(suFolded);
					if (bytesFolded.length() == 1) {
						pcf->SetTranslation(sCharacter[0], bytesFolded[0]);
					}
				}
				return pcf;
			} else {
				return new CaseFolderDBCS(QTextCodec::codecForName(charSetBuffer));
			}
		}
		return 0;
	}
}

std::string ScintillaQt::CaseMapString(const std::string &s, int caseMapping)
{
	if (s.size() == 0)
		return std::string();

	if (caseMapping == cmSame)
		return s;

	QTextCodec *codec = 0;
	QString text;
	if (IsUnicodeMode()) {
		text = QString::fromUtf8(s.c_str(), s.length());
	} else {
		codec = QTextCodec::codecForName(CharacterSetIDOfDocument());
		text = codec->toUnicode(s.c_str(), s.length());
	}

	if (caseMapping == cmUpper) {
		text = text.toUpper();
	} else {
		text = text.toLower();
	}

	QByteArray bytes = BytesForDocument(text);
	return std::string(bytes.data(), bytes.length());
}

void ScintillaQt::SetMouseCapture(bool on)
{
	// This is handled automatically by Qt
	if (mouseDownCaptures) {
		haveMouseCapture = on;
	}
}

bool ScintillaQt::HaveMouseCapture()
{
	return haveMouseCapture;
}

void ScintillaQt::StartDrag()
{
	inDragDrop = ddDragging;
	dropWentOutside = true;
	if (drag.len) {
		QMimeData *mimeData = new QMimeData;
		QString sText = StringFromSelectedText(drag);
		mimeData->setText(sText);
		if (drag.rectangular) {
			AddRectangularToMime(mimeData, sText);
		}
		// This QDrag is not freed as that causes a crash on Linux
		QDrag *dragon = new QDrag(scrollArea);
		dragon->setMimeData(mimeData);

		Qt::DropAction dropAction = dragon->exec(Qt::CopyAction|Qt::MoveAction);
		if ((dropAction == Qt::MoveAction) && dropWentOutside) {
			// Remove dragged out text
			ClearSelection();
		}
	}
	inDragDrop = ddNone;
	SetDragPosition(SelectionPosition(invalidPosition));
}

void ScintillaQt::CreateCallTipWindow(PRectangle rc)
{

	if (!ct.wCallTip.Created()) {
		QWidget *pCallTip =  new QWidget(0, Qt::ToolTip);
		ct.wCallTip = pCallTip;
		pCallTip->move(rc.left, rc.top);
		pCallTip->resize(rc.Width(), rc.Height());
	}
}

void ScintillaQt::AddToPopUp(const char *label,
                             int cmd,
                             bool enabled)
{
	QMenu *menu = static_cast<QMenu *>(popup.GetID());
	QString text(label);

	if (text.isEmpty()) {
		menu->addSeparator();
	} else {
		QAction *action = menu->addAction(text);
		action->setData(cmd);
		action->setEnabled(enabled);
	}

	// Make sure the menu's signal is connected only once.
	menu->disconnect();
	connect(menu, SIGNAL(triggered(QAction *)),
	        this, SLOT(execCommand(QAction *)));
}

sptr_t ScintillaQt::WndProc(unsigned int message, uptr_t wParam, sptr_t lParam)
{
	try {
		switch (message) {

		case SCI_GRABFOCUS:
			scrollArea->setFocus(Qt::OtherFocusReason);
			break;

		case SCI_GETDIRECTFUNCTION:
			return reinterpret_cast<sptr_t>(DirectFunction);

		case SCI_GETDIRECTPOINTER:
			return reinterpret_cast<sptr_t>(this);

#ifdef SCI_LEXER
		case SCI_LOADLEXERLIBRARY:
			LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
			break;
#endif

		default:
			return ScintillaBase::WndProc(message, wParam, lParam);
		}
	} catch (std::bad_alloc &) {
		errorStatus = SC_STATUS_BADALLOC;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return 0l;
}

sptr_t ScintillaQt::DefWndProc(unsigned int, uptr_t, sptr_t)
{
	return 0;
}

sptr_t ScintillaQt::DirectFunction(
    ScintillaQt *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam)
{
	return sciThis->WndProc(iMessage, wParam, lParam);
}

// Additions to merge in Scientific Toolworks widget structure

void ScintillaQt::PartialPaint(const PRectangle &rect)
{
	rcPaint = rect;
	paintState = painting;
	PRectangle rcClient = GetClientRectangle();
	paintingAllText = rcPaint.Contains(rcClient);

	AutoSurface surface(this);
	Paint(surface, rcPaint);
	surface->Release();

	if (paintState == paintAbandoned) {
		// FIXME: Failure to paint the requested rectangle in each
		// paint event causes flicker on some platforms (Mac?)
		// Paint rect immediately.
		paintState = painting;
		paintingAllText = true;

		AutoSurface surface(this);
		Paint(surface, rcPaint);
		surface->Release();

		// Queue a full repaint.
		scrollArea->viewport()->update();
	}

	paintState = notPainting;
}

void ScintillaQt::DragEnter(const Point &point)
{
	SetDragPosition(SPositionFromLocation(point,
					      false, false, UserVirtualSpace()));
}

void ScintillaQt::DragMove(const Point &point)
{
	SetDragPosition(SPositionFromLocation(point,
					      false, false, UserVirtualSpace()));
}

void ScintillaQt::DragLeave()
{
	SetDragPosition(SelectionPosition(invalidPosition));
}

void ScintillaQt::Drop(const Point &point, const QMimeData *data, bool move)
{
	QString text = data->text();
	bool rectangular = IsRectangularInMime(data);
	QByteArray bytes = BytesForDocument(text);
	int len = bytes.length();
	char *dest = Document::TransformLineEnds(&len, bytes, len, pdoc->eolMode);

	SelectionPosition movePos = SPositionFromLocation(point,
				false, false, UserVirtualSpace());

	DropAt(movePos, dest, move, rectangular);

	delete []dest;
}

Added qt/ScintillaEditBase/ScintillaQt.h.





























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
//
//          Copyright (c) 1990-2011, Scientific Toolworks, Inc.
//
// The License.txt file describes the conditions under which this software may be distributed.
//
// Author: Jason Haslam
//
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
// ScintillaQt.h - Qt specific subclass of ScintillaBase

#ifndef SCINTILLAQT_H
#define SCINTILLAQT_H

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <string>
#include <vector>
#include <map>

#include "Scintilla.h"
#include "Platform.h"
#include "ILexer.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"

#ifdef SCI_LEXER
#include "SciLexer.h"
#include "PropSetSimple.h"
#endif

#include <QObject>
#include <QAbstractScrollArea>
#include <QAction>
#include <QClipboard>
#include <QPaintEvent>

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class ScintillaQt : public QObject, public ScintillaBase {
	Q_OBJECT

public:
	ScintillaQt(QAbstractScrollArea *parent);
	virtual ~ScintillaQt();

signals:
	void horizontalScrolled(int value);
	void verticalScrolled(int value);
	void horizontalRangeChanged(int max, int page);
	void verticalRangeChanged(int max, int page);

	void notifyParent(SCNotification scn);
	void notifyChange();

	// Clients can use this hook to add additional
	// formats (e.g. rich text) to the MIME data.
	void aboutToCopy(QMimeData *data);

	void command(uptr_t wParam, sptr_t lParam);

private slots:
	void tick();
	void onIdle();
	void execCommand(QAction *action);
	void SelectionChanged();

private:
	virtual void Initialise();
	virtual void Finalise();
	virtual bool DragThreshold(Point ptStart, Point ptNow);
	virtual bool ValidCodePage(int codePage) const;

private:
	virtual void ScrollText(int linesToMove);
	virtual void SetVerticalScrollPos();
	virtual void SetHorizontalScrollPos();
	virtual bool ModifyScrollBars(int nMax, int nPage);
	virtual void ReconfigureScrollBars();
	void CopyToModeClipboard(const SelectionText &selectedText, QClipboard::Mode clipboardMode_);
	virtual void Copy();
	virtual void CopyToClipboard(const SelectionText &selectedText);
	void PasteFromMode(QClipboard::Mode clipboardMode_);
	virtual void Paste();
	virtual void ClaimSelection();
	virtual void NotifyChange();
	virtual void NotifyFocus(bool focus);
	virtual void NotifyParent(SCNotification scn);
	virtual void SetTicking(bool on);
	virtual bool SetIdle(bool on);
	virtual void SetMouseCapture(bool on);
	virtual bool HaveMouseCapture();
	virtual void StartDrag();
	int CharacterSetOfDocument() const;
	const char *CharacterSetIDOfDocument() const;
	QString StringFromDocument(const char *s) const;
	QByteArray BytesForDocument(const QString &text) const;
	virtual CaseFolder *CaseFolderForEncoding();
	virtual std::string CaseMapString(const std::string &s, int caseMapping);

	virtual void CreateCallTipWindow(PRectangle rc);
	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

	static sptr_t DirectFunction(ScintillaQt *sciThis,
				     unsigned int iMessage, uptr_t wParam, sptr_t lParam);

protected:

	void PartialPaint(const PRectangle &rect);

	void DragEnter(const Point &point);
	void DragMove(const Point &point);
	void DragLeave();
	void Drop(const Point &point, const QMimeData *data, bool move);

private:
	QAbstractScrollArea *scrollArea;

	int vMax, hMax;   // Scroll bar maximums.
	int vPage, hPage; // Scroll bar page sizes.

	bool haveMouseCapture;
	bool dragWasDropped;
	int rectangularSelectionModifier;

	friend class ScintillaEditBase;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif // SCINTILLAQT_H

Added qt/ScintillaEditPy/README.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
README for building of ScintillaEditPy on Qt with PySide

This directory is for building a Python encapsulation of Scintilla for use
with PySide. For C++ libraries see the README in the parent directory.

	Prerequisites
	
PySide and ScintillaEditPy currently only support Python 2.x.

CMake may be used to rebuild PySide and is required on Windows.
It can be downloaded from
http://www.cmake.org/cmake/resources/software.html

On Windows, PySide only supports Visual C++ 2008. The "Visual Studio 2008
Command Prompt" should be used to run all build commands.
Visual C++ 2008 Express Edition can be downloaded from
http://msdn.microsoft.com/en-us/express/future/bb421473

Download and install PySide. Instructions are on the PySide web site
http://developer.qt.nokia.com/wiki/Category:LanguageBindings::PySide::Downloads

For Linux, there may be both PySide library packages and PySide development
files. Both should be installed as ScintillaEditPy needs the headers and
libraries from the development package and runs with the normal library package.
On apt-based systems, the packages are libshiboken-dev, shiboken, libpyside-dev,
and python-pyside. python-dev is also needed for Python language headers.
On yum-based systems the packages are shiboken-devel, python-pyside-devel,
and python-devel.
The qmake program may not be in the path and can be found with
"find /usr -name qmake".

On Windows, the PySide library packages can be downloaded from 
http://developer.qt.nokia.com/wiki/PySide_Binaries_Windows
The PySide development files must be built from source using CMake as 
described on the PySide site. This will create a Unix-style set of [bin, include,
lib, and share] directories in packaging\setuptools\install-py<ver>-qt<qver>. 
There is no standard place for the PySide development files so copy them
to "\usr", creating it if needed.

On OS X, a combined package with PySide libraries and PySide development
files can be downloaded from 
http://developer.qt.nokia.com/wiki/PySide_Binaries_MacOSX
This package works best in combination with the Qt libraries for Mac from
http://qt.nokia.com/downloads/downloads#qt-lib

The path should be modified so that a Python 2.x interpreter and Qt's "qmake"
program can be run by typing "python" or "qmake".

	Building

There are several steps to building and they are encapsulated in the sepbuild.py
script which is run:

python sepbuild.py

This script first runs the WidgetGen.py script to fill out the ScintillaEdit.h, 
ScintillaEdit.cpp and ScintillaConstants.py files.

A short file "sepbuild.pri" is written out which contains a series of version and 
path properties discovered by sepbuild.py which are used by qmake.

Then it runs PySide's "shiboken" program to create C++ code that will act as a
bridge between Python and the C++ libraries. This code goes into the 
ScintillaEditPy/ScintillaEditPy directory. Several log files are produced which can
help uncover problems in the bridge if it fails to build.

The qmake program is run to produce make files from ScintillaEditPy.pro.

The system make program is then run to build the library. The library is located in
the scintilla/bin directory as ScintillaEditPy.so for Unix systems and 
ScintillaEditPy.pyd for Windows.

A demonstration program can be run:

python testsepq.py

The individual steps in the script can be run manually if wanted although the
shiboken program has complex arguments and differs between systems so run 
sepbuild.py and copy the section starting with a line containing "generatorrunner"
and continuing to "typesystem_ScintillaEdit.xml".

On Windows, it is more difficult to set up an environment to debug ScintillaEditPy
since all the libraries have to be debug or all have to be release. The easy path 
is to always build for release with "nmake release".

To remove generated code, run "python sepbuild.py --clean".

Added qt/ScintillaEditPy/ScintillaConstants.py.template.













>
>
>
>
>
>
1
2
3
4
5
6
# ScintillaConstants.py
# Define all the symbolic constants from Scintilla.iface so Python code can use them
# Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware

# ++Autogenerated -- start of section automatically generated from Scintilla.iface */
# --Autogenerated -- end of section automatically generated from Scintilla.iface */

Added qt/ScintillaEditPy/ScintillaEditPy.pro.











































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
TEMPLATE = lib
QT += core gui

TARGET = ScintillaEditPy

# Clear debug & release so that sepbuild.pri can set one or the other
CONFIG -= debug release

include(sepbuild.pri)

VERSION = $$SCINTILLA_VERSION

win32 {
	DebugBuild {
		TARGET_EXT = _d.pyd
	}
	else {
		TARGET_EXT = .pyd
	}
}

INCLUDEPATH += ../ScintillaEdit
INCLUDEPATH += ../ScintillaEditBase
INCLUDEPATH += ../../include ../../lexlib ../../src

INCLUDEPATH += $$PY_INCLUDES

INCLUDEPATH += $$SHIBOKEN_INCLUDES
INCLUDEPATH += $$PYSIDE_INCLUDES
INCLUDEPATH += $$PYSIDE_INCLUDES/QtCore
INCLUDEPATH += $$PYSIDE_INCLUDES/QtGui

unix:!mac {
	LIBS += -ldl
	LIBS += `pkg-config pyside --libs`
	QMAKE_CXXFLAGS += -Wno-unused-parameter -Wno-empty-body
}

macx {
	# Only build for x64 for now
	# QMAKE_CFLAGS = -arch i386 -arch x86_64
	# QMAKE_CXXFLAGS = -arch i386 -arch x86_64
	# QMAKE_LFLAGS = -arch i386 -arch x86_64
	LIBS += -L$$PY_LIBDIR -lpython$$PY_VERSION_SUFFIX
	LIBS += -L$$PYSIDE_LIB
	debug {
		LIBS += -lshiboken-python$$PY_VERSION_SUFFIX-dbg
		LIBS += -lpyside-python$$PY_VERSION_SUFFIX-dbg
	}
	else {
		LIBS += -lshiboken-python$$PY_VERSION_SUFFIX
		LIBS += -lpyside-python$$PY_VERSION_SUFFIX
	}
}

win32 {
	DebugBuild {
		DEFINES += DEBUG
		LIBS += -lQtCored4
	}
	else {
		LIBS += -lQtCore
	}
	LIBS += -L$$PY_PREFIX/libs # Note python lib is pulled in via a #pragma
	LIBS += -L$$PYSIDE_LIB
	# PySide uses x.y suffix on Windows even though Python uses xy
	DebugBuild {
		LIBS += -lshiboken-python$${PY_VERSION}_d
		LIBS += -lpyside-python$${PY_VERSION}_d
	}
	else {
		LIBS += -lshiboken-python$${PY_VERSION}
		LIBS += -lpyside-python$${PY_VERSION}
	}
}

# Wrapper sources; notifyheader commented out due to shiboken bug
SOURCES += \
	ScintillaEditPy/scintillaeditpy_module_wrapper.cpp \
	ScintillaEditPy/sci_notifyheader_wrapper.cpp \
	ScintillaEditPy/scnotification_wrapper.cpp \
	ScintillaEditPy/scintillaeditbase_wrapper.cpp \
	ScintillaEditPy/scintillaedit_wrapper.cpp \
	ScintillaEditPy/scintilladocument_wrapper.cpp

# ScintillaEdit sources

SOURCES += \
    ../ScintillaEdit/ScintillaEdit.cpp \
    ../ScintillaEdit/ScintillaDocument.cpp \
    ../ScintillaEditBase/PlatQt.cpp \
    ../ScintillaEditBase/ScintillaQt.cpp \
    ../ScintillaEditBase/ScintillaEditBase.cpp \
    ../../src/*.cxx \
    ../../lexlib/*.cxx \
    ../../lexers/*.cxx

# HEADERS is used to find what needs to be run through moc
HEADERS  += \
    ../ScintillaEdit/ScintillaEdit.h \
    ../ScintillaEdit/ScintillaDocument.h \
    ../ScintillaEditBase/ScintillaQt.h \
    ../ScintillaEditBase/ScintillaEditBase.h

DEFINES += SCINTILLA_QT=1 MAKING_LIBRARY=1 SCI_LEXER=1 _CRT_SECURE_NO_DEPRECATE=1

DESTDIR = ../../bin

unix:!mac {
	# Rename to not have 'lib' at start
	QMAKE_POST_LINK += rm -rf ../../bin/ScintillaEditPy.so && ln -s libScintillaEditPy.so ../../bin/ScintillaEditPy.so
}

macx {
	# Rename to .so and not have 'lib' at start
	QMAKE_POST_LINK += rm -rf ../../bin/ScintillaEditPy.so && ln -s libScintillaEditPy.dylib ../../bin/ScintillaEditPy.so
}

Added qt/ScintillaEditPy/global.h.









>
>
>
>
1
2
3
4
#include "pyside_global.h"

#include "ScintillaEditBase.h"
#include "ScintillaEdit.h"

Added qt/ScintillaEditPy/sepbuild.py.





































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
import distutils.sysconfig
import getopt
import glob
import os
import platform
import shutil
import subprocess
import stat
import sys

sys.path.append(os.path.join("..", "ScintillaEdit"))
import WidgetGen

# Decide up front which platform, treat anything other than Windows or OS X as Linux
PLAT_WINDOWS = platform.system() == "Windows"
PLAT_DARWIN = platform.system() == "Darwin"
PLAT_LINUX = not (PLAT_DARWIN or PLAT_WINDOWS)

def IsFileNewer(name1, name2):
	""" Returns whether file with name1 is newer than file with name2.  Returns 1
	if name2 doesn't exist. """

	if not os.path.exists(name1):
		return 0

	if not os.path.exists(name2):
		return 1

	mod_time1 = os.stat(name1)[stat.ST_MTIME]
	mod_time2 = os.stat(name2)[stat.ST_MTIME]
	return (mod_time1 > mod_time2)

def textFromRun(args):
	(stdoutdata, stderrdata) = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE).communicate()
	return stdoutdata

def runProgram(args, exitOnFailure):
	print(" ".join(args))
	retcode = subprocess.call(" ".join(args), shell=True, stderr=subprocess.STDOUT)
	if retcode:
		print("Failed in " + " ".join(args) + " return code = " + str(retcode))
		if exitOnFailure:
			sys.exit()

def usage():
	print("sepbuild.py [-h|--help][-c|--clean][-u|--underscore-names]")
	print("")
	print("Generate PySide wappers and build them.")
	print("")
	print("options:")
	print("")
	print("-c --clean remove all object and generated files")
	print("-b --pyside-base  Location of the PySide+Qt4 sandbox to use")
	print("-h --help  display this text")
	print("-d --debug=yes|no  force debug build (or non-debug build)")
	print("-u --underscore-names  use method_names consistent with GTK+ standards")

modifyFunctionElement = """		<modify-function signature="%s">%s
		</modify-function>
"""

injectCode = """
			<inject-code class="target" position="beginning">%s
			</inject-code>"""

injectCheckN = """
				if (!cppArg%d) {
					PyErr_SetString(PyExc_ValueError, "Null string argument");
					return 0;
				}"""

def methodSignature(name, v, options):
	argTypes = ""
	p1Type = WidgetGen.cppAlias(v["Param1Type"])
	if p1Type:
		argTypes = argTypes + p1Type
	p2Type = WidgetGen.cppAlias(v["Param2Type"])
	if p2Type and v["Param2Type"] != "stringresult":
		if p1Type:
			argTypes = argTypes + ", "
		argTypes = argTypes + p2Type
	methodName = WidgetGen.normalisedName(name, options, v["FeatureType"])
	constDeclarator = " const" if v["FeatureType"] == "get" else ""
	return methodName + "(" + argTypes + ")" + constDeclarator

def printTypeSystemFile(f,out, options):
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["fun", "get", "set"]:
				checks = ""
				if v["Param1Type"] == "string":
					checks = checks + (injectCheckN % 0)
				if v["Param2Type"] == "string":
					if v["Param1Type"] == "":	# Only arg 2 -> treat as first
						checks = checks + (injectCheckN % 0)
					else:
						checks = checks + (injectCheckN % 1)
				if checks:
					inject = injectCode % checks
					out.write(modifyFunctionElement % (methodSignature(name, v, options), inject))
				#if v["Param1Type"] == "string":
				#	out.write("<string-xml>" + name + "</string-xml>\n")

def doubleBackSlashes(s):
	# Quote backslashes so qmake does not produce warnings
	return s.replace("\\", "\\\\")

class SepBuilder:
	def __init__(self):
		# Discover configuration parameters
		self.ScintillaEditIncludes = [".", "../ScintillaEdit", "../ScintillaEditBase", "../../include"]
		if PLAT_WINDOWS:
			self.MakeCommand = "nmake"
			self.MakeTarget = "release"
		else:
			self.MakeCommand = "make"
			self.MakeTarget = ""

		if PLAT_DARWIN:
			self.QMakeOptions = "-spec macx-g++"
		else:
			self.QMakeOptions = ""

		# Default to debug build if running in a debug build interpreter
		self.DebugBuild = hasattr(sys, 'getobjects')

		# Python
		self.PyVersion = "%d.%d" % sys.version_info[:2]
		self.PyVersionSuffix = distutils.sysconfig.get_config_var("VERSION")
		self.PyIncludes = distutils.sysconfig.get_python_inc()
		self.PyPrefix = distutils.sysconfig.get_config_var("prefix")
		self.PyLibDir = distutils.sysconfig.get_config_var(
			("LIBDEST" if sys.platform == 'win32' else "LIBDIR"))

		# Scintilla
		with open("../../version.txt") as f:
			version = f.read()
			self.ScintillaVersion = version[0] + '.' + version[1] + '.' + version[2]

		# Find out what qmake is called
		self.QMakeCommand = "qmake"
		if not PLAT_WINDOWS:
			# On Unix qmake may not be present but qmake-qt4 may be so check
			pathToQMake = textFromRun("which qmake-qt4 || which qmake").rstrip()
			self.QMakeCommand = os.path.basename(pathToQMake)

		# Qt default location from qmake
		self._SetQtIncludeBase(textFromRun(self.QMakeCommand + " -query QT_INSTALL_HEADERS").rstrip())

		# PySide default location
		# No standard for installing PySide development headers and libs on Windows so
		# choose /usr to be like Linux
		self._setPySideBase('\\usr' if PLAT_WINDOWS else '/usr')

		self.ProInclude = "sepbuild.pri"

		self.qtStyleInterface = True

	def _setPySideBase(self, base):
		
		self.PySideBase = base
		if PLAT_LINUX:
			self.PySideTypeSystem = textFromRun("pkg-config --variable=typesystemdir pyside").rstrip()
			self.PySideIncludeBase = textFromRun("pkg-config --variable=includedir pyside").rstrip()
			self.ShibokenIncludeBase = textFromRun("pkg-config --variable=includedir shiboken").rstrip()
		else:
			self.PySideTypeSystem = os.path.join(self.PySideBase, "share", "PySide", "typesystems")
			self.ShibokenIncludeBase = os.path.join(self.PySideBase, "include", "shiboken")
			self.PySideIncludeBase = os.path.join(self.PySideBase, "include", "PySide")

		self.PySideIncludes = [
			self.ShibokenIncludeBase,
			self.PySideIncludeBase,
			os.path.join(self.PySideIncludeBase, "QtCore"),
			os.path.join(self.PySideIncludeBase, "QtGui")]

		self.PySideLibDir = os.path.join(self.PySideBase, "lib")
		self.AllIncludes = os.pathsep.join(self.QtIncludes + self.ScintillaEditIncludes + self.PySideIncludes)

		self.ShibokenGenerator = "shiboken"
		# Is this still needed? It doesn't work with latest shiboken sources
		#if PLAT_DARWIN:
		#	# On OS X, can not automatically find Shiboken dylib so provide a full path
		#	self.ShibokenGenerator = os.path.join(self.PySideLibDir, "generatorrunner", "shiboken")

	def generateAPI(self, args):
		os.chdir(os.path.join("..", "ScintillaEdit"))
		if not self.qtStyleInterface:
			args.insert(0, '--underscore-names')
		WidgetGen.main(args)
		f = WidgetGen.readInterface(False)
		os.chdir(os.path.join("..", "ScintillaEditPy"))
		options = {"qtStyle": self.qtStyleInterface}
		WidgetGen.Generate("typesystem_ScintillaEdit.xml.template", "typesystem_ScintillaEdit.xml", printTypeSystemFile, f, options)

	def runGenerator(self):
		generatorrunner = "shiboken"
		for name in ('shiboken', 'generatorrunner'):
			if PLAT_WINDOWS:
				name += '.exe'
			name = os.path.join(self.PySideBase, "bin", name)
			if os.path.exists(name):
				generatorrunner = name
				break
				
		args = [
			generatorrunner,
			"--generator-set=" + self.ShibokenGenerator,
			"global.h ",
			"--avoid-protected-hack",
			"--enable-pyside-extensions",
			"--include-paths=" + self.AllIncludes,
			"--typesystem-paths=" + self.PySideTypeSystem,
			"--output-directory=.",
			"typesystem_ScintillaEdit.xml"]
		print(" ".join(args))
		retcode = subprocess.call(" ".join(args), shell=True, stderr=subprocess.STDOUT)
		if retcode:
			print("Failed in generatorrunner", retcode)
			sys.exit()

	def writeVariables(self):
		# Write variables needed into file to be included from project so it does not have to discover much
		with open(self.ProInclude, "w") as f:
			f.write("SCINTILLA_VERSION=" + self.ScintillaVersion + "\n")
			f.write("PY_VERSION=" + self.PyVersion + "\n")
			f.write("PY_VERSION_SUFFIX=" + self.PyVersionSuffix + "\n")
			f.write("PY_PREFIX=" + doubleBackSlashes(self.PyPrefix) + "\n")
			f.write("PY_INCLUDES=" + doubleBackSlashes(self.PyIncludes) + "\n")
			f.write("PY_LIBDIR=" + doubleBackSlashes(self.PyLibDir) + "\n")
			f.write("PYSIDE_INCLUDES=" + doubleBackSlashes(self.PySideIncludeBase) + "\n")
			f.write("PYSIDE_LIB=" + doubleBackSlashes(self.PySideLibDir) + "\n")
			f.write("SHIBOKEN_INCLUDES=" + doubleBackSlashes(self.ShibokenIncludeBase) + "\n")
			if self.DebugBuild:
				f.write("CONFIG += debug\n")
			else:
				f.write("CONFIG += release\n")

	def make(self):
		runProgram([self.QMakeCommand, self.QMakeOptions], exitOnFailure=True)
		runProgram([self.MakeCommand, self.MakeTarget], exitOnFailure=True)

	def cleanEverything(self):
		self.generateAPI(["--clean"])
		runProgram([self.MakeCommand, "distclean"], exitOnFailure=False)
		filesToRemove = [self.ProInclude, "typesystem_ScintillaEdit.xml", 
			"../../bin/ScintillaEditPy.so", "../../bin/ScintillaConstants.py"]
		for file in filesToRemove:
			try:
				os.remove(file)
			except OSError:
				pass
		for logFile in glob.glob("*.log"):
			try:
				os.remove(logFile)
			except OSError:
				pass
		shutil.rmtree("debug", ignore_errors=True)
		shutil.rmtree("release", ignore_errors=True)
		shutil.rmtree("ScintillaEditPy", ignore_errors=True)

	def buildEverything(self):
		cleanGenerated = False
		opts, args = getopt.getopt(sys.argv[1:], "hcdub",
					["help", "clean", "debug=", 
					"underscore-names", "pyside-base="])
		for opt, arg in opts:
			if opt in ("-h", "--help"):
				usage()
				sys.exit()
			elif opt in ("-c", "--clean"):
				cleanGenerated = True
			elif opt in ("-d", "--debug"):
				self.DebugBuild = (arg == '' or arg.lower() == 'yes')
				if self.DebugBuild and sys.platform == 'win32':
					self.MakeTarget = 'debug'
			elif opt in ("-b", '--pyside-base'):
				self._SetQtIncludeBase(os.path.join(os.path.normpath(arg), 'include'))
				self._setPySideBase(os.path.normpath(arg))
			elif opt in ("-u", "--underscore-names"):
				self.qtStyleInterface = False

		if cleanGenerated:
			self.cleanEverything()
		else:
			self.writeVariables()
			self.generateAPI([""])
			self.runGenerator()
			self.make()
			self.copyScintillaConstants()
			
	def copyScintillaConstants(self):
		
		orig = 'ScintillaConstants.py'
		dest = '../../bin/' + orig
		if IsFileNewer(dest, orig):
			return
		
		f = open(orig, 'r')
		contents = f.read()
		f.close()
		
		f = open(dest, 'w')
		f.write(contents)
		f.close()

	def _SetQtIncludeBase(self, base):

		self.QtIncludeBase = base
		self.QtIncludes = [self.QtIncludeBase] + [os.path.join(self.QtIncludeBase, sub) for sub in ["QtCore", "QtGui"]]
		# Set path so correct qmake is found
		path = os.environ.get('PATH', '').split(os.pathsep)
		qt_bin_dir = os.path.join(os.path.dirname(base), 'bin')
		if qt_bin_dir not in path:
			path.insert(0, qt_bin_dir)
			os.environ['PATH'] = os.pathsep.join(path)

if __name__ == "__main__":
	sepBuild = SepBuilder()
	sepBuild.buildEverything()

Added qt/ScintillaEditPy/testsepq.py.



























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys

from PySide.QtCore import *
from PySide.QtGui import *

import ScintillaConstants as sci

sys.path.append("../..")
from bin import ScintillaEditPy

txtInit =	"int main(int argc, char **argv) {\n" \
		"    // Start up the gnome\n" \
		"    gnome_init(\"stest\", \"1.0\", argc, argv);\n}\n";

keywords = \
		"and and_eq asm auto bitand bitor bool break " \
		"case catch char class compl const const_cast continue " \
		"default delete do double dynamic_cast else enum explicit export extern false float for " \
		"friend goto if inline int long mutable namespace new not not_eq " \
		"operator or or_eq private protected public " \
		"register reinterpret_cast return short signed sizeof static static_cast struct switch " \
		"template this throw true try typedef typeid typename union unsigned using " \
		"virtual void volatile wchar_t while xor xor_eq";

def uriDropped():
	print "uriDropped"

class Form(QDialog):

	def __init__(self, parent=None):
		super(Form, self).__init__(parent)
		self.resize(460,300)
		# Create widgets
		self.edit = ScintillaEditPy.ScintillaEdit(self)
		self.edit.uriDropped.connect(uriDropped)
		self.edit.command.connect(self.receive_command)
		self.edit.notify.connect(self.receive_notification)

		self.edit.styleClearAll()
		self.edit.setMarginWidthN(0, 35)
		self.edit.setScrollWidth(200)
		self.edit.setScrollWidthTracking(1)
		self.edit.setLexer(sci.SCLEX_CPP)
		self.edit.styleSetFore(sci.SCE_C_COMMENT, 0x008000)
		self.edit.styleSetFore(sci.SCE_C_COMMENTLINE, 0x008000)
		self.edit.styleSetFore(sci.SCE_C_COMMENTDOC, 0x008040)
		self.edit.styleSetItalic(sci.SCE_C_COMMENTDOC, 1)
		self.edit.styleSetFore(sci.SCE_C_NUMBER, 0x808000)
		self.edit.styleSetFore(sci.SCE_C_WORD, 0x800000)
		self.edit.styleSetBold(sci.SCE_C_WORD, True)
		self.edit.styleSetFore(sci.SCE_C_STRING, 0x800080)
		self.edit.styleSetFore(sci.SCE_C_PREPROCESSOR, 0x008080)
		self.edit.styleSetBold(sci.SCE_C_OPERATOR, True)
		self.edit.setMultipleSelection(1)
		self.edit.setVirtualSpaceOptions(
			sci.SCVS_RECTANGULARSELECTION | sci.SCVS_USERACCESSIBLE)
		self.edit.setAdditionalSelectionTyping(1)

		self.edit.styleSetFore(sci.STYLE_INDENTGUIDE, 0x808080)
		self.edit.setIndentationGuides(sci.SC_IV_LOOKBOTH)

		self.edit.setKeyWords(0, keywords)
		self.edit.addText(len(txtInit), txtInit)
		self.edit.setSel(1,10)
		retriever = str(self.edit.getLine(1))
		print(type(retriever), len(retriever))
		print('[' + retriever + ']')
		someText = str(self.edit.textRange(2,5))
		print(len(someText), '[' + someText + ']')
		someText = self.edit.getCurLine(100)
		print(len(someText), '[' + someText + ']')
		someText = self.edit.styleFont(1)
		print(len(someText), '[' + someText + ']')
		someText = self.edit.getSelText()
		print(len(someText), '[' + someText + ']')
		someText = self.edit.tag(1)
		print(len(someText), '[' + someText + ']')
		someText = self.edit.autoCCurrentText()
		print(len(someText), '[' + someText + ']')
		someText = self.edit.annotationText(1)
		print(len(someText), '[' + someText + ']')
		someText = self.edit.annotationStyles(1)
		print(len(someText), '[' + someText + ']')
		someText = self.edit.describeKeyWordSets()
		print(len(someText), '[' + someText + ']')
		someText = self.edit.propertyNames()
		print(len(someText), '[' + someText + ']')
		self.edit.setProperty("fold", "1")
		someText = self.edit.property("fold")
		print(len(someText), '[' + someText + ']')
		someText = self.edit.propertyExpanded("fold")
		print(len(someText), '[' + someText + ']')
		someText = self.edit.lexerLanguage()
		print(len(someText), '[' + someText + ']')
		someText = self.edit.describeProperty("styling.within.preprocessor")
		print(len(someText), '[' + someText + ']')

		xx = self.edit.findText(0, "main", 0, 25)
		print(type(xx), xx)
		print("isBold", self.edit.styleBold(sci.SCE_C_WORD))

		# Retrieve the document and write into it
		doc = self.edit.get_doc()
		doc.insert_string(40, "***")
		stars = doc.get_char_range(40,3)
		assert stars == "***"

		# Create a new independent document and attach it to the editor
		doc = ScintillaEditPy.ScintillaDocument()
		doc.insert_string(0, "/***/\nif(a)\n")
		self.edit.set_doc(doc)
		self.edit.setLexer(sci.SCLEX_CPP)

	def Call(self, message, wParam=0, lParam=0):
		return self.edit.send(message, wParam, lParam)

	def resizeEvent(self, e):
		self.edit.resize(e.size().width(), e.size().height())

	def receive_command(self, wParam, lParam):
		# Show underline at start when focussed
		notifyCode = wParam >> 16
		if (notifyCode == sci.SCEN_SETFOCUS) or (notifyCode == sci.SCEN_KILLFOCUS):
			self.edit.setIndicatorCurrent(sci.INDIC_CONTAINER);
			self.edit.indicatorClearRange(0, self.edit.length())
			if notifyCode == sci.SCEN_SETFOCUS:
				self.edit.indicatorFillRange(0, 2);

	def receive_notification(self, scn):
		if scn.nmhdr.code == sci.SCN_CHARADDED:
			print "Char %02X" % scn.ch
		elif scn.nmhdr.code == sci.SCN_SAVEPOINTREACHED:
			print "Saved"
		elif scn.nmhdr.code == sci.SCN_SAVEPOINTLEFT:
			print "Unsaved"
		elif scn.nmhdr.code == sci.SCN_MODIFIED:
			print "Modified"
		elif scn.nmhdr.code == sci.SCN_UPDATEUI:
			print "Update UI"
		elif scn.nmhdr.code == sci.SCN_PAINTED:
			#print "Painted"
			pass
		else:
			print "Notification", scn.nmhdr.code
			pass

if __name__ == '__main__':
    # Create the Qt Application
    app = QApplication(sys.argv)
    # Create and show the form
    form = Form()
    form.show()
    # Run the main Qt loop
    sys.exit(app.exec_())

Added qt/ScintillaEditPy/typesystem_ScintillaEdit.xml.template.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>
<typesystem package="ScintillaEditPy">
	<load-typesystem name="typesystem_core.xml" generate="no" />
	<load-typesystem name="typesystem_gui_common.xml" generate="no"/>
	<primitive-type name="sptr_t"/>
	<primitive-type name="uptr_t"/>
	<value-type name="Sci_NotifyHeader" />
	<rejection class="Sci_NotifyHeader" field-name="hwndFrom" />
	<value-type name="SCNotification" />
	<object-type name="ScintillaEditBase" />
	<object-type name="ScintillaEdit">
	<!-- ++Autogenerated start of section automatically generated from Scintilla.iface -->
	<!-- ~~Autogenerated end of section automatically generated from Scintilla.iface -->
	</object-type>
	<object-type name="ScintillaDocument" />
</typesystem>

Added src/AutoComplete.cxx.







































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file AutoComplete.cxx
 ** Defines the auto completion list box.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>

#include <string>

#include "Platform.h"

#include "CharacterSet.h"
#include "AutoComplete.h"
#include "Scintilla.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

AutoComplete::AutoComplete() :
	active(false),
	separator(' '),
	typesep('?'),
	ignoreCase(false),
	chooseSingle(false),
	lb(0),
	posStart(0),
	startLen(0),
	cancelAtStartPos(true),
	autoHide(true),
	dropRestOfWord(false),
	ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE),
	widthLBDefault(100),
	heightLBDefault(100) {
	lb = ListBox::Allocate();
	stopChars[0] = '\0';
	fillUpChars[0] = '\0';
}

AutoComplete::~AutoComplete() {
	if (lb) {
		lb->Destroy();
		delete lb;
		lb = 0;
	}
}

bool AutoComplete::Active() const {
	return active;
}

void AutoComplete::Start(Window &parent, int ctrlID,
	int position, Point location, int startLen_,
	int lineHeight, bool unicodeMode, int technology) {
	if (active) {
		Cancel();
	}
	lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology);
	lb->Clear();
	active = true;
	startLen = startLen_;
	posStart = position;
}

void AutoComplete::SetStopChars(const char *stopChars_) {
	strncpy(stopChars, stopChars_, sizeof(stopChars));
	stopChars[sizeof(stopChars) - 1] = '\0';
}

bool AutoComplete::IsStopChar(char ch) {
	return ch && strchr(stopChars, ch);
}

void AutoComplete::SetFillUpChars(const char *fillUpChars_) {
	strncpy(fillUpChars, fillUpChars_, sizeof(fillUpChars));
	fillUpChars[sizeof(fillUpChars) - 1] = '\0';
}

bool AutoComplete::IsFillUpChar(char ch) {
	return ch && strchr(fillUpChars, ch);
}

void AutoComplete::SetSeparator(char separator_) {
	separator = separator_;
}

char AutoComplete::GetSeparator() const {
	return separator;
}

void AutoComplete::SetTypesep(char separator_) {
	typesep = separator_;
}

char AutoComplete::GetTypesep() const {
	return typesep;
}

void AutoComplete::SetList(const char *list) {
	lb->SetList(list, separator, typesep);
}

int AutoComplete::GetSelection() const {
	return lb->GetSelection();
}

std::string AutoComplete::GetValue(int item) const {
	char value[maxItemLen];
	lb->GetValue(item, value, sizeof(value));
	return std::string(value);
}

void AutoComplete::Show(bool show) {
	lb->Show(show);
	if (show)
		lb->Select(0);
}

void AutoComplete::Cancel() {
	if (lb->Created()) {
		lb->Clear();
		lb->Destroy();
		active = false;
	}
}


void AutoComplete::Move(int delta) {
	int count = lb->Length();
	int current = lb->GetSelection();
	current += delta;
	if (current >= count)
		current = count - 1;
	if (current < 0)
		current = 0;
	lb->Select(current);
}

void AutoComplete::Select(const char *word) {
	size_t lenWord = strlen(word);
	int location = -1;
	int start = 0; // lower bound of the api array block to search
	int end = lb->Length() - 1; // upper bound of the api array block to search
	while ((start <= end) && (location == -1)) { // Binary searching loop
		int pivot = (start + end) / 2;
		char item[maxItemLen];
		lb->GetValue(pivot, item, maxItemLen);
		int cond;
		if (ignoreCase)
			cond = CompareNCaseInsensitive(word, item, lenWord);
		else
			cond = strncmp(word, item, lenWord);
		if (!cond) {
			// Find first match
			while (pivot > start) {
				lb->GetValue(pivot-1, item, maxItemLen);
				if (ignoreCase)
					cond = CompareNCaseInsensitive(word, item, lenWord);
				else
					cond = strncmp(word, item, lenWord);
				if (0 != cond)
					break;
				--pivot;
			}
			location = pivot;
			if (ignoreCase
				&& ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) {
				// Check for exact-case match
				for (; pivot <= end; pivot++) {
					lb->GetValue(pivot, item, maxItemLen);
					if (!strncmp(word, item, lenWord)) {
						location = pivot;
						break;
					}
					if (CompareNCaseInsensitive(word, item, lenWord))
						break;
				}
			}
		} else if (cond < 0) {
			end = pivot - 1;
		} else if (cond > 0) {
			start = pivot + 1;
		}
	}
	if (location == -1 && autoHide)
		Cancel();
	else
		lb->Select(location);
}

Added src/AutoComplete.h.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file AutoComplete.h
 ** Defines the auto completion list box.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef AUTOCOMPLETE_H
#define AUTOCOMPLETE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class AutoComplete {
	bool active;
	char stopChars[256];
	char fillUpChars[256];
	char separator;
	char typesep; // Type seperator
	enum { maxItemLen=1000 };

public:

	bool ignoreCase;
	bool chooseSingle;
	ListBox *lb;
	int posStart;
	int startLen;
	/// Should autocompletion be canceled if editor's currentPos <= startPos?
	bool cancelAtStartPos;
	bool autoHide;
	bool dropRestOfWord;
	unsigned int ignoreCaseBehaviour;
	int widthLBDefault;
	int heightLBDefault;

	AutoComplete();
	~AutoComplete();

	/// Is the auto completion list displayed?
	bool Active() const;

	/// Display the auto completion list positioned to be near a character position
	void Start(Window &parent, int ctrlID, int position, Point location,
		int startLen_, int lineHeight, bool unicodeMode, int technology);

	/// The stop chars are characters which, when typed, cause the auto completion list to disappear
	void SetStopChars(const char *stopChars_);
	bool IsStopChar(char ch);

	/// The fillup chars are characters which, when typed, fill up the selected word
	void SetFillUpChars(const char *fillUpChars_);
	bool IsFillUpChar(char ch);

	/// The separator character is used when interpreting the list in SetList
	void SetSeparator(char separator_);
	char GetSeparator() const;

	/// The typesep character is used for seperating the word from the type
	void SetTypesep(char separator_);
	char GetTypesep() const;

	/// The list string contains a sequence of words separated by the separator character
	void SetList(const char *list);
	
	/// Return the position of the currently selected list item
	int GetSelection() const;

	/// Return the value of an item in the list
	std::string GetValue(int item) const;

	void Show(bool show);
	void Cancel();

	/// Move the current list element by delta, scrolling appropriately
	void Move(int delta);

	/// Select a list element that starts with word as the current element
	void Select(const char *word);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/CallTip.cxx.



































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
// Scintilla source code edit control
/** @file CallTip.cxx
 ** Code for displaying call tips.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "CallTip.h"
#include <stdio.h>

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

CallTip::CallTip() {
	wCallTip = 0;
	inCallTipMode = false;
	posStartCallTip = 0;
	val = 0;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	lineHeight = 1;
	offsetMain = 0;
	startHighlight = 0;
	endHighlight = 0;
	tabSize = 0;
	above = false;
	useStyleCallTip = false;    // for backwards compatibility

	insetX = 5;
	widthArrow = 14;
	borderHeight = 2; // Extra line for border and an empty line at top and bottom.
	verticalOffset = 1;

#ifdef __APPLE__
	// proper apple colours for the default
	colourBG = ColourDesired(0xff, 0xff, 0xc6);
	colourUnSel = ColourDesired(0, 0, 0);
#else
	colourBG = ColourDesired(0xff, 0xff, 0xff);
	colourUnSel = ColourDesired(0x80, 0x80, 0x80);
#endif
	colourSel = ColourDesired(0, 0, 0x80);
	colourShade = ColourDesired(0, 0, 0);
	colourLight = ColourDesired(0xc0, 0xc0, 0xc0);
	codePage = 0;
	clickPlace = 0;
}

CallTip::~CallTip() {
	font.Release();
	wCallTip.Destroy();
	delete []val;
	val = 0;
}

// Although this test includes 0, we should never see a \0 character.
static bool IsArrowCharacter(char ch) {
	return (ch == 0) || (ch == '\001') || (ch == '\002');
}

// We ignore tabs unless a tab width has been set.
bool CallTip::IsTabCharacter(char ch) const {
	return (tabSize > 0) && (ch == '\t');
}

int CallTip::NextTabPos(int x) {
	if (tabSize > 0) {              // paranoia... not called unless this is true
		x -= insetX;                // position relative to text
		x = (x + tabSize) / tabSize;  // tab "number"
		return tabSize*x + insetX;  // position of next tab
	} else {
		return x + 1;                 // arbitrary
	}
}

// Draw a section of the call tip that does not include \n in one colour.
// The text may include up to numEnds tabs or arrow characters.
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
	int posStart, int posEnd, int ytext, PRectangle rcClient,
	bool highlight, bool draw) {
	s += posStart;
	int len = posEnd - posStart;

	// Divide the text into sections that are all text, or that are
	// single arrows or single tab characters (if tabSize > 0).
	int maxEnd = 0;
	const int numEnds = 10;
	int ends[numEnds + 2];
	for (int i=0; i<len; i++) {
		if ((maxEnd < numEnds) &&
		        (IsArrowCharacter(s[i]) || IsTabCharacter(s[i]))) {
			if (i > 0)
				ends[maxEnd++] = i;
			ends[maxEnd++] = i+1;
		}
	}
	ends[maxEnd++] = len;
	int startSeg = 0;
	int xEnd;
	for (int seg = 0; seg<maxEnd; seg++) {
		int endSeg = ends[seg];
		if (endSeg > startSeg) {
			if (IsArrowCharacter(s[startSeg])) {
				bool upArrow = s[startSeg] == '\001';
				rcClient.left = x;
				rcClient.right = rcClient.left + widthArrow;
				if (draw) {
					const int halfWidth = widthArrow / 2 - 3;
					const int centreX = rcClient.left + widthArrow / 2 - 1;
					const int centreY = (rcClient.top + rcClient.bottom) / 2;
					surface->FillRectangle(rcClient, colourBG);
					PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1,
					                         rcClient.right - 2, rcClient.bottom - 1);
					surface->FillRectangle(rcClientInner, colourUnSel);

					if (upArrow) {      // Up arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY + halfWidth / 2),
    						Point(centreX + halfWidth, centreY + halfWidth / 2),
    						Point(centreX, centreY - halfWidth + halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG, colourBG);
					} else {            // Down arrow
						Point pts[] = {
    						Point(centreX - halfWidth, centreY - halfWidth / 2),
    						Point(centreX + halfWidth, centreY - halfWidth / 2),
    						Point(centreX, centreY + halfWidth - halfWidth / 2),
						};
						surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 						colourBG, colourBG);
					}
				}
				xEnd = rcClient.right;
				offsetMain = xEnd;
				if (upArrow) {
					rectUp = rcClient;
				} else {
					rectDown = rcClient;
				}
			} else if (IsTabCharacter(s[startSeg])) {
				xEnd = NextTabPos(x);
			} else {
				xEnd = x + surface->WidthText(font, s + startSeg, endSeg - startSeg);
				if (draw) {
					rcClient.left = x;
					rcClient.right = xEnd;
					surface->DrawTextTransparent(rcClient, font, ytext,
										s+startSeg, endSeg - startSeg,
					                             highlight ? colourSel : colourUnSel);
				}
			}
			x = xEnd;
			startSeg = endSeg;
		}
	}
}

int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	// To make a nice small call tip window, it is only sized to fit most normal characters without accents
	int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);

	// For each line...
	// Draw the definition in three parts: before highlight, highlighted, after highlight
	int ytext = rcClient.top + ascent + 1;
	rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
	char *chunkVal = val;
	bool moreChunks = true;
	int maxWidth = 0;

	while (moreChunks) {
		char *chunkEnd = strchr(chunkVal, '\n');
		if (chunkEnd == NULL) {
			chunkEnd = chunkVal + strlen(chunkVal);
			moreChunks = false;
		}
		int chunkOffset = chunkVal - val;
		int chunkLength = chunkEnd - chunkVal;
		int chunkEndOffset = chunkOffset + chunkLength;
		int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
		thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
		thisStartHighlight -= chunkOffset;
		int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
		thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
		thisEndHighlight -= chunkOffset;
		rcClient.top = ytext - ascent - 1;

		int x = insetX;     // start each line at this inset

		DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
			ytext, rcClient, false, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
			ytext, rcClient, true, draw);
		DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
			ytext, rcClient, false, draw);

		chunkVal = chunkEnd + 1;
		ytext += lineHeight;
		rcClient.bottom += lineHeight;
		maxWidth = Platform::Maximum(maxWidth, x);
	}
	return maxWidth;
}

void CallTip::PaintCT(Surface *surfaceWindow) {
	if (!val)
		return;
	PRectangle rcClientPos = wCallTip.GetClientPosition();
	PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
	                        rcClientPos.bottom - rcClientPos.top);
	PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);

	surfaceWindow->FillRectangle(rcClient, colourBG);

	offsetMain = insetX;    // initial alignment assuming no arrows
	PaintContents(surfaceWindow, true);

#ifndef __APPLE__
	// OSX doesn't put borders on "help tags"
	// Draw a raised border around the edges of the window
	surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
	surfaceWindow->PenColour(colourShade);
	surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
	surfaceWindow->LineTo(rcClientSize.right - 1, 0);
	surfaceWindow->PenColour(colourLight);
	surfaceWindow->LineTo(0, 0);
	surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
#endif
}

void CallTip::MouseClick(Point pt) {
	clickPlace = 0;
	if (rectUp.Contains(pt))
		clickPlace = 1;
	if (rectDown.Contains(pt))
		clickPlace = 2;
}

PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *defn,
                                 const char *faceName, int size,
                                 int codePage_, int characterSet,
								 int technology, Window &wParent) {
	clickPlace = 0;
	delete []val;
	val = 0;
	val = new char[strlen(defn) + 1];
	strcpy(val, defn);
	codePage = codePage_;
	Surface *surfaceMeasure = Surface::Allocate(technology);
	if (!surfaceMeasure)
		return PRectangle();
	surfaceMeasure->Init(wParent.GetID());
	surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
	surfaceMeasure->SetDBCSMode(codePage);
	startHighlight = 0;
	endHighlight = 0;
	inCallTipMode = true;
	posStartCallTip = pos;
	int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
	FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet);
	font.Create(fp);
	// Look for multiple lines in the text
	// Only support \n here - simply means container must avoid \r!
	int numLines = 1;
	const char *newline;
	const char *look = val;
	rectUp = PRectangle(0,0,0,0);
	rectDown = PRectangle(0,0,0,0);
	offsetMain = insetX;            // changed to right edge of any arrows
	int width = PaintContents(surfaceMeasure, false) + insetX;
	while ((newline = strchr(look, '\n')) != NULL) {
		look = newline + 1;
		numLines++;
	}
	lineHeight = surfaceMeasure->Height(font);

	// The returned
	// rectangle is aligned to the right edge of the last arrow encountered in
	// the tip text, else to the tip text left edge.
	int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + borderHeight * 2;
	delete surfaceMeasure;
	if (above) {
		return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset);
	} else {
		return PRectangle(pt.x - offsetMain, pt.y + verticalOffset + textHeight, pt.x + width - offsetMain, pt.y + verticalOffset + textHeight + height);
	}
}

void CallTip::CallTipCancel() {
	inCallTipMode = false;
	if (wCallTip.Created()) {
		wCallTip.Destroy();
	}
}

void CallTip::SetHighlight(int start, int end) {
	// Avoid flashing by checking something has really changed
	if ((start != startHighlight) || (end != endHighlight)) {
		startHighlight = start;
		endHighlight = (end > start) ? end : start;
		if (wCallTip.Created()) {
			wCallTip.InvalidateAll();
		}
	}
}

// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
// use of the STYLE_CALLTIP.
void CallTip::SetTabSize(int tabSz) {
	tabSize = tabSz;
	useStyleCallTip = true;
}

// Set the calltip position, below the text by default or if above is false
// else above the text.
void CallTip::SetPosition(bool aboveText) {
	above = aboveText;
}

// It might be better to have two access functions for this and to use
// them for all settings of colours.
void CallTip::SetForeBack(const ColourDesired &fore, const ColourDesired &back) {
	colourBG = back;
	colourUnSel = fore;
}

Added src/CallTip.h.



























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CallTip.h
 ** Interface to the call tip control.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CALLTIP_H
#define CALLTIP_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class CallTip {
	int startHighlight;    // character offset to start and...
	int endHighlight;      // ...end of highlighted text
	char *val;
	Font font;
	PRectangle rectUp;      // rectangle of last up angle in the tip
	PRectangle rectDown;    // rectangle of last down arrow in the tip
	int lineHeight;         // vertical line spacing
	int offsetMain;         // The alignment point of the call tip
	int tabSize;            // Tab size in pixels, <=0 no TAB expand
	bool useStyleCallTip;   // if true, STYLE_CALLTIP should be used
	bool above;		// if true, display calltip above text

	// Private so CallTip objects can not be copied
	CallTip(const CallTip &);
	CallTip &operator=(const CallTip &);
	void DrawChunk(Surface *surface, int &x, const char *s,
		int posStart, int posEnd, int ytext, PRectangle rcClient,
		bool highlight, bool draw);
	int PaintContents(Surface *surfaceWindow, bool draw);
	bool IsTabCharacter(char c) const;
	int NextTabPos(int x);

public:
	Window wCallTip;
	Window wDraw;
	bool inCallTipMode;
	int posStartCallTip;
	ColourDesired colourBG;
	ColourDesired colourUnSel;
	ColourDesired colourSel;
	ColourDesired colourShade;
	ColourDesired colourLight;
	int codePage;
	int clickPlace;

	int insetX; // text inset in x from calltip border
	int widthArrow;
	int borderHeight;
	int verticalOffset; // pixel offset up or down of the calltip with respect to the line

	CallTip();
	~CallTip();

	void PaintCT(Surface *surfaceWindow);

	void MouseClick(Point pt);

	/// Setup the calltip and return a rectangle of the area required.
	PRectangle CallTipStart(int pos, Point pt, int textHeight, const char *defn,
		const char *faceName, int size, int codePage_,
		int characterSet, int technology, Window &wParent);

	void CallTipCancel();

	/// Set a range of characters to be displayed in a highlight style.
	/// Commonly used to highlight the current parameter.
	void SetHighlight(int start, int end);

	/// Set the tab size in pixels for the call tip. 0 or -ve means no tab expand.
	void SetTabSize(int tabSz);

	/// Set calltip position.
	void SetPosition(bool aboveText);

	/// Used to determine which STYLE_xxxx to use for call tip information
	bool UseStyleCallTip() const { return useStyleCallTip;}

	// Modify foreground and background colours
	void SetForeBack(const ColourDesired &fore, const ColourDesired &back);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Catalogue.cxx.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file KeyWords.cxx
 ** Colourise for particular languages.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

#include <vector>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "LexerModule.h"
#include "Catalogue.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static std::vector<LexerModule *> lexerCatalogue;
static int nextLanguage = SCLEX_AUTOMATIC+1;

const LexerModule *Catalogue::Find(int language) {
	Scintilla_LinkLexers();
	for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin();
		it != lexerCatalogue.end(); ++it) {
		if ((*it)->GetLanguage() == language) {
			return *it;
		}
	}
	return 0;
}

const LexerModule *Catalogue::Find(const char *languageName) {
	Scintilla_LinkLexers();
	if (languageName) {
		for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin();
			it != lexerCatalogue.end(); ++it) {
			if ((*it)->languageName && (0 == strcmp((*it)->languageName, languageName))) {
				return *it;
			}
		}
	}
	return 0;
}

void Catalogue::AddLexerModule(LexerModule *plm) {
	if (plm->GetLanguage() == SCLEX_AUTOMATIC) {
		plm->language = nextLanguage;
		nextLanguage++;
	}
	lexerCatalogue.push_back(plm);
}

// Alternative historical name for Scintilla_LinkLexers
int wxForceScintillaLexers(void) {
	return Scintilla_LinkLexers();
}

// To add or remove a lexer, add or remove its file and run LexGen.py.

// Force a reference to all of the Scintilla lexers so that the linker will
// not remove the code of the lexers.
int Scintilla_LinkLexers() {

	static int initialised = 0;
	if (initialised)
		return 0;
	initialised = 1;

// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
#define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer);

//++Autogenerated -- run src/LexGen.py to regenerate
//**\(\tLINK_LEXER(\*);\n\)
	LINK_LEXER(lmA68k);
	LINK_LEXER(lmAbaqus);
	LINK_LEXER(lmAda);
	LINK_LEXER(lmAns1);
	LINK_LEXER(lmAPDL);
	LINK_LEXER(lmAsm);
	LINK_LEXER(lmASY);
	LINK_LEXER(lmAU3);
	LINK_LEXER(lmAVE);
	LINK_LEXER(lmAVS);
	LINK_LEXER(lmBaan);
	LINK_LEXER(lmBash);
	LINK_LEXER(lmBatch);
	LINK_LEXER(lmBlitzBasic);
	LINK_LEXER(lmBullant);
	LINK_LEXER(lmCaml);
	LINK_LEXER(lmClw);
	LINK_LEXER(lmClwNoCase);
	LINK_LEXER(lmCmake);
	LINK_LEXER(lmCOBOL);
	LINK_LEXER(lmCoffeeScript);
	LINK_LEXER(lmConf);
	LINK_LEXER(lmCPP);
	LINK_LEXER(lmCPPNoCase);
	LINK_LEXER(lmCsound);
	LINK_LEXER(lmCss);
	LINK_LEXER(lmD);
	LINK_LEXER(lmDiff);
	LINK_LEXER(lmECL);
	LINK_LEXER(lmEiffel);
	LINK_LEXER(lmEiffelkw);
	LINK_LEXER(lmErlang);
	LINK_LEXER(lmErrorList);
	LINK_LEXER(lmESCRIPT);
	LINK_LEXER(lmF77);
	LINK_LEXER(lmFlagShip);
	LINK_LEXER(lmForth);
	LINK_LEXER(lmFortran);
	LINK_LEXER(lmFreeBasic);
	LINK_LEXER(lmGAP);
	LINK_LEXER(lmGui4Cli);
	LINK_LEXER(lmHaskell);
	LINK_LEXER(lmHTML);
	LINK_LEXER(lmInno);
	LINK_LEXER(lmKix);
	LINK_LEXER(lmLatex);
	LINK_LEXER(lmLISP);
	LINK_LEXER(lmLot);
	LINK_LEXER(lmLout);
	LINK_LEXER(lmLua);
	LINK_LEXER(lmMagikSF);
	LINK_LEXER(lmMake);
	LINK_LEXER(lmMarkdown);
	LINK_LEXER(lmMatlab);
	LINK_LEXER(lmMETAPOST);
	LINK_LEXER(lmMMIXAL);
	LINK_LEXER(lmModula);
	LINK_LEXER(lmMSSQL);
	LINK_LEXER(lmMySQL);
	LINK_LEXER(lmNimrod);
	LINK_LEXER(lmNncrontab);
	LINK_LEXER(lmNsis);
	LINK_LEXER(lmNull);
	LINK_LEXER(lmOctave);
	LINK_LEXER(lmOpal);
	LINK_LEXER(lmOScript);
	LINK_LEXER(lmPascal);
	LINK_LEXER(lmPB);
	LINK_LEXER(lmPerl);
	LINK_LEXER(lmPHPSCRIPT);
	LINK_LEXER(lmPLM);
	LINK_LEXER(lmPO);
	LINK_LEXER(lmPOV);
	LINK_LEXER(lmPowerPro);
	LINK_LEXER(lmPowerShell);
	LINK_LEXER(lmProgress);
	LINK_LEXER(lmProps);
	LINK_LEXER(lmPS);
	LINK_LEXER(lmPureBasic);
	LINK_LEXER(lmPython);
	LINK_LEXER(lmR);
	LINK_LEXER(lmREBOL);
	LINK_LEXER(lmRuby);
	LINK_LEXER(lmScriptol);
	LINK_LEXER(lmSmalltalk);
	LINK_LEXER(lmSML);
	LINK_LEXER(lmSorc);
	LINK_LEXER(lmSpecman);
	LINK_LEXER(lmSpice);
	LINK_LEXER(lmSQL);
	LINK_LEXER(lmTACL);
	LINK_LEXER(lmTADS3);
	LINK_LEXER(lmTAL);
	LINK_LEXER(lmTCL);
	LINK_LEXER(lmTCMD);
	LINK_LEXER(lmTeX);
	LINK_LEXER(lmTxt2tags);
	LINK_LEXER(lmVB);
	LINK_LEXER(lmVBScript);
	LINK_LEXER(lmVerilog);
	LINK_LEXER(lmVHDL);
	LINK_LEXER(lmVisualProlog);
	LINK_LEXER(lmXML);
	LINK_LEXER(lmYAML);

//--Autogenerated -- end of automatically generated section

	return 1;
}

Added src/Catalogue.h.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Catalogue.h
 ** Lexer infrastructure.
 **/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CATALOGUE_H
#define CATALOGUE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class Catalogue {
public:
	static const LexerModule *Find(int language);
	static const LexerModule *Find(const char *languageName);
	static void AddLexerModule(LexerModule *plm);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/CellBuffer.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
// Scintilla source code edit control
/** @file CellBuffer.cxx
 ** Manages a buffer of cells.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "Platform.h"

#include "Scintilla.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
#include "UniConversion.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LineVector::LineVector() : starts(256), perLine(0) {
	Init();
}

LineVector::~LineVector() {
	starts.DeleteAll();
}

void LineVector::Init() {
	starts.DeleteAll();
	if (perLine) {
		perLine->Init();
	}
}

void LineVector::SetPerLine(PerLine *pl) {
	perLine = pl;
}

void LineVector::InsertText(int line, int delta) {
	starts.InsertText(line, delta);
}

void LineVector::InsertLine(int line, int position, bool lineStart) {
	starts.InsertPartition(line, position);
	if (perLine) {
		if ((line > 0) && lineStart)
			line--;
		perLine->InsertLine(line);
	}
}

void LineVector::SetLineStart(int line, int position) {
	starts.SetPartitionStartPosition(line, position);
}

void LineVector::RemoveLine(int line) {
	starts.RemovePartition(line);
	if (perLine) {
		perLine->RemoveLine(line);
	}
}

int LineVector::LineFromPosition(int pos) const {
	return starts.PartitionFromPosition(pos);
}

Action::Action() {
	at = startAction;
	position = 0;
	data = 0;
	lenData = 0;
	mayCoalesce = false;
}

Action::~Action() {
	Destroy();
}

void Action::Create(actionType at_, int position_, char *data_, int lenData_, bool mayCoalesce_) {
	delete []data;
	position = position_;
	at = at_;
	data = data_;
	lenData = lenData_;
	mayCoalesce = mayCoalesce_;
}

void Action::Destroy() {
	delete []data;
	data = 0;
}

void Action::Grab(Action *source) {
	delete []data;

	position = source->position;
	at = source->at;
	data = source->data;
	lenData = source->lenData;
	mayCoalesce = source->mayCoalesce;

	// Ownership of source data transferred to this
	source->position = 0;
	source->at = startAction;
	source->data = 0;
	source->lenData = 0;
	source->mayCoalesce = true;
}

// The undo history stores a sequence of user operations that represent the user's view of the
// commands executed on the text.
// Each user operation contains a sequence of text insertion and text deletion actions.
// All the user operations are stored in a list of individual actions with 'start' actions used
// as delimiters between user operations.
// Initially there is one start action in the history.
// As each action is performed, it is recorded in the history. The action may either become
// part of the current user operation or may start a new user operation. If it is to be part of the
// current operation, then it overwrites the current last action. If it is to be part of a new
// operation, it is appended after the current last action.
// After writing the new action, a new start action is appended at the end of the history.
// The decision of whether to start a new user operation is based upon two factors. If a
// compound operation has been explicitly started by calling BeginUndoAction and no matching
// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
// operation. If there is no outstanding BeginUndoAction call then a new operation is started
// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
// Sequences that look like typing or deletion are coalesced into a single user operation.

UndoHistory::UndoHistory() {

	lenActions = 100;
	actions = new Action[lenActions];
	maxAction = 0;
	currentAction = 0;
	undoSequenceDepth = 0;
	savePoint = 0;

	actions[currentAction].Create(startAction);
}

UndoHistory::~UndoHistory() {
	delete []actions;
	actions = 0;
}

void UndoHistory::EnsureUndoRoom() {
	// Have to test that there is room for 2 more actions in the array
	// as two actions may be created by the calling function
	if (currentAction >= (lenActions - 2)) {
		// Run out of undo nodes so extend the array
		int lenActionsNew = lenActions * 2;
		Action *actionsNew = new Action[lenActionsNew];
		for (int act = 0; act <= currentAction; act++)
			actionsNew[act].Grab(&actions[act]);
		delete []actions;
		lenActions = lenActionsNew;
		actions = actionsNew;
	}
}

void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData,
	bool &startSequence, bool mayCoalesce) {
	EnsureUndoRoom();
	//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
	//Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
	//	actions[currentAction - 1].position, actions[currentAction - 1].lenData);
	if (currentAction < savePoint) {
		savePoint = -1;
	}
	int oldCurrentAction = currentAction;
	if (currentAction >= 1) {
		if (0 == undoSequenceDepth) {
			// Top level actions may not always be coalesced
			int targetAct = -1;
			const Action *actPrevious = &(actions[currentAction + targetAct]);
			// Container actions may forward the coalesce state of Scintilla Actions.
			while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) {
				targetAct--;
				actPrevious = &(actions[currentAction + targetAct]);
			}
			// See if current action can be coalesced into previous action
			// Will work if both are inserts or deletes and position is same
			if (currentAction == savePoint) {
				currentAction++;
			} else if (!actions[currentAction].mayCoalesce) {
				// Not allowed to coalesce if this set
				currentAction++;
			} else if (!mayCoalesce || !actPrevious->mayCoalesce) {
				currentAction++;
			} else if (at == containerAction || actions[currentAction].at == containerAction) {
				;	// A coalescible containerAction
			} else if ((at != actPrevious->at) && (actPrevious->at != startAction)) {
				currentAction++;
			} else if ((at == insertAction) &&
			           (position != (actPrevious->position + actPrevious->lenData))) {
				// Insertions must be immediately after to coalesce
				currentAction++;
			} else if (at == removeAction) {
				if ((lengthData == 1) || (lengthData == 2)) {
					if ((position + lengthData) == actPrevious->position) {
						; // Backspace -> OK
					} else if (position == actPrevious->position) {
						; // Delete -> OK
					} else {
						// Removals must be at same position to coalesce
						currentAction++;
					}
				} else {
					// Removals must be of one character to coalesce
					currentAction++;
				}
			} else {
				// Action coalesced.
			}

		} else {
			// Actions not at top level are always coalesced unless this is after return to top level
			if (!actions[currentAction].mayCoalesce)
				currentAction++;
		}
	} else {
		currentAction++;
	}
	startSequence = oldCurrentAction != currentAction;
	actions[currentAction].Create(at, position, data, lengthData, mayCoalesce);
	currentAction++;
	actions[currentAction].Create(startAction);
	maxAction = currentAction;
}

void UndoHistory::BeginUndoAction() {
	EnsureUndoRoom();
	if (undoSequenceDepth == 0) {
		if (actions[currentAction].at != startAction) {
			currentAction++;
			actions[currentAction].Create(startAction);
			maxAction = currentAction;
		}
		actions[currentAction].mayCoalesce = false;
	}
	undoSequenceDepth++;
}

void UndoHistory::EndUndoAction() {
	PLATFORM_ASSERT(undoSequenceDepth > 0);
	EnsureUndoRoom();
	undoSequenceDepth--;
	if (0 == undoSequenceDepth) {
		if (actions[currentAction].at != startAction) {
			currentAction++;
			actions[currentAction].Create(startAction);
			maxAction = currentAction;
		}
		actions[currentAction].mayCoalesce = false;
	}
}

void UndoHistory::DropUndoSequence() {
	undoSequenceDepth = 0;
}

void UndoHistory::DeleteUndoHistory() {
	for (int i = 1; i < maxAction; i++)
		actions[i].Destroy();
	maxAction = 0;
	currentAction = 0;
	actions[currentAction].Create(startAction);
	savePoint = 0;
}

void UndoHistory::SetSavePoint() {
	savePoint = currentAction;
}

bool UndoHistory::IsSavePoint() const {
	return savePoint == currentAction;
}

bool UndoHistory::CanUndo() const {
	return (currentAction > 0) && (maxAction > 0);
}

int UndoHistory::StartUndo() {
	// Drop any trailing startAction
	if (actions[currentAction].at == startAction && currentAction > 0)
		currentAction--;

	// Count the steps in this action
	int act = currentAction;
	while (actions[act].at != startAction && act > 0) {
		act--;
	}
	return currentAction - act;
}

const Action &UndoHistory::GetUndoStep() const {
	return actions[currentAction];
}

void UndoHistory::CompletedUndoStep() {
	currentAction--;
}

bool UndoHistory::CanRedo() const {
	return maxAction > currentAction;
}

int UndoHistory::StartRedo() {
	// Drop any leading startAction
	if (actions[currentAction].at == startAction && currentAction < maxAction)
		currentAction++;

	// Count the steps in this action
	int act = currentAction;
	while (actions[act].at != startAction && act < maxAction) {
		act++;
	}
	return act - currentAction;
}

const Action &UndoHistory::GetRedoStep() const {
	return actions[currentAction];
}

void UndoHistory::CompletedRedoStep() {
	currentAction++;
}

CellBuffer::CellBuffer() {
	readOnly = false;
	utf8LineEnds = 0;
	collectingUndo = true;
}

CellBuffer::~CellBuffer() {
}

char CellBuffer::CharAt(int position) const {
	return substance.ValueAt(position);
}

void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const {
	if (lengthRetrieve < 0)
		return;
	if (position < 0)
		return;
	if ((position + lengthRetrieve) > substance.Length()) {
		Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position,
		                      lengthRetrieve, substance.Length());
		return;
	}
	substance.GetRange(buffer, position, lengthRetrieve);
}

char CellBuffer::StyleAt(int position) const {
	return style.ValueAt(position);
}

void CellBuffer::GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const {
	if (lengthRetrieve < 0)
		return;
	if (position < 0)
		return;
	if ((position + lengthRetrieve) > style.Length()) {
		Platform::DebugPrintf("Bad GetStyleRange %d for %d of %d\n", position,
		                      lengthRetrieve, style.Length());
		return;
	}
	style.GetRange(reinterpret_cast<char *>(buffer), position, lengthRetrieve);
}

const char *CellBuffer::BufferPointer() {
	return substance.BufferPointer();
}

const char *CellBuffer::RangePointer(int position, int rangeLength) {
	return substance.RangePointer(position, rangeLength);
}

int CellBuffer::GapPosition() const {
	return substance.GapPosition();
}

// The char* returned is to an allocation owned by the undo history
const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) {
	char *data = 0;
	// InsertString and DeleteChars are the bottleneck though which all changes occur
	if (!readOnly) {
		if (collectingUndo) {
			// Save into the undo/redo stack, but only the characters - not the formatting
			// This takes up about half load time
			data = new char[insertLength];
			for (int i = 0; i < insertLength; i++) {
				data[i] = s[i];
			}
			uh.AppendAction(insertAction, position, data, insertLength, startSequence);
		}

		BasicInsertString(position, s, insertLength);
	}
	return data;
}

bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) {
	styleValue &= mask;
	char curVal = style.ValueAt(position);
	if ((curVal & mask) != styleValue) {
		style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
		return true;
	} else {
		return false;
	}
}

bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) {
	bool changed = false;
	PLATFORM_ASSERT(lengthStyle == 0 ||
		(lengthStyle > 0 && lengthStyle + position <= style.Length()));
	while (lengthStyle--) {
		char curVal = style.ValueAt(position);
		if ((curVal & mask) != styleValue) {
			style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
			changed = true;
		}
		position++;
	}
	return changed;
}

// The char* returned is to an allocation owned by the undo history
const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) {
	// InsertString and DeleteChars are the bottleneck though which all changes occur
	PLATFORM_ASSERT(deleteLength > 0);
	char *data = 0;
	if (!readOnly) {
		if (collectingUndo) {
			// Save into the undo/redo stack, but only the characters - not the formatting
			data = new char[deleteLength];
			for (int i = 0; i < deleteLength; i++) {
				data[i] = substance.ValueAt(position + i);
			}
			uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
		}

		BasicDeleteChars(position, deleteLength);
	}
	return data;
}

int CellBuffer::Length() const {
	return substance.Length();
}

void CellBuffer::Allocate(int newSize) {
	substance.ReAllocate(newSize);
	style.ReAllocate(newSize);
}

void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
	if (utf8LineEnds != utf8LineEnds_) {
		utf8LineEnds = utf8LineEnds_;
		ResetLineEnds();
	}
}

void CellBuffer::SetPerLine(PerLine *pl) {
	lv.SetPerLine(pl);
}

int CellBuffer::Lines() const {
	return lv.Lines();
}

int CellBuffer::LineStart(int line) const {
	if (line < 0)
		return 0;
	else if (line >= Lines())
		return Length();
	else
		return lv.LineStart(line);
}

bool CellBuffer::IsReadOnly() const {
	return readOnly;
}

void CellBuffer::SetReadOnly(bool set) {
	readOnly = set;
}

void CellBuffer::SetSavePoint() {
	uh.SetSavePoint();
}

bool CellBuffer::IsSavePoint() {
	return uh.IsSavePoint();
}

// Without undo

void CellBuffer::InsertLine(int line, int position, bool lineStart) {
	lv.InsertLine(line, position, lineStart);
}

void CellBuffer::RemoveLine(int line) {
	lv.RemoveLine(line);
}

bool CellBuffer::UTF8LineEndOverlaps(int position) const {
	unsigned char bytes[] = {
		static_cast<unsigned char>(substance.ValueAt(position-2)),
		static_cast<unsigned char>(substance.ValueAt(position-1)),
		static_cast<unsigned char>(substance.ValueAt(position)),
		static_cast<unsigned char>(substance.ValueAt(position+1)),
	};
	return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1);
}

void CellBuffer::ResetLineEnds() {
	// Reinitialize line data -- too much work to preserve
	lv.Init();

	int position = 0;
	int length = Length();
	int lineInsert = 1;
	bool atLineStart = true;
	lv.InsertText(lineInsert-1, length);
	unsigned char chBeforePrev = 0;
	unsigned char chPrev = 0;
	for (int i = 0; i < length; i++) {
		unsigned char ch = substance.ValueAt(position + i);
		if (ch == '\r') {
			InsertLine(lineInsert, (position + i) + 1, atLineStart);
			lineInsert++;
		} else if (ch == '\n') {
			if (chPrev == '\r') {
				// Patch up what was end of line
				lv.SetLineStart(lineInsert - 1, (position + i) + 1);
			} else {
				InsertLine(lineInsert, (position + i) + 1, atLineStart);
				lineInsert++;
			}
		} else if (utf8LineEnds) {
			unsigned char back3[3] = {chBeforePrev, chPrev, ch};
			if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
				InsertLine(lineInsert, (position + i) + 1, atLineStart);
				lineInsert++;
			}
		}
		chBeforePrev = chPrev;
		chPrev = ch;
	}
}

void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
	if (insertLength == 0)
		return;
	PLATFORM_ASSERT(insertLength > 0);

	unsigned char chAfter = substance.ValueAt(position);
	bool breakingUTF8LineEnd = false;
	if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
		breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
	}

	substance.InsertFromArray(position, s, 0, insertLength);
	style.InsertValue(position, insertLength, 0);

	int lineInsert = lv.LineFromPosition(position) + 1;
	bool atLineStart = lv.LineStart(lineInsert-1) == position;
	// Point all the lines after the insertion point further along in the buffer
	lv.InsertText(lineInsert-1, insertLength);
	unsigned char chBeforePrev = substance.ValueAt(position - 2);
	unsigned char chPrev = substance.ValueAt(position - 1);
	if (chPrev == '\r' && chAfter == '\n') {
		// Splitting up a crlf pair at position
		InsertLine(lineInsert, position, false);
		lineInsert++;
	}
	if (breakingUTF8LineEnd) {
		RemoveLine(lineInsert);
	}
	unsigned char ch = ' ';
	for (int i = 0; i < insertLength; i++) {
		ch = s[i];
		if (ch == '\r') {
			InsertLine(lineInsert, (position + i) + 1, atLineStart);
			lineInsert++;
		} else if (ch == '\n') {
			if (chPrev == '\r') {
				// Patch up what was end of line
				lv.SetLineStart(lineInsert - 1, (position + i) + 1);
			} else {
				InsertLine(lineInsert, (position + i) + 1, atLineStart);
				lineInsert++;
			}
		} else if (utf8LineEnds) {
			unsigned char back3[3] = {chBeforePrev, chPrev, ch};
			if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
				InsertLine(lineInsert, (position + i) + 1, atLineStart);
				lineInsert++;
			}
		}
		chBeforePrev = chPrev;
		chPrev = ch;
	}
	// Joining two lines where last insertion is cr and following substance starts with lf
	if (chAfter == '\n') {
		if (ch == '\r') {
			// End of line already in buffer so drop the newly created one
			RemoveLine(lineInsert - 1);
		}
	} else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
		// May have end of UTF-8 line end in buffer and start in insertion
		for (int j = 0; j < UTF8SeparatorLength-1; j++) {
			unsigned char chAt = substance.ValueAt(position + insertLength + j);
			unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
			if (UTF8IsSeparator(back3)) {
				InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
				lineInsert++;
			}
			if ((j == 0) && UTF8IsNEL(back3+1)) {
				InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
				lineInsert++;
			}
			chBeforePrev = chPrev;
			chPrev = chAt;
		}
	}
}

void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
	if (deleteLength == 0)
		return;

	if ((position == 0) && (deleteLength == substance.Length())) {
		// If whole buffer is being deleted, faster to reinitialise lines data
		// than to delete each line.
		lv.Init();
	} else {
		// Have to fix up line positions before doing deletion as looking at text in buffer
		// to work out which lines have been removed

		int lineRemove = lv.LineFromPosition(position) + 1;
		lv.InsertText(lineRemove-1, - (deleteLength));
		unsigned char chPrev = substance.ValueAt(position - 1);
		unsigned char chBefore = chPrev;
		unsigned char chNext = substance.ValueAt(position);
		bool ignoreNL = false;
		if (chPrev == '\r' && chNext == '\n') {
			// Move back one
			lv.SetLineStart(lineRemove, position);
			lineRemove++;
			ignoreNL = true; 	// First \n is not real deletion
		}
		if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
			if (UTF8LineEndOverlaps(position)) {
				RemoveLine(lineRemove);
			}
		}

		unsigned char ch = chNext;
		for (int i = 0; i < deleteLength; i++) {
			chNext = substance.ValueAt(position + i + 1);
			if (ch == '\r') {
				if (chNext != '\n') {
					RemoveLine(lineRemove);
				}
			} else if (ch == '\n') {
				if (ignoreNL) {
					ignoreNL = false; 	// Further \n are real deletions
				} else {
					RemoveLine(lineRemove);
				}
			} else if (utf8LineEnds) {
				if (!UTF8IsAscii(ch)) {
					unsigned char next3[3] = {ch, chNext,
						static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
					if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
						RemoveLine(lineRemove);
					}
				}
			}

			ch = chNext;
		}
		// May have to fix up end if last deletion causes cr to be next to lf
		// or removes one of a crlf pair
		char chAfter = substance.ValueAt(position + deleteLength);
		if (chBefore == '\r' && chAfter == '\n') {
			// Using lineRemove-1 as cr ended line before start of deletion
			RemoveLine(lineRemove - 1);
			lv.SetLineStart(lineRemove - 1, position + 1);
		}
	}
	substance.DeleteRange(position, deleteLength);
	style.DeleteRange(position, deleteLength);
}

bool CellBuffer::SetUndoCollection(bool collectUndo) {
	collectingUndo = collectUndo;
	uh.DropUndoSequence();
	return collectingUndo;
}

bool CellBuffer::IsCollectingUndo() const {
	return collectingUndo;
}

void CellBuffer::BeginUndoAction() {
	uh.BeginUndoAction();
}

void CellBuffer::EndUndoAction() {
	uh.EndUndoAction();
}

void CellBuffer::AddUndoAction(int token, bool mayCoalesce) {
	bool startSequence;
	uh.AppendAction(containerAction, token, 0, 0, startSequence, mayCoalesce);
}

void CellBuffer::DeleteUndoHistory() {
	uh.DeleteUndoHistory();
}

bool CellBuffer::CanUndo() {
	return uh.CanUndo();
}

int CellBuffer::StartUndo() {
	return uh.StartUndo();
}

const Action &CellBuffer::GetUndoStep() const {
	return uh.GetUndoStep();
}

void CellBuffer::PerformUndoStep() {
	const Action &actionStep = uh.GetUndoStep();
	if (actionStep.at == insertAction) {
		BasicDeleteChars(actionStep.position, actionStep.lenData);
	} else if (actionStep.at == removeAction) {
		BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
	}
	uh.CompletedUndoStep();
}

bool CellBuffer::CanRedo() {
	return uh.CanRedo();
}

int CellBuffer::StartRedo() {
	return uh.StartRedo();
}

const Action &CellBuffer::GetRedoStep() const {
	return uh.GetRedoStep();
}

void CellBuffer::PerformRedoStep() {
	const Action &actionStep = uh.GetRedoStep();
	if (actionStep.at == insertAction) {
		BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
	} else if (actionStep.at == removeAction) {
		BasicDeleteChars(actionStep.position, actionStep.lenData);
	}
	uh.CompletedRedoStep();
}

Added src/CellBuffer.h.























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CellBuffer.h
 ** Manages the text of the document.
 **/
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CELLBUFFER_H
#define CELLBUFFER_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

// Interface to per-line data that wants to see each line insertion and deletion
class PerLine {
public:
	virtual ~PerLine() {}
	virtual void Init()=0;
	virtual void InsertLine(int)=0;
	virtual void RemoveLine(int)=0;
};

/**
 * The line vector contains information about each of the lines in a cell buffer.
 */
class LineVector {

	Partitioning starts;
	PerLine *perLine;

public:

	LineVector();
	~LineVector();
	void Init();
	void SetPerLine(PerLine *pl);

	void InsertText(int line, int delta);
	void InsertLine(int line, int position, bool lineStart);
	void SetLineStart(int line, int position);
	void RemoveLine(int line);
	int Lines() const {
		return starts.Partitions();
	}
	int LineFromPosition(int pos) const;
	int LineStart(int line) const {
		return starts.PositionFromPartition(line);
	}

	int MarkValue(int line);
	int AddMark(int line, int marker);
	void MergeMarkers(int pos);
	void DeleteMark(int line, int markerNum, bool all);
	void DeleteMarkFromHandle(int markerHandle);
	int LineFromHandle(int markerHandle);

	void ClearLevels();
	int SetLevel(int line, int level);
	int GetLevel(int line);

	int SetLineState(int line, int state);
	int GetLineState(int line);
	int GetMaxLineState();

};

enum actionType { insertAction, removeAction, startAction, containerAction };

/**
 * Actions are used to store all the information required to perform one undo/redo step.
 */
class Action {
public:
	actionType at;
	int position;
	char *data;
	int lenData;
	bool mayCoalesce;

	Action();
	~Action();
	void Create(actionType at_, int position_=0, char *data_=0, int lenData_=0, bool mayCoalesce_=true);
	void Destroy();
	void Grab(Action *source);
};

/**
 *
 */
class UndoHistory {
	Action *actions;
	int lenActions;
	int maxAction;
	int currentAction;
	int undoSequenceDepth;
	int savePoint;

	void EnsureUndoRoom();

	// Private so UndoHistory objects can not be copied
	UndoHistory(const UndoHistory &);

public:
	UndoHistory();
	~UndoHistory();

	void AppendAction(actionType at, int position, char *data, int length, bool &startSequence, bool mayCoalesce=true);

	void BeginUndoAction();
	void EndUndoAction();
	void DropUndoSequence();
	void DeleteUndoHistory();

	/// The save point is a marker in the undo stack where the container has stated that
	/// the buffer was saved. Undo and redo can move over the save point.
	void SetSavePoint();
	bool IsSavePoint() const;

	/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
	/// called that many times. Similarly for redo.
	bool CanUndo() const;
	int StartUndo();
	const Action &GetUndoStep() const;
	void CompletedUndoStep();
	bool CanRedo() const;
	int StartRedo();
	const Action &GetRedoStep() const;
	void CompletedRedoStep();
};

/**
 * Holder for an expandable array of characters that supports undo and line markers.
 * Based on article "Data Structures in a Bit-Mapped Text Editor"
 * by Wilfred J. Hansen, Byte January 1987, page 183.
 */
class CellBuffer {
private:
	SplitVector<char> substance;
	SplitVector<char> style;
	bool readOnly;
	int utf8LineEnds;

	bool collectingUndo;
	UndoHistory uh;

	LineVector lv;

	bool UTF8LineEndOverlaps(int position) const;
	void ResetLineEnds();
	/// Actions without undo
	void BasicInsertString(int position, const char *s, int insertLength);
	void BasicDeleteChars(int position, int deleteLength);

public:

	CellBuffer();
	~CellBuffer();

	/// Retrieving positions outside the range of the buffer works and returns 0
	char CharAt(int position) const;
	void GetCharRange(char *buffer, int position, int lengthRetrieve) const;
	char StyleAt(int position) const;
	void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const;
	const char *BufferPointer();
	const char *RangePointer(int position, int rangeLength);
	int GapPosition() const;

	int Length() const;
	void Allocate(int newSize);
	int GetLineEndTypes() const { return utf8LineEnds; }
	void SetLineEndTypes(int utf8LineEnds_);
	void SetPerLine(PerLine *pl);
	int Lines() const;
	int LineStart(int line) const;
	int LineFromPosition(int pos) const { return lv.LineFromPosition(pos); }
	void InsertLine(int line, int position, bool lineStart);
	void RemoveLine(int line);
	const char *InsertString(int position, const char *s, int insertLength, bool &startSequence);

	/// Setting styles for positions outside the range of the buffer is safe and has no effect.
	/// @return true if the style of a character is changed.
	bool SetStyleAt(int position, char styleValue, char mask='\377');
	bool SetStyleFor(int position, int length, char styleValue, char mask);

	const char *DeleteChars(int position, int deleteLength, bool &startSequence);

	bool IsReadOnly() const;
	void SetReadOnly(bool set);

	/// The save point is a marker in the undo stack where the container has stated that
	/// the buffer was saved. Undo and redo can move over the save point.
	void SetSavePoint();
	bool IsSavePoint();

	bool SetUndoCollection(bool collectUndo);
	bool IsCollectingUndo() const;
	void BeginUndoAction();
	void EndUndoAction();
	void AddUndoAction(int token, bool mayCoalesce);
	void DeleteUndoHistory();

	/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
	/// called that many times. Similarly for redo.
	bool CanUndo();
	int StartUndo();
	const Action &GetUndoStep() const;
	void PerformUndoStep();
	bool CanRedo();
	int StartRedo();
	const Action &GetRedoStep() const;
	void PerformRedoStep();
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/CharClassify.cxx.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CharClassify.cxx
 ** Character classifications used by Document and RESearch.
 **/
// Copyright 2006 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <ctype.h>

#include "CharClassify.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Shut up annoying Visual C++ warnings:
#ifdef _MSC_VER
#pragma warning(disable: 4514)
#endif

CharClassify::CharClassify() {
	SetDefaultCharClasses(true);
}

void CharClassify::SetDefaultCharClasses(bool includeWordClass) {
	// Initialize all char classes to default values
	for (int ch = 0; ch < 256; ch++) {
		if (ch == '\r' || ch == '\n')
			charClass[ch] = ccNewLine;
		else if (ch < 0x20 || ch == ' ')
			charClass[ch] = ccSpace;
		else if (includeWordClass && (ch >= 0x80 || isalnum(ch) || ch == '_'))
			charClass[ch] = ccWord;
		else
			charClass[ch] = ccPunctuation;
	}
}

void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) {
	// Apply the newCharClass to the specifed chars
	if (chars) {
		while (*chars) {
			charClass[*chars] = static_cast<unsigned char>(newCharClass);
			chars++;
		}
	}
}

int CharClassify::GetCharsOfClass(cc characterClass, unsigned char *buffer) {
	// Get characters belonging to the given char class; return the number
	// of characters (if the buffer is NULL, don't write to it).
	int count = 0;
	for (int ch = maxChar - 1; ch >= 0; --ch) {
		if (charClass[ch] == characterClass) {
			++count;
			if (buffer) {
				*buffer = static_cast<unsigned char>(ch);
				buffer++;
			}
		}
	}
	return count;
}

Added src/CharClassify.h.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file CharClassify.h
 ** Character classifications used by Document and RESearch.
 **/
// Copyright 2006-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CHARCLASSIFY_H
#define CHARCLASSIFY_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class CharClassify {
public:
	CharClassify();

	enum cc { ccSpace, ccNewLine, ccWord, ccPunctuation };
	void SetDefaultCharClasses(bool includeWordClass);
	void SetCharClasses(const unsigned char *chars, cc newCharClass);
	int GetCharsOfClass(cc charClass, unsigned char *buffer);
	cc GetClass(unsigned char ch) const { return static_cast<cc>(charClass[ch]);}
	bool IsWord(unsigned char ch) const { return static_cast<cc>(charClass[ch]) == ccWord;}

private:
	enum { maxChar=256 };
	unsigned char charClass[maxChar];    // not type cc to save space
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/ContractionState.cxx.













































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Scintilla source code edit control
/** @file ContractionState.cxx
 ** Manages visibility of lines for folding and wrapping.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
	//InsertLine(0);
}

ContractionState::~ContractionState() {
	Clear();
}

void ContractionState::EnsureData() {
	if (OneToOne()) {
		visible = new RunStyles();
		expanded = new RunStyles();
		heights = new RunStyles();
		displayLines = new Partitioning(4);
		InsertLines(0, linesInDocument);
	}
}

void ContractionState::Clear() {
	delete visible;
	visible = 0;
	delete expanded;
	expanded = 0;
	delete heights;
	heights = 0;
	delete displayLines;
	displayLines = 0;
	linesInDocument = 1;
}

int ContractionState::LinesInDoc() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->Partitions() - 1;
	}
}

int ContractionState::LinesDisplayed() const {
	if (OneToOne()) {
		return linesInDocument;
	} else {
		return displayLines->PositionFromPartition(LinesInDoc());
	}
}

int ContractionState::DisplayFromDoc(int lineDoc) const {
	if (OneToOne()) {
		return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
	} else {
		if (lineDoc > displayLines->Partitions())
			lineDoc = displayLines->Partitions();
		return displayLines->PositionFromPartition(lineDoc);
	}
}

int ContractionState::DocFromDisplay(int lineDisplay) const {
	if (OneToOne()) {
		return lineDisplay;
	} else {
		if (lineDisplay <= 0) {
			return 0;
		}
		if (lineDisplay > LinesDisplayed()) {
			return displayLines->PartitionFromPosition(LinesDisplayed());
		}
		int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
		PLATFORM_ASSERT(GetVisible(lineDoc));
		return lineDoc;
	}
}

void ContractionState::InsertLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument++;
	} else {
		visible->InsertSpace(lineDoc, 1);
		visible->SetValueAt(lineDoc, 1);
		expanded->InsertSpace(lineDoc, 1);
		expanded->SetValueAt(lineDoc, 1);
		heights->InsertSpace(lineDoc, 1);
		heights->SetValueAt(lineDoc, 1);
		int lineDisplay = DisplayFromDoc(lineDoc);
		displayLines->InsertPartition(lineDoc, lineDisplay);
		displayLines->InsertText(lineDoc, 1);
	}
}

void ContractionState::InsertLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		InsertLine(lineDoc + l);
	}
	Check();
}

void ContractionState::DeleteLine(int lineDoc) {
	if (OneToOne()) {
		linesInDocument--;
	} else {
		if (GetVisible(lineDoc)) {
			displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
		}
		displayLines->RemovePartition(lineDoc);
		visible->DeleteRange(lineDoc, 1);
		expanded->DeleteRange(lineDoc, 1);
		heights->DeleteRange(lineDoc, 1);
	}
}

void ContractionState::DeleteLines(int lineDoc, int lineCount) {
	for (int l = 0; l < lineCount; l++) {
		DeleteLine(lineDoc);
	}
	Check();
}

bool ContractionState::GetVisible(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		if (lineDoc >= visible->Length())
			return true;
		return visible->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
	if (OneToOne() && visible_) {
		return false;
	} else {
		EnsureData();
		int delta = 0;
		Check();
		if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
			for (int line = lineDocStart; line <= lineDocEnd; line++) {
				if (GetVisible(line) != visible_) {
					int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
					visible->SetValueAt(line, visible_ ? 1 : 0);
					displayLines->InsertText(line, difference);
					delta += difference;
				}
			}
		} else {
			return false;
		}
		Check();
		return delta != 0;
	}
}

bool ContractionState::HiddenLines() const {
	if (OneToOne()) {
		return false;
	} else {
		return !visible->AllSameAs(1);
	}
}

bool ContractionState::GetExpanded(int lineDoc) const {
	if (OneToOne()) {
		return true;
	} else {
		Check();
		return expanded->ValueAt(lineDoc) == 1;
	}
}

bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
	if (OneToOne() && expanded_) {
		return false;
	} else {
		EnsureData();
		if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
			expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	}
}

int ContractionState::ContractedNext(int lineDocStart) const {
	if (OneToOne()) {
		return -1;
	} else {
		Check();
		if (!expanded->ValueAt(lineDocStart)) {
			return lineDocStart;
		} else {
			int lineDocNextChange = expanded->EndRun(lineDocStart);
			if (lineDocNextChange < LinesInDoc())
				return lineDocNextChange;
			else
				return -1;
		}
	}
}

int ContractionState::GetHeight(int lineDoc) const {
	if (OneToOne()) {
		return 1;
	} else {
		return heights->ValueAt(lineDoc);
	}
}

// Set the number of display lines needed for this line.
// Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) {
	if (OneToOne() && (height == 1)) {
		return false;
	} else if (lineDoc < LinesInDoc()) {
		EnsureData();
		if (GetHeight(lineDoc) != height) {
			if (GetVisible(lineDoc)) {
				displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
			}
			heights->SetValueAt(lineDoc, height);
			Check();
			return true;
		} else {
			Check();
			return false;
		}
	} else {
		return false;
	}
}

void ContractionState::ShowAll() {
	int lines = LinesInDoc();
	Clear();
	linesInDocument = lines;
}

// Debugging checks

void ContractionState::Check() const {
#ifdef CHECK_CORRECTNESS
	for (int vline = 0; vline < LinesDisplayed(); vline++) {
		const int lineDoc = DocFromDisplay(vline);
		PLATFORM_ASSERT(GetVisible(lineDoc));
	}
	for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
		const int displayThis = DisplayFromDoc(lineDoc);
		const int displayNext = DisplayFromDoc(lineDoc + 1);
		const int height = displayNext - displayThis;
		PLATFORM_ASSERT(height >= 0);
		if (GetVisible(lineDoc)) {
			PLATFORM_ASSERT(GetHeight(lineDoc) == height);
		} else {
			PLATFORM_ASSERT(0 == height);
		}
	}
#endif
}

Added src/ContractionState.h.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ContractionState.h
 ** Manages visibility of lines for folding and wrapping.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef CONTRACTIONSTATE_H
#define CONTRACTIONSTATE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class ContractionState {
	// These contain 1 element for every document line.
	RunStyles *visible;
	RunStyles *expanded;
	RunStyles *heights;
	Partitioning *displayLines;
	int linesInDocument;

	void EnsureData();

	bool OneToOne() const {
		// True when each document line is exactly one display line so need for
		// complex data structures.
		return visible == 0;
	}

public:
	ContractionState();
	virtual ~ContractionState();

	void Clear();

	int LinesInDoc() const;
	int LinesDisplayed() const;
	int DisplayFromDoc(int lineDoc) const;
	int DocFromDisplay(int lineDisplay) const;

	void InsertLine(int lineDoc);
	void InsertLines(int lineDoc, int lineCount);
	void DeleteLine(int lineDoc);
	void DeleteLines(int lineDoc, int lineCount);

	bool GetVisible(int lineDoc) const;
	bool SetVisible(int lineDocStart, int lineDocEnd, bool visible);
	bool HiddenLines() const;

	bool GetExpanded(int lineDoc) const;
	bool SetExpanded(int lineDoc, bool expanded);
	int ContractedNext(int lineDocStart) const;

	int GetHeight(int lineDoc) const;
	bool SetHeight(int lineDoc, int height);

	void ShowAll();
	void Check() const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Decoration.cxx.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/** @file Decoration.cxx
 ** Visual elements added over text.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "Platform.h"

#include "Scintilla.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "Decoration.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) {
}

Decoration::~Decoration() {
}

bool Decoration::Empty() {
	return (rs.Runs() == 1) && (rs.AllSameAs(0));
}

DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0),
	lengthDocument(0), root(0), clickNotified(false) {
}

DecorationList::~DecorationList() {
	Decoration *deco = root;
	while (deco) {
		Decoration *decoNext = deco->next;
		delete deco;
		deco = decoNext;
	}
	root = 0;
	current = 0;
}

Decoration *DecorationList::DecorationFromIndicator(int indicator) {
	for (Decoration *deco=root; deco; deco = deco->next) {
		if (deco->indicator == indicator) {
			return deco;
		}
	}
	return 0;
}

Decoration *DecorationList::Create(int indicator, int length) {
	currentIndicator = indicator;
	Decoration *decoNew = new Decoration(indicator);
	decoNew->rs.InsertSpace(0, length);

	Decoration *decoPrev = 0;
	Decoration *deco = root;

	while (deco && (deco->indicator < indicator)) {
		decoPrev = deco;
		deco = deco->next;
	}
	if (decoPrev == 0) {
		decoNew->next = root;
		root = decoNew;
	} else {
		decoNew->next = deco;
		decoPrev->next = decoNew;
	}
	return decoNew;
}

void DecorationList::Delete(int indicator) {
	Decoration *decoToDelete = 0;
	if (root) {
		if (root->indicator == indicator) {
			decoToDelete = root;
			root = root->next;
		} else {
			Decoration *deco=root;
			while (deco->next && !decoToDelete) {
				if (deco->next && deco->next->indicator == indicator) {
					decoToDelete = deco->next;
					deco->next = decoToDelete->next;
				} else {
					deco = deco->next;
				}
			}
		}
	}
	if (decoToDelete) {
		delete decoToDelete;
		current = 0;
	}
}

void DecorationList::SetCurrentIndicator(int indicator) {
	currentIndicator = indicator;
	current = DecorationFromIndicator(indicator);
	currentValue = 1;
}

void DecorationList::SetCurrentValue(int value) {
	currentValue = value ? value : 1;
}

bool DecorationList::FillRange(int &position, int value, int &fillLength) {
	if (!current) {
		current = DecorationFromIndicator(currentIndicator);
		if (!current) {
			current = Create(currentIndicator, lengthDocument);
		}
	}
	bool changed = current->rs.FillRange(position, value, fillLength);
	if (current->Empty()) {
		Delete(currentIndicator);
	}
	return changed;
}

void DecorationList::InsertSpace(int position, int insertLength) {
	const bool atEnd = position == lengthDocument;
	lengthDocument += insertLength;
	for (Decoration *deco=root; deco; deco = deco->next) {
		deco->rs.InsertSpace(position, insertLength);
		if (atEnd) {
			deco->rs.FillRange(position, 0, insertLength);
		}
	}
}

void DecorationList::DeleteRange(int position, int deleteLength) {
	lengthDocument -= deleteLength;
	Decoration *deco;
	for (deco=root; deco; deco = deco->next) {
		deco->rs.DeleteRange(position, deleteLength);
	}
	DeleteAnyEmpty();
}

void DecorationList::DeleteAnyEmpty() {
	Decoration *deco = root;
	while (deco) {
		if ((lengthDocument == 0) || deco->Empty()) {
			Delete(deco->indicator);
			deco = root;
		} else {
			deco = deco->next;
		}
	}
}

int DecorationList::AllOnFor(int position) {
	int mask = 0;
	for (Decoration *deco=root; deco; deco = deco->next) {
		if (deco->rs.ValueAt(position)) {
			mask |= 1 << deco->indicator;
		}
	}
	return mask;
}

int DecorationList::ValueAt(int indicator, int position) {
	Decoration *deco = DecorationFromIndicator(indicator);
	if (deco) {
		return deco->rs.ValueAt(position);
	}
	return 0;
}

int DecorationList::Start(int indicator, int position) {
	Decoration *deco = DecorationFromIndicator(indicator);
	if (deco) {
		return deco->rs.StartRun(position);
	}
	return 0;
}

int DecorationList::End(int indicator, int position) {
	Decoration *deco = DecorationFromIndicator(indicator);
	if (deco) {
		return deco->rs.EndRun(position);
	}
	return 0;
}

Added src/Decoration.h.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/** @file Decoration.h
 ** Visual elements added over text.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef DECORATION_H
#define DECORATION_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class Decoration {
public:
	Decoration *next;
	RunStyles rs;
	int indicator;

	Decoration(int indicator_);
	~Decoration();

	bool Empty();
};

class DecorationList {
	int currentIndicator;
	int currentValue;
	Decoration *current;
	int lengthDocument;
	Decoration *DecorationFromIndicator(int indicator);
	Decoration *Create(int indicator, int length);
	void Delete(int indicator);
	void DeleteAnyEmpty();
public:
	Decoration *root;
	bool clickNotified;

	DecorationList();
	~DecorationList();

	void SetCurrentIndicator(int indicator);
	int GetCurrentIndicator() const { return currentIndicator; }

	void SetCurrentValue(int value);
	int GetCurrentValue() const { return currentValue; }

	// Returns true if some values may have changed
	bool FillRange(int &position, int value, int &fillLength);

	void InsertSpace(int position, int insertLength);
	void DeleteRange(int position, int deleteLength);

	int AllOnFor(int position);
	int ValueAt(int indicator, int position);
	int Start(int indicator, int position);
	int End(int indicator, int position);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Document.cxx.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
// Scintilla source code edit control
/** @file Document.cxx
 ** Text document that handles notifications, DBCS, styling, words and end of line.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>

#include <string>
#include <vector>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "CellBuffer.h"
#include "PerLine.h"
#include "CharClassify.h"
#include "CharacterSet.h"
#include "Decoration.h"
#include "Document.h"
#include "RESearch.h"
#include "UniConversion.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsPunctuation(char ch) {
	return isascii(ch) && ispunct(ch);
}

void LexInterface::Colourise(int start, int end) {
	if (pdoc && instance && !performingStyle) {
		// Protect against reentrance, which may occur, for example, when
		// fold points are discovered while performing styling and the folding
		// code looks for child lines which may trigger styling.
		performingStyle = true;

		int lengthDoc = pdoc->Length();
		if (end == -1)
			end = lengthDoc;
		int len = end - start;

		PLATFORM_ASSERT(len >= 0);
		PLATFORM_ASSERT(start + len <= lengthDoc);

		int styleStart = 0;
		if (start > 0)
			styleStart = pdoc->StyleAt(start - 1) & pdoc->stylingBitsMask;

		if (len > 0) {
			instance->Lex(start, len, styleStart, pdoc);
			instance->Fold(start, len, styleStart, pdoc);
		}

		performingStyle = false;
	}
}

int LexInterface::LineEndTypesSupported() {
	if (instance) {
		int interfaceVersion = instance->Version();
		if (interfaceVersion >= lvSubStyles) {
			ILexerWithSubStyles *ssinstance = static_cast<ILexerWithSubStyles *>(instance);
			return ssinstance->LineEndTypesSupported();
		}
	}
	return 0;
}

Document::Document() {
	refCount = 0;
	pcf = NULL;
#ifdef _WIN32
	eolMode = SC_EOL_CRLF;
#else
	eolMode = SC_EOL_LF;
#endif
	dbcsCodePage = 0;
	lineEndBitSet = SC_LINE_END_TYPE_DEFAULT;
	stylingBits = 5;
	stylingBitsMask = 0x1F;
	stylingMask = 0;
	endStyled = 0;
	styleClock = 0;
	enteredModification = 0;
	enteredStyling = 0;
	enteredReadOnlyCount = 0;
	tabInChars = 8;
	indentInChars = 0;
	actualIndentInChars = 8;
	useTabs = true;
	tabIndents = true;
	backspaceUnindents = false;
	watchers = 0;
	lenWatchers = 0;

	matchesValid = false;
	regex = 0;

	UTF8BytesOfLeadInitialise();

	perLineData[ldMarkers] = new LineMarkers();
	perLineData[ldLevels] = new LineLevels();
	perLineData[ldState] = new LineState();
	perLineData[ldMargin] = new LineAnnotation();
	perLineData[ldAnnotation] = new LineAnnotation();

	cb.SetPerLine(this);

	pli = 0;
}

Document::~Document() {
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifyDeleted(this, watchers[i].userData);
	}
	delete []watchers;
	for (int j=0; j<ldSize; j++) {
		delete perLineData[j];
		perLineData[j] = 0;
	}
	watchers = 0;
	lenWatchers = 0;
	delete regex;
	regex = 0;
	delete pli;
	pli = 0;
	delete pcf;
	pcf = 0;
}

void Document::Init() {
	for (int j=0; j<ldSize; j++) {
		if (perLineData[j])
			perLineData[j]->Init();
	}
}

int Document::LineEndTypesSupported() const {
	if ((SC_CP_UTF8 == dbcsCodePage) && pli)
		return pli->LineEndTypesSupported();
	else
		return 0;
}

bool Document::SetDBCSCodePage(int dbcsCodePage_) {
	if (dbcsCodePage != dbcsCodePage_) {
		dbcsCodePage = dbcsCodePage_;
		SetCaseFolder(NULL);
		cb.SetLineEndTypes(lineEndBitSet & LineEndTypesSupported());
		return true;
	} else {
		return false;
	}
}

bool Document::SetLineEndTypesAllowed(int lineEndBitSet_) {
	if (lineEndBitSet != lineEndBitSet_) {
		lineEndBitSet = lineEndBitSet_;
		int lineEndBitSetActive = lineEndBitSet & LineEndTypesSupported();
		if (lineEndBitSetActive != cb.GetLineEndTypes()) {
			ModifiedAt(0);
			cb.SetLineEndTypes(lineEndBitSetActive);
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

void Document::InsertLine(int line) {
	for (int j=0; j<ldSize; j++) {
		if (perLineData[j])
			perLineData[j]->InsertLine(line);
	}
}

void Document::RemoveLine(int line) {
	for (int j=0; j<ldSize; j++) {
		if (perLineData[j])
			perLineData[j]->RemoveLine(line);
	}
}

// Increase reference count and return its previous value.
int Document::AddRef() {
	return refCount++;
}

// Decrease reference count and return its previous value.
// Delete the document if reference count reaches zero.
int SCI_METHOD Document::Release() {
	int curRefCount = --refCount;
	if (curRefCount == 0)
		delete this;
	return curRefCount;
}

void Document::SetSavePoint() {
	cb.SetSavePoint();
	NotifySavePoint(true);
}

int Document::GetMark(int line) {
	return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkValue(line);
}

int Document::MarkerNext(int lineStart, int mask) const {
	return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkerNext(lineStart, mask);
}

int Document::AddMark(int line, int markerNum) {
	if (line >= 0 && line <= LinesTotal()) {
		int prev = static_cast<LineMarkers *>(perLineData[ldMarkers])->
			AddMark(line, markerNum, LinesTotal());
		DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
		NotifyModified(mh);
		return prev;
	} else {
		return 0;
	}
}

void Document::AddMarkSet(int line, int valueSet) {
	if (line < 0 || line > LinesTotal()) {
		return;
	}
	unsigned int m = valueSet;
	for (int i = 0; m; i++, m >>= 1)
		if (m & 1)
			static_cast<LineMarkers *>(perLineData[ldMarkers])->
				AddMark(line, i, LinesTotal());
	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
	NotifyModified(mh);
}

void Document::DeleteMark(int line, int markerNum) {
	static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false);
	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
	NotifyModified(mh);
}

void Document::DeleteMarkFromHandle(int markerHandle) {
	static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle);
	DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
	mh.line = -1;
	NotifyModified(mh);
}

void Document::DeleteAllMarks(int markerNum) {
	bool someChanges = false;
	for (int line = 0; line < LinesTotal(); line++) {
		if (static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true))
			someChanges = true;
	}
	if (someChanges) {
		DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
		mh.line = -1;
		NotifyModified(mh);
	}
}

int Document::LineFromHandle(int markerHandle) {
	return static_cast<LineMarkers *>(perLineData[ldMarkers])->LineFromHandle(markerHandle);
}

int SCI_METHOD Document::LineStart(int line) const {
	return cb.LineStart(line);
}

int SCI_METHOD Document::LineEnd(int line) const {
	if (line == LinesTotal() - 1) {
		return LineStart(line + 1);
	} else {
		int position = LineStart(line + 1);
		if (SC_CP_UTF8 == dbcsCodePage) {
			unsigned char bytes[] = {
				static_cast<unsigned char>(cb.CharAt(position-3)),
				static_cast<unsigned char>(cb.CharAt(position-2)),
				static_cast<unsigned char>(cb.CharAt(position-1)),
			};
			if (UTF8IsSeparator(bytes)) {
				return position - UTF8SeparatorLength;
			}
			if (UTF8IsNEL(bytes+1)) {
				return position - UTF8NELLength;
			}
		}
		position--; // Back over CR or LF
		// When line terminator is CR+LF, may need to go back one more
		if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
			position--;
		}
		return position;
	}
}

void SCI_METHOD Document::SetErrorStatus(int status) {
	// Tell the watchers the lexer has changed.
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status);
	}
}

int SCI_METHOD Document::LineFromPosition(int pos) const {
	return cb.LineFromPosition(pos);
}

int Document::LineEndPosition(int position) const {
	return LineEnd(LineFromPosition(position));
}

bool Document::IsLineEndPosition(int position) const {
	return LineEnd(LineFromPosition(position)) == position;
}

bool Document::IsPositionInLineEnd(int position) const {
	return position >= LineEnd(LineFromPosition(position));
}

int Document::VCHomePosition(int position) const {
	int line = LineFromPosition(position);
	int startPosition = LineStart(line);
	int endLine = LineEnd(line);
	int startText = startPosition;
	while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t'))
		startText++;
	if (position == startText)
		return startPosition;
	else
		return startText;
}

int SCI_METHOD Document::SetLevel(int line, int level) {
	int prev = static_cast<LineLevels *>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());
	if (prev != level) {
		DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
		                   LineStart(line), 0, 0, 0, line);
		mh.foldLevelNow = level;
		mh.foldLevelPrev = prev;
		NotifyModified(mh);
	}
	return prev;
}

int SCI_METHOD Document::GetLevel(int line) const {
	return static_cast<LineLevels *>(perLineData[ldLevels])->GetLevel(line);
}

void Document::ClearLevels() {
	static_cast<LineLevels *>(perLineData[ldLevels])->ClearLevels();
}

static bool IsSubordinate(int levelStart, int levelTry) {
	if (levelTry & SC_FOLDLEVELWHITEFLAG)
		return true;
	else
		return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK);
}

int Document::GetLastChild(int lineParent, int level, int lastLine) {
	if (level == -1)
		level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK;
	int maxLine = LinesTotal();
	int lookLastLine = (lastLine != -1) ? Platform::Minimum(LinesTotal() - 1, lastLine) : -1;
	int lineMaxSubord = lineParent;
	while (lineMaxSubord < maxLine - 1) {
		EnsureStyledTo(LineStart(lineMaxSubord + 2));
		if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1)))
			break;
		if ((lookLastLine != -1) && (lineMaxSubord >= lookLastLine) && !(GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG))
			break;
		lineMaxSubord++;
	}
	if (lineMaxSubord > lineParent) {
		if (level > (GetLevel(lineMaxSubord + 1) & SC_FOLDLEVELNUMBERMASK)) {
			// Have chewed up some whitespace that belongs to a parent so seek back
			if (GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG) {
				lineMaxSubord--;
			}
		}
	}
	return lineMaxSubord;
}

int Document::GetFoldParent(int line) {
	int level = GetLevel(line) & SC_FOLDLEVELNUMBERMASK;
	int lineLook = line - 1;
	while ((lineLook > 0) && (
	            (!(GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG)) ||
	            ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) >= level))
	      ) {
		lineLook--;
	}
	if ((GetLevel(lineLook) & SC_FOLDLEVELHEADERFLAG) &&
	        ((GetLevel(lineLook) & SC_FOLDLEVELNUMBERMASK) < level)) {
		return lineLook;
	} else {
		return -1;
	}
}

void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, int line, int lastLine) {
	int level = GetLevel(line);
	int lookLastLine = Platform::Maximum(line, lastLine) + 1;

	int lookLine = line;
	int lookLineLevel = level;
	int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
	while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || 
		((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) {
		lookLineLevel = GetLevel(--lookLine);
		lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
	}

	int beginFoldBlock = (lookLineLevel & SC_FOLDLEVELHEADERFLAG) ? lookLine : GetFoldParent(lookLine);
	if (beginFoldBlock == -1) {
		highlightDelimiter.Clear();
		return;
	}

	int endFoldBlock = GetLastChild(beginFoldBlock, -1, lookLastLine);
	int firstChangeableLineBefore = -1;
	if (endFoldBlock < line) {
		lookLine = beginFoldBlock - 1;
		lookLineLevel = GetLevel(lookLine);
		lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
		while ((lookLine >= 0) && (lookLineLevelNum >= SC_FOLDLEVELBASE)) {
			if (lookLineLevel & SC_FOLDLEVELHEADERFLAG) {
				if (GetLastChild(lookLine, -1, lookLastLine) == line) {
					beginFoldBlock = lookLine;
					endFoldBlock = line;
					firstChangeableLineBefore = line - 1;
				}
			}
			if ((lookLine > 0) && (lookLineLevelNum == SC_FOLDLEVELBASE) && ((GetLevel(lookLine - 1) & SC_FOLDLEVELNUMBERMASK) > lookLineLevelNum))
				break;
			lookLineLevel = GetLevel(--lookLine);
			lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK;
		}
	}
	if (firstChangeableLineBefore == -1) {
		for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; 
			lookLine >= beginFoldBlock; 
			lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
			if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) {
				firstChangeableLineBefore = lookLine;
				break;
			}
		}
	}
	if (firstChangeableLineBefore == -1)
		firstChangeableLineBefore = beginFoldBlock - 1;

	int firstChangeableLineAfter = -1;
	for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; 
		lookLine <= endFoldBlock; 
		lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) {
		if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) {
			firstChangeableLineAfter = lookLine;
			break;
		}
	}
	if (firstChangeableLineAfter == -1)
		firstChangeableLineAfter = endFoldBlock + 1;

	highlightDelimiter.beginFoldBlock = beginFoldBlock;
	highlightDelimiter.endFoldBlock = endFoldBlock;
	highlightDelimiter.firstChangeableLineBefore = firstChangeableLineBefore;
	highlightDelimiter.firstChangeableLineAfter = firstChangeableLineAfter;
}

int Document::ClampPositionIntoDocument(int pos) {
	return Platform::Clamp(pos, 0, Length());
}

bool Document::IsCrLf(int pos) {
	if (pos < 0)
		return false;
	if (pos >= (Length() - 1))
		return false;
	return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n');
}

int Document::LenChar(int pos) {
	if (pos < 0) {
		return 1;
	} else if (IsCrLf(pos)) {
		return 2;
	} else if (SC_CP_UTF8 == dbcsCodePage) {
		const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(pos));
		const int widthCharBytes = UTF8BytesOfLead[leadByte];
		int lengthDoc = Length();
		if ((pos + widthCharBytes) > lengthDoc)
			return lengthDoc - pos;
		else
			return widthCharBytes;
	} else if (dbcsCodePage) {
		return IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1;
	} else {
		return 1;
	}
}

bool Document::InGoodUTF8(int pos, int &start, int &end) const {
	int trail = pos;
	while ((trail>0) && (pos-trail < UTF8MaxBytes) && UTF8IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail-1))))
		trail--;
	start = (trail > 0) ? trail-1 : trail;

	const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(start));
	const int widthCharBytes = UTF8BytesOfLead[leadByte];
	if (widthCharBytes == 1) {
		return false;
	} else {
		int trailBytes = widthCharBytes - 1;
		int len = pos - start;
		if (len > trailBytes)
			// pos too far from lead
			return false;
		char charBytes[UTF8MaxBytes] = {static_cast<char>(leadByte),0,0,0};
		for (int b=1; b<widthCharBytes && ((start+b) < Length()); b++)
			charBytes[b] = cb.CharAt(static_cast<int>(start+b));
		int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(charBytes), widthCharBytes);
		if (utf8status & UTF8MaskInvalid)
			return false;
		end = start + widthCharBytes;
		return true;
	}
}

// Normalise a position so that it is not halfway through a two byte character.
// This can occur in two situations -
// When lines are terminated with \r\n pairs which should be treated as one character.
// When displaying DBCS text such as Japanese.
// If moving, move the position in the indicated direction.
int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
	//Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir);
	// If out of range, just return minimum/maximum value.
	if (pos <= 0)
		return 0;
	if (pos >= Length())
		return Length();

	// PLATFORM_ASSERT(pos > 0 && pos < Length());
	if (checkLineEnd && IsCrLf(pos - 1)) {
		if (moveDir > 0)
			return pos + 1;
		else
			return pos - 1;
	}

	if (dbcsCodePage) {
		if (SC_CP_UTF8 == dbcsCodePage) {
			unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
			// If ch is not a trail byte then pos is valid intercharacter position
			if (UTF8IsTrailByte(ch)) {
				int startUTF = pos;
				int endUTF = pos;
				if (InGoodUTF8(pos, startUTF, endUTF)) {
					// ch is a trail byte within a UTF-8 character
					if (moveDir > 0)
						pos = endUTF;
					else
						pos = startUTF;
				}
				// Else invalid UTF-8 so return position of isolated trail byte
			}
		} else {
			// Anchor DBCS calculations at start of line because start of line can
			// not be a DBCS trail byte.
			int posStartLine = LineStart(LineFromPosition(pos));
			if (pos == posStartLine)
				return pos;

			// Step back until a non-lead-byte is found.
			int posCheck = pos;
			while ((posCheck > posStartLine) && IsDBCSLeadByte(cb.CharAt(posCheck-1)))
				posCheck--;

			// Check from known start of character.
			while (posCheck < pos) {
				int mbsize = IsDBCSLeadByte(cb.CharAt(posCheck)) ? 2 : 1;
				if (posCheck + mbsize == pos) {
					return pos;
				} else if (posCheck + mbsize > pos) {
					if (moveDir > 0) {
						return posCheck + mbsize;
					} else {
						return posCheck;
					}
				}
				posCheck += mbsize;
			}
		}
	}

	return pos;
}

// NextPosition moves between valid positions - it can not handle a position in the middle of a
// multi-byte character. It is used to iterate through text more efficiently than MovePositionOutsideChar.
// A \r\n pair is treated as two characters.
int Document::NextPosition(int pos, int moveDir) const {
	// If out of range, just return minimum/maximum value.
	int increment = (moveDir > 0) ? 1 : -1;
	if (pos + increment <= 0)
		return 0;
	if (pos + increment >= Length())
		return Length();

	if (dbcsCodePage) {
		if (SC_CP_UTF8 == dbcsCodePage) {
			if (increment == 1) {
				// Simple forward movement case so can avoid some checks
				const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(pos));
				if (UTF8IsAscii(leadByte)) {
					// Single byte character or invalid
					pos++;
				} else {
					const int widthCharBytes = UTF8BytesOfLead[leadByte];
					char charBytes[UTF8MaxBytes] = {static_cast<char>(leadByte),0,0,0};
					for (int b=1; b<widthCharBytes; b++)
						charBytes[b] = cb.CharAt(static_cast<int>(pos+b));
					int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(charBytes), widthCharBytes);
					if (utf8status & UTF8MaskInvalid)
						pos++;
					else
						pos += utf8status & UTF8MaskWidth;
				}
			} else {
				// Examine byte before position
				pos--;
				unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
				// If ch is not a trail byte then pos is valid intercharacter position
				if (UTF8IsTrailByte(ch)) {
					// If ch is a trail byte in a valid UTF-8 character then return start of character
					int startUTF = pos;
					int endUTF = pos;
					if (InGoodUTF8(pos, startUTF, endUTF)) {
						pos = startUTF;
					}
					// Else invalid UTF-8 so return position of isolated trail byte
				}
			}
		} else {
			if (moveDir > 0) {
				int mbsize = IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1;
				pos += mbsize;
				if (pos > Length())
					pos = Length();
			} else {
				// Anchor DBCS calculations at start of line because start of line can
				// not be a DBCS trail byte.
				int posStartLine = LineStart(LineFromPosition(pos));
				// See http://msdn.microsoft.com/en-us/library/cc194792%28v=MSDN.10%29.aspx
				// http://msdn.microsoft.com/en-us/library/cc194790.aspx
				if ((pos - 1) <= posStartLine) {
					return pos - 1;
				} else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) {
					// Must actually be trail byte
					return pos - 2;
				} else {
					// Otherwise, step back until a non-lead-byte is found.
					int posTemp = pos - 1;
					while (posStartLine <= --posTemp && IsDBCSLeadByte(cb.CharAt(posTemp)))
						;
					// Now posTemp+1 must point to the beginning of a character,
					// so figure out whether we went back an even or an odd
					// number of bytes and go back 1 or 2 bytes, respectively.
					return (pos - 1 - ((pos - posTemp) & 1));
				}
			}
		}
	} else {
		pos += increment;
	}

	return pos;
}

bool Document::NextCharacter(int &pos, int moveDir) {
	// Returns true if pos changed
	int posNext = NextPosition(pos, moveDir);
	if (posNext == pos) {
		return false;
	} else {
		pos = posNext;
		return true;
	}
}

int SCI_METHOD Document::CodePage() const {
	return dbcsCodePage;
}

bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const {
	// Byte ranges found in Wikipedia articles with relevant search strings in each case
	unsigned char uch = static_cast<unsigned char>(ch);
	switch (dbcsCodePage) {
		case 932:
			// Shift_jis
			return ((uch >= 0x81) && (uch <= 0x9F)) ||
				((uch >= 0xE0) && (uch <= 0xFC));
				// Lead bytes F0 to FC may be a Microsoft addition. 
		case 936:
			// GBK
			return (uch >= 0x81) && (uch <= 0xFE);
		case 949:
			// Korean Wansung KS C-5601-1987
			return (uch >= 0x81) && (uch <= 0xFE);
		case 950:
			// Big5
			return (uch >= 0x81) && (uch <= 0xFE);
		case 1361:
			// Korean Johab KS C-5601-1992
			return
				((uch >= 0x84) && (uch <= 0xD3)) ||
				((uch >= 0xD8) && (uch <= 0xDE)) ||
				((uch >= 0xE0) && (uch <= 0xF9));
	}
	return false;
}

static inline bool IsSpaceOrTab(int ch) {
	return ch == ' ' || ch == '\t';
}

// Need to break text into segments near lengthSegment but taking into
// account the encoding to not break inside a UTF-8 or DBCS character
// and also trying to avoid breaking inside a pair of combining characters.
// The segment length must always be long enough (more than 4 bytes)
// so that there will be at least one whole character to make a segment.
// For UTF-8, text must consist only of valid whole characters.
// In preference order from best to worst:
//   1) Break after space
//   2) Break before punctuation
//   3) Break after whole character

int Document::SafeSegment(const char *text, int length, int lengthSegment) {
	if (length <= lengthSegment)
		return length;
	int lastSpaceBreak = -1;
	int lastPunctuationBreak = -1;
	int lastEncodingAllowedBreak = -1;
	for (int j=0; j < lengthSegment;) {
		unsigned char ch = static_cast<unsigned char>(text[j]);
		if (j > 0) {
			if (IsSpaceOrTab(text[j - 1]) && !IsSpaceOrTab(text[j])) {
				lastSpaceBreak = j;
			}
			if (ch < 'A') {
				lastPunctuationBreak = j;
			}
		}
		lastEncodingAllowedBreak = j;

		if (dbcsCodePage == SC_CP_UTF8) {
			j += UTF8BytesOfLead[ch];
		} else if (dbcsCodePage) {
			j += IsDBCSLeadByte(ch) ? 2 : 1;
		} else {
			j++;
		}
	}
	if (lastSpaceBreak >= 0) {
		return lastSpaceBreak;
	} else if (lastPunctuationBreak >= 0) {
		return lastPunctuationBreak;
	}
	return lastEncodingAllowedBreak;
}

void Document::ModifiedAt(int pos) {
	if (endStyled > pos)
		endStyled = pos;
}

void Document::CheckReadOnly() {
	if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
		enteredReadOnlyCount++;
		NotifyModifyAttempt();
		enteredReadOnlyCount--;
	}
}

// Document only modified by gateways DeleteChars, InsertString, Undo, Redo, and SetStyleAt.
// SetStyleAt does not change the persistent state of a document

bool Document::DeleteChars(int pos, int len) {
	if (len <= 0)
		return false;
	if ((pos + len) > Length())
		return false;
	CheckReadOnly();
	if (enteredModification != 0) {
		return false;
	} else {
		enteredModification++;
		if (!cb.IsReadOnly()) {
			NotifyModified(
			    DocModification(
			        SC_MOD_BEFOREDELETE | SC_PERFORMED_USER,
			        pos, len,
			        0, 0));
			int prevLinesTotal = LinesTotal();
			bool startSavePoint = cb.IsSavePoint();
			bool startSequence = false;
			const char *text = cb.DeleteChars(pos, len, startSequence);
			if (startSavePoint && cb.IsCollectingUndo())
				NotifySavePoint(!startSavePoint);
			if ((pos < Length()) || (pos == 0))
				ModifiedAt(pos);
			else
				ModifiedAt(pos-1);
			NotifyModified(
			    DocModification(
			        SC_MOD_DELETETEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
			        pos, len,
			        LinesTotal() - prevLinesTotal, text));
		}
		enteredModification--;
	}
	return !cb.IsReadOnly();
}

/**
 * Insert a string with a length.
 */
bool Document::InsertString(int position, const char *s, int insertLength) {
	if (insertLength <= 0) {
		return false;
	}
	CheckReadOnly();
	if (enteredModification != 0) {
		return false;
	} else {
		enteredModification++;
		if (!cb.IsReadOnly()) {
			NotifyModified(
			    DocModification(
			        SC_MOD_BEFOREINSERT | SC_PERFORMED_USER,
			        position, insertLength,
			        0, s));
			int prevLinesTotal = LinesTotal();
			bool startSavePoint = cb.IsSavePoint();
			bool startSequence = false;
			const char *text = cb.InsertString(position, s, insertLength, startSequence);
			if (startSavePoint && cb.IsCollectingUndo())
				NotifySavePoint(!startSavePoint);
			ModifiedAt(position);
			NotifyModified(
			    DocModification(
			        SC_MOD_INSERTTEXT | SC_PERFORMED_USER | (startSequence?SC_STARTACTION:0),
			        position, insertLength,
			        LinesTotal() - prevLinesTotal, text));
		}
		enteredModification--;
	}
	return !cb.IsReadOnly();
}

int SCI_METHOD Document::AddData(char *data, int length) {
	try {
		int position = Length();
		InsertString(position,data, length);
	} catch (std::bad_alloc &) {
		return SC_STATUS_BADALLOC;
	} catch (...) {
		return SC_STATUS_FAILURE;
	}
	return 0;
}

void * SCI_METHOD Document::ConvertToDocument() {
	return this;
}

int Document::Undo() {
	int newPos = -1;
	CheckReadOnly();
	if (enteredModification == 0) {
		enteredModification++;
		if (!cb.IsReadOnly()) {
			bool startSavePoint = cb.IsSavePoint();
			bool multiLine = false;
			int steps = cb.StartUndo();
			//Platform::DebugPrintf("Steps=%d\n", steps);
			int coalescedRemovePos = -1;
			int coalescedRemoveLen = 0;
			int prevRemoveActionPos = -1;
			int prevRemoveActionLen = 0;
			for (int step = 0; step < steps; step++) {
				const int prevLinesTotal = LinesTotal();
				const Action &action = cb.GetUndoStep();
				if (action.at == removeAction) {
					NotifyModified(DocModification(
									SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
				} else if (action.at == containerAction) {
					DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO);
					dm.token = action.position;
					NotifyModified(dm);
					if (!action.mayCoalesce) {
						coalescedRemovePos = -1;
						coalescedRemoveLen = 0;
						prevRemoveActionPos = -1;
						prevRemoveActionLen = 0;
					}
				} else {
					NotifyModified(DocModification(
									SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
				}
				cb.PerformUndoStep();
				if (action.at != containerAction) {
					ModifiedAt(action.position);
					newPos = action.position;
				}

				int modFlags = SC_PERFORMED_UNDO;
				// With undo, an insertion action becomes a deletion notification
				if (action.at == removeAction) {
					newPos += action.lenData;
					modFlags |= SC_MOD_INSERTTEXT;
					if ((coalescedRemoveLen > 0) &&
						(action.position == prevRemoveActionPos || action.position == (prevRemoveActionPos + prevRemoveActionLen))) {
						coalescedRemoveLen += action.lenData;
						newPos = coalescedRemovePos + coalescedRemoveLen;
					} else {
						coalescedRemovePos = action.position;
						coalescedRemoveLen = action.lenData;
					}
					prevRemoveActionPos = action.position;
					prevRemoveActionLen = action.lenData;
				} else if (action.at == insertAction) {
					modFlags |= SC_MOD_DELETETEXT;
					coalescedRemovePos = -1;
					coalescedRemoveLen = 0;
					prevRemoveActionPos = -1;
					prevRemoveActionLen = 0;
				}
				if (steps > 1)
					modFlags |= SC_MULTISTEPUNDOREDO;
				const int linesAdded = LinesTotal() - prevLinesTotal;
				if (linesAdded != 0)
					multiLine = true;
				if (step == steps - 1) {
					modFlags |= SC_LASTSTEPINUNDOREDO;
					if (multiLine)
						modFlags |= SC_MULTILINEUNDOREDO;
				}
				NotifyModified(DocModification(modFlags, action.position, action.lenData,
											   linesAdded, action.data));
			}

			bool endSavePoint = cb.IsSavePoint();
			if (startSavePoint != endSavePoint)
				NotifySavePoint(endSavePoint);
		}
		enteredModification--;
	}
	return newPos;
}

int Document::Redo() {
	int newPos = -1;
	CheckReadOnly();
	if (enteredModification == 0) {
		enteredModification++;
		if (!cb.IsReadOnly()) {
			bool startSavePoint = cb.IsSavePoint();
			bool multiLine = false;
			int steps = cb.StartRedo();
			for (int step = 0; step < steps; step++) {
				const int prevLinesTotal = LinesTotal();
				const Action &action = cb.GetRedoStep();
				if (action.at == insertAction) {
					NotifyModified(DocModification(
									SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
				} else if (action.at == containerAction) {
					DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_REDO);
					dm.token = action.position;
					NotifyModified(dm);
				} else {
					NotifyModified(DocModification(
									SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
				}
				cb.PerformRedoStep();
				if (action.at != containerAction) {
					ModifiedAt(action.position);
					newPos = action.position;
				}

				int modFlags = SC_PERFORMED_REDO;
				if (action.at == insertAction) {
					newPos += action.lenData;
					modFlags |= SC_MOD_INSERTTEXT;
				} else if (action.at == removeAction) {
					modFlags |= SC_MOD_DELETETEXT;
				}
				if (steps > 1)
					modFlags |= SC_MULTISTEPUNDOREDO;
				const int linesAdded = LinesTotal() - prevLinesTotal;
				if (linesAdded != 0)
					multiLine = true;
				if (step == steps - 1) {
					modFlags |= SC_LASTSTEPINUNDOREDO;
					if (multiLine)
						modFlags |= SC_MULTILINEUNDOREDO;
				}
				NotifyModified(
					DocModification(modFlags, action.position, action.lenData,
									linesAdded, action.data));
			}

			bool endSavePoint = cb.IsSavePoint();
			if (startSavePoint != endSavePoint)
				NotifySavePoint(endSavePoint);
		}
		enteredModification--;
	}
	return newPos;
}

/**
 * Insert a single character.
 */
bool Document::InsertChar(int pos, char ch) {
	char chs[1];
	chs[0] = ch;
	return InsertString(pos, chs, 1);
}

/**
 * Insert a null terminated string.
 */
bool Document::InsertCString(int position, const char *s) {
	return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0));
}

void Document::ChangeChar(int pos, char ch) {
	DeleteChars(pos, 1);
	InsertChar(pos, ch);
}

void Document::DelChar(int pos) {
	DeleteChars(pos, LenChar(pos));
}

void Document::DelCharBack(int pos) {
	if (pos <= 0) {
		return;
	} else if (IsCrLf(pos - 2)) {
		DeleteChars(pos - 2, 2);
	} else if (dbcsCodePage) {
		int startChar = NextPosition(pos, -1);
		DeleteChars(startChar, pos - startChar);
	} else {
		DeleteChars(pos - 1, 1);
	}
}

static int NextTab(int pos, int tabSize) {
	return ((pos / tabSize) + 1) * tabSize;
}

static std::string CreateIndentation(int indent, int tabSize, bool insertSpaces) {
	std::string indentation;
	if (!insertSpaces) {
		while (indent >= tabSize) {
			indentation += '\t';
			indent -= tabSize;
		}
	}
	while (indent > 0) {
		indentation += ' ';
		indent--;
	}
	return indentation;
}

int SCI_METHOD Document::GetLineIndentation(int line) {
	int indent = 0;
	if ((line >= 0) && (line < LinesTotal())) {
		int lineStart = LineStart(line);
		int length = Length();
		for (int i = lineStart; i < length; i++) {
			char ch = cb.CharAt(i);
			if (ch == ' ')
				indent++;
			else if (ch == '\t')
				indent = NextTab(indent, tabInChars);
			else
				return indent;
		}
	}
	return indent;
}

void Document::SetLineIndentation(int line, int indent) {
	int indentOfLine = GetLineIndentation(line);
	if (indent < 0)
		indent = 0;
	if (indent != indentOfLine) {
		std::string linebuf = CreateIndentation(indent, tabInChars, !useTabs);
		int thisLineStart = LineStart(line);
		int indentPos = GetLineIndentPosition(line);
		UndoGroup ug(this);
		DeleteChars(thisLineStart, indentPos - thisLineStart);
		InsertCString(thisLineStart, linebuf.c_str());
	}
}

int Document::GetLineIndentPosition(int line) const {
	if (line < 0)
		return 0;
	int pos = LineStart(line);
	int length = Length();
	while ((pos < length) && IsSpaceOrTab(cb.CharAt(pos))) {
		pos++;
	}
	return pos;
}

int Document::GetColumn(int pos) {
	int column = 0;
	int line = LineFromPosition(pos);
	if ((line >= 0) && (line < LinesTotal())) {
		for (int i = LineStart(line); i < pos;) {
			char ch = cb.CharAt(i);
			if (ch == '\t') {
				column = NextTab(column, tabInChars);
				i++;
			} else if (ch == '\r') {
				return column;
			} else if (ch == '\n') {
				return column;
			} else if (i >= Length()) {
				return column;
			} else {
				column++;
				i = NextPosition(i, 1);
			}
		}
	}
	return column;
}

int Document::CountCharacters(int startPos, int endPos) {
	startPos = MovePositionOutsideChar(startPos, 1, false);
	endPos = MovePositionOutsideChar(endPos, -1, false);
	int count = 0;
	int i = startPos;
	while (i < endPos) {
		count++;
		if (IsCrLf(i))
			i++;
		i = NextPosition(i, 1);
	}
	return count;
}

int Document::FindColumn(int line, int column) {
	int position = LineStart(line);
	if ((line >= 0) && (line < LinesTotal())) {
		int columnCurrent = 0;
		while ((columnCurrent < column) && (position < Length())) {
			char ch = cb.CharAt(position);
			if (ch == '\t') {
				columnCurrent = NextTab(columnCurrent, tabInChars);
				if (columnCurrent > column)
					return position;
				position++;
			} else if (ch == '\r') {
				return position;
			} else if (ch == '\n') {
				return position;
			} else {
				columnCurrent++;
				position = NextPosition(position, 1);
			}
		}
	}
	return position;
}

void Document::Indent(bool forwards, int lineBottom, int lineTop) {
	// Dedent - suck white space off the front of the line to dedent by equivalent of a tab
	for (int line = lineBottom; line >= lineTop; line--) {
		int indentOfLine = GetLineIndentation(line);
		if (forwards) {
			if (LineStart(line) < LineEnd(line)) {
				SetLineIndentation(line, indentOfLine + IndentSize());
			}
		} else {
			SetLineIndentation(line, indentOfLine - IndentSize());
		}
	}
}

// Convert line endings for a piece of text to a particular mode.
// Stop at len or when a NUL is found.
// Caller must delete the returned pointer.
char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted) {
	char *dest = new char[2 * len + 1];
	const char *sptr = s;
	char *dptr = dest;
	for (size_t i = 0; (i < len) && (*sptr != '\0'); i++) {
		if (*sptr == '\n' || *sptr == '\r') {
			if (eolModeWanted == SC_EOL_CR) {
				*dptr++ = '\r';
			} else if (eolModeWanted == SC_EOL_LF) {
				*dptr++ = '\n';
			} else { // eolModeWanted == SC_EOL_CRLF
				*dptr++ = '\r';
				*dptr++ = '\n';
			}
			if ((*sptr == '\r') && (i+1 < len) && (*(sptr+1) == '\n')) {
				i++;
				sptr++;
			}
			sptr++;
		} else {
			*dptr++ = *sptr++;
		}
	}
	*dptr++ = '\0';
	*pLenOut = (dptr - dest) - 1;
	return dest;
}

void Document::ConvertLineEnds(int eolModeSet) {
	UndoGroup ug(this);

	for (int pos = 0; pos < Length(); pos++) {
		if (cb.CharAt(pos) == '\r') {
			if (cb.CharAt(pos + 1) == '\n') {
				// CRLF
				if (eolModeSet == SC_EOL_CR) {
					DeleteChars(pos + 1, 1); // Delete the LF
				} else if (eolModeSet == SC_EOL_LF) {
					DeleteChars(pos, 1); // Delete the CR
				} else {
					pos++;
				}
			} else {
				// CR
				if (eolModeSet == SC_EOL_CRLF) {
					InsertString(pos + 1, "\n", 1); // Insert LF
					pos++;
				} else if (eolModeSet == SC_EOL_LF) {
					InsertString(pos, "\n", 1); // Insert LF
					DeleteChars(pos + 1, 1); // Delete CR
				}
			}
		} else if (cb.CharAt(pos) == '\n') {
			// LF
			if (eolModeSet == SC_EOL_CRLF) {
				InsertString(pos, "\r", 1); // Insert CR
				pos++;
			} else if (eolModeSet == SC_EOL_CR) {
				InsertString(pos, "\r", 1); // Insert CR
				DeleteChars(pos + 1, 1); // Delete LF
			}
		}
	}

}

bool Document::IsWhiteLine(int line) const {
	int currentChar = LineStart(line);
	int endLine = LineEnd(line);
	while (currentChar < endLine) {
		if (cb.CharAt(currentChar) != ' ' && cb.CharAt(currentChar) != '\t') {
			return false;
		}
		++currentChar;
	}
	return true;
}

int Document::ParaUp(int pos) {
	int line = LineFromPosition(pos);
	line--;
	while (line >= 0 && IsWhiteLine(line)) { // skip empty lines
		line--;
	}
	while (line >= 0 && !IsWhiteLine(line)) { // skip non-empty lines
		line--;
	}
	line++;
	return LineStart(line);
}

int Document::ParaDown(int pos) {
	int line = LineFromPosition(pos);
	while (line < LinesTotal() && !IsWhiteLine(line)) { // skip non-empty lines
		line++;
	}
	while (line < LinesTotal() && IsWhiteLine(line)) { // skip empty lines
		line++;
	}
	if (line < LinesTotal())
		return LineStart(line);
	else // end of a document
		return LineEnd(line-1);
}

CharClassify::cc Document::WordCharClass(unsigned char ch) {
	if ((SC_CP_UTF8 == dbcsCodePage) && (!UTF8IsAscii(ch)))
		return CharClassify::ccWord;
	return charClass.GetClass(ch);
}

/**
 * Used by commmands that want to select whole words.
 * Finds the start of word at pos when delta < 0 or the end of the word when delta >= 0.
 */
int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) {
	CharClassify::cc ccStart = CharClassify::ccWord;
	if (delta < 0) {
		if (!onlyWordCharacters)
			ccStart = WordCharClass(cb.CharAt(pos-1));
		while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart))
			pos--;
	} else {
		if (!onlyWordCharacters && pos < Length())
			ccStart = WordCharClass(cb.CharAt(pos));
		while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart))
			pos++;
	}
	return MovePositionOutsideChar(pos, delta, true);
}

/**
 * Find the start of the next word in either a forward (delta >= 0) or backwards direction
 * (delta < 0).
 * This is looking for a transition between character classes although there is also some
 * additional movement to transit white space.
 * Used by cursor movement by word commands.
 */
int Document::NextWordStart(int pos, int delta) {
	if (delta < 0) {
		while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace))
			pos--;
		if (pos > 0) {
			CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1));
			while (pos > 0 && (WordCharClass(cb.CharAt(pos - 1)) == ccStart)) {
				pos--;
			}
		}
	} else {
		CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos));
		while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart))
			pos++;
		while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace))
			pos++;
	}
	return pos;
}

/**
 * Find the end of the next word in either a forward (delta >= 0) or backwards direction
 * (delta < 0).
 * This is looking for a transition between character classes although there is also some
 * additional movement to transit white space.
 * Used by cursor movement by word commands.
 */
int Document::NextWordEnd(int pos, int delta) {
	if (delta < 0) {
		if (pos > 0) {
			CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos-1));
			if (ccStart != CharClassify::ccSpace) {
				while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == ccStart) {
					pos--;
				}
			}
			while (pos > 0 && WordCharClass(cb.CharAt(pos - 1)) == CharClassify::ccSpace) {
				pos--;
			}
		}
	} else {
		while (pos < Length() && WordCharClass(cb.CharAt(pos)) == CharClassify::ccSpace) {
			pos++;
		}
		if (pos < Length()) {
			CharClassify::cc ccStart = WordCharClass(cb.CharAt(pos));
			while (pos < Length() && WordCharClass(cb.CharAt(pos)) == ccStart) {
				pos++;
			}
		}
	}
	return pos;
}

/**
 * Check that the character at the given position is a word or punctuation character and that
 * the previous character is of a different character class.
 */
bool Document::IsWordStartAt(int pos) {
	if (pos > 0) {
		CharClassify::cc ccPos = WordCharClass(CharAt(pos));
		return (ccPos == CharClassify::ccWord || ccPos == CharClassify::ccPunctuation) &&
			(ccPos != WordCharClass(CharAt(pos - 1)));
	}
	return true;
}

/**
 * Check that the character at the given position is a word or punctuation character and that
 * the next character is of a different character class.
 */
bool Document::IsWordEndAt(int pos) {
	if (pos < Length()) {
		CharClassify::cc ccPrev = WordCharClass(CharAt(pos-1));
		return (ccPrev == CharClassify::ccWord || ccPrev == CharClassify::ccPunctuation) &&
			(ccPrev != WordCharClass(CharAt(pos)));
	}
	return true;
}

/**
 * Check that the given range is has transitions between character classes at both
 * ends and where the characters on the inside are word or punctuation characters.
 */
bool Document::IsWordAt(int start, int end) {
	return IsWordStartAt(start) && IsWordEndAt(end);
}

static inline char MakeLowerCase(char ch) {
	if (ch < 'A' || ch > 'Z')
		return ch;
	else
		return static_cast<char>(ch - 'A' + 'a');
}

CaseFolderTable::CaseFolderTable() {
	for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
		mapping[iChar] = static_cast<char>(iChar);
	}
}

CaseFolderTable::~CaseFolderTable() {
}

size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
	if (lenMixed > sizeFolded) {
		return 0;
	} else {
		for (size_t i=0; i<lenMixed; i++) {
			folded[i] = mapping[static_cast<unsigned char>(mixed[i])];
		}
		return lenMixed;
	}
}

void CaseFolderTable::SetTranslation(char ch, char chTranslation) {
	mapping[static_cast<unsigned char>(ch)] = chTranslation;
}

void CaseFolderTable::StandardASCII() {
	for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
		if (iChar >= 'A' && iChar <= 'Z') {
			mapping[iChar] = static_cast<char>(iChar - 'A' + 'a');
		} else {
			mapping[iChar] = static_cast<char>(iChar);
		}
	}
}

bool Document::MatchesWordOptions(bool word, bool wordStart, int pos, int length) {
	return (!word && !wordStart) ||
			(word && IsWordAt(pos, pos + length)) ||
			(wordStart && IsWordStartAt(pos));
}

bool Document::HasCaseFolder(void) const {
	return pcf != 0;
}

void Document::SetCaseFolder(CaseFolder *pcf_) {
	delete pcf;
	pcf = pcf_;
}

/**
 * Find text in document, supporting both forward and backward
 * searches (just pass minPos > maxPos to do a backward search)
 * Has not been tested with backwards DBCS searches yet.
 */
long Document::FindText(int minPos, int maxPos, const char *search,
                        bool caseSensitive, bool word, bool wordStart, bool regExp, int flags,
                        int *length) {
	if (*length <= 0)
		return minPos;
	if (regExp) {
		if (!regex)
			regex = CreateRegexSearch(&charClass);
		return regex->FindText(this, minPos, maxPos, search, caseSensitive, word, wordStart, flags, length);
	} else {

		const bool forward = minPos <= maxPos;
		const int increment = forward ? 1 : -1;

		// Range endpoints should not be inside DBCS characters, but just in case, move them.
		const int startPos = MovePositionOutsideChar(minPos, increment, false);
		const int endPos = MovePositionOutsideChar(maxPos, increment, false);

		// Compute actual search ranges needed
		const int lengthFind = *length;

		//Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind);
		const int limitPos = Platform::Maximum(startPos, endPos);
		int pos = startPos;
		if (!forward) {
			// Back all of a character
			pos = NextPosition(pos, increment);
		}
		if (caseSensitive) {
			const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos;
			const char charStartSearch =  search[0];
			while (forward ? (pos < endSearch) : (pos >= endSearch)) {
				if (CharAt(pos) == charStartSearch) {
					bool found = (pos + lengthFind) <= limitPos;
					for (int indexSearch = 1; (indexSearch < lengthFind) && found; indexSearch++) {
						found = CharAt(pos + indexSearch) == search[indexSearch];
					}
					if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) {
						return pos;
					}
				}
				if (!NextCharacter(pos, increment))
					break;
			}
		} else if (SC_CP_UTF8 == dbcsCodePage) {
			const size_t maxFoldingExpansion = 4;
			std::vector<char> searchThing(lengthFind * UTF8MaxBytes * maxFoldingExpansion + 1);
			const int lenSearch = static_cast<int>(
				pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind));
			char bytes[UTF8MaxBytes + 1];
			char folded[UTF8MaxBytes * maxFoldingExpansion + 1];
			while (forward ? (pos < endPos) : (pos >= endPos)) {
				int widthFirstCharacter = 0;
				int posIndexDocument = pos;
				int indexSearch = 0;
				bool characterMatches = true;
				for (;;) {
					const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(posIndexDocument));
					bytes[0] = leadByte;
					int widthChar = 1;
					if (!UTF8IsAscii(leadByte)) {
						const int widthCharBytes = UTF8BytesOfLead[leadByte];
						for (int b=1; b<widthCharBytes; b++) {
							bytes[b] = cb.CharAt(posIndexDocument+b);
						}
						widthChar = UTF8Classify(reinterpret_cast<const unsigned char *>(bytes), widthCharBytes) & UTF8MaskWidth;
					}
					if (!widthFirstCharacter)
						widthFirstCharacter = widthChar;
					if ((posIndexDocument + widthChar) > limitPos)
						break;
					const int lenFlat = static_cast<int>(pcf->Fold(folded, sizeof(folded), bytes, widthChar));
					folded[lenFlat] = 0;
					// Does folded match the buffer
					characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat);
					if (!characterMatches)
						break;
					posIndexDocument += widthChar;
					indexSearch += lenFlat;
					if (indexSearch >= lenSearch)
						break;
				}
				if (characterMatches && (indexSearch == static_cast<int>(lenSearch))) {
					if (MatchesWordOptions(word, wordStart, pos, posIndexDocument - pos)) {
						*length = posIndexDocument - pos;
						return pos;
					}
				}
				if (forward) {
					pos += widthFirstCharacter;
				} else {
					if (!NextCharacter(pos, increment))
						break;
				}
			}
		} else if (dbcsCodePage) {
			const size_t maxBytesCharacter = 2;
			const size_t maxFoldingExpansion = 4;
			std::vector<char> searchThing(lengthFind * maxBytesCharacter * maxFoldingExpansion + 1);
			const int lenSearch = static_cast<int>(
				pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind));
			while (forward ? (pos < endPos) : (pos >= endPos)) {
				int indexDocument = 0;
				int indexSearch = 0;
				bool characterMatches = true;
				while (characterMatches &&
					((pos + indexDocument) < limitPos) &&
					(indexSearch < lenSearch)) {
					char bytes[maxBytesCharacter + 1];
					bytes[0] = cb.CharAt(pos + indexDocument);
					const int widthChar = IsDBCSLeadByte(bytes[0]) ? 2 : 1;
					if (widthChar == 2)
						bytes[1] = cb.CharAt(pos + indexDocument + 1);
					if ((pos + indexDocument + widthChar) > limitPos)
						break;
					char folded[maxBytesCharacter * maxFoldingExpansion + 1];
					const int lenFlat = static_cast<int>(pcf->Fold(folded, sizeof(folded), bytes, widthChar));
					folded[lenFlat] = 0;
					// Does folded match the buffer
					characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat);
					indexDocument += widthChar;
					indexSearch += lenFlat;
				}
				if (characterMatches && (indexSearch == static_cast<int>(lenSearch))) {
					if (MatchesWordOptions(word, wordStart, pos, indexDocument)) {
						*length = indexDocument;
						return pos;
					}
				}
				if (!NextCharacter(pos, increment))
					break;
			}
		} else {
			const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos;
			std::vector<char> searchThing(lengthFind + 1);
			pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind);
			while (forward ? (pos < endSearch) : (pos >= endSearch)) {
				bool found = (pos + lengthFind) <= limitPos;
				for (int indexSearch = 0; (indexSearch < lengthFind) && found; indexSearch++) {
					char ch = CharAt(pos + indexSearch);
					char folded[2];
					pcf->Fold(folded, sizeof(folded), &ch, 1);
					found = folded[0] == searchThing[indexSearch];
				}
				if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) {
					return pos;
				}
				if (!NextCharacter(pos, increment))
					break;
			}
		}
	}
	//Platform::DebugPrintf("Not found\n");
	return -1;
}

const char *Document::SubstituteByPosition(const char *text, int *length) {
	if (regex)
		return regex->SubstituteByPosition(this, text, length);
	else
		return 0;
}

int Document::LinesTotal() const {
	return cb.Lines();
}

void Document::ChangeCase(Range r, bool makeUpperCase) {
	for (int pos = r.start; pos < r.end;) {
		int len = LenChar(pos);
		if (len == 1) {
			char ch = CharAt(pos);
			if (makeUpperCase) {
				if (IsLowerCase(ch)) {
					ChangeChar(pos, static_cast<char>(MakeUpperCase(ch)));
				}
			} else {
				if (IsUpperCase(ch)) {
					ChangeChar(pos, static_cast<char>(MakeLowerCase(ch)));
				}
			}
		}
		pos += len;
	}
}

void Document::SetDefaultCharClasses(bool includeWordClass) {
    charClass.SetDefaultCharClasses(includeWordClass);
}

void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass) {
    charClass.SetCharClasses(chars, newCharClass);
}

int Document::GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) {
    return charClass.GetCharsOfClass(characterClass, buffer);
}

void Document::SetStylingBits(int bits) {
	stylingBits = bits;
	stylingBitsMask = (1 << stylingBits) - 1;
}

void SCI_METHOD Document::StartStyling(int position, char mask) {
	stylingMask = mask;
	endStyled = position;
}

bool SCI_METHOD Document::SetStyleFor(int length, char style) {
	if (enteredStyling != 0) {
		return false;
	} else {
		enteredStyling++;
		style &= stylingMask;
		int prevEndStyled = endStyled;
		if (cb.SetStyleFor(endStyled, length, style, stylingMask)) {
			DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
			                   prevEndStyled, length);
			NotifyModified(mh);
		}
		endStyled += length;
		enteredStyling--;
		return true;
	}
}

bool SCI_METHOD Document::SetStyles(int length, const char *styles) {
	if (enteredStyling != 0) {
		return false;
	} else {
		enteredStyling++;
		bool didChange = false;
		int startMod = 0;
		int endMod = 0;
		for (int iPos = 0; iPos < length; iPos++, endStyled++) {
			PLATFORM_ASSERT(endStyled < Length());
			if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) {
				if (!didChange) {
					startMod = endStyled;
				}
				didChange = true;
				endMod = endStyled;
			}
		}
		if (didChange) {
			DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
			                   startMod, endMod - startMod + 1);
			NotifyModified(mh);
		}
		enteredStyling--;
		return true;
	}
}

void Document::EnsureStyledTo(int pos) {
	if ((enteredStyling == 0) && (pos > GetEndStyled())) {
		IncrementStyleClock();
		if (pli && !pli->UseContainerLexing()) {
			int lineEndStyled = LineFromPosition(GetEndStyled());
			int endStyledTo = LineStart(lineEndStyled);
			pli->Colourise(endStyledTo, pos);
		} else {
			// Ask the watchers to style, and stop as soon as one responds.
			for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) {
				watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos);
			}
		}
	}
}

void Document::LexerChanged() {
	// Tell the watchers the lexer has changed.
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifyLexerChanged(this, watchers[i].userData);
	}
}

int SCI_METHOD Document::SetLineState(int line, int state) {
	int statePrevious = static_cast<LineState *>(perLineData[ldState])->SetLineState(line, state);
	if (state != statePrevious) {
		DocModification mh(SC_MOD_CHANGELINESTATE, LineStart(line), 0, 0, 0, line);
		NotifyModified(mh);
	}
	return statePrevious;
}

int SCI_METHOD Document::GetLineState(int line) const {
	return static_cast<LineState *>(perLineData[ldState])->GetLineState(line);
}

int Document::GetMaxLineState() {
	return static_cast<LineState *>(perLineData[ldState])->GetMaxLineState();
}

void SCI_METHOD Document::ChangeLexerState(int start, int end) {
	DocModification mh(SC_MOD_LEXERSTATE, start, end-start, 0, 0, 0);
	NotifyModified(mh);
}

StyledText Document::MarginStyledText(int line) {
	LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldMargin]);
	return StyledText(pla->Length(line), pla->Text(line),
		pla->MultipleStyles(line), pla->Style(line), pla->Styles(line));
}

void Document::MarginSetText(int line, const char *text) {
	static_cast<LineAnnotation *>(perLineData[ldMargin])->SetText(line, text);
	DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line);
	NotifyModified(mh);
}

void Document::MarginSetStyle(int line, int style) {
	static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyle(line, style);
	NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line));
}

void Document::MarginSetStyles(int line, const unsigned char *styles) {
	static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyles(line, styles);
	NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line));
}

int Document::MarginLength(int line) const {
	return static_cast<LineAnnotation *>(perLineData[ldMargin])->Length(line);
}

void Document::MarginClearAll() {
	int maxEditorLine = LinesTotal();
	for (int l=0; l<maxEditorLine; l++)
		MarginSetText(l, 0);
	// Free remaining data
	static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll();
}

bool Document::AnnotationAny() const {
	return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->AnySet();
}

StyledText Document::AnnotationStyledText(int line) {
	LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]);
	return StyledText(pla->Length(line), pla->Text(line),
		pla->MultipleStyles(line), pla->Style(line), pla->Styles(line));
}

void Document::AnnotationSetText(int line, const char *text) {
	if (line >= 0 && line < LinesTotal()) {
		const int linesBefore = AnnotationLines(line);
		static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetText(line, text);
		const int linesAfter = AnnotationLines(line);
		DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line);
		mh.annotationLinesAdded = linesAfter - linesBefore;
		NotifyModified(mh);
	}
}

void Document::AnnotationSetStyle(int line, int style) {
	static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyle(line, style);
	DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line);
	NotifyModified(mh);
}

void Document::AnnotationSetStyles(int line, const unsigned char *styles) {
	if (line >= 0 && line < LinesTotal()) {
		static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyles(line, styles);
	}
}

int Document::AnnotationLength(int line) const {
	return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Length(line);
}

int Document::AnnotationLines(int line) const {
	return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Lines(line);
}

void Document::AnnotationClearAll() {
	int maxEditorLine = LinesTotal();
	for (int l=0; l<maxEditorLine; l++)
		AnnotationSetText(l, 0);
	// Free remaining data
	static_cast<LineAnnotation *>(perLineData[ldAnnotation])->ClearAll();
}

void Document::IncrementStyleClock() {
	styleClock = (styleClock + 1) % 0x100000;
}

void SCI_METHOD Document::DecorationFillRange(int position, int value, int fillLength) {
	if (decorations.FillRange(position, value, fillLength)) {
		DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER,
							position, fillLength);
		NotifyModified(mh);
	}
}

bool Document::AddWatcher(DocWatcher *watcher, void *userData) {
	for (int i = 0; i < lenWatchers; i++) {
		if ((watchers[i].watcher == watcher) &&
		        (watchers[i].userData == userData))
			return false;
	}
	WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers + 1];
	for (int j = 0; j < lenWatchers; j++)
		pwNew[j] = watchers[j];
	pwNew[lenWatchers].watcher = watcher;
	pwNew[lenWatchers].userData = userData;
	delete []watchers;
	watchers = pwNew;
	lenWatchers++;
	return true;
}

bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) {
	for (int i = 0; i < lenWatchers; i++) {
		if ((watchers[i].watcher == watcher) &&
		        (watchers[i].userData == userData)) {
			if (lenWatchers == 1) {
				delete []watchers;
				watchers = 0;
				lenWatchers = 0;
			} else {
				WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers];
				for (int j = 0; j < lenWatchers - 1; j++) {
					pwNew[j] = (j < i) ? watchers[j] : watchers[j + 1];
				}
				delete []watchers;
				watchers = pwNew;
				lenWatchers--;
			}
			return true;
		}
	}
	return false;
}

void Document::NotifyModifyAttempt() {
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifyModifyAttempt(this, watchers[i].userData);
	}
}

void Document::NotifySavePoint(bool atSavePoint) {
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifySavePoint(this, watchers[i].userData, atSavePoint);
	}
}

void Document::NotifyModified(DocModification mh) {
	if (mh.modificationType & SC_MOD_INSERTTEXT) {
		decorations.InsertSpace(mh.position, mh.length);
	} else if (mh.modificationType & SC_MOD_DELETETEXT) {
		decorations.DeleteRange(mh.position, mh.length);
	}
	for (int i = 0; i < lenWatchers; i++) {
		watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
	}
}

bool Document::IsWordPartSeparator(char ch) {
	return (WordCharClass(ch) == CharClassify::ccWord) && IsPunctuation(ch);
}

int Document::WordPartLeft(int pos) {
	if (pos > 0) {
		--pos;
		char startChar = cb.CharAt(pos);
		if (IsWordPartSeparator(startChar)) {
			while (pos > 0 && IsWordPartSeparator(cb.CharAt(pos))) {
				--pos;
			}
		}
		if (pos > 0) {
			startChar = cb.CharAt(pos);
			--pos;
			if (IsLowerCase(startChar)) {
				while (pos > 0 && IsLowerCase(cb.CharAt(pos)))
					--pos;
				if (!IsUpperCase(cb.CharAt(pos)) && !IsLowerCase(cb.CharAt(pos)))
					++pos;
			} else if (IsUpperCase(startChar)) {
				while (pos > 0 && IsUpperCase(cb.CharAt(pos)))
					--pos;
				if (!IsUpperCase(cb.CharAt(pos)))
					++pos;
			} else if (IsADigit(startChar)) {
				while (pos > 0 && IsADigit(cb.CharAt(pos)))
					--pos;
				if (!IsADigit(cb.CharAt(pos)))
					++pos;
			} else if (IsPunctuation(startChar)) {
				while (pos > 0 && IsPunctuation(cb.CharAt(pos)))
					--pos;
				if (!IsPunctuation(cb.CharAt(pos)))
					++pos;
			} else if (isspacechar(startChar)) {
				while (pos > 0 && isspacechar(cb.CharAt(pos)))
					--pos;
				if (!isspacechar(cb.CharAt(pos)))
					++pos;
			} else if (!isascii(startChar)) {
				while (pos > 0 && !isascii(cb.CharAt(pos)))
					--pos;
				if (isascii(cb.CharAt(pos)))
					++pos;
			} else {
				++pos;
			}
		}
	}
	return pos;
}

int Document::WordPartRight(int pos) {
	char startChar = cb.CharAt(pos);
	int length = Length();
	if (IsWordPartSeparator(startChar)) {
		while (pos < length && IsWordPartSeparator(cb.CharAt(pos)))
			++pos;
		startChar = cb.CharAt(pos);
	}
	if (!isascii(startChar)) {
		while (pos < length && !isascii(cb.CharAt(pos)))
			++pos;
	} else if (IsLowerCase(startChar)) {
		while (pos < length && IsLowerCase(cb.CharAt(pos)))
			++pos;
	} else if (IsUpperCase(startChar)) {
		if (IsLowerCase(cb.CharAt(pos + 1))) {
			++pos;
			while (pos < length && IsLowerCase(cb.CharAt(pos)))
				++pos;
		} else {
			while (pos < length && IsUpperCase(cb.CharAt(pos)))
				++pos;
		}
		if (IsLowerCase(cb.CharAt(pos)) && IsUpperCase(cb.CharAt(pos - 1)))
			--pos;
	} else if (IsADigit(startChar)) {
		while (pos < length && IsADigit(cb.CharAt(pos)))
			++pos;
	} else if (IsPunctuation(startChar)) {
		while (pos < length && IsPunctuation(cb.CharAt(pos)))
			++pos;
	} else if (isspacechar(startChar)) {
		while (pos < length && isspacechar(cb.CharAt(pos)))
			++pos;
	} else {
		++pos;
	}
	return pos;
}

bool IsLineEndChar(char c) {
	return (c == '\n' || c == '\r');
}

int Document::ExtendStyleRange(int pos, int delta, bool singleLine) {
	int sStart = cb.StyleAt(pos);
	if (delta < 0) {
		while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
			pos--;
		pos++;
	} else {
		while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
			pos++;
	}
	return pos;
}

static char BraceOpposite(char ch) {
	switch (ch) {
	case '(':
		return ')';
	case ')':
		return '(';
	case '[':
		return ']';
	case ']':
		return '[';
	case '{':
		return '}';
	case '}':
		return '{';
	case '<':
		return '>';
	case '>':
		return '<';
	default:
		return '\0';
	}
}

// TODO: should be able to extend styled region to find matching brace
int Document::BraceMatch(int position, int /*maxReStyle*/) {
	char chBrace = CharAt(position);
	char chSeek = BraceOpposite(chBrace);
	if (chSeek == '\0')
		return - 1;
	char styBrace = static_cast<char>(StyleAt(position) & stylingBitsMask);
	int direction = -1;
	if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
		direction = 1;
	int depth = 1;
	position = NextPosition(position, direction);
	while ((position >= 0) && (position < Length())) {
		char chAtPos = CharAt(position);
		char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask);
		if ((position > GetEndStyled()) || (styAtPos == styBrace)) {
			if (chAtPos == chBrace)
				depth++;
			if (chAtPos == chSeek)
				depth--;
			if (depth == 0)
				return position;
		}
		int positionBeforeMove = position;
		position = NextPosition(position, direction);
		if (position == positionBeforeMove)
			break;
	}
	return - 1;
}

/**
 * Implementation of RegexSearchBase for the default built-in regular expression engine
 */
class BuiltinRegex : public RegexSearchBase {
public:
	BuiltinRegex(CharClassify *charClassTable) : search(charClassTable), substituted(NULL) {}

	virtual ~BuiltinRegex() {
		delete substituted;
	}

	virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
                        bool caseSensitive, bool word, bool wordStart, int flags,
                        int *length);

	virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length);

private:
	RESearch search;
	char *substituted;
};

// Define a way for the Regular Expression code to access the document
class DocumentIndexer : public CharacterIndexer {
	Document *pdoc;
	int end;
public:
	DocumentIndexer(Document *pdoc_, int end_) :
		pdoc(pdoc_), end(end_) {
	}

	virtual ~DocumentIndexer() {
	}

	virtual char CharAt(int index) {
		if (index < 0 || index >= end)
			return 0;
		else
			return pdoc->CharAt(index);
	}
};

long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s,
                        bool caseSensitive, bool, bool, int flags,
                        int *length) {
	bool posix = (flags & SCFIND_POSIX) != 0;
	int increment = (minPos <= maxPos) ? 1 : -1;

	int startPos = minPos;
	int endPos = maxPos;

	// Range endpoints should not be inside DBCS characters, but just in case, move them.
	startPos = doc->MovePositionOutsideChar(startPos, 1, false);
	endPos = doc->MovePositionOutsideChar(endPos, 1, false);

	const char *errmsg = search.Compile(s, *length, caseSensitive, posix);
	if (errmsg) {
		return -1;
	}
	// Find a variable in a property file: \$(\([A-Za-z0-9_.]+\))
	// Replace first '.' with '-' in each property file variable reference:
	//     Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
	//     Replace: $(\1-\2)
	int lineRangeStart = doc->LineFromPosition(startPos);
	int lineRangeEnd = doc->LineFromPosition(endPos);
	if ((increment == 1) &&
		(startPos >= doc->LineEnd(lineRangeStart)) &&
		(lineRangeStart < lineRangeEnd)) {
		// the start position is at end of line or between line end characters.
		lineRangeStart++;
		startPos = doc->LineStart(lineRangeStart);
	} else if ((increment == -1) &&
	           (startPos <= doc->LineStart(lineRangeStart)) &&
	           (lineRangeStart > lineRangeEnd)) {
		// the start position is at beginning of line.
		lineRangeStart--;
		startPos = doc->LineEnd(lineRangeStart);
	}
	int pos = -1;
	int lenRet = 0;
	char searchEnd = s[*length - 1];
	char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0';
	int lineRangeBreak = lineRangeEnd + increment;
	for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
		int startOfLine = doc->LineStart(line);
		int endOfLine = doc->LineEnd(line);
		if (increment == 1) {
			if (line == lineRangeStart) {
				if ((startPos != startOfLine) && (s[0] == '^'))
					continue;	// Can't match start of line if start position after start of line
				startOfLine = startPos;
			}
			if (line == lineRangeEnd) {
				if ((endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
					continue;	// Can't match end of line if end position before end of line
				endOfLine = endPos;
			}
		} else {
			if (line == lineRangeEnd) {
				if ((endPos != startOfLine) && (s[0] == '^'))
					continue;	// Can't match start of line if end position after start of line
				startOfLine = endPos;
			}
			if (line == lineRangeStart) {
				if ((startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
					continue;	// Can't match end of line if start position before end of line
				endOfLine = startPos;
			}
		}

		DocumentIndexer di(doc, endOfLine);
		int success = search.Execute(di, startOfLine, endOfLine);
		if (success) {
			pos = search.bopat[0];
			lenRet = search.eopat[0] - search.bopat[0];
			// There can be only one start of a line, so no need to look for last match in line
			if ((increment == -1) && (s[0] != '^')) {
				// Check for the last match on this line.
				int repetitions = 1000;	// Break out of infinite loop
				while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
					success = search.Execute(di, pos+1, endOfLine);
					if (success) {
						if (search.eopat[0] <= minPos) {
							pos = search.bopat[0];
							lenRet = search.eopat[0] - search.bopat[0];
						} else {
							success = 0;
						}
					}
				}
			}
			break;
		}
	}
	*length = lenRet;
	return pos;
}

const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) {
	delete []substituted;
	substituted = 0;
	DocumentIndexer di(doc, doc->Length());
	if (!search.GrabMatches(di))
		return 0;
	unsigned int lenResult = 0;
	for (int i = 0; i < *length; i++) {
		if (text[i] == '\\') {
			if (text[i + 1] >= '0' && text[i + 1] <= '9') {
				unsigned int patNum = text[i + 1] - '0';
				lenResult += search.eopat[patNum] - search.bopat[patNum];
				i++;
			} else {
				switch (text[i + 1]) {
				case 'a':
				case 'b':
				case 'f':
				case 'n':
				case 'r':
				case 't':
				case 'v':
				case '\\':
					i++;
				}
				lenResult++;
			}
		} else {
			lenResult++;
		}
	}
	substituted = new char[lenResult + 1];
	char *o = substituted;
	for (int j = 0; j < *length; j++) {
		if (text[j] == '\\') {
			if (text[j + 1] >= '0' && text[j + 1] <= '9') {
				unsigned int patNum = text[j + 1] - '0';
				unsigned int len = search.eopat[patNum] - search.bopat[patNum];
				if (search.pat[patNum])	// Will be null if try for a match that did not occur
					memcpy(o, search.pat[patNum], len);
				o += len;
				j++;
			} else {
				j++;
				switch (text[j]) {
				case 'a':
					*o++ = '\a';
					break;
				case 'b':
					*o++ = '\b';
					break;
				case 'f':
					*o++ = '\f';
					break;
				case 'n':
					*o++ = '\n';
					break;
				case 'r':
					*o++ = '\r';
					break;
				case 't':
					*o++ = '\t';
					break;
				case 'v':
					*o++ = '\v';
					break;
				case '\\':
					*o++ = '\\';
					break;
				default:
					*o++ = '\\';
					j--;
				}
			}
		} else {
			*o++ = text[j];
		}
	}
	*o = '\0';
	*length = lenResult;
	return substituted;
}

#ifndef SCI_OWNREGEX

#ifdef SCI_NAMESPACE

RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) {
	return new BuiltinRegex(charClassTable);
}

#else

RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) {
	return new BuiltinRegex(charClassTable);
}

#endif

#endif

Added src/Document.h.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
// Scintilla source code edit control
/** @file Document.h
 ** Text document that handles notifications, DBCS, styling, words and end of line.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef DOCUMENT_H
#define DOCUMENT_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 * A Position is a position within a document between two characters or at the beginning or end.
 * Sometimes used as a character index where it identifies the character after the position.
 */
typedef int Position;
const Position invalidPosition = -1;

/**
 * The range class represents a range of text in a document.
 * The two values are not sorted as one end may be more significant than the other
 * as is the case for the selection where the end position is the position of the caret.
 * If either position is invalidPosition then the range is invalid and most operations will fail.
 */
class Range {
public:
	Position start;
	Position end;

	Range(Position pos=0) :
		start(pos), end(pos) {
	}
	Range(Position start_, Position end_) :
		start(start_), end(end_) {
	}

	bool Valid() const {
		return (start != invalidPosition) && (end != invalidPosition);
	}

	// Is the position within the range?
	bool Contains(Position pos) const {
		if (start < end) {
			return (pos >= start && pos <= end);
		} else {
			return (pos <= start && pos >= end);
		}
	}

	// Is the character after pos within the range?
	bool ContainsCharacter(Position pos) const {
		if (start < end) {
			return (pos >= start && pos < end);
		} else {
			return (pos < start && pos >= end);
		}
	}

	bool Contains(Range other) const {
		return Contains(other.start) && Contains(other.end);
	}

	bool Overlaps(Range other) const {
		return
		Contains(other.start) ||
		Contains(other.end) ||
		other.Contains(start) ||
		other.Contains(end);
	}
};

class DocWatcher;
class DocModification;
class Document;

/**
 * Interface class for regular expression searching
 */
class RegexSearchBase {
public:
	virtual ~RegexSearchBase() {}

	virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
                        bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0;

	///@return String with the substitutions, must remain valid until the next call or destruction
	virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0;
};

/// Factory function for RegexSearchBase
extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);

struct StyledText {
	size_t length;
	const char *text;
	bool multipleStyles;
	size_t style;
	const unsigned char *styles;
	StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) :
		length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
	}
	// Return number of bytes from start to before '\n' or end of text.
	// Return 1 when start is outside text
	size_t LineLength(size_t start) const {
		size_t cur = start;
		while ((cur < length) && (text[cur] != '\n'))
			cur++;
		return cur-start;
	}
	size_t StyleAt(size_t i) const {
		return multipleStyles ? styles[i] : style;
	}
};

class HighlightDelimiter {
public:
	HighlightDelimiter() : isEnabled(false) {
		Clear();
	}

	void Clear() {
		beginFoldBlock = -1;
		endFoldBlock = -1;
		firstChangeableLineBefore = -1;
		firstChangeableLineAfter = -1;
	}

	bool NeedsDrawing(int line) {
		return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
	}

	bool IsFoldBlockHighlighted(int line) {
		return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
	}

	bool IsHeadOfFoldBlock(int line) {
		return beginFoldBlock == line && line < endFoldBlock;
	}

	bool IsBodyOfFoldBlock(int line) {
		return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
	}

	bool IsTailOfFoldBlock(int line) {
		return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
	}

	int beginFoldBlock;	// Begin of current fold block
	int endFoldBlock;	// End of current fold block
	int firstChangeableLineBefore;	// First line that triggers repaint before starting line that determined current fold block
	int firstChangeableLineAfter;	// First line that triggers repaint after starting line that determined current fold block
	bool isEnabled;
};

class CaseFolder {
public:
	virtual ~CaseFolder() {
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0;
};

class CaseFolderTable : public CaseFolder {
protected:
	char mapping[256];
public:
	CaseFolderTable();
	virtual ~CaseFolderTable();
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed);
	void SetTranslation(char ch, char chTranslation);
	void StandardASCII();
};

class Document;

class LexInterface {
protected:
	Document *pdoc;
	ILexer *instance;
	bool performingStyle;	///< Prevent reentrance
public:
	LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) {
	}
	virtual ~LexInterface() {
	}
	void Colourise(int start, int end);
	int LineEndTypesSupported();
	bool UseContainerLexing() const {
		return instance == 0;
	}
};

/**
 */
class Document : PerLine, public IDocumentWithLineEnd, public ILoader {

public:
	/** Used to pair watcher pointer with user data. */
	class WatcherWithUserData {
	public:
		DocWatcher *watcher;
		void *userData;
		WatcherWithUserData() {
			watcher = 0;
			userData = 0;
		}
	};

	enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation };
private:
	int refCount;
	CellBuffer cb;
	CharClassify charClass;
	CaseFolder *pcf;
	char stylingMask;
	int endStyled;
	int styleClock;
	int enteredModification;
	int enteredStyling;
	int enteredReadOnlyCount;

	WatcherWithUserData *watchers;
	int lenWatchers;

	// ldSize is not real data - it is for dimensions and loops
	enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
	PerLine *perLineData[ldSize];

	bool matchesValid;
	RegexSearchBase *regex;

public:

	LexInterface *pli;

	int stylingBits;
	int stylingBitsMask;

	int eolMode;
	/// Can also be SC_CP_UTF8 to enable UTF-8 mode
	int dbcsCodePage;
	int lineEndBitSet;
	int tabInChars;
	int indentInChars;
	int actualIndentInChars;
	bool useTabs;
	bool tabIndents;
	bool backspaceUnindents;

	DecorationList decorations;

	Document();
	virtual ~Document();

	int AddRef();
	int SCI_METHOD Release();

	virtual void Init();
	int LineEndTypesSupported() const;
	bool SetDBCSCodePage(int dbcsCodePage_);
	int GetLineEndTypesAllowed() { return cb.GetLineEndTypes(); }
	bool SetLineEndTypesAllowed(int lineEndBitSet_);
	int GetLineEndTypesActive() { return cb.GetLineEndTypes(); }
	virtual void InsertLine(int line);
	virtual void RemoveLine(int line);

	int SCI_METHOD Version() const {
		return dvLineEnd;
	}

	void SCI_METHOD SetErrorStatus(int status);

	int SCI_METHOD LineFromPosition(int pos) const;
	int ClampPositionIntoDocument(int pos);
	bool IsCrLf(int pos);
	int LenChar(int pos);
	bool InGoodUTF8(int pos, int &start, int &end) const;
	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
	int NextPosition(int pos, int moveDir) const;
	bool NextCharacter(int &pos, int moveDir);	// Returns true if pos changed
	int SCI_METHOD CodePage() const;
	bool SCI_METHOD IsDBCSLeadByte(char ch) const;
	int SafeSegment(const char *text, int length, int lengthSegment);

	// Gateways to modifying document
	void ModifiedAt(int pos);
	void CheckReadOnly();
	bool DeleteChars(int pos, int len);
	bool InsertString(int position, const char *s, int insertLength);
	int SCI_METHOD AddData(char *data, int length);
	void * SCI_METHOD ConvertToDocument();
	int Undo();
	int Redo();
	bool CanUndo() { return cb.CanUndo(); }
	bool CanRedo() { return cb.CanRedo(); }
	void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
	bool SetUndoCollection(bool collectUndo) {
		return cb.SetUndoCollection(collectUndo);
	}
	bool IsCollectingUndo() { return cb.IsCollectingUndo(); }
	void BeginUndoAction() { cb.BeginUndoAction(); }
	void EndUndoAction() { cb.EndUndoAction(); }
	void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
	void SetSavePoint();
	bool IsSavePoint() { return cb.IsSavePoint(); }
	const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); }
	const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); }
	int GapPosition() const { return cb.GapPosition(); }

	int SCI_METHOD GetLineIndentation(int line);
	void SetLineIndentation(int line, int indent);
	int GetLineIndentPosition(int line) const;
	int GetColumn(int position);
	int CountCharacters(int startPos, int endPos);
	int FindColumn(int line, int column);
	void Indent(bool forwards, int lineBottom, int lineTop);
	static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted);
	void ConvertLineEnds(int eolModeSet);
	void SetReadOnly(bool set) { cb.SetReadOnly(set); }
	bool IsReadOnly() { return cb.IsReadOnly(); }

	bool InsertChar(int pos, char ch);
	bool InsertCString(int position, const char *s);
	void ChangeChar(int pos, char ch);
	void DelChar(int pos);
	void DelCharBack(int pos);

	char CharAt(int position) { return cb.CharAt(position); }
	void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const {
		cb.GetCharRange(buffer, position, lengthRetrieve);
	}
	char SCI_METHOD StyleAt(int position) const { return cb.StyleAt(position); }
	void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const {
		cb.GetStyleRange(buffer, position, lengthRetrieve);
	}
	int GetMark(int line);
	int MarkerNext(int lineStart, int mask) const;
	int AddMark(int line, int markerNum);
	void AddMarkSet(int line, int valueSet);
	void DeleteMark(int line, int markerNum);
	void DeleteMarkFromHandle(int markerHandle);
	void DeleteAllMarks(int markerNum);
	int LineFromHandle(int markerHandle);
	int SCI_METHOD LineStart(int line) const;
	int SCI_METHOD LineEnd(int line) const;
	int LineEndPosition(int position) const;
	bool IsLineEndPosition(int position) const;
	bool IsPositionInLineEnd(int position) const;
	int VCHomePosition(int position) const;

	int SCI_METHOD SetLevel(int line, int level);
	int SCI_METHOD GetLevel(int line) const;
	void ClearLevels();
	int GetLastChild(int lineParent, int level=-1, int lastLine=-1);
	int GetFoldParent(int line);
	void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int lastLine);

	void Indent(bool forwards);
	int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
	int NextWordStart(int pos, int delta);
	int NextWordEnd(int pos, int delta);
	int SCI_METHOD Length() const { return cb.Length(); }
	void Allocate(int newSize) { cb.Allocate(newSize); }
	bool MatchesWordOptions(bool word, bool wordStart, int pos, int length);
	bool HasCaseFolder(void) const;
	void SetCaseFolder(CaseFolder *pcf_);
	long FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word,
		bool wordStart, bool regExp, int flags, int *length);
	const char *SubstituteByPosition(const char *text, int *length);
	int LinesTotal() const;

	void ChangeCase(Range r, bool makeUpperCase);

	void SetDefaultCharClasses(bool includeWordClass);
	void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
	int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer);
	void SetStylingBits(int bits);
	void SCI_METHOD StartStyling(int position, char mask);
	bool SCI_METHOD SetStyleFor(int length, char style);
	bool SCI_METHOD SetStyles(int length, const char *styles);
	int GetEndStyled() { return endStyled; }
	void EnsureStyledTo(int pos);
	void LexerChanged();
	int GetStyleClock() { return styleClock; }
	void IncrementStyleClock();
	void SCI_METHOD DecorationSetCurrentIndicator(int indicator) {
		decorations.SetCurrentIndicator(indicator);
	}
	void SCI_METHOD DecorationFillRange(int position, int value, int fillLength);

	int SCI_METHOD SetLineState(int line, int state);
	int SCI_METHOD GetLineState(int line) const;
	int GetMaxLineState();
	void SCI_METHOD ChangeLexerState(int start, int end);

	StyledText MarginStyledText(int line);
	void MarginSetStyle(int line, int style);
	void MarginSetStyles(int line, const unsigned char *styles);
	void MarginSetText(int line, const char *text);
	int MarginLength(int line) const;
	void MarginClearAll();

	bool AnnotationAny() const;
	StyledText AnnotationStyledText(int line);
	void AnnotationSetText(int line, const char *text);
	void AnnotationSetStyle(int line, int style);
	void AnnotationSetStyles(int line, const unsigned char *styles);
	int AnnotationLength(int line) const;
	int AnnotationLines(int line) const;
	void AnnotationClearAll();

	bool AddWatcher(DocWatcher *watcher, void *userData);
	bool RemoveWatcher(DocWatcher *watcher, void *userData);
	const WatcherWithUserData *GetWatchers() const { return watchers; }
	int GetLenWatchers() const { return lenWatchers; }

	CharClassify::cc WordCharClass(unsigned char ch);
	bool IsWordPartSeparator(char ch);
	int WordPartLeft(int pos);
	int WordPartRight(int pos);
	int ExtendStyleRange(int pos, int delta, bool singleLine = false);
	bool IsWhiteLine(int line) const;
	int ParaUp(int pos);
	int ParaDown(int pos);
	int IndentSize() { return actualIndentInChars; }
	int BraceMatch(int position, int maxReStyle);

private:
	bool IsWordStartAt(int pos);
	bool IsWordEndAt(int pos);
	bool IsWordAt(int start, int end);

	void NotifyModifyAttempt();
	void NotifySavePoint(bool atSavePoint);
	void NotifyModified(DocModification mh);
};

class UndoGroup {
	Document *pdoc;
	bool groupNeeded;
public:
	UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
		pdoc(pdoc_), groupNeeded(groupNeeded_) {
		if (groupNeeded) {
			pdoc->BeginUndoAction();
		}
	}
	~UndoGroup() {
		if (groupNeeded) {
			pdoc->EndUndoAction();
		}
	}
	bool Needed() const {
		return groupNeeded;
	}
};


/**
 * To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
 * scope of the change.
 * If the DocWatcher is a document view then this can be used to optimise screen updating.
 */
class DocModification {
public:
  	int modificationType;
	int position;
 	int length;
 	int linesAdded;	/**< Negative if lines deleted. */
 	const char *text;	/**< Only valid for changes to text, not for changes to style. */
 	int line;
	int foldLevelNow;
	int foldLevelPrev;
	int annotationLinesAdded;
	int token;

	DocModification(int modificationType_, int position_=0, int length_=0,
		int linesAdded_=0, const char *text_=0, int line_=0) :
		modificationType(modificationType_),
		position(position_),
		length(length_),
		linesAdded(linesAdded_),
		text(text_),
		line(line_),
		foldLevelNow(0),
		foldLevelPrev(0),
		annotationLinesAdded(0),
		token(0) {}

	DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
		modificationType(modificationType_),
		position(act.position),
		length(act.lenData),
		linesAdded(linesAdded_),
		text(act.data),
		line(0),
		foldLevelNow(0),
		foldLevelPrev(0),
		annotationLinesAdded(0),
		token(0) {}
};

/**
 * A class that wants to receive notifications from a Document must be derived from DocWatcher
 * and implement the notification methods. It can then be added to the watcher list with AddWatcher.
 */
class DocWatcher {
public:
	virtual ~DocWatcher() {}

	virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
	virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
	virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
	virtual void NotifyDeleted(Document *doc, void *userData) = 0;
	virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0;
	virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
	virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Editor.cxx.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
// Scintilla source code edit control
/** @file Editor.cxx
 ** Main code for the edit control.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <assert.h>

#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <memory>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
	return whether this modification represents an operation that
	may reasonably be deferred (not done now OR [possibly] at all)
*/
static bool CanDeferToLastStep(const DocModification &mh) {
	if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
		return true;	// CAN skip
	if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
		return false;	// MUST do
	if (mh.modificationType & SC_MULTISTEPUNDOREDO)
		return true;	// CAN skip
	return false;		// PRESUMABLY must do
}

static bool CanEliminate(const DocModification &mh) {
	return
	    (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
}

/*
	return whether this modification represents the FINAL step
	in a [possibly lengthy] multi-step Undo/Redo sequence
*/
static bool IsLastStep(const DocModification &mh) {
	return
	    (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
	    && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
	    && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
	    && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
}

Caret::Caret() :
		active(false), on(false), period(500) {}

Timer::Timer() :
		ticking(false), ticksToWait(0), tickerID(0) {}

Idler::Idler() :
		state(false), idlerID(0) {}

static inline bool IsControlCharacter(int ch) {
	// iscntrl returns true for lots of chars > 127 which are displayable
	return ch >= 0 && ch < ' ';
}

static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {
	for (unsigned int i = 0; i < len; i++) {
		// This is safe because IsSpaceOrTab() will return false for null terminators
		if (!IsSpaceOrTab(s[i]))
			return false;
	}
	return true;
}

Editor::Editor() {
	ctrlID = 0;

	stylesValid = false;
	technology = SC_TECHNOLOGY_DEFAULT;
	scaleRGBAImage = 100;
	
	printMagnification = 0;
	printColourMode = SC_PRINT_NORMAL;
	printWrapState = eWrapWord;
	cursorMode = SC_CURSORNORMAL;
	controlCharSymbol = 0;	/* Draw the control characters */

	hasFocus = false;
	hideSelection = false;
	inOverstrike = false;
	errorStatus = 0;
	mouseDownCaptures = true;

	bufferedDraw = true;
	twoPhaseDraw = true;

	lastClickTime = 0;
	dwellDelay = SC_TIME_FOREVER;
	ticksToDwell = SC_TIME_FOREVER;
	dwelling = false;
	ptMouseLast.x = 0;
	ptMouseLast.y = 0;
	inDragDrop = ddNone;
	dropWentOutside = false;
	posDrag = SelectionPosition(invalidPosition);
	posDrop = SelectionPosition(invalidPosition);
	hotSpotClickPos = INVALID_POSITION;
	selectionType = selChar;

	lastXChosen = 0;
	lineAnchorPos = 0;
	originalAnchorPos = 0;
	wordSelectAnchorStartPos = 0;
	wordSelectAnchorEndPos = 0;
	wordSelectInitialCaretPos = -1;

	primarySelection = true;

	caretXPolicy = CARET_SLOP | CARET_EVEN;
	caretXSlop = 50;

	caretYPolicy = CARET_EVEN;
	caretYSlop = 0;
	
	visiblePolicy = 0;
	visibleSlop = 0;

	searchAnchor = 0;

	xOffset = 0;
	xCaretMargin = 50;
	horizontalScrollBarVisible = true;
	scrollWidth = 2000;
	trackLineWidth = false;
	lineWidthMaxSeen = 0;
	verticalScrollBarVisible = true;
	endAtLastLine = true;
	caretSticky = SC_CARETSTICKY_OFF;
	marginOptions = SC_MARGINOPTION_NONE;
	multipleSelection = false;
	additionalSelectionTyping = false;
	multiPasteMode = SC_MULTIPASTE_ONCE;
	additionalCaretsBlink = true;
	additionalCaretsVisible = true;
	virtualSpaceOptions = SCVS_NONE;

	pixmapLine = 0;
	pixmapSelMargin = 0;
	pixmapSelPattern = 0;
	pixmapSelPatternOffset1 = 0;
	pixmapIndentGuide = 0;
	pixmapIndentGuideHighlight = 0;

	targetStart = 0;
	targetEnd = 0;
	searchFlags = 0;

	topLine = 0;
	posTopLine = 0;

	lengthForEncode = -1;

	needUpdateUI = 0;
	ContainerNeedsUpdate(SC_UPDATE_CONTENT);
	braces[0] = invalidPosition;
	braces[1] = invalidPosition;
	bracesMatchStyle = STYLE_BRACEBAD;
	highlightGuideColumn = 0;

	theEdge = 0;

	paintState = notPainting;
	willRedrawAll = false;

	modEventMask = SC_MODEVENTMASKALL;

	pdoc = new Document();
	pdoc->AddRef();
	pdoc->AddWatcher(this, 0);

	recordingMacro = false;
	foldFlags = 0;

	wrapState = eWrapNone;
	wrapWidth = LineLayout::wrapWidthInfinite;
	wrapStart = wrapLineLarge;
	wrapEnd = wrapLineLarge;
	wrapVisualFlags = 0;
	wrapVisualFlagsLocation = 0;
	wrapVisualStartIndent = 0;
	wrapIndentMode = SC_WRAPINDENT_FIXED;

	convertPastes = true;

	marginNumberPadding = 3;
	ctrlCharPadding = 3; // +3 For a blank on front and rounded edge each side
	lastSegItalicsOffset = 2;

	hsStart = -1;
	hsEnd = -1;

	llc.SetLevel(LineLayoutCache::llcCaret);
	posCache.SetSize(0x400);
}

Editor::~Editor() {
	pdoc->RemoveWatcher(this, 0);
	pdoc->Release();
	pdoc = 0;
	DropGraphics(true);
}

void Editor::Finalise() {
	SetIdle(false);
	CancelModes();
}

void Editor::DropGraphics(bool freeObjects) {
	if (freeObjects) {
		delete pixmapLine;
		pixmapLine = 0;
		delete pixmapSelMargin;
		pixmapSelMargin = 0;
		delete pixmapSelPattern;
		pixmapSelPattern = 0;
		delete pixmapSelPatternOffset1;
		pixmapSelPatternOffset1 = 0;
		delete pixmapIndentGuide;
		pixmapIndentGuide = 0;
		delete pixmapIndentGuideHighlight;
		pixmapIndentGuideHighlight = 0;
	} else {
		if (pixmapLine)
			pixmapLine->Release();
		if (pixmapSelMargin)
			pixmapSelMargin->Release();
		if (pixmapSelPattern)
			pixmapSelPattern->Release();
		if (pixmapSelPatternOffset1)
			pixmapSelPatternOffset1->Release();
		if (pixmapIndentGuide)
			pixmapIndentGuide->Release();
		if (pixmapIndentGuideHighlight)
			pixmapIndentGuideHighlight->Release();
	}
}

void Editor::AllocateGraphics() {
	if (!pixmapLine)
		pixmapLine = Surface::Allocate(technology);
	if (!pixmapSelMargin)
		pixmapSelMargin = Surface::Allocate(technology);
	if (!pixmapSelPattern)
		pixmapSelPattern = Surface::Allocate(technology);
	if (!pixmapSelPatternOffset1)
		pixmapSelPatternOffset1 = Surface::Allocate(technology);
	if (!pixmapIndentGuide)
		pixmapIndentGuide = Surface::Allocate(technology);
	if (!pixmapIndentGuideHighlight)
		pixmapIndentGuideHighlight = Surface::Allocate(technology);
}

void Editor::InvalidateStyleData() {
	stylesValid = false;
	vs.technology = technology;
	DropGraphics(false);
	AllocateGraphics();
	llc.Invalidate(LineLayout::llInvalid);
	posCache.Clear();
}

void Editor::InvalidateStyleRedraw() {
	NeedWrapping();
	InvalidateStyleData();
	Redraw();
}

void Editor::RefreshStyleData() {
	if (!stylesValid) {
		stylesValid = true;
		AutoSurface surface(this);
		if (surface) {
			vs.Refresh(*surface);
		}
		SetScrollBars();
		SetRectangularRange();
	}
}

Point Editor::GetVisibleOriginInMain() {
	return Point(0,0);
}

Point Editor::DocumentPointFromView(Point ptView) {
	Point ptDocument = ptView;
	if (wMargin.GetID()) {
		Point ptOrigin = GetVisibleOriginInMain();
		ptDocument.x += ptOrigin.x;
		ptDocument.y += ptOrigin.y;
	} else {
		ptDocument.x += xOffset;
		ptDocument.y += topLine * vs.lineHeight;
	}
	return ptDocument;
}

int Editor::TopLineOfMain() {
	if (wMargin.GetID())
		return 0;
	else
		return topLine;
}

PRectangle Editor::GetClientRectangle() {
	return wMain.GetClientPosition();
}

PRectangle Editor::GetTextRectangle() {
	PRectangle rc = GetClientRectangle();
	rc.left += vs.textStart;
	rc.right -= vs.rightMarginWidth;
	return rc;
}

int Editor::LinesOnScreen() {
	PRectangle rcClient = GetClientRectangle();
	int htClient = rcClient.bottom - rcClient.top;
	//Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
	return htClient / vs.lineHeight;
}

int Editor::LinesToScroll() {
	int retVal = LinesOnScreen() - 1;
	if (retVal < 1)
		return 1;
	else
		return retVal;
}

int Editor::MaxScrollPos() {
	//Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
	//LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
	int retVal = cs.LinesDisplayed();
	if (endAtLastLine) {
		retVal -= LinesOnScreen();
	} else {
		retVal--;
	}
	if (retVal < 0) {
		return 0;
	} else {
		return retVal;
	}
}

const char *ControlCharacterString(unsigned char ch) {
	const char *reps[] = {
		"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
		"BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
		"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
		"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
	};
	if (ch < (sizeof(reps) / sizeof(reps[0]))) {
		return reps[ch];
	} else {
		return "BAD";
	}
}

/**
 * Convenience class to ensure LineLayout objects are always disposed.
 */
class AutoLineLayout {
	LineLayoutCache &llc;
	LineLayout *ll;
	AutoLineLayout &operator=(const AutoLineLayout &);
public:
	AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
	~AutoLineLayout() {
		llc.Dispose(ll);
		ll = 0;
	}
	LineLayout *operator->() const {
		return ll;
	}
	operator LineLayout *() const {
		return ll;
	}
	void Set(LineLayout *ll_) {
		llc.Dispose(ll);
		ll = ll_;
	}
};

SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
	if (sp.Position() < 0) {
		return SelectionPosition(0);
	} else if (sp.Position() > pdoc->Length()) {
		return SelectionPosition(pdoc->Length());
	} else {
		// If not at end of line then set offset to 0
		if (!pdoc->IsLineEndPosition(sp.Position()))
			sp.SetVirtualSpace(0);
		return sp;
	}
}

Point Editor::LocationFromPosition(SelectionPosition pos) {
	Point pt;
	RefreshStyleData();
	if (pos.Position() == INVALID_POSITION)
		return pt;
	int line = pdoc->LineFromPosition(pos.Position());
	int lineVisible = cs.DisplayFromDoc(line);
	//Platform::DebugPrintf("line=%d\n", line);
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(line));
	if (surface && ll) {
		// -1 because of adding in for visible lines in following loop.
		pt.y = (lineVisible - topLine - 1) * vs.lineHeight;
		pt.x = 0;
		unsigned int posLineStart = pdoc->LineStart(line);
		LayoutLine(line, surface, vs, ll, wrapWidth);
		int posInLine = pos.Position() - posLineStart;
		// In case of very long line put x at arbitrary large position
		if (posInLine > ll->maxLineLength) {
			pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];
		}

		for (int subLine = 0; subLine < ll->lines; subLine++) {
			if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
				pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)];
				if (ll->wrapIndent != 0) {
					int lineStart = ll->LineStart(subLine);
					if (lineStart != 0)	// Wrapped
						pt.x += ll->wrapIndent;
				}
			}
			if (posInLine >= ll->LineStart(subLine)) {
				pt.y += vs.lineHeight;
			}
		}
		pt.x += vs.textStart - xOffset;
	}
	pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
	return pt;
}

Point Editor::LocationFromPosition(int pos) {
	return LocationFromPosition(SelectionPosition(pos));
}

int Editor::XFromPosition(int pos) {
	Point pt = LocationFromPosition(pos);
	return pt.x - vs.textStart + xOffset;
}

int Editor::XFromPosition(SelectionPosition sp) {
	Point pt = LocationFromPosition(sp);
	return pt.x - vs.textStart + xOffset;
}

int Editor::LineFromLocation(Point pt) {
	return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
}

void Editor::SetTopLine(int topLineNew) {
	if ((topLine != topLineNew) && (topLineNew >= 0)) {
		topLine = topLineNew;
		ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
	}
	posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
}

SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) {
	RefreshStyleData();
	if (canReturnInvalid) {
		PRectangle rcClient = GetTextRectangle();
		if (!rcClient.Contains(pt))
			return SelectionPosition(INVALID_POSITION);
		if (pt.x < vs.textStart)
			return SelectionPosition(INVALID_POSITION);
		if (pt.y < 0)
			return SelectionPosition(INVALID_POSITION);
	}
	pt = DocumentPointFromView(pt);
	pt.x = pt.x - vs.textStart;
	int visibleLine = (int)floor((double)(pt.y / vs.lineHeight));
	if (!canReturnInvalid && (visibleLine < 0))
		visibleLine = 0;
	int lineDoc = cs.DocFromDisplay(visibleLine);
	if (canReturnInvalid && (lineDoc < 0))
		return SelectionPosition(INVALID_POSITION);
	if (lineDoc >= pdoc->LinesTotal())
		return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length());
	unsigned int posLineStart = pdoc->LineStart(lineDoc);
	SelectionPosition retVal(canReturnInvalid ? INVALID_POSITION : static_cast<int>(posLineStart));
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
	if (surface && ll) {
		LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
		int lineStartSet = cs.DisplayFromDoc(lineDoc);
		int subLine = visibleLine - lineStartSet;
		if (subLine < ll->lines) {
			int lineStart = ll->LineStart(subLine);
			int lineEnd = ll->LineLastVisible(subLine);
			XYPOSITION subLineStart = ll->positions[lineStart];

			if (ll->wrapIndent != 0) {
				if (lineStart != 0)	// Wrapped
					pt.x -= ll->wrapIndent;
			}
			int i = ll->FindBefore(pt.x + subLineStart, lineStart, lineEnd);
			while (i < lineEnd) {
				if (charPosition) {
					if ((pt.x + subLineStart) < (ll->positions[i + 1])) {
						return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
					}
				} else {
					if ((pt.x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
						return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
					}
				}
				i++;
			}
			if (virtualSpace) {
				const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
				int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) /
					spaceWidth;
				return SelectionPosition(lineEnd + posLineStart, spaceOffset);
			} else if (canReturnInvalid) {
				if (pt.x < (ll->positions[lineEnd] - subLineStart)) {
					return SelectionPosition(pdoc->MovePositionOutsideChar(lineEnd + posLineStart, 1));
				}
			} else {
				return SelectionPosition(lineEnd + posLineStart);
			}
		}
		if (!canReturnInvalid)
			return SelectionPosition(ll->numCharsInLine + posLineStart);
	}
	return retVal;
}

int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) {
	return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position();
}

/**
 * Find the document position corresponding to an x coordinate on a particular document line.
 * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
 */
SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) {
	RefreshStyleData();
	if (lineDoc >= pdoc->LinesTotal())
		return SelectionPosition(pdoc->Length());
	//Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
	int retVal = 0;
	if (surface && ll) {
		unsigned int posLineStart = pdoc->LineStart(lineDoc);
		LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
		int subLine = 0;
		int lineStart = ll->LineStart(subLine);
		int lineEnd = ll->LineLastVisible(subLine);
		XYPOSITION subLineStart = ll->positions[lineStart];
		XYPOSITION newX = x;

		if (ll->wrapIndent != 0) {
			if (lineStart != 0)	// Wrapped
				newX -= ll->wrapIndent;
		}
		int i = ll->FindBefore(newX + subLineStart, lineStart, lineEnd);
		while (i < lineEnd) {
			if ((newX + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
				retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1);
				return SelectionPosition(retVal);
			}
			i++;
		}
		const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
		int spaceOffset = (newX + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth;
		return SelectionPosition(lineEnd + posLineStart, spaceOffset);
	}
	return SelectionPosition(retVal);
}

int Editor::PositionFromLineX(int lineDoc, int x) {
	return SPositionFromLineX(lineDoc, x).Position();
}

/**
 * If painting then abandon the painting because a wider redraw is needed.
 * @return true if calling code should stop drawing.
 */
bool Editor::AbandonPaint() {
	if ((paintState == painting) && !paintingAllText) {
		paintState = paintAbandoned;
	}
	return paintState == paintAbandoned;
}

void Editor::RedrawRect(PRectangle rc) {
	//Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);

	// Clip the redraw rectangle into the client area
	PRectangle rcClient = GetClientRectangle();
	if (rc.top < rcClient.top)
		rc.top = rcClient.top;
	if (rc.bottom > rcClient.bottom)
		rc.bottom = rcClient.bottom;
	if (rc.left < rcClient.left)
		rc.left = rcClient.left;
	if (rc.right > rcClient.right)
		rc.right = rcClient.right;

	if ((rc.bottom > rc.top) && (rc.right > rc.left)) {
		wMain.InvalidateRectangle(rc);
	}
}

void Editor::Redraw() {
	//Platform::DebugPrintf("Redraw all\n");
	PRectangle rcClient = GetClientRectangle();
	wMain.InvalidateRectangle(rcClient);
	if (wMargin.GetID())
		wMargin.InvalidateAll();
	//wMain.InvalidateAll();
}

void Editor::RedrawSelMargin(int line, bool allAfter) {
	if (!AbandonPaint()) {
		if (vs.maskInLine) {
			Redraw();
		} else {
			PRectangle rcSelMargin = GetClientRectangle();
			rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;
			if (line != -1) {
				int position = pdoc->LineStart(line);
				PRectangle rcLine = RectangleFromRange(position, position);

				// Inflate line rectangle if there are image markers with height larger than line height
				if (vs.largestMarkerHeight > vs.lineHeight) {
					int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2;
					rcLine.top -= delta;
					rcLine.bottom += delta;
					if (rcLine.top < rcSelMargin.top)
						rcLine.top = rcSelMargin.top;
					if (rcLine.bottom > rcSelMargin.bottom)
						rcLine.bottom = rcSelMargin.bottom;
				}

				rcSelMargin.top = rcLine.top;
				if (!allAfter)
					rcSelMargin.bottom = rcLine.bottom;
			}
			if (wMargin.GetID()) {
				Point ptOrigin = GetVisibleOriginInMain();
				rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y);
				wMargin.InvalidateRectangle(rcSelMargin);
			} else {
				wMain.InvalidateRectangle(rcSelMargin);
			}
		}
	}
}

PRectangle Editor::RectangleFromRange(int start, int end) {
	int minPos = start;
	if (minPos > end)
		minPos = end;
	int maxPos = start;
	if (maxPos < end)
		maxPos = end;
	int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
	int lineDocMax = pdoc->LineFromPosition(maxPos);
	int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1;
	PRectangle rcClient = GetTextRectangle();
	PRectangle rc;
	const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
	rc.left = vs.textStart - leftTextOverlap;
	rc.top = (minLine - TopLineOfMain()) * vs.lineHeight;
	if (rc.top < rcClient.top)
		rc.top = rcClient.top;
	rc.right = rcClient.right;
	rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight;

	return rc;
}

void Editor::InvalidateRange(int start, int end) {
	RedrawRect(RectangleFromRange(start, end));
}

int Editor::CurrentPosition() {
	return sel.MainCaret();
}

bool Editor::SelectionEmpty() {
	return sel.Empty();
}

SelectionPosition Editor::SelectionStart() {
	return sel.RangeMain().Start();
}

SelectionPosition Editor::SelectionEnd() {
	return sel.RangeMain().End();
}

void Editor::SetRectangularRange() {
	if (sel.IsRectangular()) {
		int xAnchor = XFromPosition(sel.Rectangular().anchor);
		int xCaret = XFromPosition(sel.Rectangular().caret);
		if (sel.selType == Selection::selThin) {
			xCaret = xAnchor;
		}
		int lineAnchorRect = pdoc->LineFromPosition(sel.Rectangular().anchor.Position());
		int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position());
		int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
		for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) {
			SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor));
			if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
				range.ClearVirtualSpace();
			if (line == lineAnchorRect)
				sel.SetSelection(range);
			else
				sel.AddSelectionWithoutTrim(range);
		}
	}
}

void Editor::ThinRectangularRange() {
	if (sel.IsRectangular()) {
		sel.selType = Selection::selThin;
		if (sel.Rectangular().caret < sel.Rectangular().anchor) {
			sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor);
		} else {
			sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret);
		}
		SetRectangularRange();
	}
}

void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) {
	if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) {
		invalidateWholeSelection = true;
	}
	int firstAffected = Platform::Minimum(sel.RangeMain().Start().Position(), newMain.Start().Position());
	// +1 for lastAffected ensures caret repainted
	int lastAffected = Platform::Maximum(newMain.caret.Position()+1, newMain.anchor.Position());
	lastAffected = Platform::Maximum(lastAffected, sel.RangeMain().End().Position());
	if (invalidateWholeSelection) {
		for (size_t r=0; r<sel.Count(); r++) {
			firstAffected = Platform::Minimum(firstAffected, sel.Range(r).caret.Position());
			firstAffected = Platform::Minimum(firstAffected, sel.Range(r).anchor.Position());
			lastAffected = Platform::Maximum(lastAffected, sel.Range(r).caret.Position()+1);
			lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position());
		}
	}
	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
	InvalidateRange(firstAffected, lastAffected);
}

void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
	currentPos_ = ClampPositionIntoDocument(currentPos_);
	anchor_ = ClampPositionIntoDocument(anchor_);
	int currentLine = pdoc->LineFromPosition(currentPos_.Position());
	/* For Line selection - ensure the anchor and caret are always
	   at the beginning and end of the region lines. */
	if (sel.selType == Selection::selLines) {
		if (currentPos_ > anchor_) {
			anchor_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position())));
			currentPos_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position())));
		} else {
			currentPos_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position())));
			anchor_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position())));
		}
	}
	SelectionRange rangeNew(currentPos_, anchor_);
	if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
		InvalidateSelection(rangeNew);
	}
	sel.RangeMain() = rangeNew;
	SetRectangularRange();
	ClaimSelection();

	if (highlightDelimiter.NeedsDrawing(currentLine)) {
		RedrawSelMargin();
	}
	QueueIdleWork(WorkNeeded::workUpdateUI);
}

void Editor::SetSelection(int currentPos_, int anchor_) {
	SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_));
}

// Just move the caret on the main selection
void Editor::SetSelection(SelectionPosition currentPos_) {
	currentPos_ = ClampPositionIntoDocument(currentPos_);
	int currentLine = pdoc->LineFromPosition(currentPos_.Position());
	if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) {
		InvalidateSelection(SelectionRange(currentPos_));
	}
	if (sel.IsRectangular()) {
		sel.Rectangular() =
			SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
		SetRectangularRange();
	} else {
		sel.RangeMain() =
			SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
	}
	ClaimSelection();

	if (highlightDelimiter.NeedsDrawing(currentLine)) {
		RedrawSelMargin();
	}
	QueueIdleWork(WorkNeeded::workUpdateUI);
}

void Editor::SetSelection(int currentPos_) {
	SetSelection(SelectionPosition(currentPos_));
}

void Editor::SetEmptySelection(SelectionPosition currentPos_) {
	int currentLine = pdoc->LineFromPosition(currentPos_.Position());
	SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_));
	if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
		InvalidateSelection(rangeNew);
	}
	sel.Clear();
	sel.RangeMain() = rangeNew;
	SetRectangularRange();
	ClaimSelection();

	if (highlightDelimiter.NeedsDrawing(currentLine)) {
		RedrawSelMargin();
	}
	QueueIdleWork(WorkNeeded::workUpdateUI);
}

void Editor::SetEmptySelection(int currentPos_) {
	SetEmptySelection(SelectionPosition(currentPos_));
}

bool Editor::RangeContainsProtected(int start, int end) const {
	if (vs.ProtectionActive()) {
		if (start > end) {
			int t = start;
			start = end;
			end = t;
		}
		int mask = pdoc->stylingBitsMask;
		for (int pos = start; pos < end; pos++) {
			if (vs.styles[pdoc->StyleAt(pos) & mask].IsProtected())
				return true;
		}
	}
	return false;
}

bool Editor::SelectionContainsProtected() {
	for (size_t r=0; r<sel.Count(); r++) {
		if (RangeContainsProtected(sel.Range(r).Start().Position(),
			sel.Range(r).End().Position())) {
			return true;
		}
	}
	return false;
}

/**
 * Asks document to find a good position and then moves out of any invisible positions.
 */
int Editor::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const {
	return MovePositionOutsideChar(SelectionPosition(pos), moveDir, checkLineEnd).Position();
}

SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd) const {
	int posMoved = pdoc->MovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd);
	if (posMoved != pos.Position())
		pos.SetPosition(posMoved);
	if (vs.ProtectionActive()) {
		int mask = pdoc->stylingBitsMask;
		if (moveDir > 0) {
			if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()) {
				while ((pos.Position() < pdoc->Length()) &&
				        (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()))
					pos.Add(1);
			}
		} else if (moveDir < 0) {
			if (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()) {
				while ((pos.Position() > 0) &&
				        (vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()))
					pos.Add(-1);
			}
		}
	}
	return pos;
}

int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) {
	bool simpleCaret = (sel.Count() == 1) && sel.Empty();
	SelectionPosition spCaret = sel.Last();

	int delta = newPos.Position() - sel.MainCaret();
	newPos = ClampPositionIntoDocument(newPos);
	newPos = MovePositionOutsideChar(newPos, delta);
	if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) {
		// Can't turn into multiple selection so clear additional selections
		InvalidateSelection(SelectionRange(newPos), true);
		SelectionRange rangeMain = sel.RangeMain();
		sel.SetSelection(rangeMain);
	}
	if (!sel.IsRectangular() && (selt == Selection::selRectangle)) {
		// Switching to rectangular
		SelectionRange rangeMain = sel.RangeMain();
		sel.Clear();
		sel.Rectangular() = rangeMain;
	}
	if (selt != Selection::noSel) {
		sel.selType = selt;
	}
	if (selt != Selection::noSel || sel.MoveExtends()) {
		SetSelection(newPos);
	} else {
		SetEmptySelection(newPos);
	}
	ShowCaretAtCurrentPosition();

	int currentLine = pdoc->LineFromPosition(newPos.Position());
	if (ensureVisible) {
		// In case in need of wrapping to ensure DisplayFromDoc works.
		if (currentLine >= wrapStart)
			WrapLines(true, -1);
		XYScrollPosition newXY = XYScrollToMakeVisible(
			SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);
		if (simpleCaret && (newXY.xOffset == xOffset)) {
			// simple vertical scroll then invalidate
			ScrollTo(newXY.topLine);
			InvalidateSelection(SelectionRange(spCaret), true);
		} else {
			SetXYScroll(newXY);
		}
	}

	if (highlightDelimiter.NeedsDrawing(currentLine)) {
		RedrawSelMargin();
	}
	return 0;
}

int Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) {
	return MovePositionTo(SelectionPosition(newPos), selt, ensureVisible);
}

SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) {
	pos = ClampPositionIntoDocument(pos);
	pos = MovePositionOutsideChar(pos, moveDir);
	int lineDoc = pdoc->LineFromPosition(pos.Position());
	if (cs.GetVisible(lineDoc)) {
		return pos;
	} else {
		int lineDisplay = cs.DisplayFromDoc(lineDoc);
		if (moveDir > 0) {
			// lineDisplay is already line before fold as lines in fold use display line of line after fold
			lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
			return SelectionPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
		} else {
			lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed());
			return SelectionPosition(pdoc->LineEnd(cs.DocFromDisplay(lineDisplay)));
		}
	}
}

SelectionPosition Editor::MovePositionSoVisible(int pos, int moveDir) {
	return MovePositionSoVisible(SelectionPosition(pos), moveDir);
}

Point Editor::PointMainCaret() {
	return LocationFromPosition(sel.Range(sel.Main()).caret);
}

/**
 * Choose the x position that the caret will try to stick to
 * as it moves up and down.
 */
void Editor::SetLastXChosen() {
	Point pt = PointMainCaret();
	lastXChosen = pt.x + xOffset;
}

void Editor::ScrollTo(int line, bool moveThumb) {
	int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
	if (topLineNew != topLine) {
		// Try to optimise small scrolls
#ifndef UNDER_CE
		int linesToMove = topLine - topLineNew;
		bool performBlit = (abs(linesToMove) <= 10) && (paintState == notPainting);
		willRedrawAll = !performBlit;
#endif
		SetTopLine(topLineNew);
		// Optimize by styling the view as this will invalidate any needed area
		// which could abort the initial paint if discovered later.
		StyleToPositionInView(PositionAfterArea(GetClientRectangle()));
#ifndef UNDER_CE
		// Perform redraw rather than scroll if many lines would be redrawn anyway.
		if (performBlit) {
			ScrollText(linesToMove);
		} else {
			Redraw();
		}
		willRedrawAll = false;
#else
		Redraw();
#endif
		if (moveThumb) {
			SetVerticalScrollPos();
		}
	}
}

void Editor::ScrollText(int /* linesToMove */) {
	//Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
	Redraw();
}

void Editor::HorizontalScrollTo(int xPos) {
	//Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
	if (xPos < 0)
		xPos = 0;
	if ((wrapState == eWrapNone) && (xOffset != xPos)) {
		xOffset = xPos;
		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
		SetHorizontalScrollPos();
		RedrawRect(GetClientRectangle());
	}
}

void Editor::VerticalCentreCaret() {
	int lineDoc = pdoc->LineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret());
	int lineDisplay = cs.DisplayFromDoc(lineDoc);
	int newTop = lineDisplay - (LinesOnScreen() / 2);
	if (topLine != newTop) {
		SetTopLine(newTop > 0 ? newTop : 0);
		RedrawRect(GetClientRectangle());
	}
}

// Avoid 64 bit compiler warnings.
// Scintilla does not support text buffers larger than 2**31
static int istrlen(const char *s) {
	return static_cast<int>(strlen(s));
}

void Editor::MoveSelectedLines(int lineDelta) {

	// if selection doesn't start at the beginning of the line, set the new start
	int selectionStart = SelectionStart().Position();
	int startLine = pdoc->LineFromPosition(selectionStart);
	int beginningOfStartLine = pdoc->LineStart(startLine);
	selectionStart = beginningOfStartLine;

	// if selection doesn't end at the beginning of a line greater than that of the start,
	// then set it at the beginning of the next one
	int selectionEnd = SelectionEnd().Position();
	int endLine = pdoc->LineFromPosition(selectionEnd);
	int beginningOfEndLine = pdoc->LineStart(endLine);
	bool appendEol = false;
	if (selectionEnd > beginningOfEndLine
		|| selectionStart == selectionEnd) {
		selectionEnd = pdoc->LineStart(endLine + 1);
		appendEol = (selectionEnd == pdoc->Length() && pdoc->LineFromPosition(selectionEnd) == endLine);
	}

	// if there's nowhere for the selection to move
	// (i.e. at the beginning going up or at the end going down),
	// stop it right there!
	if ((selectionStart == 0 && lineDelta < 0)
		|| (selectionEnd == pdoc->Length() && lineDelta > 0)
	        || selectionStart == selectionEnd) {
		return;
	}

	UndoGroup ug(pdoc);

	if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) {
		SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd);
		ClearSelection();
		selectionEnd = CurrentPosition();
	}
	SetSelection(selectionStart, selectionEnd);

	SelectionText selectedText;
	CopySelectionRange(&selectedText);

	int selectionLength = SelectionRange(selectionStart, selectionEnd).Length();
	Point currentLocation = LocationFromPosition(CurrentPosition());
	int currentLine = LineFromLocation(currentLocation);

	if (appendEol)
		SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd);
	ClearSelection();

	const char *eol = StringFromEOLMode(pdoc->eolMode);
	if (currentLine + lineDelta >= pdoc->LinesTotal())
		pdoc->InsertCString(pdoc->Length(), eol);
	GoToLine(currentLine + lineDelta);

	pdoc->InsertCString(CurrentPosition(), selectedText.s);
	if (appendEol) {
		pdoc->InsertCString(CurrentPosition() + selectionLength, eol);
		selectionLength += istrlen(eol);
	}
	SetSelection(CurrentPosition(), CurrentPosition() + selectionLength);
}

void Editor::MoveSelectedLinesUp() {
	MoveSelectedLines(-1);
}

void Editor::MoveSelectedLinesDown() {
	MoveSelectedLines(1);
}

void Editor::MoveCaretInsideView(bool ensureVisible) {
	PRectangle rcClient = GetTextRectangle();
	Point pt = PointMainCaret();
	if (pt.y < rcClient.top) {
		MovePositionTo(SPositionFromLocation(
		            Point(lastXChosen - xOffset, rcClient.top),
					false, false, UserVirtualSpace()),
					Selection::noSel, ensureVisible);
	} else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
		int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight;
		MovePositionTo(SPositionFromLocation(
		            Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed),
					false, false, UserVirtualSpace()),
		        Selection::noSel, ensureVisible);
	}
}

int Editor::DisplayFromPosition(int pos) {
	int lineDoc = pdoc->LineFromPosition(pos);
	int lineDisplay = cs.DisplayFromDoc(lineDoc);
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
	if (surface && ll) {
		LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
		unsigned int posLineStart = pdoc->LineStart(lineDoc);
		int posInLine = pos - posLineStart;
		lineDisplay--; // To make up for first increment ahead.
		for (int subLine = 0; subLine < ll->lines; subLine++) {
			if (posInLine >= ll->LineStart(subLine)) {
				lineDisplay++;
			}
		}
	}
	return lineDisplay;
}

/**
 * Ensure the caret is reasonably visible in context.
 *
Caret policy in SciTE

If slop is set, we can define a slop value.
This value defines an unwanted zone (UZ) where the caret is... unwanted.
This zone is defined as a number of pixels near the vertical margins,
and as a number of lines near the horizontal margins.
By keeping the caret away from the edges, it is seen within its context,
so it is likely that the identifier that the caret is on can be completely seen,
and that the current line is seen with some of the lines following it which are
often dependent on that line.

If strict is set, the policy is enforced... strictly.
The caret is centred on the display if slop is not set,
and cannot go in the UZ if slop is set.

If jumps is set, the display is moved more energetically
so the caret can move in the same direction longer before the policy is applied again.
'3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.

If even is not set, instead of having symmetrical UZs,
the left and bottom UZs are extended up to right and top UZs respectively.
This way, we favour the displaying of useful information: the begining of lines,
where most code reside, and the lines after the caret, eg. the body of a function.

     |        |       |      |                                            |
slop | strict | jumps | even | Caret can go to the margin                 | When reaching limit (caret going out of
     |        |       |      |                                            | visibility or going into the UZ) display is...
-----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
  0  |   0    |   0   |   0  | Yes                                        | moved to put caret on top/on right
  0  |   0    |   0   |   1  | Yes                                        | moved by one position
  0  |   0    |   1   |   0  | Yes                                        | moved to put caret on top/on right
  0  |   0    |   1   |   1  | Yes                                        | centred on the caret
  0  |   1    |   -   |   0  | Caret is always on top/on right of display | -
  0  |   1    |   -   |   1  | No, caret is always centred                | -
  1  |   0    |   0   |   0  | Yes                                        | moved to put caret out of the asymmetrical UZ
  1  |   0    |   0   |   1  | Yes                                        | moved to put caret out of the UZ
  1  |   0    |   1   |   0  | Yes                                        | moved to put caret at 3UZ of the top or right margin
  1  |   0    |   1   |   1  | Yes                                        | moved to put caret at 3UZ of the margin
  1  |   1    |   -   |   0  | Caret is always at UZ of top/right margin  | -
  1  |   1    |   0   |   1  | No, kept out of UZ                         | moved by one position
  1  |   1    |   1   |   1  | No, kept out of UZ                         | moved to put caret at 3UZ of the margin
*/

Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {
	PRectangle rcClient = GetTextRectangle();
	Point pt = LocationFromPosition(range.caret);
	Point ptAnchor = LocationFromPosition(range.anchor);
	const Point ptOrigin = GetVisibleOriginInMain();
	pt.x += ptOrigin.x;
	ptAnchor.x += ptOrigin.x;
	const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);

	XYScrollPosition newXY(xOffset, topLine);

	// Vertical positioning
	if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
		const int lineCaret = DisplayFromPosition(range.caret.Position());
		const int linesOnScreen = LinesOnScreen();
		const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
		const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
		const bool bStrict = (caretYPolicy & CARET_STRICT) != 0;
		const bool bJump = (caretYPolicy & CARET_JUMPS) != 0;
		const bool bEven = (caretYPolicy & CARET_EVEN) != 0;

		// It should be possible to scroll the window to show the caret,
		// but this fails to remove the caret on GTK+
		if (bSlop) {	// A margin is defined
			int yMoveT, yMoveB;
			if (bStrict) {
				int yMarginT, yMarginB;
				if (!(options & xysUseMargin)) {
					// In drag mode, avoid moves
					// otherwise, a double click will select several lines.
					yMarginT = yMarginB = 0;
				} else {
					// yMarginT must equal to caretYSlop, with a minimum of 1 and
					// a maximum of slightly less than half the heigth of the text area.
					yMarginT = Platform::Clamp(caretYSlop, 1, halfScreen);
					if (bEven) {
						yMarginB = yMarginT;
					} else {
						yMarginB = linesOnScreen - yMarginT - 1;
					}
				}
				yMoveT = yMarginT;
				if (bEven) {
					if (bJump) {
						yMoveT = Platform::Clamp(caretYSlop * 3, 1, halfScreen);
					}
					yMoveB = yMoveT;
				} else {
					yMoveB = linesOnScreen - yMoveT - 1;
				}
				if (lineCaret < topLine + yMarginT) {
					// Caret goes too high
					newXY.topLine = lineCaret - yMoveT;
				} else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) {
					// Caret goes too low
					newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
				}
			} else {	// Not strict
				yMoveT = bJump ? caretYSlop * 3 : caretYSlop;
				yMoveT = Platform::Clamp(yMoveT, 1, halfScreen);
				if (bEven) {
					yMoveB = yMoveT;
				} else {
					yMoveB = linesOnScreen - yMoveT - 1;
				}
				if (lineCaret < topLine) {
					// Caret goes too high
					newXY.topLine = lineCaret - yMoveT;
				} else if (lineCaret > topLine + linesOnScreen - 1) {
					// Caret goes too low
					newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
				}
			}
		} else {	// No slop
			if (!bStrict && !bJump) {
				// Minimal move
				if (lineCaret < topLine) {
					// Caret goes too high
					newXY.topLine = lineCaret;
				} else if (lineCaret > topLine + linesOnScreen - 1) {
					// Caret goes too low
					if (bEven) {
						newXY.topLine = lineCaret - linesOnScreen + 1;
					} else {
						newXY.topLine = lineCaret;
					}
				}
			} else {	// Strict or going out of display
				if (bEven) {
					// Always center caret
					newXY.topLine = lineCaret - halfScreen;
				} else {
					// Always put caret on top of display
					newXY.topLine = lineCaret;
				}
			}
		}
		if (!(range.caret == range.anchor)) {
			const int lineAnchor = DisplayFromPosition(range.anchor.Position());
			if (lineAnchor < lineCaret) {
				// Shift up to show anchor or as much of range as possible
				newXY.topLine = std::min(newXY.topLine, lineAnchor);
				newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
			} else {
				// Shift down to show anchor or as much of range as possible
				newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
				newXY.topLine = std::min(newXY.topLine, lineCaret);
			}
		}
		newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
	}

	// Horizontal positioning
	if ((options & xysHorizontal) && (wrapState == eWrapNone)) {
		const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
		const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
		const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
		const bool bJump = (caretXPolicy & CARET_JUMPS) != 0;
		const bool bEven = (caretXPolicy & CARET_EVEN) != 0;

		if (bSlop) {	// A margin is defined
			int xMoveL, xMoveR;
			if (bStrict) {
				int xMarginL, xMarginR;
				if (!(options & xysUseMargin)) {
					// In drag mode, avoid moves unless very near of the margin
					// otherwise, a simple click will select text.
					xMarginL = xMarginR = 2;
				} else {
					// xMargin must equal to caretXSlop, with a minimum of 2 and
					// a maximum of slightly less than half the width of the text area.
					xMarginR = Platform::Clamp(caretXSlop, 2, halfScreen);
					if (bEven) {
						xMarginL = xMarginR;
					} else {
						xMarginL = rcClient.Width() - xMarginR - 4;
					}
				}
				if (bJump && bEven) {
					// Jump is used only in even mode
					xMoveL = xMoveR = Platform::Clamp(caretXSlop * 3, 1, halfScreen);
				} else {
					xMoveL = xMoveR = 0;	// Not used, avoid a warning
				}
				if (pt.x < rcClient.left + xMarginL) {
					// Caret is on the left of the display
					if (bJump && bEven) {
						newXY.xOffset -= xMoveL;
					} else {
						// Move just enough to allow to display the caret
						newXY.xOffset -= (rcClient.left + xMarginL) - pt.x;
					}
				} else if (pt.x >= rcClient.right - xMarginR) {
					// Caret is on the right of the display
					if (bJump && bEven) {
						newXY.xOffset += xMoveR;
					} else {
						// Move just enough to allow to display the caret
						newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1;
					}
				}
			} else {	// Not strict
				xMoveR = bJump ? caretXSlop * 3 : caretXSlop;
				xMoveR = Platform::Clamp(xMoveR, 1, halfScreen);
				if (bEven) {
					xMoveL = xMoveR;
				} else {
					xMoveL = rcClient.Width() - xMoveR - 4;
				}
				if (pt.x < rcClient.left) {
					// Caret is on the left of the display
					newXY.xOffset -= xMoveL;
				} else if (pt.x >= rcClient.right) {
					// Caret is on the right of the display
					newXY.xOffset += xMoveR;
				}
			}
		} else {	// No slop
			if (bStrict ||
			        (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) {
				// Strict or going out of display
				if (bEven) {
					// Center caret
					newXY.xOffset += pt.x - rcClient.left - halfScreen;
				} else {
					// Put caret on right
					newXY.xOffset += pt.x - rcClient.right + 1;
				}
			} else {
				// Move just enough to allow to display the caret
				if (pt.x < rcClient.left) {
					// Caret is on the left of the display
					if (bEven) {
						newXY.xOffset -= rcClient.left - pt.x;
					} else {
						newXY.xOffset += pt.x - rcClient.right + 1;
					}
				} else if (pt.x >= rcClient.right) {
					// Caret is on the right of the display
					newXY.xOffset += pt.x - rcClient.right + 1;
				}
			}
		}
		// In case of a jump (find result) largely out of display, adjust the offset to display the caret
		if (pt.x + xOffset < rcClient.left + newXY.xOffset) {
			newXY.xOffset = pt.x + xOffset - rcClient.left;
		} else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) {
			newXY.xOffset = pt.x + xOffset - rcClient.right + 1;
			if (vs.caretStyle == CARETSTYLE_BLOCK) {
				// Ensure we can see a good portion of the block caret
				newXY.xOffset += static_cast<int>(vs.aveCharWidth);
			}
		}
		if (!(range.caret == range.anchor)) {
			if (ptAnchor.x < pt.x) {
				// Shift to left to show anchor or as much of range as possible
				int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1;
				int minOffset = pt.x + xOffset - rcClient.right + 1;
				newXY.xOffset = std::min(newXY.xOffset, maxOffset);
				newXY.xOffset = std::max(newXY.xOffset, minOffset);
			} else {
				// Shift to right to show anchor or as much of range as possible
				int minOffset = ptAnchor.x + xOffset - rcClient.right + 1;
				int maxOffset = pt.x + xOffset - rcClient.left - 1;
				newXY.xOffset = std::max(newXY.xOffset, minOffset);
				newXY.xOffset = std::min(newXY.xOffset, maxOffset);
			}
		}
		if (newXY.xOffset < 0) {
			newXY.xOffset = 0;
		}
	}

	return newXY;
}

void Editor::SetXYScroll(XYScrollPosition newXY) {
	if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) {
		if (newXY.topLine != topLine) {
			SetTopLine(newXY.topLine);
			SetVerticalScrollPos();
		}
		if (newXY.xOffset != xOffset) {
			xOffset = newXY.xOffset;
			ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
			if (newXY.xOffset > 0) {
				PRectangle rcText = GetTextRectangle();
				if (horizontalScrollBarVisible &&
					rcText.Width() + xOffset > scrollWidth) {
					scrollWidth = xOffset + rcText.Width();
					SetScrollBars();
				}
			}
			SetHorizontalScrollPos();
		}
		Redraw();
		UpdateSystemCaret();
	}
}

void Editor::ScrollRange(SelectionRange range) {
	SetXYScroll(XYScrollToMakeVisible(range, xysDefault));
}

void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
	SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
		static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));
}

void Editor::ShowCaretAtCurrentPosition() {
	if (hasFocus) {
		caret.active = true;
		caret.on = true;
		SetTicking(true);
	} else {
		caret.active = false;
		caret.on = false;
	}
	InvalidateCaret();
}

void Editor::DropCaret() {
	caret.active = false;
	InvalidateCaret();
}

void Editor::InvalidateCaret() {
	if (posDrag.IsValid()) {
		InvalidateRange(posDrag.Position(), posDrag.Position() + 1);
	} else {
		for (size_t r=0; r<sel.Count(); r++) {
			InvalidateRange(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1);
		}
	}
	UpdateSystemCaret();
}

void Editor::UpdateSystemCaret() {
}

void Editor::NeedWrapping(int docLineStart, int docLineEnd) {
	docLineStart = Platform::Clamp(docLineStart, 0, pdoc->LinesTotal());
	if (wrapStart > docLineStart) {
		wrapStart = docLineStart;
		llc.Invalidate(LineLayout::llPositions);
	}
	if (wrapEnd < docLineEnd) {
		wrapEnd = docLineEnd;
	}
	wrapEnd = Platform::Clamp(wrapEnd, 0, pdoc->LinesTotal());
	// Wrap lines during idle.
	if ((wrapState != eWrapNone) && (wrapEnd != wrapStart)) {
		SetIdle(true);
	}
}

bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
	AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
	int linesWrapped = 1;
	if (ll) {
		LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
		linesWrapped = ll->lines;
	}
	return cs.SetHeight(lineToWrap, linesWrapped +
		(vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
}

// Check if wrapping needed and perform any needed wrapping.
// fullwrap: if true, all lines which need wrapping will be done,
//           in this single call.
// priorityWrapLineStart: If greater than or equal to zero, all lines starting from
//           here to 1 page + 100 lines past will be wrapped (even if there are
//           more lines under wrapping process in idle).
// If it is neither fullwrap, nor priorityWrap, then 1 page + 100 lines will be
// wrapped, if there are any wrapping going on in idle. (Generally this
// condition is called only from idler).
// Return true if wrapping occurred.
bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
	// If there are any pending wraps, do them during idle if possible.
	int linesInOneCall = LinesOnScreen() + 100;
	if (priorityWrapLineStart >= 0) {
		// Using DocFromDisplay() here may result in chicken and egg problem in certain corner cases,
		// which will hopefully be handled by added 100 lines. If some lines are still missed, idle wrapping will catch on.
		int docLinesInOneCall = cs.DocFromDisplay(topLine + LinesOnScreen() + 100) - cs.DocFromDisplay(topLine);
		linesInOneCall = Platform::Maximum(linesInOneCall, docLinesInOneCall);
	}
	if (wrapState != eWrapNone) {
		if (wrapStart < wrapEnd) {
			if (!SetIdle(true)) {
				// Idle processing not supported so full wrap required.
				fullWrap = true;
			}
		}
		if (!fullWrap && priorityWrapLineStart >= 0 &&
		        // .. and if the paint window is outside pending wraps
		        (((priorityWrapLineStart + linesInOneCall) < wrapStart) ||
		         (priorityWrapLineStart > wrapEnd))) {
			// No priority wrap pending
			return false;
		}
	}
	int goodTopLine = topLine;
	bool wrapOccurred = false;
	if (wrapStart <= pdoc->LinesTotal()) {
		if (wrapState == eWrapNone) {
			if (wrapWidth != LineLayout::wrapWidthInfinite) {
				wrapWidth = LineLayout::wrapWidthInfinite;
				for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
					cs.SetHeight(lineDoc, 1 +
						(vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
				}
				wrapOccurred = true;
			}
			wrapStart = wrapLineLarge;
			wrapEnd = wrapLineLarge;
		} else {
			if (wrapEnd >= pdoc->LinesTotal())
				wrapEnd = pdoc->LinesTotal();
			//ElapsedTime et;
			int lineDocTop = cs.DocFromDisplay(topLine);
			int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
			PRectangle rcTextArea = GetClientRectangle();
			rcTextArea.left = vs.textStart;
			rcTextArea.right -= vs.textStart;
			wrapWidth = rcTextArea.Width();
			RefreshStyleData();
			AutoSurface surface(this);
			if (surface) {
				bool priorityWrap = false;
				int lastLineToWrap = wrapEnd;
				int lineToWrap = wrapStart;
				if (!fullWrap) {
					if (priorityWrapLineStart >= 0) {
						// This is a priority wrap.
						lineToWrap = priorityWrapLineStart;
						lastLineToWrap = priorityWrapLineStart + linesInOneCall;
						priorityWrap = true;
					} else {
						// This is idle wrap.
						lastLineToWrap = wrapStart + linesInOneCall;
					}
					if (lastLineToWrap >= wrapEnd)
						lastLineToWrap = wrapEnd;
				} // else do a fullWrap.

				// Ensure all lines being wrapped are styled.
				pdoc->EnsureStyledTo(pdoc->LineEnd(lastLineToWrap));

				// Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap);
				// Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd);
				while (lineToWrap < lastLineToWrap) {
					if (WrapOneLine(surface, lineToWrap)) {
						wrapOccurred = true;
					}
					lineToWrap++;
				}
				if (!priorityWrap)
					wrapStart = lineToWrap;
				// If wrapping is done, bring it to resting position
				if (wrapStart >= wrapEnd) {
					wrapStart = wrapLineLarge;
					wrapEnd = wrapLineLarge;
				}
			}
			goodTopLine = cs.DisplayFromDoc(lineDocTop);
			if (subLineTop < cs.GetHeight(lineDocTop))
				goodTopLine += subLineTop;
			else
				goodTopLine += cs.GetHeight(lineDocTop);
			//double durWrap = et.Duration(true);
			//Platform::DebugPrintf("Wrap:%9.6g \n", durWrap);
		}
	}
	if (wrapOccurred) {
		SetScrollBars();
		SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos()));
		SetVerticalScrollPos();
	}
	return wrapOccurred;
}

void Editor::LinesJoin() {
	if (!RangeContainsProtected(targetStart, targetEnd)) {
		UndoGroup ug(pdoc);
		bool prevNonWS = true;
		for (int pos = targetStart; pos < targetEnd; pos++) {
			if (pdoc->IsPositionInLineEnd(pos)) {
				targetEnd -= pdoc->LenChar(pos);
				pdoc->DelChar(pos);
				if (prevNonWS) {
					// Ensure at least one space separating previous lines
					pdoc->InsertChar(pos, ' ');
					targetEnd++;
				}
			} else {
				prevNonWS = pdoc->CharAt(pos) != ' ';
			}
		}
	}
}

const char *Editor::StringFromEOLMode(int eolMode) {
	if (eolMode == SC_EOL_CRLF) {
		return "\r\n";
	} else if (eolMode == SC_EOL_CR) {
		return "\r";
	} else {
		return "\n";
	}
}

void Editor::LinesSplit(int pixelWidth) {
	if (!RangeContainsProtected(targetStart, targetEnd)) {
		if (pixelWidth == 0) {
			PRectangle rcText = GetTextRectangle();
			pixelWidth = rcText.Width();
		}
		int lineStart = pdoc->LineFromPosition(targetStart);
		int lineEnd = pdoc->LineFromPosition(targetEnd);
		const char *eol = StringFromEOLMode(pdoc->eolMode);
		UndoGroup ug(pdoc);
		for (int line = lineStart; line <= lineEnd; line++) {
			AutoSurface surface(this);
			AutoLineLayout ll(llc, RetrieveLineLayout(line));
			if (surface && ll) {
				unsigned int posLineStart = pdoc->LineStart(line);
				LayoutLine(line, surface, vs, ll, pixelWidth);
				for (int subLine = 1; subLine < ll->lines; subLine++) {
					pdoc->InsertCString(
						static_cast<int>(posLineStart + (subLine - 1) * strlen(eol) +
							ll->LineStart(subLine)),
						eol);
					targetEnd += static_cast<int>(strlen(eol));
				}
			}
			lineEnd = pdoc->LineFromPosition(targetEnd);
		}
	}
}

int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) {
	if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
		return markerDefault;
	return markerCheck;
}

bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) {
	if (st.multipleStyles) {
		for (size_t iStyle=0; iStyle<st.length; iStyle++) {
			if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
				return false;
		}
	} else {
		if (!vs.ValidStyle(styleOffset + st.style))
			return false;
	}
	return true;
}

static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset,
	const char *text, const unsigned char *styles, size_t len) {
	int width = 0;
	size_t start = 0;
	while (start < len) {
		size_t style = styles[start];
		size_t endSegment = start;
		while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style))
			endSegment++;
		width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, 
			static_cast<int>(endSegment - start + 1));
		start = endSegment + 1;
	}
	return width;
}

static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, const StyledText &st) {
	int widthMax = 0;
	size_t start = 0;
	while (start < st.length) {
		size_t lenLine = st.LineLength(start);
		int widthSubLine;
		if (st.multipleStyles) {
			widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
		} else {
			widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font,
				st.text + start, static_cast<int>(lenLine));
		}
		if (widthSubLine > widthMax)
			widthMax = widthSubLine;
		start += lenLine + 1;
	}
	return widthMax;
}

void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,
	const StyledText &st, size_t start, size_t length) {

	if (st.multipleStyles) {
		int x = rcText.left;
		size_t i = 0;
		while (i < length) {
			size_t end = i;
			int style = st.styles[i + start];
			while (end < length-1 && st.styles[start+end+1] == style)
				end++;
			style += styleOffset;
			int width = surface->WidthText(vs.styles[style].font,
				st.text + start + i, static_cast<int>(end - i + 1));
			PRectangle rcSegment = rcText;
			rcSegment.left = x;
			rcSegment.right = x + width + 1;
			surface->DrawTextNoClip(rcSegment, vs.styles[style].font,
					ascent, st.text + start + i,
					static_cast<int>(end - i + 1),
					vs.styles[style].fore,
					vs.styles[style].back);
			x += width;
			i = end + 1;
		}
	} else {
		size_t style = st.style + styleOffset;
		surface->DrawTextNoClip(rcText, vs.styles[style].font,
				rcText.top + vs.maxAscent, st.text + start,
				static_cast<int>(length),
				vs.styles[style].fore,
				vs.styles[style].back);
	}
}

void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
	if (vs.fixedColumnWidth == 0)
		return;

	RefreshPixMaps(surfWindow);

	PRectangle rcMargin = GetClientRectangle();
	Point ptOrigin = GetVisibleOriginInMain();
	rcMargin.Move(0, -ptOrigin.y);
	rcMargin.left = 0;
	rcMargin.right = vs.fixedColumnWidth;

	if (!rc.Intersects(rcMargin))
		return;

	Surface *surface;
	if (bufferedDraw) {
		surface = pixmapSelMargin;
	} else {
		surface = surfWindow;
	}

	// Clip vertically to paint area to avoid drawing line numbers
	if (rcMargin.bottom > rc.bottom)
		rcMargin.bottom = rc.bottom;
	if (rcMargin.top < rc.top)
		rcMargin.top = rc.top;

	PRectangle rcSelMargin = rcMargin;
	rcSelMargin.right = rcMargin.left;
	if (rcSelMargin.bottom < rc.bottom)
		rcSelMargin.bottom = rc.bottom;

	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
		if (vs.ms[margin].width > 0) {

			rcSelMargin.left = rcSelMargin.right;
			rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;

			if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
				if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
					// Required because of special way brush is created for selection margin
					// Ensure patterns line up when scrolling with separate margin view
					// by choosing correctly aligned variant.
					bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
					surface->FillRectangle(rcSelMargin,
					  invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
				} else {
					ColourDesired colour;
					switch (vs.ms[margin].style) {
					case SC_MARGIN_BACK:
						colour = vs.styles[STYLE_DEFAULT].back;
						break;
					case SC_MARGIN_FORE:
						colour = vs.styles[STYLE_DEFAULT].fore;
						break;
					default:
						colour = vs.styles[STYLE_LINENUMBER].back;
						break;
					}
					surface->FillRectangle(rcSelMargin, colour);
				}
			} else {
				surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
			}

			const int lineStartPaint = (rcMargin.top + ptOrigin.y) / vs.lineHeight;
			int visibleLine = TopLineOfMain() + lineStartPaint;
			int yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
			// Work out whether the top line is whitespace located after a
			// lessening of fold level which implies a 'fold tail' but which should not
			// be displayed until the last of a sequence of whitespace.
			bool needWhiteClosure = false;
			if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
				int level = pdoc->GetLevel(cs.DocFromDisplay(visibleLine));
				if (level & SC_FOLDLEVELWHITEFLAG) {
					int lineBack = cs.DocFromDisplay(visibleLine);
					int levelPrev = level;
					while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
						lineBack--;
						levelPrev = pdoc->GetLevel(lineBack);
					}
					if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
						if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
							needWhiteClosure = true;
					}
				}
				if (highlightDelimiter.isEnabled) {
					int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1;
					pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine);
				}
			}

			// Old code does not know about new markers needed to distinguish all cases
			int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
			        SC_MARKNUM_FOLDEROPEN);
			int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
			        SC_MARKNUM_FOLDER);

			while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) {

				PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
				int lineDoc = cs.DocFromDisplay(visibleLine);
				PLATFORM_ASSERT(cs.GetVisible(lineDoc));
				bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc);
				bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1);

				int marks = pdoc->GetMark(lineDoc);
				if (!firstSubLine)
					marks = 0;

				bool headWithTail = false;

				if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
					// Decide which fold indicator should be displayed
					int level = pdoc->GetLevel(lineDoc);
					int levelNext = pdoc->GetLevel(lineDoc + 1);
					int levelNum = level & SC_FOLDLEVELNUMBERMASK;
					int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
					if (level & SC_FOLDLEVELHEADERFLAG) {
						if (firstSubLine) {
							if (levelNum < levelNextNum) {
								if (cs.GetExpanded(lineDoc)) {
									if (levelNum == SC_FOLDLEVELBASE)
										marks |= 1 << SC_MARKNUM_FOLDEROPEN;
									else
										marks |= 1 << folderOpenMid;
								} else {
									if (levelNum == SC_FOLDLEVELBASE)
										marks |= 1 << SC_MARKNUM_FOLDER;
									else
										marks |= 1 << folderEnd;
								}
							} else if (levelNum > SC_FOLDLEVELBASE) {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
 							}
						} else {
							if (levelNum < levelNextNum) {
								if (cs.GetExpanded(lineDoc)) {
									marks |= 1 << SC_MARKNUM_FOLDERSUB;
								} else if (levelNum > SC_FOLDLEVELBASE) {
									marks |= 1 << SC_MARKNUM_FOLDERSUB;
								}
							} else if (levelNum > SC_FOLDLEVELBASE) {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
 							}
						}
						needWhiteClosure = false;
						int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1));
						int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine);
						int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK;
						if (!cs.GetExpanded(lineDoc)) {
							if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
								(levelNum > secondFollowupLineLevelNum))
								needWhiteClosure = true;

							if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
								headWithTail = true;
						}
					} else if (level & SC_FOLDLEVELWHITEFLAG) {
						if (needWhiteClosure) {
							if (levelNext & SC_FOLDLEVELWHITEFLAG) {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
							} else if (levelNextNum > SC_FOLDLEVELBASE) {
								marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
								needWhiteClosure = false;
							} else {
								marks |= 1 << SC_MARKNUM_FOLDERTAIL;
								needWhiteClosure = false;
							}
						} else if (levelNum > SC_FOLDLEVELBASE) {
							if (levelNextNum < levelNum) {
								if (levelNextNum > SC_FOLDLEVELBASE) {
									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
								} else {
									marks |= 1 << SC_MARKNUM_FOLDERTAIL;
								}
							} else {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
							}
						}
					} else if (levelNum > SC_FOLDLEVELBASE) {
						if (levelNextNum < levelNum) {
							needWhiteClosure = false;
							if (levelNext & SC_FOLDLEVELWHITEFLAG) {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
								needWhiteClosure = true;
							} else if (lastSubLine) {
								if (levelNextNum > SC_FOLDLEVELBASE) {
									marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
								} else {
									marks |= 1 << SC_MARKNUM_FOLDERTAIL;
								}
							} else {
								marks |= 1 << SC_MARKNUM_FOLDERSUB;
							}
						} else {
							marks |= 1 << SC_MARKNUM_FOLDERSUB;
						}
					}
				}

				marks &= vs.ms[margin].mask;

				PRectangle rcMarker = rcSelMargin;
				rcMarker.top = yposScreen;
				rcMarker.bottom = yposScreen + vs.lineHeight;
				if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
					if (firstSubLine) {
						char number[100] = "";
						if (lineDoc >= 0)
							sprintf(number, "%d", lineDoc + 1);
						if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
							int lev = pdoc->GetLevel(lineDoc);
							sprintf(number, "%c%c %03X %03X",
									(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
									(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
									lev & SC_FOLDLEVELNUMBERMASK,
									lev >> 16
								   );
						}
						PRectangle rcNumber = rcMarker;
						// Right justify
						XYPOSITION width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number));
						XYPOSITION xpos = rcNumber.right - width - marginNumberPadding;
						rcNumber.left = xpos;
						surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font,
								rcNumber.top + vs.maxAscent, number, istrlen(number),
								vs.styles[STYLE_LINENUMBER].fore,
								vs.styles[STYLE_LINENUMBER].back);
					} else if (wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
						PRectangle rcWrapMarker = rcMarker;
						rcWrapMarker.right -= 3;
						rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
						DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
					}
				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
					if (firstSubLine) {
						const StyledText stMargin  = pdoc->MarginStyledText(lineDoc);
						if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
							surface->FillRectangle(rcMarker,
								vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back);
							if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
								int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
								rcMarker.left = rcMarker.right - width - 3;
							}
							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent,
								stMargin, 0, stMargin.length);
						}
					}
				}

				if (marks) {
					for (int markBit = 0; (markBit < 32) && marks; markBit++) {
						if (marks & 1) {
							LineMarker::typeOfFold tFold = LineMarker::undefined;
							if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
								if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
									tFold = LineMarker::body;
								} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
									if (firstSubLine) {
										tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head;
									} else {
										if (cs.GetExpanded(lineDoc) || headWithTail) {
											tFold = LineMarker::body;
										} else {
											tFold = LineMarker::undefined;
										}
									}
								} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
									tFold = LineMarker::tail;
								}
							}
							vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font, tFold, vs.ms[margin].style);
						}
						marks >>= 1;
					}
				}

				visibleLine++;
				yposScreen += vs.lineHeight;
			}
		}
	}

	PRectangle rcBlankMargin = rcMargin;
	rcBlankMargin.left = rcSelMargin.right;
	surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);

	if (bufferedDraw) {
		surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *pixmapSelMargin);
	}
}

void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
	int ydiff = (rcTab.bottom - rcTab.top) / 2;
	int xhead = rcTab.right - 1 - ydiff;
	if (xhead <= rcTab.left) {
		ydiff -= rcTab.left - xhead - 1;
		xhead = rcTab.left - 1;
	}
	if ((rcTab.left + 2) < (rcTab.right - 1))
		surface->MoveTo(rcTab.left + 2, ymid);
	else
		surface->MoveTo(rcTab.right - 1, ymid);
	surface->LineTo(rcTab.right - 1, ymid);
	surface->LineTo(xhead, ymid - ydiff);
	surface->MoveTo(rcTab.right - 1, ymid);
	surface->LineTo(xhead, ymid + ydiff);
}

LineLayout *Editor::RetrieveLineLayout(int lineNumber) {
	int posLineStart = pdoc->LineStart(lineNumber);
	int posLineEnd = pdoc->LineStart(lineNumber + 1);
	PLATFORM_ASSERT(posLineEnd >= posLineStart);
	int lineCaret = pdoc->LineFromPosition(sel.MainCaret());
	return llc.Retrieve(lineNumber, lineCaret,
	        posLineEnd - posLineStart, pdoc->GetStyleClock(),
	        LinesOnScreen() + 1, pdoc->LinesTotal());
}

bool BadUTF(const char *s, int len, int &trailBytes) {
	// For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
	if (trailBytes) {
		trailBytes--;
		return false;
	}
	int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(s), len);
	if (utf8status & UTF8MaskInvalid) {
		return true;
	} else {
		trailBytes = (utf8status & UTF8MaskWidth) - 1;
		return false;
	}
}

/**
 * Fill in the LineLayout data for the given line.
 * Copy the given @a line and its styles from the document into local arrays.
 * Also determine the x position at which each character starts.
 */
void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) {
	if (!ll)
		return;

	PLATFORM_ASSERT(line < pdoc->LinesTotal());
	PLATFORM_ASSERT(ll->chars != NULL);
	int posLineStart = pdoc->LineStart(line);
	int posLineEnd = pdoc->LineStart(line + 1);
	// If the line is very long, limit the treatment to a length that should fit in the viewport
	if (posLineEnd > (posLineStart + ll->maxLineLength)) {
		posLineEnd = posLineStart + ll->maxLineLength;
	}
	if (ll->validity == LineLayout::llCheckTextAndStyle) {
		int lineLength = posLineEnd - posLineStart;
		if (!vstyle.viewEOL) {
			lineLength = pdoc->LineEnd(line) - posLineStart;
		}
		if (lineLength == ll->numCharsInLine) {
			// See if chars, styles, indicators, are all the same
			bool allSame = true;
			const int styleMask = pdoc->stylingBitsMask;
			// Check base line layout
			char styleByte = 0;
			int numCharsInLine = 0;
			while (numCharsInLine < lineLength) {
				int charInDoc = numCharsInLine + posLineStart;
				char chDoc = pdoc->CharAt(charInDoc);
				styleByte = pdoc->StyleAt(charInDoc);
				allSame = allSame &&
				        (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
				allSame = allSame &&
				        (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
				if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
					allSame = allSame &&
					        (ll->chars[numCharsInLine] == chDoc);
				else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
					allSame = allSame &&
					        (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
				else	// Style::caseUpper
					allSame = allSame &&
					        (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
				numCharsInLine++;
			}
			allSame = allSame && (ll->styles[numCharsInLine] == styleByte);	// For eolFilled
			if (allSame) {
				ll->validity = LineLayout::llPositions;
			} else {
				ll->validity = LineLayout::llInvalid;
			}
		} else {
			ll->validity = LineLayout::llInvalid;
		}
	}
	if (ll->validity == LineLayout::llInvalid) {
		ll->widthLine = LineLayout::wrapWidthInfinite;
		ll->lines = 1;
		if (vstyle.edgeState == EDGE_BACKGROUND) {
			ll->edgeColumn = pdoc->FindColumn(line, theEdge);
			if (ll->edgeColumn >= posLineStart) {
				ll->edgeColumn -= posLineStart;
			}
		} else {
			ll->edgeColumn = -1;
		}

		char styleByte;
		const int styleMask = pdoc->stylingBitsMask;
		ll->styleBitsSet = 0;
		// Fill base line layout
		const int lineLength = posLineEnd - posLineStart;
		pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
		pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
		int numCharsBeforeEOL = pdoc->LineEnd(line) - posLineStart;
		const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
		for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
			styleByte = ll->styles[styleInLine];
			ll->styleBitsSet |= styleByte;
			ll->styles[styleInLine] = static_cast<char>(styleByte & styleMask);
			ll->indicators[styleInLine] = static_cast<char>(styleByte & ~styleMask);
		}
		styleByte = static_cast<char>(((lineLength > 0) ? ll->styles[lineLength-1] : 0) & styleMask);
		if (vstyle.someStylesForceCase) {
			for (int charInLine = 0; charInLine<lineLength; charInLine++) {
				char chDoc = ll->chars[charInLine];
				if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper)
					ll->chars[charInLine] = static_cast<char>(toupper(chDoc));
				else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower)
					ll->chars[charInLine] = static_cast<char>(tolower(chDoc));
			}
		}
		ll->xHighlightGuide = 0;
		// Extra element at the end of the line to hold end x position and act as
		ll->chars[numCharsInLine] = 0;   // Also triggers processing in the loops as this is a control character
		ll->styles[numCharsInLine] = styleByte;	// For eolFilled
		ll->indicators[numCharsInLine] = 0;

		// Layout the line, determining the position of each character,
		// with an extra element at the end for the end of the line.
		int startseg = 0;	// Start of the current segment, in char. number
		XYACCUMULATOR startsegx = 0;	// Start of the current segment, in pixels
		ll->positions[0] = 0;
		XYPOSITION tabWidth = vstyle.spaceWidth * pdoc->tabInChars;
		bool lastSegItalics = false;
		Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;

		XYPOSITION ctrlCharWidth[32] = {0};
		bool isControlNext = IsControlCharacter(ll->chars[0]);
		int trailBytes = 0;
		bool isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars, numCharsInLine, trailBytes);
		for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
			bool isControl = isControlNext;
			isControlNext = IsControlCharacter(ll->chars[charInLine + 1]);
			bool isBadUTF = isBadUTFNext;
			isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
			if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
			        isControl || isControlNext || isBadUTF || isBadUTFNext || ((charInLine+1) >= numCharsBeforeEOL)) {
				ll->positions[startseg] = 0;
				if (vstyle.styles[ll->styles[charInLine]].visible) {
					if (isControl) {
						if (ll->chars[charInLine] == '\t') {
							ll->positions[charInLine + 1] = 
								((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx;
						} else if (controlCharSymbol < 32) {
							if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
								const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
								ctrlCharWidth[ll->chars[charInLine]] =
								    surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + ctrlCharPadding;
							}
							ll->positions[charInLine + 1] = ctrlCharWidth[ll->chars[charInLine]];
						} else {
							char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
							surface->MeasureWidths(ctrlCharsFont, cc, 1,
							        ll->positions + startseg + 1);
						}
						lastSegItalics = false;
					} else if ((isBadUTF) || (charInLine >= numCharsBeforeEOL)) {
						char hexits[4];
						sprintf(hexits, "x%2X", ll->chars[charInLine] & 0xff);
						ll->positions[charInLine + 1] =
						    surface->WidthText(ctrlCharsFont, hexits, istrlen(hexits)) + 3;
					} else {	// Regular character
						int lenSeg = charInLine - startseg + 1;
						if ((lenSeg == 1) && (' ' == ll->chars[startseg])) {
							lastSegItalics = false;
							// Over half the segments are single characters and of these about half are space characters.
							ll->positions[charInLine + 1] = vstyle.styles[ll->styles[charInLine]].spaceWidth;
						} else {
							lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic;
							posCache.MeasureWidths(surface, vstyle, ll->styles[charInLine], ll->chars + startseg,
							        lenSeg, ll->positions + startseg + 1, pdoc);
						}
					}
				} else {    // invisible
					for (int posToZero = startseg; posToZero <= (charInLine + 1); posToZero++) {
						ll->positions[posToZero] = 0;
					}
				}
				for (int posToIncrease = startseg; posToIncrease <= (charInLine + 1); posToIncrease++) {
					ll->positions[posToIncrease] += startsegx;
				}
				startsegx = ll->positions[charInLine + 1];
				startseg = charInLine + 1;
			}
		}
		// Small hack to make lines that end with italics not cut off the edge of the last character
		if ((startseg > 0) && lastSegItalics) {
			ll->positions[startseg] += lastSegItalicsOffset;
		}
		ll->numCharsInLine = numCharsInLine;
		ll->numCharsBeforeEOL = numCharsBeforeEOL;
		ll->validity = LineLayout::llPositions;
	}
	// Hard to cope when too narrow, so just assume there is space
	if (width < 20) {
		width = 20;
	}
	if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
		ll->widthLine = width;
		if (width == LineLayout::wrapWidthInfinite) {
			ll->lines = 1;
		} else if (width > ll->positions[ll->numCharsInLine]) {
			// Simple common case where line does not need wrapping.
			ll->lines = 1;
		} else {
			if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
				width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark
			}
			XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line
			if (wrapIndentMode == SC_WRAPINDENT_INDENT) {
				wrapAddIndent = pdoc->IndentSize() * vstyle.spaceWidth;
			} else if (wrapIndentMode == SC_WRAPINDENT_FIXED) {
				wrapAddIndent = wrapVisualStartIndent * vstyle.aveCharWidth;
			}
			ll->wrapIndent = wrapAddIndent;
			if (wrapIndentMode != SC_WRAPINDENT_FIXED)
				for (int i = 0; i < ll->numCharsInLine; i++) {
					if (!IsSpaceOrTab(ll->chars[i])) {
						ll->wrapIndent += ll->positions[i]; // Add line indent
						break;
					}
				}
			// Check for text width minimum
			if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
				ll->wrapIndent = wrapAddIndent;
			// Check for wrapIndent minimum
			if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth))
				ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
			ll->lines = 0;
			// Calculate line start positions based upon width.
			int lastGoodBreak = 0;
			int lastLineStart = 0;
			XYACCUMULATOR startOffset = 0;
			int p = 0;
			while (p < ll->numCharsInLine) {
				if ((ll->positions[p + 1] - startOffset) >= width) {
					if (lastGoodBreak == lastLineStart) {
						// Try moving to start of last character
						if (p > 0) {
							lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
							        - posLineStart;
						}
						if (lastGoodBreak == lastLineStart) {
							// Ensure at least one character on line.
							lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
							        - posLineStart;
						}
					}
					lastLineStart = lastGoodBreak;
					ll->lines++;
					ll->SetLineStart(ll->lines, lastGoodBreak);
					startOffset = ll->positions[lastGoodBreak];
					// take into account the space for start wrap mark and indent
					startOffset -= ll->wrapIndent;
					p = lastGoodBreak + 1;
					continue;
				}
				if (p > 0) {
					if (wrapState == eWrapChar) {
						lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
						        - posLineStart;
						p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
						continue;
					} else if (ll->styles[p] != ll->styles[p - 1]) {
						lastGoodBreak = p;
					} else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
						lastGoodBreak = p;
					}
				}
				p++;
			}
			ll->lines++;
		}
		ll->validity = LineLayout::llLines;
	}
}

ColourDesired Editor::SelectionBackground(ViewStyle &vsDraw, bool main) {
	return main ?
		(primarySelection ? vsDraw.selbackground : vsDraw.selbackground2) :
		vsDraw.selAdditionalBackground;
}

ColourDesired Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground,
        ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) {
	if (inSelection == 1) {
		if (vsDraw.selbackset && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
			return SelectionBackground(vsDraw, true);
		}
	} else if (inSelection == 2) {
		if (vsDraw.selbackset && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
			return SelectionBackground(vsDraw, false);
		}
	} else {
		if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
		        (i >= ll->edgeColumn) &&
		        (i < ll->numCharsBeforeEOL))
			return vsDraw.edgecolour;
		if (inHotspot && vsDraw.hotspotBackgroundSet)
			return vsDraw.hotspotBackground;
	}
	if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
		return background;
	} else {
		return vsDraw.styles[styleMain].back;
	}
}

void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
	Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
	PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom);
	surface->Copy(rcCopyArea, from,
	        highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
}

void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace,
        bool isEndMarker, ColourDesired wrapColour) {
	surface->PenColour(wrapColour);

	enum { xa = 1 }; // gap before start
	int w = rcPlace.right - rcPlace.left - xa - 1;

	bool xStraight = isEndMarker;  // x-mirrored symbol for start marker
	bool yStraight = true;
	//bool yStraight= isEndMarker; // comment in for start marker y-mirrowed

	int x0 = xStraight ? rcPlace.left : rcPlace.right - 1;
	int y0 = yStraight ? rcPlace.top : rcPlace.bottom - 1;

	int dy = (rcPlace.bottom - rcPlace.top) / 5;
	int y = (rcPlace.bottom - rcPlace.top) / 2 + dy;

	struct Relative {
		Surface *surface;
		int xBase;
		int xDir;
		int yBase;
		int yDir;
		void MoveTo(int xRelative, int yRelative) {
			surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
		}
		void LineTo(int xRelative, int yRelative) {
			surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
		}
	};
	Relative rel = {surface, x0, xStraight ? 1 : -1, y0, yStraight ? 1 : -1};

	// arrow head
	rel.MoveTo(xa, y);
	rel.LineTo(xa + 2*w / 3, y - dy);
	rel.MoveTo(xa, y);
	rel.LineTo(xa + 2*w / 3, y + dy);

	// arrow body
	rel.MoveTo(xa, y);
	rel.LineTo(xa + w, y);
	rel.LineTo(xa + w, y - 2 * dy);
	rel.LineTo(xa - 1,   // on windows lineto is exclusive endpoint, perhaps GTK not...
	        y - 2 * dy);
}

static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) {
	if (alpha != SC_ALPHA_NOALPHA) {
		surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
	}
}

void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
				  const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) {
	if (!twoPhaseDraw) {
		surface->FillRectangle(rcSegment, textBack);
	}
	Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
	int normalCharHeight = surface->Ascent(ctrlCharsFont) -
	        surface->InternalLeading(ctrlCharsFont);
	PRectangle rcCChar = rcSegment;
	rcCChar.left = rcCChar.left + 1;
	rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
	rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
	PRectangle rcCentral = rcCChar;
	rcCentral.top++;
	rcCentral.bottom--;
	surface->FillRectangle(rcCentral, textFore);
	PRectangle rcChar = rcCChar;
	rcChar.left++;
	rcChar.right--;
	surface->DrawTextClipped(rcChar, ctrlCharsFont,
	        rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
	        textBack, textFore);
}

void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
        int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
        bool overrideBackground, ColourDesired background,
        bool drawWrapMarkEnd, ColourDesired wrapColour) {

	const int posLineStart = pdoc->LineStart(line);
	const int styleMask = pdoc->stylingBitsMask;
	PRectangle rcSegment = rcLine;

	const bool lastSubLine = subLine == (ll->lines - 1);
	XYPOSITION virtualSpace = 0;
	if (lastSubLine) {
		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
		virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth;
	}
	XYPOSITION xEol = ll->positions[lineEnd] - subLineStart;

	// Fill the virtual space and show selections within it
	if (virtualSpace) {
		rcSegment.left = xEol + xStart;
		rcSegment.right = xEol + xStart + virtualSpace;
		surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
		if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
			SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line))));
			for (size_t r=0; r<sel.Count(); r++) {
				int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
				if (alpha == SC_ALPHA_NOALPHA) {
					SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
					if (!portion.Empty()) {
						const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
						rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
						rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
						rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
						rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
						surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == sel.Main()));
					}
				}
			}
		}
	}

	int eolInSelection = 0;
	int alpha = SC_ALPHA_NOALPHA;
	if (!hideSelection) {
		int posAfterLineEnd = pdoc->LineStart(line + 1);
		eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0;
		alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
	}

	// Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
	XYPOSITION blobsWidth = 0;
	if (lastSubLine) {
		for (int eolPos=ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
			rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
			rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
			blobsWidth += rcSegment.Width();
			char hexits[4];
			const char *ctrlChar;
			unsigned char chEOL = ll->chars[eolPos];
			if (UTF8IsAscii(chEOL)) {
				ctrlChar = ControlCharacterString(chEOL);
			} else {
				sprintf(hexits, "x%2X", chEOL);
				ctrlChar = hexits;
			}
			int styleMain = ll->styles[eolPos];
			ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll);
			ColourDesired textFore = vsDraw.styles[styleMain].fore;
			if (eolInSelection && vsDraw.selforeset) {
				textFore = (eolInSelection == 1) ? vsDraw.selforeground : vsDraw.selAdditionalForeground;
			}
			if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) {
				if (alpha == SC_ALPHA_NOALPHA) {
					surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
				} else {
					surface->FillRectangle(rcSegment, textBack);
				}
			} else {
				surface->FillRectangle(rcSegment, textBack);
			}
			DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
			if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
				SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
			}
		}
	}

	// Draw the eol-is-selected rectangle
	rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
	rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;

	if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
	} else {
		if (overrideBackground) {
			surface->FillRectangle(rcSegment, background);
		} else if (line < pdoc->LinesTotal() - 1) {
			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
		} else {
			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
		}
		if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
		}
	}

	// Fill the remainder of the line
	rcSegment.left = rcSegment.right;
	if (rcSegment.left < rcLine.left)
		rcSegment.left = rcLine.left;
	rcSegment.right = rcLine.right;

	if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
	} else {
		if (overrideBackground) {
			surface->FillRectangle(rcSegment, background);
		} else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
			surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
		} else {
			surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
		}
		if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
		}
	}

	if (drawWrapMarkEnd) {
		PRectangle rcPlace = rcSegment;

		if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
			rcPlace.left = xEol + xStart + virtualSpace;
			rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
		} else {
			// rcLine is clipped to text area
			rcPlace.right = rcLine.right;
			rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
		}
		DrawWrapMarker(surface, rcPlace, true, wrapColour);
	}
}

void Editor::DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw,
		int xStart, PRectangle rcLine, LineLayout *ll, int subLine) {
	const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
	PRectangle rcIndic(
		ll->positions[startPos] + xStart - subLineStart,
		rcLine.top + vsDraw.maxAscent,
		ll->positions[endPos] + xStart - subLineStart,
		rcLine.top + vsDraw.maxAscent + 3);
	vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine);
}

void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
        PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
	// Draw decorators
	const int posLineStart = pdoc->LineStart(line);
	const int lineStart = ll->LineStart(subLine);
	const int posLineEnd = posLineStart + lineEnd;

	if (!under) {
		// Draw indicators
		// foreach indicator...
		for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
			if (!(mask & ll->styleBitsSet)) {
				mask <<= 1;
				continue;
			}
			int startPos = -1;
			// foreach style pos in line...
			for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
				// look for starts...
				if (startPos < 0) {
					// NOT in indicator run, looking for START
					if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
						startPos = indicPos;
				}
				// ... or ends
				if (startPos >= 0) {
					// IN indicator run, looking for END
					if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
						// AT end of indicator run, DRAW it!
						DrawIndicator(indicnum, startPos, indicPos, surface, vsDraw, xStart, rcLine, ll, subLine);
						// RESET control var
						startPos = -1;
					}
				}
			}
			mask <<= 1;
		}
	}

	for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) {
		if (under == vsDraw.indicators[deco->indicator].under) {
			int startPos = posLineStart + lineStart;
			if (!deco->rs.ValueAt(startPos)) {
				startPos = deco->rs.EndRun(startPos);
			}
			while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
				int endPos = deco->rs.EndRun(startPos);
				if (endPos > posLineEnd)
					endPos = posLineEnd;
				DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
					surface, vsDraw, xStart, rcLine, ll, subLine);
				startPos = deco->rs.EndRun(endPos);
			}
		}
	}

	// Use indicators to highlight matching braces
	if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
		(vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
		int braceIndicator = (bracesMatchStyle == STYLE_BRACELIGHT) ? vs.braceHighlightIndicator : vs.braceBadLightIndicator;
		if (under == vsDraw.indicators[braceIndicator].under) {
			Range rangeLine(posLineStart + lineStart, posLineEnd);
			if (rangeLine.ContainsCharacter(braces[0])) {
				int braceOffset = braces[0] - posLineStart;
				if (braceOffset < ll->numCharsInLine) {
					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
				}
			}
			if (rangeLine.ContainsCharacter(braces[1])) {
				int braceOffset = braces[1] - posLineStart;
				if (braceOffset < ll->numCharsInLine) {
					DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
				}
			}
		}
	}
}

void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
    PRectangle rcLine, LineLayout *ll, int subLine) {
	int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth;
	PRectangle rcSegment = rcLine;
	int annotationLine = subLine - ll->lines;
	const StyledText stAnnotation  = pdoc->AnnotationStyledText(line);
	if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
		surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
		if (vs.annotationVisible == ANNOTATION_BOXED) {
			// Only care about calculating width if need to draw box
			int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
			widthAnnotation += vsDraw.spaceWidth * 2; // Margins
			rcSegment.left = xStart + indent;
			rcSegment.right = rcSegment.left + widthAnnotation;
		} else {
			rcSegment.left = xStart;
		}
		const int annotationLines = pdoc->AnnotationLines(line);
		size_t start = 0;
		size_t lengthAnnotation = stAnnotation.LineLength(start);
		int lineInAnnotation = 0;
		while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
			start += lengthAnnotation + 1;
			lengthAnnotation = stAnnotation.LineLength(start);
			lineInAnnotation++;
		}
		PRectangle rcText = rcSegment;
		if (vs.annotationVisible == ANNOTATION_BOXED) {
			surface->FillRectangle(rcText,
				vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
			rcText.left += vsDraw.spaceWidth;
		}
		DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,
			stAnnotation, start, lengthAnnotation);
		if (vs.annotationVisible == ANNOTATION_BOXED) {
			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
			surface->MoveTo(rcSegment.left, rcSegment.top);
			surface->LineTo(rcSegment.left, rcSegment.bottom);
			surface->MoveTo(rcSegment.right, rcSegment.top);
			surface->LineTo(rcSegment.right, rcSegment.bottom);
			if (subLine == ll->lines) {
				surface->MoveTo(rcSegment.left, rcSegment.top);
				surface->LineTo(rcSegment.right, rcSegment.top);
			}
			if (subLine == ll->lines+annotationLines-1) {
				surface->MoveTo(rcSegment.left, rcSegment.bottom - 1);
				surface->LineTo(rcSegment.right, rcSegment.bottom - 1);
			}
		}
	}
}

void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
        PRectangle rcLine, LineLayout *ll, int subLine) {

	PRectangle rcSegment = rcLine;

	// Using one font for all control characters so it can be controlled independently to ensure
	// the box goes around the characters tightly. Seems to be no way to work out what height
	// is taken by an individual character - internal leading gives varying results.
	Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;

	// See if something overrides the line background color:  Either if caret is on the line
	// and background color is set for that, or if a marker is defined that forces its background
	// color onto the line, or if a marker is defined but has no selection margin in which to
	// display itself (as long as it's not an SC_MARK_EMPTY marker).  These are checked in order
	// with the earlier taking precedence.  When multiple markers cause background override,
	// the color for the highest numbered one is used.
	bool overrideBackground = false;
	ColourDesired background;
	if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
		overrideBackground = true;
		background = vsDraw.caretLineBackground;
	}
	if (!overrideBackground) {
		int marks = pdoc->GetMark(line);
		for (int markBit = 0; (markBit < 32) && marks; markBit++) {
			if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) &&
			        (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
				background = vsDraw.markers[markBit].back;
				overrideBackground = true;
			}
			marks >>= 1;
		}
	}
	if (!overrideBackground) {
		if (vsDraw.maskInLine) {
			int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
			if (marksMasked) {
				for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
					if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) &&
					        (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
						overrideBackground = true;
						background = vsDraw.markers[markBit].back;
					}
					marksMasked >>= 1;
				}
			}
		}
	}

	bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
	        (!overrideBackground) && (vsDraw.whitespaceBackgroundSet);

	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline.
	const XYPOSITION indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;
	const XYPOSITION epsilon = 0.0001f;	// A small nudge to avoid floating point precision issues

	int posLineStart = pdoc->LineStart(line);

	int startseg = ll->LineStart(subLine);
	XYACCUMULATOR subLineStart = ll->positions[startseg];
	if (subLine >= ll->lines) {
		DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine);
		return; // No further drawing
	}
	int lineStart = 0;
	int lineEnd = 0;
	if (subLine < ll->lines) {
		lineStart = ll->LineStart(subLine);
		lineEnd = ll->LineStart(subLine + 1);
		if (subLine == ll->lines - 1) {
			lineEnd = ll->numCharsBeforeEOL;
		}
	}

	ColourDesired wrapColour = vsDraw.styles[STYLE_DEFAULT].fore;
	if (vsDraw.whitespaceForegroundSet)
		wrapColour = vsDraw.whitespaceForeground;

	bool drawWrapMarkEnd = false;

	if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
		if (subLine + 1 < ll->lines) {
			drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
		}
	}

	if (ll->wrapIndent != 0) {

		bool continuedWrapLine = false;
		if (subLine < ll->lines) {
			continuedWrapLine = ll->LineStart(subLine) != 0;
		}

		if (continuedWrapLine) {
			// draw continuation rect
			PRectangle rcPlace = rcSegment;

			rcPlace.left = ll->positions[startseg] + xStart - subLineStart;
			rcPlace.right = rcPlace.left + ll->wrapIndent;

			// default bgnd here..
			surface->FillRectangle(rcSegment, overrideBackground ? background :
			        vsDraw.styles[STYLE_DEFAULT].back);

			// main line style would be below but this would be inconsistent with end markers
			// also would possibly not be the style at wrap point
			//int styleMain = ll->styles[lineStart];
			//surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back);

			if (wrapVisualFlags & SC_WRAPVISUALFLAG_START) {

				if (wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT)
					rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
				else
					rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;

				DrawWrapMarker(surface, rcPlace, false, wrapColour);
			}

			xStart += static_cast<int>(ll->wrapIndent);
		}
	}

	bool selBackDrawn = vsDraw.selbackset &&
		((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA));

	// Does not take margin into account but not significant
	int xStartVisible = static_cast<int>(subLineStart) - xStart;

	ll->psel = &sel;

	BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc);
	int next = bfBack.First();

	// Background drawing loop
	while (twoPhaseDraw && (next < lineEnd)) {

		startseg = next;
		next = bfBack.Next();
		int i = next - 1;
		int iDoc = i + posLineStart;

		rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
		rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
		// Only try to draw if really visible - enhances performance by not calling environment to
		// draw strings that are completely past the right side of the window.
		if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
			// Clip to line rectangle, since may have a huge position which will not work with some platforms
			if (rcSegment.left < rcLine.left)
				rcSegment.left = rcLine.left;
			if (rcSegment.right > rcLine.right)
				rcSegment.right = rcLine.right;

			int styleMain = ll->styles[i];
			const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
			bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
			ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
			if (ll->chars[i] == '\t') {
				// Tab display
				if (drawWhitespaceBackground &&
				        (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
					textBack = vsDraw.whitespaceBackground;
				surface->FillRectangle(rcSegment, textBack);
			} else if (IsControlCharacter(ll->chars[i])) {
				// Control character display
				inIndentation = false;
				surface->FillRectangle(rcSegment, textBack);
			} else {
				// Normal text display
				surface->FillRectangle(rcSegment, textBack);
				if (vsDraw.viewWhitespace != wsInvisible ||
				        (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
					for (int cpos = 0; cpos <= i - startseg; cpos++) {
						if (ll->chars[cpos + startseg] == ' ') {
							if (drawWhitespaceBackground &&
							        (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
								PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
									rcSegment.top,
									ll->positions[cpos + startseg + 1] + xStart - subLineStart,
									rcSegment.bottom);
								surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground);
							}
						} else {
							inIndentation = false;
						}
					}
				}
			}
		} else if (rcSegment.left > rcLine.right) {
			break;
		}
	}

	if (twoPhaseDraw) {
		DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
		        xStart, subLine, subLineStart, overrideBackground, background,
		        drawWrapMarkEnd, wrapColour);
	}

	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true);

	if (vsDraw.edgeState == EDGE_LINE) {
		int edgeX = theEdge * vsDraw.spaceWidth;
		rcSegment.left = edgeX + xStart;
		if ((ll->wrapIndent != 0) && (lineStart != 0))
			rcSegment.left -= ll->wrapIndent;
		rcSegment.right = rcSegment.left + 1;
		surface->FillRectangle(rcSegment, vsDraw.edgecolour);
	}

	// Draw underline mark as part of background if not transparent
	int marks = pdoc->GetMark(line);
	int markBit;
	for (markBit = 0; (markBit < 32) && marks; markBit++) {
		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) &&
		    (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
			PRectangle rcUnderline = rcLine;
			rcUnderline.top = rcUnderline.bottom - 2;
			surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back);
		}
		marks >>= 1;
	}

	inIndentation = subLine == 0;	// Do not handle indentation except on first subline.
	// Foreground drawing loop
	BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible,
		((!twoPhaseDraw && selBackDrawn) || vsDraw.selforeset), pdoc);
	next = bfFore.First();

	while (next < lineEnd) {

		startseg = next;
		next = bfFore.Next();
		int i = next - 1;

		int iDoc = i + posLineStart;

		rcSegment.left = ll->positions[startseg] + xStart - subLineStart;
		rcSegment.right = ll->positions[i + 1] + xStart - subLineStart;
		// Only try to draw if really visible - enhances performance by not calling environment to
		// draw strings that are completely past the right side of the window.
		if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {
			int styleMain = ll->styles[i];
			ColourDesired textFore = vsDraw.styles[styleMain].fore;
			Font &textFont = vsDraw.styles[styleMain].font;
			//hotspot foreground
			if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
				if (vsDraw.hotspotForegroundSet)
					textFore = vsDraw.hotspotForeground;
			}
			const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
			if (inSelection && (vsDraw.selforeset)) {
				textFore = (inSelection == 1) ? vsDraw.selforeground : vsDraw.selAdditionalForeground;
			}
			bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
			ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
			if (ll->chars[i] == '\t') {
				// Tab display
				if (!twoPhaseDraw) {
					if (drawWhitespaceBackground &&
					        (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
						textBack = vsDraw.whitespaceBackground;
					surface->FillRectangle(rcSegment, textBack);
				}
				if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
					for (int indentCount = (ll->positions[i] + epsilon) / indentWidth;
						indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
						indentCount++) {
						if (indentCount > 0) {
							int xIndent = indentCount * indentWidth;
							DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
								    (ll->xHighlightGuide == xIndent));
						}
					}
				}
				if (vsDraw.viewWhitespace != wsInvisible) {
					if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
						if (vsDraw.whitespaceForegroundSet)
							textFore = vsDraw.whitespaceForeground;
						surface->PenColour(textFore);
						PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
						        rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
						DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
					}
				}
			} else if (IsControlCharacter(ll->chars[i])) {
				// Control character display
				inIndentation = false;
				if (controlCharSymbol < 32) {
					// Draw the character
					const char *ctrlChar = ControlCharacterString(ll->chars[i]);
					DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
				} else {
					char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
					surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
					        rcSegment.top + vsDraw.maxAscent,
					        cc, 1, textBack, textFore);
				}
			} else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) {
				// A single byte >= 0x80 in UTF-8 is a bad byte and is displayed as its hex value
				char hexits[4];
				sprintf(hexits, "x%2X", ll->chars[i] & 0xff);
				DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw);
			} else {
				// Normal text display
				if (vsDraw.styles[styleMain].visible) {
					if (twoPhaseDraw) {
						surface->DrawTextTransparent(rcSegment, textFont,
						        rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
						        i - startseg + 1, textFore);
					} else {
						surface->DrawTextNoClip(rcSegment, textFont,
						        rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
						        i - startseg + 1, textFore, textBack);
					}
				}
				if (vsDraw.viewWhitespace != wsInvisible ||
				        (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
					for (int cpos = 0; cpos <= i - startseg; cpos++) {
						if (ll->chars[cpos + startseg] == ' ') {
							if (vsDraw.viewWhitespace != wsInvisible) {
								if (vsDraw.whitespaceForegroundSet)
									textFore = vsDraw.whitespaceForeground;
								if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
									XYPOSITION xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2;
									if (!twoPhaseDraw && drawWhitespaceBackground &&
									        (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
										textBack = vsDraw.whitespaceBackground;
										PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart,
											rcSegment.top,
											ll->positions[cpos + startseg + 1] + xStart - subLineStart,
											rcSegment.bottom);
										surface->FillRectangle(rcSpace, textBack);
									}
									PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
									rcDot.right = rcDot.left + vs.whitespaceSize;
									rcDot.bottom = rcDot.top + vs.whitespaceSize;
									surface->FillRectangle(rcDot, textFore);
								}
							}
							if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
								for (int indentCount = (ll->positions[cpos + startseg] + epsilon) / indentWidth;
									indentCount <= (ll->positions[cpos + startseg + 1] - epsilon) / indentWidth;
									indentCount++) {
									if (indentCount > 0) {
										int xIndent = indentCount * indentWidth;
										DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
												(ll->xHighlightGuide == xIndent));
									}
								}
							}
						} else {
							inIndentation = false;
						}
					}
				}
			}
			if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) {
				PRectangle rcUL = rcSegment;
				rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
				rcUL.bottom = rcUL.top + 1;
				if (vsDraw.hotspotForegroundSet)
					surface->FillRectangle(rcUL, vsDraw.hotspotForeground);
				else
					surface->FillRectangle(rcUL, textFore);
			} else if (vsDraw.styles[styleMain].underline) {
				PRectangle rcUL = rcSegment;
				rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
				rcUL.bottom = rcUL.top + 1;
				surface->FillRectangle(rcUL, textFore);
			}
		} else if (rcSegment.left > rcLine.right) {
			break;
		}
	}
	if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
	        && (subLine == 0)) {
		int indentSpace = pdoc->GetLineIndentation(line);
		int xStartText = ll->positions[pdoc->GetLineIndentPosition(line) - posLineStart];

		// Find the most recent line with some text

		int lineLastWithText = line;
		while (lineLastWithText > Platform::Maximum(line-20, 0) && pdoc->IsWhiteLine(lineLastWithText)) {
			lineLastWithText--;
		}
		if (lineLastWithText < line) {
			xStartText = 100000;	// Don't limit to visible indentation on empty line
			// This line is empty, so use indentation of last line with text
			int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
			int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
			if (isFoldHeader) {
				// Level is one more level than parent
				indentLastWithText += pdoc->IndentSize();
			}
			if (vsDraw.viewIndentationGuides == ivLookForward) {
				// In viLookForward mode, previous line only used if it is a fold header
				if (isFoldHeader) {
					indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
				}
			} else {	// viLookBoth
				indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
			}
		}

		int lineNextWithText = line;
		while (lineNextWithText < Platform::Minimum(line+20, pdoc->LinesTotal()) && pdoc->IsWhiteLine(lineNextWithText)) {
			lineNextWithText++;
		}
		if (lineNextWithText > line) {
			xStartText = 100000;	// Don't limit to visible indentation on empty line
			// This line is empty, so use indentation of first next line with text
			indentSpace = Platform::Maximum(indentSpace,
			        pdoc->GetLineIndentation(lineNextWithText));
		}

		for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
			int xIndent = indentPos * vsDraw.spaceWidth;
			if (xIndent < xStartText) {
				DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
					(ll->xHighlightGuide == xIndent));
			}
		}
	}

	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);

	// End of the drawing of the current line
	if (!twoPhaseDraw) {
		DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
		        xStart, subLine, subLineStart, overrideBackground, background,
		        drawWrapMarkEnd, wrapColour);
	}
	if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) {
		// For each selection draw
		int virtualSpaces = 0;
		if (subLine == (ll->lines - 1)) {
			virtualSpaces = sel.VirtualSpaceFor(pdoc->LineEnd(line));
		}
		SelectionPosition posStart(posLineStart + lineStart);
		SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces);
		SelectionSegment virtualSpaceRange(posStart, posEnd);
		for (size_t r=0; r<sel.Count(); r++) {
			int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
			if (alpha != SC_ALPHA_NOALPHA) {
				SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange);
				if (!portion.Empty()) {
					const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
					rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
					rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
					if ((ll->wrapIndent != 0) && (lineStart != 0)) {
						if ((portion.start.Position() - posLineStart) == lineStart && sel.Range(r).ContainsCharacter(portion.start.Position() - 1))
							rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here
					}
					rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
					rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
					if (rcSegment.right > rcLine.left)
						SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha);
				}
			}
		}
	}

	// Draw any translucent whole line states
	rcSegment = rcLine;
	if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
		SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
	}
	marks = pdoc->GetMark(line);
	for (markBit = 0; (markBit < 32) && marks; markBit++) {
		if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
			SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
		} else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
			PRectangle rcUnderline = rcSegment;
			rcUnderline.top = rcUnderline.bottom - 2;
			SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
		}
		marks >>= 1;
	}
	if (vsDraw.maskInLine) {
		int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
		if (marksMasked) {
			for (markBit = 0; (markBit < 32) && marksMasked; markBit++) {
				if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) {
					SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
				}
				marksMasked >>= 1;
			}
		}
	}
}

void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
							int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) {

	int lineStart = ll->LineStart(subLine);
	int posBefore = posCaret;
	int posAfter = MovePositionOutsideChar(posCaret + 1, 1);
	int numCharsToDraw = posAfter - posCaret;

	// Work out where the starting and ending offsets are. We need to
	// see if the previous character shares horizontal space, such as a
	// glyph / combining character. If so we'll need to draw that too.
	int offsetFirstChar = offset;
	int offsetLastChar = offset + (posAfter - posCaret);
	while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) {
		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
			// The char does not share horizontal space
			break;
		}
		// Char shares horizontal space, update the numChars to draw
		// Update posBefore to point to the prev char
		posBefore = MovePositionOutsideChar(posBefore - 1, -1);
		numCharsToDraw = posAfter - posBefore;
		offsetFirstChar = offset - (posCaret - posBefore);
	}

	// See if the next character shares horizontal space, if so we'll
	// need to draw that too.
	if (offsetFirstChar < 0)
		offsetFirstChar = 0;
	numCharsToDraw = offsetLastChar - offsetFirstChar;
	while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
		// Update posAfter to point to the 2nd next char, this is where
		// the next character ends, and 2nd next begins. We'll need
		// to compare these two
		posBefore = posAfter;
		posAfter = MovePositionOutsideChar(posAfter + 1, 1);
		offsetLastChar = offset + (posAfter - posCaret);
		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
			// The char does not share horizontal space
			break;
		}
		// Char shares horizontal space, update the numChars to draw
		numCharsToDraw = offsetLastChar - offsetFirstChar;
	}

	// We now know what to draw, update the caret drawing rectangle
	rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
	rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[lineStart] + xStart;

	// Adjust caret position to take into account any word wrapping symbols.
	if ((ll->wrapIndent != 0) && (lineStart != 0)) {
		XYPOSITION wordWrapCharWidth = ll->wrapIndent;
		rcCaret.left += wordWrapCharWidth;
		rcCaret.right += wordWrapCharWidth;
	}

	// This character is where the caret block is, we override the colours
	// (inversed) for drawing the caret here.
	int styleMain = ll->styles[offsetFirstChar];
	surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font,
	        rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
	        numCharsToDraw, vsDraw.styles[styleMain].back,
	        caretColour);
}

void Editor::RefreshPixMaps(Surface *surfaceWindow) {
	if (!pixmapSelPattern->Initialised()) {
		const int patternSize = 8;
		pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
		pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
		// This complex procedure is to reproduce the checkerboard dithered pattern used by windows
		// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
		// way between the chrome colour and the chrome highlight colour making a nice transition
		// between the window chrome and the content area. And it works in low colour depths.
		PRectangle rcPattern(0, 0, patternSize, patternSize);

		// Initialize default colours based on the chrome colour scheme.  Typically the highlight is white.
		ColourDesired colourFMFill = vs.selbar;
		ColourDesired colourFMStripes = vs.selbarlight;

		if (!(vs.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
			// User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
			// (Typically, the highlight colour is white.)
			colourFMFill = vs.selbarlight;
		}

		if (vs.foldmarginColourSet) {
			// override default fold margin colour
			colourFMFill = vs.foldmarginColour;
		}
		if (vs.foldmarginHighlightColourSet) {
			// override default fold margin highlight colour
			colourFMStripes = vs.foldmarginHighlightColour;
		}

		pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
		pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
		for (int y = 0; y < patternSize; y++) {
			for (int x = y % 2; x < patternSize; x+=2) {
				PRectangle rcPixel(x, y, x+1, y+1);
				pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
				pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
			}
		}
	}

	if (!pixmapIndentGuide->Initialised()) {
		// 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
		pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
		pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
		PRectangle rcIG(0, 0, 1, vs.lineHeight);
		pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back);
		pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore);
		pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back);
		pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore);
		for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) {
			PRectangle rcPixel(0, stripe, 1, stripe+1);
			pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore);
			pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore);
		}
	}

	if (bufferedDraw) {
		if (!pixmapLine->Initialised()) {
			PRectangle rcClient = GetClientRectangle();
			pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
			        surfaceWindow, wMain.GetID());
			pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
			        rcClient.Height(), surfaceWindow, wMain.GetID());
		}
	}
}

void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xStart,
        PRectangle rcLine, LineLayout *ll, int subLine) {
	// When drag is active it is the only caret drawn
	bool drawDrag = posDrag.IsValid();
	if (hideSelection && !drawDrag)
		return;
	const int posLineStart = pdoc->LineStart(lineDoc);
	// For each selection draw
	for (size_t r=0; (r<sel.Count()) || drawDrag; r++) {
		const bool mainCaret = r == sel.Main();
		const SelectionPosition posCaret = (drawDrag ? posDrag : sel.Range(r).caret);
		const int offset = posCaret.Position() - posLineStart;
		const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
		const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
		if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
			XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
			if (ll->wrapIndent != 0) {
				int lineStart = ll->LineStart(subLine);
				if (lineStart != 0)	// Wrapped
					xposCaret += ll->wrapIndent;
			}
			bool caretBlinkState = (caret.active && caret.on) || (!additionalCaretsBlink && !mainCaret);
			bool caretVisibleState = additionalCaretsVisible || mainCaret;
			if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
			        ((posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
				bool caretAtEOF = false;
				bool caretAtEOL = false;
				bool drawBlockCaret = false;
				XYPOSITION widthOverstrikeCaret;
				int caretWidthOffset = 0;
				PRectangle rcCaret = rcLine;

				if (posCaret.Position() == pdoc->Length())	{   // At end of document
					caretAtEOF = true;
					widthOverstrikeCaret = vsDraw.aveCharWidth;
				} else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) {	// At end of line
					caretAtEOL = true;
					widthOverstrikeCaret = vsDraw.aveCharWidth;
				} else {
					widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset];
				}
				if (widthOverstrikeCaret < 3)	// Make sure its visible
					widthOverstrikeCaret = 3;

				if (xposCaret > 0)
					caretWidthOffset = 1;	// Move back so overlaps both character cells.
				xposCaret += xStart;
				if (posDrag.IsValid()) {
					/* Dragging text, use a line caret */
					rcCaret.left = xposCaret - caretWidthOffset;
					rcCaret.right = rcCaret.left + vsDraw.caretWidth;
				} else if (inOverstrike) {
					/* Overstrike (insert mode), use a modified bar caret */
					rcCaret.top = rcCaret.bottom - 2;
					rcCaret.left = xposCaret + 1;
					rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
				} else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) {
					/* Block caret */
					rcCaret.left = xposCaret;
					if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) {
						drawBlockCaret = true;
						rcCaret.right = xposCaret + widthOverstrikeCaret;
					} else {
						rcCaret.right = xposCaret + vsDraw.aveCharWidth;
					}
				} else {
					/* Line caret */
					rcCaret.left = xposCaret - caretWidthOffset;
					rcCaret.right = rcCaret.left + vsDraw.caretWidth;
				}
				ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour;
				if (drawBlockCaret) {
					DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour);
				} else {
					surface->FillRectangle(rcCaret, caretColour);
				}
			}
		}
		if (drawDrag)
			break;
	}
}

void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
	//Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
	//	paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
	AllocateGraphics();

	RefreshStyleData();
	if (paintState == paintAbandoned)
		return;	// Scroll bars may have changed so need redraw
	RefreshPixMaps(surfaceWindow);

	StyleToPositionInView(PositionAfterArea(rcArea));

	PRectangle rcClient = GetClientRectangle();
	Point ptOrigin = GetVisibleOriginInMain();
	//Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d)   %d\n",
	//	rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);

	int screenLinePaintFirst = rcArea.top / vs.lineHeight;

	int xStart = vs.textStart - xOffset + ptOrigin.x;
	int ypos = 0;
	if (!bufferedDraw)
		ypos += screenLinePaintFirst * vs.lineHeight;
	int yposScreen = screenLinePaintFirst * vs.lineHeight;

	bool paintAbandonedByStyling = paintState == paintAbandoned;
	if (NotifyUpdateUI()) {
		RefreshStyleData();
		RefreshPixMaps(surfaceWindow);
	}

	// Call priority lines wrap on a window of lines which are likely
	// to rendered with the following paint (that is wrap the visible
	// 	lines first).
	int startLineToWrap = cs.DocFromDisplay(topLine) - 5;
	if (startLineToWrap < 0)
		startLineToWrap = 0;
	if (WrapLines(false, startLineToWrap)) {
		// The wrapping process has changed the height of some lines so
		// abandon this paint for a complete repaint.
		if (AbandonPaint()) {
			return;
		}
		RefreshPixMaps(surfaceWindow);	// In case pixmaps invalidated by scrollbar change
	}
	PLATFORM_ASSERT(pixmapSelPattern->Initialised());

	if (!bufferedDraw)
		surfaceWindow->SetClip(rcArea);

	if (paintState != paintAbandoned) {
		if (vs.marginInside) {
			PaintSelMargin(surfaceWindow, rcArea);
			PRectangle rcRightMargin = rcClient;
			rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
			if (rcArea.Intersects(rcRightMargin)) {
				surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
			}
		} else { // Else separate view so separate paint event but leftMargin included to allow overlap
			PRectangle rcLeftMargin = rcArea;
			rcLeftMargin.left = 0;
			rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
			if (rcArea.Intersects(rcLeftMargin)) {
				surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
			}
		}
	}

	if (paintState == paintAbandoned) {
		// Either styling or NotifyUpdateUI noticed that painting is needed
		// outside the current painting rectangle
		//Platform::DebugPrintf("Abandoning paint\n");
		if (wrapState != eWrapNone) {
			if (paintAbandonedByStyling) {
				// Styling has spilled over a line end, such as occurs by starting a multiline
				// comment. The width of subsequent text may have changed, so rewrap.
				NeedWrapping(cs.DocFromDisplay(topLine));
			}
		}
		return;
	}
	//Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);

	// Allow text at start of line to overlap 1 pixel into the margin as this displays
	// serifs and italic stems for aliased text.
	const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;

	// Do the painting
	if (rcArea.right > vs.textStart - leftTextOverlap) {

		Surface *surface = surfaceWindow;
		if (bufferedDraw) {
			surface = pixmapLine;
			PLATFORM_ASSERT(pixmapLine->Initialised());
		}
		surface->SetUnicodeMode(IsUnicodeMode());
		surface->SetDBCSMode(CodePage());

		int visibleLine = TopLineOfMain() + screenLinePaintFirst;

		SelectionPosition posCaret = sel.RangeMain().caret;
		if (posDrag.IsValid())
			posCaret = posDrag;
		int lineCaret = pdoc->LineFromPosition(posCaret.Position());

		PRectangle rcTextArea = rcClient;
		if (vs.marginInside) {
			rcTextArea.left += vs.textStart;
			rcTextArea.right -= vs.rightMarginWidth;
		} else {
			rcTextArea = rcArea;
		}

		// Remove selection margin from drawing area so text will not be drawn
		// on it in unbuffered mode.
		if (!bufferedDraw && vs.marginInside) {
			PRectangle rcClipText = rcTextArea;
			rcClipText.left -= leftTextOverlap;
			surfaceWindow->SetClip(rcClipText);
		}

		// Loop on visible lines
		//double durLayout = 0.0;
		//double durPaint = 0.0;
		//double durCopy = 0.0;
		//ElapsedTime etWhole;
		int lineDocPrevious = -1;	// Used to avoid laying out one document line multiple times
		AutoLineLayout ll(llc, 0);
		while (visibleLine < cs.LinesDisplayed() && yposScreen < rcArea.bottom) {

			int lineDoc = cs.DocFromDisplay(visibleLine);
			// Only visible lines should be handled by the code within the loop
			PLATFORM_ASSERT(cs.GetVisible(lineDoc));
			int lineStartSet = cs.DisplayFromDoc(lineDoc);
			int subLine = visibleLine - lineStartSet;

			// Copy this line and its styles from the document into local arrays
			// and determine the x position at which each character starts.
			//ElapsedTime et;
			if (lineDoc != lineDocPrevious) {
				ll.Set(0);
				ll.Set(RetrieveLineLayout(lineDoc));
				LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
				lineDocPrevious = lineDoc;
			}
			//durLayout += et.Duration(true);

			if (ll) {
				ll->containsCaret = lineDoc == lineCaret;
				if (hideSelection) {
					ll->containsCaret = false;
				}

				GetHotSpotRange(ll->hsStart, ll->hsEnd);

				PRectangle rcLine = rcTextArea;
				rcLine.top = ypos;
				rcLine.bottom = ypos + vs.lineHeight;

				bool bracesIgnoreStyle = false;
				if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
					(vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
					bracesIgnoreStyle = true;
				}
				Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1));
				// Highlight the current braces if any
				ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle),
				        highlightGuideColumn * vs.spaceWidth, bracesIgnoreStyle);

				if (leftTextOverlap && bufferedDraw) {
					PRectangle rcSpacer = rcLine;
					rcSpacer.right = rcSpacer.left;
					rcSpacer.left -= 1;
					surface->FillRectangle(rcSpacer, vs.styles[STYLE_DEFAULT].back);
				}

				// Draw the line
				DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine);
				//durPaint += et.Duration(true);

				// Restore the previous styles for the brace highlights in case layout is in cache.
				ll->RestoreBracesHighlight(rangeLine, braces, bracesIgnoreStyle);

				bool expanded = cs.GetExpanded(lineDoc);
				const int level = pdoc->GetLevel(lineDoc);
				const int levelNext = pdoc->GetLevel(lineDoc + 1);
				if ((level & SC_FOLDLEVELHEADERFLAG) &&
					((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) {
					// Paint the line above the fold
					if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
						||
						(!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
						PRectangle rcFoldLine = rcLine;
						rcFoldLine.bottom = rcFoldLine.top + 1;
						surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
					}
					// Paint the line below the fold
					if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
						||
						(!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
						PRectangle rcFoldLine = rcLine;
						rcFoldLine.top = rcFoldLine.bottom - 1;
						surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
					}
				}

				DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);

				if (bufferedDraw) {
					Point from(vs.textStart-leftTextOverlap, 0);
					PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen,
					        rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight);
					surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
				}

				lineWidthMaxSeen = Platform::Maximum(
					    lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
				//durCopy += et.Duration(true);
			}

			if (!bufferedDraw) {
				ypos += vs.lineHeight;
			}

			yposScreen += vs.lineHeight;
			visibleLine++;

			//gdk_flush();
		}
		ll.Set(0);
		//if (durPaint < 0.00000001)
		//	durPaint = 0.00000001;

		// Right column limit indicator
		PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea;
		rcBeyondEOF.left = vs.textStart;
		rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0);
		rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight;
		if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
			surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back);
			if (vs.edgeState == EDGE_LINE) {
				int edgeX = theEdge * vs.spaceWidth;
				rcBeyondEOF.left = edgeX + xStart;
				rcBeyondEOF.right = rcBeyondEOF.left + 1;
				surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour);
			}
		}
		//Platform::DebugPrintf(
		//"Layout:%9.6g    Paint:%9.6g    Ratio:%9.6g   Copy:%9.6g   Total:%9.6g\n",
		//durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration());
		NotifyPainted();
	}
}

// Space (3 space characters) between line numbers and text when printing.
#define lineNumberPrintSpace "   "

ColourDesired InvertedLight(ColourDesired orig) {
	unsigned int r = orig.GetRed();
	unsigned int g = orig.GetGreen();
	unsigned int b = orig.GetBlue();
	unsigned int l = (r + g + b) / 3; 	// There is a better calculation for this that matches human eye
	unsigned int il = 0xff - l;
	if (l == 0)
		return ColourDesired(0xff, 0xff, 0xff);
	r = r * il / l;
	g = g * il / l;
	b = b * il / l;
	return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff));
}

// This is mostly copied from the Paint method but with some things omitted
// such as the margin markers, line numbers, selection and caret
// Should be merged back into a combined Draw method.
long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
	if (!pfr)
		return 0;

	AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT);
	if (!surface)
		return 0;
	AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT);
	if (!surfaceMeasure) {
		return 0;
	}

	// Can't use measurements cached for screen
	posCache.Clear();

	ViewStyle vsPrint(vs);
	vsPrint.technology = SC_TECHNOLOGY_DEFAULT;

	// Modify the view style for printing as do not normally want any of the transient features to be printed
	// Printing supports only the line number margin.
	int lineNumberIndex = -1;
	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
		if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
			lineNumberIndex = margin;
		} else {
			vsPrint.ms[margin].width = 0;
		}
	}
	vsPrint.fixedColumnWidth = 0;
	vsPrint.zoomLevel = printMagnification;
	// Don't show indentation guides
	// If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT
	vsPrint.viewIndentationGuides = ivNone;
	// Don't show the selection when printing
	vsPrint.selbackset = false;
	vsPrint.selforeset = false;
	vsPrint.selAlpha = SC_ALPHA_NOALPHA;
	vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA;
	vsPrint.whitespaceBackgroundSet = false;
	vsPrint.whitespaceForegroundSet = false;
	vsPrint.showCaretLineBackground = false;
	vsPrint.alwaysShowCaretLineBackground = false;
	// Don't highlight matching braces using indicators
	vsPrint.braceHighlightIndicatorSet = false;
	vsPrint.braceBadLightIndicatorSet = false;

	// Set colours for printing according to users settings
	for (size_t sty = 0; sty < vsPrint.stylesSize; sty++) {
		if (printColourMode == SC_PRINT_INVERTLIGHT) {
			vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
			vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
		} else if (printColourMode == SC_PRINT_BLACKONWHITE) {
			vsPrint.styles[sty].fore = ColourDesired(0, 0, 0);
			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
		} else if (printColourMode == SC_PRINT_COLOURONWHITE) {
			vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
		} else if (printColourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) {
			if (sty <= STYLE_DEFAULT) {
				vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
			}
		}
	}
	// White background for the line numbers
	vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff);

	// Printing uses different margins, so reset screen margins
	vsPrint.leftMarginWidth = 0;
	vsPrint.rightMarginWidth = 0;

	vsPrint.Refresh(*surfaceMeasure);
	// Determining width must hapen after fonts have been realised in Refresh
	int lineNumberWidth = 0;
	if (lineNumberIndex >= 0) {
		lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
		        "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
		vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
		vsPrint.Refresh(*surfaceMeasure);	// Recalculate fixedColumnWidth
	}

	int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
	int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
	if (linePrintLast < linePrintStart)
		linePrintLast = linePrintStart;
	int linePrintMax = pdoc->LineFromPosition(pfr->chrg.cpMax);
	if (linePrintLast > linePrintMax)
		linePrintLast = linePrintMax;
	//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
	//      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
	//      surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
	int endPosPrint = pdoc->Length();
	if (linePrintLast < pdoc->LinesTotal())
		endPosPrint = pdoc->LineStart(linePrintLast + 1);

	// Ensure we are styled to where we are formatting.
	pdoc->EnsureStyledTo(endPosPrint);

	int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
	int ypos = pfr->rc.top;

	int lineDoc = linePrintStart;

	int nPrintPos = pfr->chrg.cpMin;
	int visibleLine = 0;
	int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
	if (printWrapState == eWrapNone)
		widthPrint = LineLayout::wrapWidthInfinite;

	while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {

		// When printing, the hdc and hdcTarget may be the same, so
		// changing the state of surfaceMeasure may change the underlying
		// state of surface. Therefore, any cached state is discarded before
		// using each surface.
		surfaceMeasure->FlushCachedState();

		// Copy this line and its styles from the document into local arrays
		// and determine the x position at which each character starts.
		LineLayout ll(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1);
		LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);

		ll.containsCaret = false;

		PRectangle rcLine;
		rcLine.left = pfr->rc.left;
		rcLine.top = ypos;
		rcLine.right = pfr->rc.right - 1;
		rcLine.bottom = ypos + vsPrint.lineHeight;

		// When document line is wrapped over multiple display lines, find where
		// to start printing from to ensure a particular position is on the first
		// line of the page.
		if (visibleLine == 0) {
			int startWithinLine = nPrintPos - pdoc->LineStart(lineDoc);
			for (int iwl = 0; iwl < ll.lines - 1; iwl++) {
				if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) {
					visibleLine = -iwl;
				}
			}

			if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) {
				visibleLine = -(ll.lines - 1);
			}
		}

		if (draw && lineNumberWidth &&
		        (ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
		        (visibleLine >= 0)) {
			char number[100];
			sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1);
			PRectangle rcNumber = rcLine;
			rcNumber.right = rcNumber.left + lineNumberWidth;
			// Right justify
			rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
			            vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number));
			surface->FlushCachedState();
			surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
			        ypos + vsPrint.maxAscent, number, istrlen(number),
			        vsPrint.styles[STYLE_LINENUMBER].fore,
			        vsPrint.styles[STYLE_LINENUMBER].back);
		}

		// Draw the line
		surface->FlushCachedState();

		for (int iwl = 0; iwl < ll.lines; iwl++) {
			if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
				if (visibleLine >= 0) {
					if (draw) {
						rcLine.top = ypos;
						rcLine.bottom = ypos + vsPrint.lineHeight;
						DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl);
					}
					ypos += vsPrint.lineHeight;
				}
				visibleLine++;
				if (iwl == ll.lines - 1)
					nPrintPos = pdoc->LineStart(lineDoc + 1);
				else
					nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl);
			}
		}

		++lineDoc;
	}

	// Clear cache so measurements are not used for screen
	posCache.Clear();

	return nPrintPos;
}

int Editor::TextWidth(int style, const char *text) {
	RefreshStyleData();
	AutoSurface surface(this);
	if (surface) {
		return surface->WidthText(vs.styles[style].font, text, istrlen(text));
	} else {
		return 1;
	}
}

// Empty method is overridden on GTK+ to show / hide scrollbars
void Editor::ReconfigureScrollBars() {}

void Editor::SetScrollBars() {
	RefreshStyleData();

	int nMax = MaxScrollPos();
	int nPage = LinesOnScreen();
	bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
	if (modified) {
		DwellEnd(true);
	}

	// TODO: ensure always showing as many lines as possible
	// May not be, if, for example, window made larger
	if (topLine > MaxScrollPos()) {
		SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
		SetVerticalScrollPos();
		Redraw();
	}
	if (modified) {
		if (!AbandonPaint())
			Redraw();
	}
	//Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
}

void Editor::ChangeSize() {
	DropGraphics(false);
	SetScrollBars();
	if (wrapState != eWrapNone) {
		PRectangle rcTextArea = GetClientRectangle();
		rcTextArea.left = vs.textStart;
		rcTextArea.right -= vs.rightMarginWidth;
		if (wrapWidth != rcTextArea.Width()) {
			NeedWrapping();
			Redraw();
		}
	}
}

int Editor::InsertSpace(int position, unsigned int spaces) {
	if (spaces > 0) {
		std::string spaceText(spaces, ' ');
		pdoc->InsertString(position, spaceText.c_str(), spaces);
		position += spaces;
	}
	return position;
}

void Editor::AddChar(char ch) {
	char s[2];
	s[0] = ch;
	s[1] = '\0';
	AddCharUTF(s, 1);
}

void Editor::FilterSelections() {
	if (!additionalSelectionTyping && (sel.Count() > 1)) {
		SelectionRange rangeOnly = sel.RangeMain();
		InvalidateSelection(rangeOnly, true);
		sel.SetSelection(rangeOnly);
	}
}

static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) {
	return *a < *b;
}

// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
	FilterSelections();
	{
		UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);

		std::vector<SelectionRange *> selPtrs;
		for (size_t r = 0; r < sel.Count(); r++) {
			selPtrs.push_back(&sel.Range(r));
		}
		std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs);

		for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
			rit != selPtrs.rend(); ++rit) {
			SelectionRange *currentSel = *rit;
			if (!RangeContainsProtected(currentSel->Start().Position(),
				currentSel->End().Position())) {
				int positionInsert = currentSel->Start().Position();
				if (!currentSel->Empty()) {
					if (currentSel->Length()) {
						pdoc->DeleteChars(positionInsert, currentSel->Length());
						currentSel->ClearVirtualSpace();
					} else {
						// Range is all virtual so collapse to start of virtual space
						currentSel->MinimizeVirtualSpace();
					}
				} else if (inOverstrike) {
					if (positionInsert < pdoc->Length()) {
						if (!pdoc->IsPositionInLineEnd(positionInsert)) {
							pdoc->DelChar(positionInsert);
							currentSel->ClearVirtualSpace();
						}
					}
				}
				positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace());
				if (pdoc->InsertString(positionInsert, s, len)) {
					currentSel->caret.SetPosition(positionInsert + len);
					currentSel->anchor.SetPosition(positionInsert + len);
				}
				currentSel->ClearVirtualSpace();
				// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
				if (wrapState != eWrapNone) {
					AutoSurface surface(this);
					if (surface) {
						if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) {
							SetScrollBars();
							SetVerticalScrollPos();
							Redraw();
						}
					}
				}
			}
		}
	}
	if (wrapState != eWrapNone) {
		SetScrollBars();
	}
	ThinRectangularRange();
	// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
	EnsureCaretVisible();
	// Avoid blinking during rapid typing:
	ShowCaretAtCurrentPosition();
	if ((caretSticky == SC_CARETSTICKY_OFF) ||
		((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(s, len))) {
		SetLastXChosen();
	}

	if (treatAsDBCS) {
		NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
		        static_cast<unsigned char>(s[1]));
	} else {
		int byte = static_cast<unsigned char>(s[0]);
		if ((byte < 0xC0) || (1 == len)) {
			// Handles UTF-8 characters between 0x01 and 0x7F and single byte
			// characters when not in UTF-8 mode.
			// Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
			// characters representing themselves.
		} else {
			// Unroll 1 to 3 byte UTF-8 sequences.  See reference data at:
			// http://www.cl.cam.ac.uk/~mgk25/unicode.html
			// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
			if (byte < 0xE0) {
				int byte2 = static_cast<unsigned char>(s[1]);
				if ((byte2 & 0xC0) == 0x80) {
					// Two-byte-character lead-byte followed by a trail-byte.
					byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F));
				}
				// A two-byte-character lead-byte not followed by trail-byte
				// represents itself.
			} else if (byte < 0xF0) {
				int byte2 = static_cast<unsigned char>(s[1]);
				int byte3 = static_cast<unsigned char>(s[2]);
				if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) {
					// Three-byte-character lead byte followed by two trail bytes.
					byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
					        (byte3 & 0x3F));
				}
				// A three-byte-character lead-byte not followed by two trail-bytes
				// represents itself.
			}
		}
		NotifyChar(byte);
	}

	if (recordingMacro) {
		NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(s));
	}
}

void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) {
	if (multiPasteMode == SC_MULTIPASTE_ONCE) {
		selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace()));
		if (pdoc->InsertString(selStart.Position(), text, len)) {
			SetEmptySelection(selStart.Position() + len);
		}
	} else {
		// SC_MULTIPASTE_EACH
		for (size_t r=0; r<sel.Count(); r++) {
			if (!RangeContainsProtected(sel.Range(r).Start().Position(),
				sel.Range(r).End().Position())) {
				int positionInsert = sel.Range(r).Start().Position();
				if (!sel.Range(r).Empty()) {
					if (sel.Range(r).Length()) {
						pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
						sel.Range(r).ClearVirtualSpace();
					} else {
						// Range is all virtual so collapse to start of virtual space
						sel.Range(r).MinimizeVirtualSpace();
					}
				}
				positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
				if (pdoc->InsertString(positionInsert, text, len)) {
					sel.Range(r).caret.SetPosition(positionInsert + len);
					sel.Range(r).anchor.SetPosition(positionInsert + len);
				}
				sel.Range(r).ClearVirtualSpace();
			}
		}
	}
}

void Editor::ClearSelection(bool retainMultipleSelections) {
	if (!sel.IsRectangular() && !retainMultipleSelections)
		FilterSelections();
	UndoGroup ug(pdoc);
	for (size_t r=0; r<sel.Count(); r++) {
		if (!sel.Range(r).Empty()) {
			if (!RangeContainsProtected(sel.Range(r).Start().Position(),
				sel.Range(r).End().Position())) {
				pdoc->DeleteChars(sel.Range(r).Start().Position(),
					sel.Range(r).Length());
				sel.Range(r) = sel.Range(r).Start();
			}
		}
	}
	ThinRectangularRange();
	sel.RemoveDuplicates();
	ClaimSelection();
}

void Editor::ClearAll() {
	{
		UndoGroup ug(pdoc);
		if (0 != pdoc->Length()) {
			pdoc->DeleteChars(0, pdoc->Length());
		}
		if (!pdoc->IsReadOnly()) {
			cs.Clear();
			pdoc->AnnotationClearAll();
			pdoc->MarginClearAll();
		}
	}
	sel.Clear();
	SetTopLine(0);
	SetVerticalScrollPos();
	InvalidateStyleRedraw();
}

void Editor::ClearDocumentStyle() {
	Decoration *deco = pdoc->decorations.root;
	while (deco) {
		// Save next in case deco deleted
		Decoration *decoNext = deco->next;
		if (deco->indicator < INDIC_CONTAINER) {
			pdoc->decorations.SetCurrentIndicator(deco->indicator);
			pdoc->DecorationFillRange(0, 0, pdoc->Length());
		}
		deco = decoNext;
	}
	pdoc->StartStyling(0, '\377');
	pdoc->SetStyleFor(pdoc->Length(), 0);
	cs.ShowAll();
	pdoc->ClearLevels();
}

void Editor::CopyAllowLine() {
	SelectionText selectedText;
	CopySelectionRange(&selectedText, true);
	CopyToClipboard(selectedText);
}

void Editor::Cut() {
	pdoc->CheckReadOnly();
	if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
		Copy();
		ClearSelection();
	}
}

void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
	if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
		return;
	}
	sel.Clear();
	sel.RangeMain() = SelectionRange(pos);
	int line = pdoc->LineFromPosition(sel.MainCaret());
	UndoGroup ug(pdoc);
	sel.RangeMain().caret = SelectionPosition(
		InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
	int xInsert = XFromPosition(sel.RangeMain().caret);
	bool prevCr = false;
	while ((len > 0) && IsEOLChar(ptr[len-1]))
		len--;
	for (int i = 0; i < len; i++) {
		if (IsEOLChar(ptr[i])) {
			if ((ptr[i] == '\r') || (!prevCr))
				line++;
			if (line >= pdoc->LinesTotal()) {
				if (pdoc->eolMode != SC_EOL_LF)
					pdoc->InsertChar(pdoc->Length(), '\r');
				if (pdoc->eolMode != SC_EOL_CR)
					pdoc->InsertChar(pdoc->Length(), '\n');
			}
			// Pad the end of lines with spaces if required
			sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert));
			if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) {
				while (XFromPosition(sel.MainCaret()) < xInsert) {
					pdoc->InsertChar(sel.MainCaret(), ' ');
					sel.RangeMain().caret.Add(1);
				}
			}
			prevCr = ptr[i] == '\r';
		} else {
			pdoc->InsertString(sel.MainCaret(), ptr + i, 1);
			sel.RangeMain().caret.Add(1);
			prevCr = false;
		}
	}
	SetEmptySelection(pos);
}

bool Editor::CanPaste() {
	return !pdoc->IsReadOnly() && !SelectionContainsProtected();
}

void Editor::Clear() {
	// If multiple selections, don't delete EOLS
	if (sel.Empty()) {
		bool singleVirtual = false;
		if ((sel.Count() == 1) &&
			!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) &&
			sel.RangeMain().Start().VirtualSpace()) {
			singleVirtual = true;
		}
		UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual);
		for (size_t r=0; r<sel.Count(); r++) {
			if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
				if (sel.Range(r).Start().VirtualSpace()) {
					if (sel.Range(r).anchor < sel.Range(r).caret)
						sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).anchor.Position(), sel.Range(r).anchor.VirtualSpace()));
					else
						sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
				}
				if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
					pdoc->DelChar(sel.Range(r).caret.Position());
					sel.Range(r).ClearVirtualSpace();
				}  // else multiple selection so don't eat line ends
			} else {
				sel.Range(r).ClearVirtualSpace();
			}
		}
	} else {
		ClearSelection();
	}
	sel.RemoveDuplicates();
}

void Editor::SelectAll() {
	sel.Clear();
	SetSelection(0, pdoc->Length());
	Redraw();
}

void Editor::Undo() {
	if (pdoc->CanUndo()) {
		InvalidateCaret();
		int newPos = pdoc->Undo();
		if (newPos >= 0)
			SetEmptySelection(newPos);
		EnsureCaretVisible();
	}
}

void Editor::Redo() {
	if (pdoc->CanRedo()) {
		int newPos = pdoc->Redo();
		if (newPos >= 0)
			SetEmptySelection(newPos);
		EnsureCaretVisible();
	}
}

void Editor::DelChar() {
	if (!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1)) {
		pdoc->DelChar(sel.MainCaret());
	}
	// Avoid blinking during rapid typing:
	ShowCaretAtCurrentPosition();
}

void Editor::DelCharBack(bool allowLineStartDeletion) {
	if (!sel.IsRectangular())
		FilterSelections();
	if (sel.IsRectangular())
		allowLineStartDeletion = false;
	UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
	if (sel.Empty()) {
		for (size_t r=0; r<sel.Count(); r++) {
			if (!RangeContainsProtected(sel.Range(r).caret.Position() - 1, sel.Range(r).caret.Position())) {
				if (sel.Range(r).caret.VirtualSpace()) {
					sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1);
					sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace());
				} else {
					int lineCurrentPos = pdoc->LineFromPosition(sel.Range(r).caret.Position());
					if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
						if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
								pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
							UndoGroup ugInner(pdoc, !ug.Needed());
							int indentation = pdoc->GetLineIndentation(lineCurrentPos);
							int indentationStep = pdoc->IndentSize();
							if (indentation % indentationStep == 0) {
								pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
							} else {
								pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep));
							}
							// SetEmptySelection
							sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos),
								pdoc->GetLineIndentPosition(lineCurrentPos));
						} else {
							pdoc->DelCharBack(sel.Range(r).caret.Position());
						}
					}
				}
			} else {
				sel.Range(r).ClearVirtualSpace();
			}
		}
		ThinRectangularRange();
	} else {
		ClearSelection();
	}
	sel.RemoveDuplicates();
	ContainerNeedsUpdate(SC_UPDATE_SELECTION);
	// Avoid blinking during rapid typing:
	ShowCaretAtCurrentPosition();
}

void Editor::NotifyFocus(bool) {}

void Editor::SetCtrlID(int identifier) {
	ctrlID = identifier; 
}

void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_STYLENEEDED;
	scn.position = endStyleNeeded;
	NotifyParent(scn);
}

void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) {
	NotifyStyleToNeeded(endStyleNeeded);
}

void Editor::NotifyLexerChanged(Document *, void *) {
}

void Editor::NotifyErrorOccurred(Document *, void *, int status) {
	errorStatus = status;
}

void Editor::NotifyChar(int ch) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_CHARADDED;
	scn.ch = ch;
	NotifyParent(scn);
}

void Editor::NotifySavePoint(bool isSavePoint) {
	SCNotification scn = {0};
	if (isSavePoint) {
		scn.nmhdr.code = SCN_SAVEPOINTREACHED;
	} else {
		scn.nmhdr.code = SCN_SAVEPOINTLEFT;
	}
	NotifyParent(scn);
}

void Editor::NotifyModifyAttempt() {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
	NotifyParent(scn);
}

void Editor::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_DOUBLECLICK;
	scn.line = LineFromLocation(pt);
	scn.position = PositionFromLocation(pt, true);
	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
	        (alt ? SCI_ALT : 0);
	NotifyParent(scn);
}

void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
	scn.position = position;
	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
	        (alt ? SCI_ALT : 0);
	NotifyParent(scn);
}

void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_HOTSPOTCLICK;
	scn.position = position;
	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
	        (alt ? SCI_ALT : 0);
	NotifyParent(scn);
}

void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK;
	scn.position = position;
	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
	        (alt ? SCI_ALT : 0);
	NotifyParent(scn);
}

bool Editor::NotifyUpdateUI() {
	if (needUpdateUI) {
		SCNotification scn = {0};
		scn.nmhdr.code = SCN_UPDATEUI;
		scn.updated = needUpdateUI;
		NotifyParent(scn);
		needUpdateUI = 0;
		return true;
	}
	return false;
}

void Editor::NotifyPainted() {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_PAINTED;
	NotifyParent(scn);
}

void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt) {
	int mask = pdoc->decorations.AllOnFor(position);
	if ((click && mask) || pdoc->decorations.clickNotified) {
		SCNotification scn = {0};
		pdoc->decorations.clickNotified = click;
		scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE;
		scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0);
		scn.position = position;
		NotifyParent(scn);
	}
}

bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
	int marginClicked = -1;
	int x = vs.textStart - vs.fixedColumnWidth;
	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
		if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
			marginClicked = margin;
		x += vs.ms[margin].width;
	}
	if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
		SCNotification scn = {0};
		scn.nmhdr.code = SCN_MARGINCLICK;
		scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
		        (alt ? SCI_ALT : 0);
		scn.position = pdoc->LineStart(LineFromLocation(pt));
		scn.margin = marginClicked;
		NotifyParent(scn);
		return true;
	} else {
		return false;
	}
}

void Editor::NotifyNeedShown(int pos, int len) {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_NEEDSHOWN;
	scn.position = pos;
	scn.length = len;
	NotifyParent(scn);
}

void Editor::NotifyDwelling(Point pt, bool state) {
	SCNotification scn = {0};
	scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
	scn.position = PositionFromLocation(pt, true);
	scn.x = pt.x;
	scn.y = pt.y;
	NotifyParent(scn);
}

void Editor::NotifyZoom() {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_ZOOM;
	NotifyParent(scn);
}

// Notifications from document
void Editor::NotifyModifyAttempt(Document *, void *) {
	//Platform::DebugPrintf("** Modify Attempt\n");
	NotifyModifyAttempt();
}

void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) {
	//Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
	NotifySavePoint(atSavePoint);
}

void Editor::CheckModificationForWrap(DocModification mh) {
	if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
		llc.Invalidate(LineLayout::llCheckTextAndStyle);
		int lineDoc = pdoc->LineFromPosition(mh.position);
		int lines = Platform::Maximum(0, mh.linesAdded);
		if (wrapState != eWrapNone) {
			NeedWrapping(lineDoc, lineDoc + lines + 1);
		}
		RefreshStyleData();
		// Fix up annotation heights
		SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
	}
}

// Move a position so it is still after the same character as before the insertion.
static inline int MovePositionForInsertion(int position, int startInsertion, int length) {
	if (position > startInsertion) {
		return position + length;
	}
	return position;
}

// Move a position so it is still after the same character as before the deletion if that
// character is still present else after the previous surviving character.
static inline int MovePositionForDeletion(int position, int startDeletion, int length) {
	if (position > startDeletion) {
		int endDeletion = startDeletion + length;
		if (position > endDeletion) {
			return position - length;
		} else {
			return startDeletion;
		}
	} else {
		return position;
	}
}

void Editor::NotifyModified(Document *, DocModification mh, void *) {
	ContainerNeedsUpdate(SC_UPDATE_CONTENT);
	if (paintState == painting) {
		CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
	}
	if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
		if (paintState == painting) {
			CheckForChangeOutsidePaint(
			    Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
		} else {
			// Could check that change is before last visible line.
			Redraw();
		}
	}
	if (mh.modificationType & SC_MOD_LEXERSTATE) {
		if (paintState == painting) {
			CheckForChangeOutsidePaint(
			    Range(mh.position, mh.position + mh.length));
		} else {
			Redraw();
		}
	}
	if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
		if (mh.modificationType & SC_MOD_CHANGESTYLE) {
			pdoc->IncrementStyleClock();
		}
		if (paintState == notPainting) {
			if (mh.position < pdoc->LineStart(topLine)) {
				// Styling performed before this view
				Redraw();
			} else {
				InvalidateRange(mh.position, mh.position + mh.length);
			}
		}
		if (mh.modificationType & SC_MOD_CHANGESTYLE) {
			llc.Invalidate(LineLayout::llCheckTextAndStyle);
		}
	} else {
		// Move selection and brace highlights
		if (mh.modificationType & SC_MOD_INSERTTEXT) {
			sel.MovePositions(true, mh.position, mh.length);
			braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
			braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
		} else if (mh.modificationType & SC_MOD_DELETETEXT) {
			sel.MovePositions(false, mh.position, mh.length);
			braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
			braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
		}
		if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && cs.HiddenLines()) {
			// Some lines are hidden so may need shown.
			// TODO: check if the modified area is hidden.
			if (mh.modificationType & SC_MOD_BEFOREINSERT) {
				int lineOfPos = pdoc->LineFromPosition(mh.position);
				bool insertingNewLine = false;
				for (int i=0; i < mh.length; i++) {
					if ((mh.text[i] == '\n') || (mh.text[i] == '\r'))
						insertingNewLine = true;
				}
				if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos)))
					NotifyNeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position);
				else
					NotifyNeedShown(mh.position, 0);
			} else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
				NotifyNeedShown(mh.position, mh.length);
			}
		}
		if (mh.linesAdded != 0) {
			// Update contraction state for inserted and removed lines
			// lineOfPos should be calculated in context of state before modification, shouldn't it
			int lineOfPos = pdoc->LineFromPosition(mh.position);
			if (mh.linesAdded > 0) {
				cs.InsertLines(lineOfPos, mh.linesAdded);
			} else {
				cs.DeleteLines(lineOfPos, -mh.linesAdded);
			}
		}
		if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
			int lineDoc = pdoc->LineFromPosition(mh.position);
			if (vs.annotationVisible) {
				cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded);
				Redraw();
			}
		}
		CheckModificationForWrap(mh);
		if (mh.linesAdded != 0) {
			// Avoid scrolling of display if change before current display
			if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
				int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
				if (newTop != topLine) {
					SetTopLine(newTop);
					SetVerticalScrollPos();
				}
			}

			if (paintState == notPainting && !CanDeferToLastStep(mh)) {
				QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
				Redraw();
			}
		} else {
			if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
				QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
				InvalidateRange(mh.position, mh.position + mh.length);
			}
		}
	}

	if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
		SetScrollBars();
	}

	if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
		if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) {
			if (mh.modificationType & SC_MOD_CHANGEFOLD) {
				// Fold changes can affect the drawing of following lines so redraw whole margin
				RedrawSelMargin(highlightDelimiter.isEnabled ? -1 : mh.line-1, true);
			} else {
				RedrawSelMargin(mh.line);
			}
		}
	}

	// NOW pay the piper WRT "deferred" visual updates
	if (IsLastStep(mh)) {
		SetScrollBars();
		Redraw();
	}

	// If client wants to see this modification
	if (mh.modificationType & modEventMask) {
		if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
			// Real modification made to text of document.
			NotifyChange();	// Send EN_CHANGE
		}

		SCNotification scn = {0};
		scn.nmhdr.code = SCN_MODIFIED;
		scn.position = mh.position;
		scn.modificationType = mh.modificationType;
		scn.text = mh.text;
		scn.length = mh.length;
		scn.linesAdded = mh.linesAdded;
		scn.line = mh.line;
		scn.foldLevelNow = mh.foldLevelNow;
		scn.foldLevelPrev = mh.foldLevelPrev;
		scn.token = mh.token;
		scn.annotationLinesAdded = mh.annotationLinesAdded;
		NotifyParent(scn);
	}
}

void Editor::NotifyDeleted(Document *, void *) {
	/* Do nothing */
}

void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {

	// Enumerates all macroable messages
	switch (iMessage) {
	case SCI_CUT:
	case SCI_COPY:
	case SCI_PASTE:
	case SCI_CLEAR:
	case SCI_REPLACESEL:
	case SCI_ADDTEXT:
	case SCI_INSERTTEXT:
	case SCI_APPENDTEXT:
	case SCI_CLEARALL:
	case SCI_SELECTALL:
	case SCI_GOTOLINE:
	case SCI_GOTOPOS:
	case SCI_SEARCHANCHOR:
	case SCI_SEARCHNEXT:
	case SCI_SEARCHPREV:
	case SCI_LINEDOWN:
	case SCI_LINEDOWNEXTEND:
	case SCI_PARADOWN:
	case SCI_PARADOWNEXTEND:
	case SCI_LINEUP:
	case SCI_LINEUPEXTEND:
	case SCI_PARAUP:
	case SCI_PARAUPEXTEND:
	case SCI_CHARLEFT:
	case SCI_CHARLEFTEXTEND:
	case SCI_CHARRIGHT:
	case SCI_CHARRIGHTEXTEND:
	case SCI_WORDLEFT:
	case SCI_WORDLEFTEXTEND:
	case SCI_WORDRIGHT:
	case SCI_WORDRIGHTEXTEND:
	case SCI_WORDPARTLEFT:
	case SCI_WORDPARTLEFTEXTEND:
	case SCI_WORDPARTRIGHT:
	case SCI_WORDPARTRIGHTEXTEND:
	case SCI_WORDLEFTEND:
	case SCI_WORDLEFTENDEXTEND:
	case SCI_WORDRIGHTEND:
	case SCI_WORDRIGHTENDEXTEND:
	case SCI_HOME:
	case SCI_HOMEEXTEND:
	case SCI_LINEEND:
	case SCI_LINEENDEXTEND:
	case SCI_HOMEWRAP:
	case SCI_HOMEWRAPEXTEND:
	case SCI_LINEENDWRAP:
	case SCI_LINEENDWRAPEXTEND:
	case SCI_DOCUMENTSTART:
	case SCI_DOCUMENTSTARTEXTEND:
	case SCI_DOCUMENTEND:
	case SCI_DOCUMENTENDEXTEND:
	case SCI_STUTTEREDPAGEUP:
	case SCI_STUTTEREDPAGEUPEXTEND:
	case SCI_STUTTEREDPAGEDOWN:
	case SCI_STUTTEREDPAGEDOWNEXTEND:
	case SCI_PAGEUP:
	case SCI_PAGEUPEXTEND:
	case SCI_PAGEDOWN:
	case SCI_PAGEDOWNEXTEND:
	case SCI_EDITTOGGLEOVERTYPE:
	case SCI_CANCEL:
	case SCI_DELETEBACK:
	case SCI_TAB:
	case SCI_BACKTAB:
	case SCI_FORMFEED:
	case SCI_VCHOME:
	case SCI_VCHOMEEXTEND:
	case SCI_VCHOMEWRAP:
	case SCI_VCHOMEWRAPEXTEND:
	case SCI_VCHOMEDISPLAY:
	case SCI_VCHOMEDISPLAYEXTEND:
	case SCI_DELWORDLEFT:
	case SCI_DELWORDRIGHT:
	case SCI_DELWORDRIGHTEND:
	case SCI_DELLINELEFT:
	case SCI_DELLINERIGHT:
	case SCI_LINECOPY:
	case SCI_LINECUT:
	case SCI_LINEDELETE:
	case SCI_LINETRANSPOSE:
	case SCI_LINEDUPLICATE:
	case SCI_LOWERCASE:
	case SCI_UPPERCASE:
	case SCI_LINESCROLLDOWN:
	case SCI_LINESCROLLUP:
	case SCI_DELETEBACKNOTLINE:
	case SCI_HOMEDISPLAY:
	case SCI_HOMEDISPLAYEXTEND:
	case SCI_LINEENDDISPLAY:
	case SCI_LINEENDDISPLAYEXTEND:
	case SCI_SETSELECTIONMODE:
	case SCI_LINEDOWNRECTEXTEND:
	case SCI_LINEUPRECTEXTEND:
	case SCI_CHARLEFTRECTEXTEND:
	case SCI_CHARRIGHTRECTEXTEND:
	case SCI_HOMERECTEXTEND:
	case SCI_VCHOMERECTEXTEND:
	case SCI_LINEENDRECTEXTEND:
	case SCI_PAGEUPRECTEXTEND:
	case SCI_PAGEDOWNRECTEXTEND:
	case SCI_SELECTIONDUPLICATE:
	case SCI_COPYALLOWLINE:
	case SCI_VERTICALCENTRECARET:
	case SCI_MOVESELECTEDLINESUP:
	case SCI_MOVESELECTEDLINESDOWN:
	case SCI_SCROLLTOSTART:
	case SCI_SCROLLTOEND:
		break;

		// Filter out all others like display changes. Also, newlines are redundant
		// with char insert messages.
	case SCI_NEWLINE:
	default:
		//		printf("Filtered out %ld of macro recording\n", iMessage);
		return ;
	}

	// Send notification
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_MACRORECORD;
	scn.message = iMessage;
	scn.wParam = wParam;
	scn.lParam = lParam;
	NotifyParent(scn);
}

// Something has changed that the container should know about
void Editor::ContainerNeedsUpdate(int flags) {
	needUpdateUI |= flags;
}

/**
 * Force scroll and keep position relative to top of window.
 *
 * If stuttered = true and not already at first/last row, move to first/last row of window.
 * If stuttered = true and already at first/last row, scroll as normal.
 */
void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
	int topLineNew;
	SelectionPosition newPos;

	int currentLine = pdoc->LineFromPosition(sel.MainCaret());
	int topStutterLine = topLine + caretYSlop;
	int bottomStutterLine =
	    pdoc->LineFromPosition(PositionFromLocation(
	                Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll())))
	    - caretYSlop - 1;

	if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
		topLineNew = topLine;
		newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop),
			false, false, UserVirtualSpace());

	} else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
		topLineNew = topLine;
		newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)),
			false, false, UserVirtualSpace());

	} else {
		Point pt = LocationFromPosition(sel.MainCaret());

		topLineNew = Platform::Clamp(
		            topLine + direction * LinesToScroll(), 0, MaxScrollPos());
		newPos = SPositionFromLocation(
			Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())),
			false, false, UserVirtualSpace());
	}

	if (topLineNew != topLine) {
		SetTopLine(topLineNew);
		MovePositionTo(newPos, selt);
		Redraw();
		SetVerticalScrollPos();
	} else {
		MovePositionTo(newPos, selt);
	}
}

void Editor::ChangeCaseOfSelection(int caseMapping) {
	UndoGroup ug(pdoc);
	for (size_t r=0; r<sel.Count(); r++) {
		SelectionRange current = sel.Range(r);
		SelectionRange currentNoVS = current;
		currentNoVS.ClearVirtualSpace();
		char *text = CopyRange(currentNoVS.Start().Position(), currentNoVS.End().Position());
		size_t rangeBytes = currentNoVS.Length();
		if (rangeBytes > 0) {
			std::string sText(text, rangeBytes);

			std::string sMapped = CaseMapString(sText, caseMapping);

			if (sMapped != sText) {
				size_t firstDifference = 0;
				while (sMapped[firstDifference] == sText[firstDifference])
					firstDifference++;
				size_t lastDifference = sMapped.size() - 1;
				while (sMapped[lastDifference] == sText[lastDifference])
					lastDifference--;
				size_t endSame = sMapped.size() - 1 - lastDifference;
				pdoc->DeleteChars(
					static_cast<int>(currentNoVS.Start().Position() + firstDifference),
					static_cast<int>(rangeBytes - firstDifference - endSame));
				pdoc->InsertString(
					static_cast<int>(currentNoVS.Start().Position() + firstDifference),
					sMapped.c_str() + firstDifference,
					static_cast<int>(lastDifference - firstDifference + 1));
				// Automatic movement changes selection so reset to exactly the same as it was.
				sel.Range(r) = current;
			}
		}
		delete []text;
	}
}

void Editor::LineTranspose() {
	int line = pdoc->LineFromPosition(sel.MainCaret());
	if (line > 0) {
		UndoGroup ug(pdoc);
		int startPrev = pdoc->LineStart(line - 1);
		int endPrev = pdoc->LineEnd(line - 1);
		int start = pdoc->LineStart(line);
		int end = pdoc->LineEnd(line);
		char *line1 = CopyRange(startPrev, endPrev);
		int len1 = endPrev - startPrev;
		char *line2 = CopyRange(start, end);
		int len2 = end - start;
		pdoc->DeleteChars(start, len2);
		pdoc->DeleteChars(startPrev, len1);
		pdoc->InsertString(startPrev, line2, len2);
		pdoc->InsertString(start - len1 + len2, line1, len1);
		MovePositionTo(SelectionPosition(start - len1 + len2));
		delete []line1;
		delete []line2;
	}
}

void Editor::Duplicate(bool forLine) {
	if (sel.Empty()) {
		forLine = true;
	}
	UndoGroup ug(pdoc);
	const char *eol = "";
	int eolLen = 0;
	if (forLine) {
		eol = StringFromEOLMode(pdoc->eolMode);
		eolLen = istrlen(eol);
	}
	for (size_t r=0; r<sel.Count(); r++) {
		SelectionPosition start = sel.Range(r).Start();
		SelectionPosition end = sel.Range(r).End();
		if (forLine) {
			int line = pdoc->LineFromPosition(sel.Range(r).caret.Position());
			start = SelectionPosition(pdoc->LineStart(line));
			end = SelectionPosition(pdoc->LineEnd(line));
		}
		char *text = CopyRange(start.Position(), end.Position());
		if (forLine)
			pdoc->InsertString(end.Position(), eol, eolLen);
		pdoc->InsertString(end.Position() + eolLen, text, SelectionRange(end, start).Length());
		delete []text;
	}
	if (sel.Count() && sel.IsRectangular()) {
		SelectionPosition last = sel.Last();
		if (forLine) {
			int line = pdoc->LineFromPosition(last.Position());
			last = SelectionPosition(last.Position() + pdoc->LineStart(line+1) - pdoc->LineStart(line));
		}
		if (sel.Rectangular().anchor > sel.Rectangular().caret)
			sel.Rectangular().anchor = last;
		else
			sel.Rectangular().caret = last;
		SetRectangularRange();
	}
}

void Editor::CancelModes() {
	sel.SetMoveExtends(false);
}

void Editor::NewLine() {
	// Remove non-main ranges
	InvalidateSelection(sel.RangeMain(), true);
	sel.SetSelection(sel.RangeMain());

	// Clear main range and insert line end
	bool needGroupUndo = !sel.Empty();
	if (needGroupUndo)
		pdoc->BeginUndoAction();

	if (!sel.Empty())
		ClearSelection();
	const char *eol = "\n";
	if (pdoc->eolMode == SC_EOL_CRLF) {
		eol = "\r\n";
	} else if (pdoc->eolMode == SC_EOL_CR) {
		eol = "\r";
	} // else SC_EOL_LF -> "\n" already set
	bool inserted = pdoc->InsertCString(sel.MainCaret(), eol);
	// Want to end undo group before NotifyChar as applications often modify text here
	if (needGroupUndo)
		pdoc->EndUndoAction();
	if (inserted) {
		SetEmptySelection(sel.MainCaret() + istrlen(eol));
		while (*eol) {
			NotifyChar(*eol);
			if (recordingMacro) {
				char txt[2];
				txt[0] = *eol;
				txt[1] = '\0';
				NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(txt));
			}
			eol++;
		}
	}
	SetLastXChosen();
	SetScrollBars();
	EnsureCaretVisible();
	// Avoid blinking during rapid typing:
	ShowCaretAtCurrentPosition();
}

void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
	SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
	if (sel.IsRectangular()) {
		if (selt ==  Selection::noSel) {
			caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start;
		} else {
			caretToUse = sel.Rectangular().caret;
		}
	}

	Point pt = LocationFromPosition(caretToUse);
	int skipLines = 0;

	if (vs.annotationVisible) {
		int lineDoc = pdoc->LineFromPosition(caretToUse.Position());
		Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
		int subLine = (pt.y - ptStartLine.y) / vs.lineHeight;

		if (direction < 0 && subLine == 0) {
			int lineDisplay = cs.DisplayFromDoc(lineDoc);
			if (lineDisplay > 0) {
				skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1));
			}
		} else if (direction > 0 && subLine >= (cs.GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) {
			skipLines = pdoc->AnnotationLines(lineDoc);
		}
	}

	int newY = pt.y + (1 + skipLines) * direction * vs.lineHeight;
	SelectionPosition posNew = SPositionFromLocation(
	            Point(lastXChosen - xOffset, newY), false, false, UserVirtualSpace());

	if (direction < 0) {
		// Line wrapping may lead to a location on the same line, so
		// seek back if that is the case.
		Point ptNew = LocationFromPosition(posNew.Position());
		while ((posNew.Position() > 0) && (pt.y == ptNew.y)) {
			posNew.Add(-1);
			posNew.SetVirtualSpace(0);
			ptNew = LocationFromPosition(posNew.Position());
		}
	} else if (direction > 0 && posNew.Position() != pdoc->Length()) {
		// There is an equivalent case when moving down which skips
		// over a line.
		Point ptNew = LocationFromPosition(posNew.Position());
		while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) {
			posNew.Add(-1);
			posNew.SetVirtualSpace(0);
			ptNew = LocationFromPosition(posNew.Position());
		}
	}

	MovePositionTo(MovePositionSoVisible(posNew, direction), selt);
}

void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) {
	int lineDoc, savedPos = sel.MainCaret();
	do {
		MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt);
		lineDoc = pdoc->LineFromPosition(sel.MainCaret());
		if (direction > 0) {
			if (sel.MainCaret() >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
				if (selt == Selection::noSel) {
					MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos)));
				}
				break;
			}
		}
	} while (!cs.GetVisible(lineDoc));
}

int Editor::StartEndDisplayLine(int pos, bool start) {
	RefreshStyleData();
	int line = pdoc->LineFromPosition(pos);
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(line));
	int posRet = INVALID_POSITION;
	if (surface && ll) {
		unsigned int posLineStart = pdoc->LineStart(line);
		LayoutLine(line, surface, vs, ll, wrapWidth);
		int posInLine = pos - posLineStart;
		if (posInLine <= ll->maxLineLength) {
			for (int subLine = 0; subLine < ll->lines; subLine++) {
				if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
					if (start) {
						posRet = ll->LineStart(subLine) + posLineStart;
					} else {
						if (subLine == ll->lines - 1)
							posRet = ll->LineStart(subLine + 1) + posLineStart;
						else
							posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
					}
				}
			}
		}
	}
	if (posRet == INVALID_POSITION) {
		return pos;
	} else {
		return posRet;
	}
}

int Editor::KeyCommand(unsigned int iMessage) {
	switch (iMessage) {
	case SCI_LINEDOWN:
		CursorUpOrDown(1);
		break;
	case SCI_LINEDOWNEXTEND:
		CursorUpOrDown(1, Selection::selStream);
		break;
	case SCI_LINEDOWNRECTEXTEND:
		CursorUpOrDown(1, Selection::selRectangle);
		break;
	case SCI_PARADOWN:
		ParaUpOrDown(1);
		break;
	case SCI_PARADOWNEXTEND:
		ParaUpOrDown(1, Selection::selStream);
		break;
	case SCI_LINESCROLLDOWN:
		ScrollTo(topLine + 1);
		MoveCaretInsideView(false);
		break;
	case SCI_LINEUP:
		CursorUpOrDown(-1);
		break;
	case SCI_LINEUPEXTEND:
		CursorUpOrDown(-1, Selection::selStream);
		break;
	case SCI_LINEUPRECTEXTEND:
		CursorUpOrDown(-1, Selection::selRectangle);
		break;
	case SCI_PARAUP:
		ParaUpOrDown(-1);
		break;
	case SCI_PARAUPEXTEND:
		ParaUpOrDown(-1, Selection::selStream);
		break;
	case SCI_LINESCROLLUP:
		ScrollTo(topLine - 1);
		MoveCaretInsideView(false);
		break;
	case SCI_CHARLEFT:
		if (SelectionEmpty() || sel.MoveExtends()) {
			if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
				SelectionPosition spCaret = sel.RangeMain().caret;
				spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
				MovePositionTo(spCaret);
			} else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
				MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1));
			} else {
				MovePositionTo(MovePositionSoVisible(
					SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1));
			}
		} else {
			MovePositionTo(sel.LimitsForRectangularElseMain().start);
		}
		SetLastXChosen();
		break;
	case SCI_CHARLEFTEXTEND:
		if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
			SelectionPosition spCaret = sel.RangeMain().caret;
			spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
			MovePositionTo(spCaret, Selection::selStream);
		} else {
			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream);
		}
		SetLastXChosen();
		break;
	case SCI_CHARLEFTRECTEXTEND:
		if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
			SelectionPosition spCaret = sel.RangeMain().caret;
			spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
			MovePositionTo(spCaret, Selection::selRectangle);
		} else {
			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle);
		}
		SetLastXChosen();
		break;
	case SCI_CHARRIGHT:
		if (SelectionEmpty() || sel.MoveExtends()) {
			if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
				SelectionPosition spCaret = sel.RangeMain().caret;
				spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
				MovePositionTo(spCaret);
			} else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
				MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1));
			} else {
				MovePositionTo(MovePositionSoVisible(
					SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1));
			}
		} else {
			MovePositionTo(sel.LimitsForRectangularElseMain().end);
		}
		SetLastXChosen();
		break;
	case SCI_CHARRIGHTEXTEND:
		if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
			SelectionPosition spCaret = sel.RangeMain().caret;
			spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
			MovePositionTo(spCaret, Selection::selStream);
		} else {
			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream);
		}
		SetLastXChosen();
		break;
	case SCI_CHARRIGHTRECTEXTEND:
		if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
			SelectionPosition spCaret = sel.RangeMain().caret;
			spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
			MovePositionTo(spCaret, Selection::selRectangle);
		} else {
			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle);
		}
		SetLastXChosen();
		break;
	case SCI_WORDLEFT:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1));
		SetLastXChosen();
		break;
	case SCI_WORDLEFTEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_WORDRIGHT:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1));
		SetLastXChosen();
		break;
	case SCI_WORDRIGHTEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream);
		SetLastXChosen();
		break;

	case SCI_WORDLEFTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1));
		SetLastXChosen();
		break;
	case SCI_WORDLEFTENDEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_WORDRIGHTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1));
		SetLastXChosen();
		break;
	case SCI_WORDRIGHTENDEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream);
		SetLastXChosen();
		break;

	case SCI_HOME:
		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
		SetLastXChosen();
		break;
	case SCI_HOMEEXTEND:
		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_HOMERECTEXTEND:
		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle);
		SetLastXChosen();
		break;
	case SCI_LINEEND:
		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()));
		SetLastXChosen();
		break;
	case SCI_LINEENDEXTEND:
		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_LINEENDRECTEXTEND:
		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle);
		SetLastXChosen();
		break;
	case SCI_HOMEWRAP: {
			SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if (sel.RangeMain().caret <= homePos)
				homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
			MovePositionTo(homePos);
			SetLastXChosen();
		}
		break;
	case SCI_HOMEWRAPEXTEND: {
			SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if (sel.RangeMain().caret <= homePos)
				homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
			MovePositionTo(homePos, Selection::selStream);
			SetLastXChosen();
		}
		break;
	case SCI_LINEENDWRAP: {
			SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
			SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
			if (endPos > realEndPos      // if moved past visible EOLs
			        || sel.RangeMain().caret >= endPos) // if at end of display line already
				endPos = realEndPos;
			MovePositionTo(endPos);
			SetLastXChosen();
		}
		break;
	case SCI_LINEENDWRAPEXTEND: {
			SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
			SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
			if (endPos > realEndPos      // if moved past visible EOLs
			        || sel.RangeMain().caret >= endPos) // if at end of display line already
				endPos = realEndPos;
			MovePositionTo(endPos, Selection::selStream);
			SetLastXChosen();
		}
		break;
	case SCI_DOCUMENTSTART:
		MovePositionTo(0);
		SetLastXChosen();
		break;
	case SCI_DOCUMENTSTARTEXTEND:
		MovePositionTo(0, Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_DOCUMENTEND:
		MovePositionTo(pdoc->Length());
		SetLastXChosen();
		break;
	case SCI_DOCUMENTENDEXTEND:
		MovePositionTo(pdoc->Length(), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_STUTTEREDPAGEUP:
		PageMove(-1, Selection::noSel, true);
		break;
	case SCI_STUTTEREDPAGEUPEXTEND:
		PageMove(-1, Selection::selStream, true);
		break;
	case SCI_STUTTEREDPAGEDOWN:
		PageMove(1, Selection::noSel, true);
		break;
	case SCI_STUTTEREDPAGEDOWNEXTEND:
		PageMove(1, Selection::selStream, true);
		break;
	case SCI_PAGEUP:
		PageMove(-1);
		break;
	case SCI_PAGEUPEXTEND:
		PageMove(-1, Selection::selStream);
		break;
	case SCI_PAGEUPRECTEXTEND:
		PageMove(-1, Selection::selRectangle);
		break;
	case SCI_PAGEDOWN:
		PageMove(1);
		break;
	case SCI_PAGEDOWNEXTEND:
		PageMove(1, Selection::selStream);
		break;
	case SCI_PAGEDOWNRECTEXTEND:
		PageMove(1, Selection::selRectangle);
		break;
	case SCI_EDITTOGGLEOVERTYPE:
		inOverstrike = !inOverstrike;
		DropCaret();
		ShowCaretAtCurrentPosition();
		ContainerNeedsUpdate(SC_UPDATE_CONTENT);
		NotifyUpdateUI();
		break;
	case SCI_CANCEL:            	// Cancel any modes - handled in subclass
		// Also unselect text
		CancelModes();
		break;
	case SCI_DELETEBACK:
		DelCharBack(true);
		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		break;
	case SCI_DELETEBACKNOTLINE:
		DelCharBack(false);
		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		break;
	case SCI_TAB:
		Indent(true);
		if (caretSticky == SC_CARETSTICKY_OFF) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		ShowCaretAtCurrentPosition();		// Avoid blinking
		break;
	case SCI_BACKTAB:
		Indent(false);
		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		ShowCaretAtCurrentPosition();		// Avoid blinking
		break;
	case SCI_NEWLINE:
		NewLine();
		break;
	case SCI_FORMFEED:
		AddChar('\f');
		break;
	case SCI_VCHOME:
		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()));
		SetLastXChosen();
		break;
	case SCI_VCHOMEEXTEND:
		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_VCHOMERECTEXTEND:
		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle);
		SetLastXChosen();
		break;
	case SCI_VCHOMEWRAP: {
			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
				homePos = viewLineStart;

			MovePositionTo(homePos);
			SetLastXChosen();
		}
		break;
	case SCI_VCHOMEWRAPEXTEND: {
			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
				homePos = viewLineStart;

			MovePositionTo(homePos, Selection::selStream);
			SetLastXChosen();
		}
		break;
	case SCI_ZOOMIN:
		if (vs.zoomLevel < 20) {
			vs.zoomLevel++;
			InvalidateStyleRedraw();
			NotifyZoom();
		}
		break;
	case SCI_ZOOMOUT:
		if (vs.zoomLevel > -10) {
			vs.zoomLevel--;
			InvalidateStyleRedraw();
			NotifyZoom();
		}
		break;
	case SCI_DELWORDLEFT: {
			int startWord = pdoc->NextWordStart(sel.MainCaret(), -1);
			pdoc->DeleteChars(startWord, sel.MainCaret() - startWord);
			sel.RangeMain().ClearVirtualSpace();
			SetLastXChosen();
		}
		break;
	case SCI_DELWORDRIGHT: {
			UndoGroup ug(pdoc);
			sel.RangeMain().caret = SelectionPosition(
				InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
			sel.RangeMain().anchor = sel.RangeMain().caret;
			int endWord = pdoc->NextWordStart(sel.MainCaret(), 1);
			pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
		}
		break;
	case SCI_DELWORDRIGHTEND: {
			UndoGroup ug(pdoc);
			sel.RangeMain().caret = SelectionPosition(
				InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
			int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1);
			pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
		}
		break;
	case SCI_DELLINELEFT: {
			int line = pdoc->LineFromPosition(sel.MainCaret());
			int start = pdoc->LineStart(line);
			pdoc->DeleteChars(start, sel.MainCaret() - start);
			sel.RangeMain().ClearVirtualSpace();
			SetLastXChosen();
		}
		break;
	case SCI_DELLINERIGHT: {
			int line = pdoc->LineFromPosition(sel.MainCaret());
			int end = pdoc->LineEnd(line);
			pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret());
		}
		break;
	case SCI_LINECOPY: {
			int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
			int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
			CopyRangeToClipboard(pdoc->LineStart(lineStart),
			        pdoc->LineStart(lineEnd + 1));
		}
		break;
	case SCI_LINECUT: {
			int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
			int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
			int start = pdoc->LineStart(lineStart);
			int end = pdoc->LineStart(lineEnd + 1);
			SetSelection(start, end);
			Cut();
			SetLastXChosen();
		}
		break;
	case SCI_LINEDELETE: {
			int line = pdoc->LineFromPosition(sel.MainCaret());
			int start = pdoc->LineStart(line);
			int end = pdoc->LineStart(line + 1);
			pdoc->DeleteChars(start, end - start);
		}
		break;
	case SCI_LINETRANSPOSE:
		LineTranspose();
		break;
	case SCI_LINEDUPLICATE:
		Duplicate(true);
		break;
	case SCI_SELECTIONDUPLICATE:
		Duplicate(false);
		break;
	case SCI_LOWERCASE:
		ChangeCaseOfSelection(cmLower);
		break;
	case SCI_UPPERCASE:
		ChangeCaseOfSelection(cmUpper);
		break;
	case SCI_WORDPARTLEFT:
		MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1));
		SetLastXChosen();
		break;
	case SCI_WORDPARTLEFTEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_WORDPARTRIGHT:
		MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1));
		SetLastXChosen();
		break;
	case SCI_WORDPARTRIGHTEXTEND:
		MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_HOMEDISPLAY:
		MovePositionTo(MovePositionSoVisible(
		            StartEndDisplayLine(sel.MainCaret(), true), -1));
		SetLastXChosen();
		break;
	case SCI_VCHOMEDISPLAY: {
			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if (viewLineStart > homePos)
				homePos = viewLineStart;

			MovePositionTo(homePos);
			SetLastXChosen();
		}
		break;
	case SCI_HOMEDISPLAYEXTEND:
		MovePositionTo(MovePositionSoVisible(
		            StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_VCHOMEDISPLAYEXTEND: {
			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
			if (viewLineStart > homePos)
				homePos = viewLineStart;

			MovePositionTo(homePos, Selection::selStream);
			SetLastXChosen();
		}
		break;
	case SCI_LINEENDDISPLAY:
		MovePositionTo(MovePositionSoVisible(
		            StartEndDisplayLine(sel.MainCaret(), false), 1));
		SetLastXChosen();
		break;
	case SCI_LINEENDDISPLAYEXTEND:
		MovePositionTo(MovePositionSoVisible(
		            StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream);
		SetLastXChosen();
		break;
	case SCI_SCROLLTOSTART:
		ScrollTo(0);
		break;
	case SCI_SCROLLTOEND:
		ScrollTo(MaxScrollPos());
		break;
	}
	return 0;
}

int Editor::KeyDefault(int, int) {
	return 0;
}

int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) {
	DwellEnd(false);
	int msg = kmap.Find(key, modifiers);
	if (msg) {
		if (consumed)
			*consumed = true;
		return WndProc(msg, 0, 0);
	} else {
		if (consumed)
			*consumed = false;
		return KeyDefault(key, modifiers);
	}
}

int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) {
	int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
	        (alt ? SCI_ALT : 0);
	return KeyDownWithModifiers(key, modifiers, consumed);
}

void Editor::Indent(bool forwards) {
	for (size_t r=0; r<sel.Count(); r++) {
		int lineOfAnchor = pdoc->LineFromPosition(sel.Range(r).anchor.Position());
		int caretPosition = sel.Range(r).caret.Position();
		int lineCurrentPos = pdoc->LineFromPosition(caretPosition);
		if (lineOfAnchor == lineCurrentPos) {
			if (forwards) {
				UndoGroup ug(pdoc);
				pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
				caretPosition = sel.Range(r).caret.Position();
				if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
						pdoc->tabIndents) {
					int indentation = pdoc->GetLineIndentation(lineCurrentPos);
					int indentationStep = pdoc->IndentSize();
					pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
					sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
				} else {
					if (pdoc->useTabs) {
						pdoc->InsertChar(caretPosition, '\t');
						sel.Range(r) = SelectionRange(caretPosition+1);
					} else {
						int numSpaces = (pdoc->tabInChars) -
								(pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
						if (numSpaces < 1)
							numSpaces = pdoc->tabInChars;
						for (int i = 0; i < numSpaces; i++) {
							pdoc->InsertChar(caretPosition + i, ' ');
						}
						sel.Range(r) = SelectionRange(caretPosition+numSpaces);
					}
				}
			} else {
				if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
						pdoc->tabIndents) {
					UndoGroup ug(pdoc);
					int indentation = pdoc->GetLineIndentation(lineCurrentPos);
					int indentationStep = pdoc->IndentSize();
					pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
					sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
				} else {
					int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
							pdoc->tabInChars;
					if (newColumn < 0)
						newColumn = 0;
					int newPos = caretPosition;
					while (pdoc->GetColumn(newPos) > newColumn)
						newPos--;
					sel.Range(r) = SelectionRange(newPos);
				}
			}
		} else {	// Multiline
			int anchorPosOnLine = sel.Range(r).anchor.Position() - pdoc->LineStart(lineOfAnchor);
			int currentPosPosOnLine = caretPosition - pdoc->LineStart(lineCurrentPos);
			// Multiple lines selected so indent / dedent
			int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
			int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
			if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
				lineBottomSel--;  	// If not selecting any characters on a line, do not indent
			{
				UndoGroup ug(pdoc);
				pdoc->Indent(forwards, lineBottomSel, lineTopSel);
			}
			if (lineOfAnchor < lineCurrentPos) {
				if (currentPosPosOnLine == 0)
					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
				else
					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
			} else {
				if (anchorPosOnLine == 0)
					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
				else
					sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
			}
		}
	}
}

class CaseFolderASCII : public CaseFolderTable {
public:
	CaseFolderASCII() {
		StandardASCII();
	}
	~CaseFolderASCII() {
	}
};


CaseFolder *Editor::CaseFolderForEncoding() {
	// Simple default that only maps ASCII upper case to lower case.
	return new CaseFolderASCII();
}

/**
 * Search of a text in the document, in the given range.
 * @return The position of the found text, -1 if not found.
 */
long Editor::FindText(
    uptr_t wParam,		///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
    ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
    sptr_t lParam) {	///< @c TextToFind structure: The text to search for in the given range.

	Sci_TextToFind *ft = reinterpret_cast<Sci_TextToFind *>(lParam);
	int lengthFound = istrlen(ft->lpstrText);
	if (!pdoc->HasCaseFolder())
		pdoc->SetCaseFolder(CaseFolderForEncoding());
	int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
	        (wParam & SCFIND_MATCHCASE) != 0,
	        (wParam & SCFIND_WHOLEWORD) != 0,
	        (wParam & SCFIND_WORDSTART) != 0,
	        (wParam & SCFIND_REGEXP) != 0,
	        wParam,
	        &lengthFound);
	if (pos != -1) {
		ft->chrgText.cpMin = pos;
		ft->chrgText.cpMax = pos + lengthFound;
	}
	return pos;
}

/**
 * Relocatable search support : Searches relative to current selection
 * point and sets the selection to the found text range with
 * each search.
 */
/**
 * Anchor following searches at current selection start: This allows
 * multiple incremental interactive searches to be macro recorded
 * while still setting the selection to found text so the find/select
 * operation is self-contained.
 */
void Editor::SearchAnchor() {
	searchAnchor = SelectionStart().Position();
}

/**
 * Find text from current search anchor: Must call @c SearchAnchor first.
 * Used for next text and previous text requests.
 * @return The position of the found text, -1 if not found.
 */
long Editor::SearchText(
    unsigned int iMessage,		///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
    uptr_t wParam,				///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
    ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
    sptr_t lParam) {			///< The text to search for.

	const char *txt = reinterpret_cast<char *>(lParam);
	int pos;
	int lengthFound = istrlen(txt);
	if (!pdoc->HasCaseFolder())
		pdoc->SetCaseFolder(CaseFolderForEncoding());
	if (iMessage == SCI_SEARCHNEXT) {
		pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
		        (wParam & SCFIND_MATCHCASE) != 0,
		        (wParam & SCFIND_WHOLEWORD) != 0,
		        (wParam & SCFIND_WORDSTART) != 0,
		        (wParam & SCFIND_REGEXP) != 0,
		        wParam,
		        &lengthFound);
	} else {
		pos = pdoc->FindText(searchAnchor, 0, txt,
		        (wParam & SCFIND_MATCHCASE) != 0,
		        (wParam & SCFIND_WHOLEWORD) != 0,
		        (wParam & SCFIND_WORDSTART) != 0,
		        (wParam & SCFIND_REGEXP) != 0,
		        wParam,
		        &lengthFound);
	}
	if (pos != -1) {
		SetSelection(pos, pos + lengthFound);
	}

	return pos;
}

std::string Editor::CaseMapString(const std::string &s, int caseMapping) {
	std::string ret(s);
	for (size_t i=0; i<ret.size(); i++) {
		switch (caseMapping) {
			case cmUpper:
				if (ret[i] >= 'a' && ret[i] <= 'z')
					ret[i] = static_cast<char>(ret[i] - 'a' + 'A');
				break;
			case cmLower:
				if (ret[i] >= 'A' && ret[i] <= 'Z')
					ret[i] = static_cast<char>(ret[i] - 'A' + 'a');
				break;
		}
	}
	return ret;
}

/**
 * Search for text in the target range of the document.
 * @return The position of the found text, -1 if not found.
 */
long Editor::SearchInTarget(const char *text, int length) {
	int lengthFound = length;

	if (!pdoc->HasCaseFolder())
		pdoc->SetCaseFolder(CaseFolderForEncoding());
	int pos = pdoc->FindText(targetStart, targetEnd, text,
	        (searchFlags & SCFIND_MATCHCASE) != 0,
	        (searchFlags & SCFIND_WHOLEWORD) != 0,
	        (searchFlags & SCFIND_WORDSTART) != 0,
	        (searchFlags & SCFIND_REGEXP) != 0,
	        searchFlags,
	        &lengthFound);
	if (pos != -1) {
		targetStart = pos;
		targetEnd = pos + lengthFound;
	}
	return pos;
}

void Editor::GoToLine(int lineNo) {
	if (lineNo > pdoc->LinesTotal())
		lineNo = pdoc->LinesTotal();
	if (lineNo < 0)
		lineNo = 0;
	SetEmptySelection(pdoc->LineStart(lineNo));
	ShowCaretAtCurrentPosition();
	EnsureCaretVisible();
}

static bool Close(Point pt1, Point pt2) {
	if (abs(pt1.x - pt2.x) > 3)
		return false;
	if (abs(pt1.y - pt2.y) > 3)
		return false;
	return true;
}

char *Editor::CopyRange(int start, int end) {
	char *text = 0;
	if (start < end) {
		int len = end - start;
		text = new char[len + 1];
		for (int i = 0; i < len; i++) {
			text[i] = pdoc->CharAt(start + i);
		}
		text[len] = '\0';
	}
	return text;
}

std::string Editor::RangeText(int start, int end) const {
	if (start < end) {
		int len = end - start;
		std::string ret(len, '\0');
		for (int i = 0; i < len; i++) {
			ret[i] = pdoc->CharAt(start + i);
		}
		return ret;
	}
	return std::string();
}

void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
	if (sel.Empty()) {
		if (allowLineCopy) {
			int currentLine = pdoc->LineFromPosition(sel.MainCaret());
			int start = pdoc->LineStart(currentLine);
			int end = pdoc->LineEnd(currentLine);

			char *text = CopyRange(start, end);
			size_t textLen = text ? strlen(text) : 0;
			// include room for \r\n\0
			textLen += 3;
			char *textWithEndl = new char[textLen];
			textWithEndl[0] = '\0';
			if (text)
				strcat(textWithEndl, text);
			if (pdoc->eolMode != SC_EOL_LF)
				strcat(textWithEndl, "\r");
			if (pdoc->eolMode != SC_EOL_CR)
				strcat(textWithEndl, "\n");
			ss->Set(textWithEndl, static_cast<int>(strlen(textWithEndl) + 1),
				pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true);
			delete []text;
		}
	} else {
		int delimiterLength = 0;
		if (sel.selType == Selection::selRectangle) {
			if (pdoc->eolMode == SC_EOL_CRLF) {
				delimiterLength = 2;
			} else {
				delimiterLength = 1;
			}
		}
		size_t size = sel.Length() + delimiterLength * sel.Count();
		char *text = new char[size + 1];
		int j = 0;
		std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
		if (sel.selType == Selection::selRectangle)
			std::sort(rangesInOrder.begin(), rangesInOrder.end());
		for (size_t r=0; r<rangesInOrder.size(); r++) {
			SelectionRange current = rangesInOrder[r];
			for (int i = current.Start().Position();
			        i < current.End().Position();
			        i++) {
				text[j++] = pdoc->CharAt(i);
			}
			if (sel.selType == Selection::selRectangle) {
				if (pdoc->eolMode != SC_EOL_LF) {
					text[j++] = '\r';
				}
				if (pdoc->eolMode != SC_EOL_CR) {
					text[j++] = '\n';
				}
			}
		}
		text[size] = '\0';
		ss->Set(text, static_cast<int>(size + 1), pdoc->dbcsCodePage,
			vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
	}
}

void Editor::CopyRangeToClipboard(int start, int end) {
	start = pdoc->ClampPositionIntoDocument(start);
	end = pdoc->ClampPositionIntoDocument(end);
	SelectionText selectedText;
	selectedText.Set(CopyRange(start, end), end - start + 1,
		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
	CopyToClipboard(selectedText);
}

void Editor::CopyText(int length, const char *text) {
	SelectionText selectedText;
	selectedText.Copy(text, length + 1,
		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
	CopyToClipboard(selectedText);
}

void Editor::SetDragPosition(SelectionPosition newPos) {
	if (newPos.Position() >= 0) {
		newPos = MovePositionOutsideChar(newPos, 1);
		posDrop = newPos;
	}
	if (!(posDrag == newPos)) {
		caret.on = true;
		SetTicking(true);
		InvalidateCaret();
		posDrag = newPos;
		InvalidateCaret();
	}
}

void Editor::DisplayCursor(Window::Cursor c) {
	if (cursorMode == SC_CURSORNORMAL)
		wMain.SetCursor(c);
	else
		wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));
}

bool Editor::DragThreshold(Point ptStart, Point ptNow) {
	int xMove = ptStart.x - ptNow.x;
	int yMove = ptStart.y - ptNow.y;
	int distanceSquared = xMove * xMove + yMove * yMove;
	return distanceSquared > 16;
}

void Editor::StartDrag() {
	// Always handled by subclasses
	//SetMouseCapture(true);
	//DisplayCursor(Window::cursorArrow);
}

void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) {
	//Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
	if (inDragDrop == ddDragging)
		dropWentOutside = false;

	bool positionWasInSelection = PositionInSelection(position.Position());

	bool positionOnEdgeOfSelection =
	    (position == SelectionStart()) || (position == SelectionEnd());

	if ((inDragDrop != ddDragging) || !(positionWasInSelection) ||
	        (positionOnEdgeOfSelection && !moving)) {

		SelectionPosition selStart = SelectionStart();
		SelectionPosition selEnd = SelectionEnd();

		UndoGroup ug(pdoc);

		SelectionPosition positionAfterDeletion = position;
		if ((inDragDrop == ddDragging) && moving) {
			// Remove dragged out text
			if (rectangular || sel.selType == Selection::selLines) {
				for (size_t r=0; r<sel.Count(); r++) {
					if (position >= sel.Range(r).Start()) {
						if (position > sel.Range(r).End()) {
							positionAfterDeletion.Add(-sel.Range(r).Length());
						} else {
							positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length());
						}
					}
				}
			} else {
				if (position > selStart) {
					positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length());
				}
			}
			ClearSelection();
		}
		position = positionAfterDeletion;

		if (rectangular) {
			PasteRectangular(position, value, istrlen(value));
			// Should try to select new rectangle but it may not be a rectangle now so just select the drop position
			SetEmptySelection(position);
		} else {
			position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position());
			position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace()));
			if (pdoc->InsertCString(position.Position(), value)) {
				SelectionPosition posAfterInsertion = position;
				posAfterInsertion.Add(istrlen(value));
				SetSelection(posAfterInsertion, position);
			}
		}
	} else if (inDragDrop == ddDragging) {
		SetEmptySelection(position);
	}
}

/**
 * @return true if given position is inside the selection,
 */
bool Editor::PositionInSelection(int pos) {
	pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos);
	for (size_t r=0; r<sel.Count(); r++) {
		if (sel.Range(r).Contains(pos))
			return true;
	}
	return false;
}

bool Editor::PointInSelection(Point pt) {
	SelectionPosition pos = SPositionFromLocation(pt, false, true);
	Point ptPos = LocationFromPosition(pos);
	for (size_t r=0; r<sel.Count(); r++) {
		SelectionRange range = sel.Range(r);
		if (range.Contains(pos)) {
			bool hit = true;
			if (pos == range.Start()) {
				// see if just before selection
				if (pt.x < ptPos.x) {
					hit = false;
				}
			}
			if (pos == range.End()) {
				// see if just after selection
				if (pt.x > ptPos.x) {
					hit = false;
				}
			}
			if (hit)
				return true;
		}
	}
	return false;
}

bool Editor::PointInSelMargin(Point pt) {
	// Really means: "Point in a margin"
	if (vs.fixedColumnWidth > 0) {	// There is a margin
		PRectangle rcSelMargin = GetClientRectangle();
		rcSelMargin.right = vs.textStart - vs.leftMarginWidth;
		rcSelMargin.left = vs.textStart - vs.fixedColumnWidth;
		return rcSelMargin.Contains(pt);
	} else {
		return false;
	}
}

Window::Cursor Editor::GetMarginCursor(Point pt) {
	int x = 0;
	for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
		if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
			return static_cast<Window::Cursor>(vs.ms[margin].cursor);
		x += vs.ms[margin].width;
	}
	return Window::cursorReverseArrow;
}

void Editor::TrimAndSetSelection(int currentPos_, int anchor_) {
	sel.TrimSelection(SelectionRange(currentPos_, anchor_));
	SetSelection(currentPos_, anchor_);
}

void Editor::LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine) {
	int selCurrentPos, selAnchorPos;
	if (wholeLine) {
		int lineCurrent_ = pdoc->LineFromPosition(lineCurrentPos_);
		int lineAnchor_ = pdoc->LineFromPosition(lineAnchorPos_);
		if (lineAnchorPos_ < lineCurrentPos_) {
			selCurrentPos = pdoc->LineStart(lineCurrent_ + 1);
			selAnchorPos = pdoc->LineStart(lineAnchor_);
		} else if (lineAnchorPos_ > lineCurrentPos_) {
			selCurrentPos = pdoc->LineStart(lineCurrent_);
			selAnchorPos = pdoc->LineStart(lineAnchor_ + 1);
		} else { // Same line, select it
			selCurrentPos = pdoc->LineStart(lineAnchor_ + 1);
			selAnchorPos = pdoc->LineStart(lineAnchor_);
		}
	} else {
		if (lineAnchorPos_ < lineCurrentPos_) {
			selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1;
			selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
		} else if (lineAnchorPos_ > lineCurrentPos_) {
			selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true);
			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
			selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1);
		} else { // Same line, select it
			selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
			selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
			selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
		}
	}
	TrimAndSetSelection(selCurrentPos, selAnchorPos);
}

void Editor::WordSelection(int pos) {
	if (pos < wordSelectAnchorStartPos) {
		// Extend backward to the word containing pos.
		// Skip ExtendWordSelect if the line is empty or if pos is after the last character.
		// This ensures that a series of empty lines isn't counted as a single "word".
		if (!pdoc->IsLineEndPosition(pos))
			pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1);
		TrimAndSetSelection(pos, wordSelectAnchorEndPos);
	} else if (pos > wordSelectAnchorEndPos) {
		// Extend forward to the word containing the character to the left of pos.
		// Skip ExtendWordSelect if the line is empty or if pos is the first position on the line.
		// This ensures that a series of empty lines isn't counted as a single "word".
		if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos)))
			pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1);
		TrimAndSetSelection(pos, wordSelectAnchorStartPos);
	} else {
		// Select only the anchored word
		if (pos >= originalAnchorPos)
			TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos);
		else
			TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos);
	}
}

void Editor::DwellEnd(bool mouseMoved) {
	if (mouseMoved)
		ticksToDwell = dwellDelay;
	else
		ticksToDwell = SC_TIME_FOREVER;
	if (dwelling && (dwellDelay < SC_TIME_FOREVER)) {
		dwelling = false;
		NotifyDwelling(ptMouseLast, dwelling);
	}
}

void Editor::MouseLeave() {
	SetHotSpotRange(NULL);
	if (!HaveMouseCapture()) {
		ptMouseLast = Point(-1,-1);
		DwellEnd(true);
	}
}

static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) {
	return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0))
		|| (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0));
}

void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
	//Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
	ptMouseLast = pt;
	SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt));
	newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
	inDragDrop = ddNone;
	sel.SetMoveExtends(false);

	if (NotifyMarginClick(pt, shift, ctrl, alt))
		return;

	NotifyIndicatorClick(true, newPos.Position(), shift, ctrl, alt);

	bool inSelMargin = PointInSelMargin(pt);
	// In margin ctrl+(double)click should always select everything
	if (ctrl && inSelMargin) {
		SelectAll();
		lastClickTime = curTime;
		lastClick = pt;
		return;
	}
	if (shift && !inSelMargin) {
		SetSelection(newPos);
	}
	if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
		//Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
		SetMouseCapture(true);
		if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord))
			SetEmptySelection(newPos.Position());
		bool doubleClick = false;
		// Stop mouse button bounce changing selection type
		if (!Platform::MouseButtonBounce() || curTime != lastClickTime) {
			if (inSelMargin) {
				// Inside margin selection type should be either selSubLine or selWholeLine.
				if (selectionType == selSubLine) {
					// If it is selSubLine, we're inside a *double* click and word wrap is enabled, 
					// so we switch to selWholeLine in order to select whole line.
					selectionType = selWholeLine;
				} else if (selectionType != selSubLine && selectionType != selWholeLine) {
					// If it is neither, reset selection type to line selection.
					selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
				}
			} else {
				if (selectionType == selChar) {
					selectionType = selWord;
					doubleClick = true;
				} else if (selectionType == selWord) {
					// Since we ended up here, we're inside a *triple* click, which should always select 
					// whole line irregardless of word wrap being enabled or not.
					selectionType = selWholeLine;
				} else {
					selectionType = selChar;
					originalAnchorPos = sel.MainCaret();
				}
			}
		}

		if (selectionType == selWord) {
			int charPos = originalAnchorPos;
			if (sel.MainCaret() == originalAnchorPos) {
				charPos = PositionFromLocation(pt, false, true);
				charPos = MovePositionOutsideChar(charPos, -1);
			}

			int startWord, endWord;
			if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) {
				startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1);
				endWord = pdoc->ExtendWordSelect(charPos, 1);
			} else {
				// Selecting backwards, or anchor beyond last character on line. In these cases,
				// we select the word containing the character to the *left* of the anchor.
				if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) {
					startWord = pdoc->ExtendWordSelect(charPos, -1);
					endWord = pdoc->ExtendWordSelect(startWord, 1);
				} else {
					// Anchor at start of line; select nothing to begin with.
					startWord = charPos;
					endWord = charPos;
				}
			}

			wordSelectAnchorStartPos = startWord;
			wordSelectAnchorEndPos = endWord;
			wordSelectInitialCaretPos = sel.MainCaret();
			WordSelection(wordSelectInitialCaretPos);
		} else if (selectionType == selSubLine || selectionType == selWholeLine) {
			lineAnchorPos = newPos.Position();
			LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
			//Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
		} else {
			SetEmptySelection(sel.MainCaret());
		}
		//Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
		if (doubleClick) {
			NotifyDoubleClick(pt, shift, ctrl, alt);
			if (PositionIsHotspot(newPos.Position()))
				NotifyHotSpotDoubleClicked(newPos.Position(), shift, ctrl, alt);
		}
	} else {	// Single click
		if (inSelMargin) {
			sel.selType = Selection::selStream;
			if (!shift) {
				// Single click in margin: select whole line or only subline if word wrap is enabled
				lineAnchorPos = newPos.Position();
				selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
				LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
			} else {
				// Single shift+click in margin: select from line anchor to clicked line
				if (sel.MainAnchor() > sel.MainCaret())
					lineAnchorPos = sel.MainAnchor() - 1;
				else
					lineAnchorPos = sel.MainAnchor();
				// Reset selection type if there is an empty selection. 
				// This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
				// Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine.
				// This ensures that we continue selecting in the same selection mode.
				if (sel.Empty() || (selectionType != selSubLine && selectionType != selWholeLine))
					selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
				LineSelection(newPos.Position(), lineAnchorPos, selectionType == selWholeLine);
			}

			SetDragPosition(SelectionPosition(invalidPosition));
			SetMouseCapture(true);
		} else {
			if (PointIsHotspot(pt)) {
				NotifyHotSpotClicked(newPos.Position(), shift, ctrl, alt);
				hotSpotClickPos = PositionFromLocation(pt,true,false);
			}
			if (!shift) {
				if (PointInSelection(pt) && !SelectionEmpty())
					inDragDrop = ddInitial;
				else
					inDragDrop = ddNone;
			}
			SetMouseCapture(true);
			if (inDragDrop != ddInitial) {
				SetDragPosition(SelectionPosition(invalidPosition));
				if (!shift) {
					if (ctrl && multipleSelection) {
						SelectionRange range(newPos);
						sel.TentativeSelection(range);
						InvalidateSelection(range, true);
					} else {
						InvalidateSelection(SelectionRange(newPos), true);
						if (sel.Count() > 1)
							Redraw();
						if ((sel.Count() > 1) || (sel.selType != Selection::selStream))
							sel.Clear();
						sel.selType = alt ? Selection::selRectangle : Selection::selStream;
						SetSelection(newPos, newPos);
					}
				}
				SelectionPosition anchorCurrent = newPos;
				if (shift)
					anchorCurrent = sel.IsRectangular() ?
						sel.Rectangular().anchor : sel.RangeMain().anchor;
				sel.selType = alt ? Selection::selRectangle : Selection::selStream;
				selectionType = selChar;
				originalAnchorPos = sel.MainCaret();
				sel.Rectangular() = SelectionRange(newPos, anchorCurrent);
				SetRectangularRange();
			}
		}
	}
	lastClickTime = curTime;
	lastClick = pt;
	lastXChosen = pt.x + xOffset;
	ShowCaretAtCurrentPosition();
}

bool Editor::PositionIsHotspot(int position) {
	return vs.styles[pdoc->StyleAt(position) & pdoc->stylingBitsMask].hotspot;
}

bool Editor::PointIsHotspot(Point pt) {
	int pos = PositionFromLocation(pt, true);
	if (pos == INVALID_POSITION)
		return false;
	return PositionIsHotspot(pos);
}

void Editor::SetHotSpotRange(Point *pt) {
	if (pt) {
		int pos = PositionFromLocation(*pt);

		// If we don't limit this to word characters then the
		// range can encompass more than the run range and then
		// the underline will not be drawn properly.
		int hsStart_ = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine);
		int hsEnd_ = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine);

		// Only invalidate the range if the hotspot range has changed...
		if (hsStart_ != hsStart || hsEnd_ != hsEnd) {
			if (hsStart != -1) {
				InvalidateRange(hsStart, hsEnd);
			}
			hsStart = hsStart_;
			hsEnd = hsEnd_;
			InvalidateRange(hsStart, hsEnd);
		}
	} else {
		if (hsStart != -1) {
			int hsStart_ = hsStart;
			int hsEnd_ = hsEnd;
			hsStart = -1;
			hsEnd = -1;
			InvalidateRange(hsStart_, hsEnd_);
		} else {
			hsStart = -1;
			hsEnd = -1;
		}
	}
}

void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) {
	hsStart_ = hsStart;
	hsEnd_ = hsEnd;
}

void Editor::ButtonMove(Point pt) {
	if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) {
		DwellEnd(true);
	}

	SelectionPosition movePos = SPositionFromLocation(pt, false, false,
		AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
	movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());

	if (inDragDrop == ddInitial) {
		if (DragThreshold(ptMouseLast, pt)) {
			SetMouseCapture(false);
			SetDragPosition(movePos);
			CopySelectionRange(&drag);
			StartDrag();
		}
		return;
	}

	ptMouseLast = pt;
	//Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
	if (HaveMouseCapture()) {

		// Slow down autoscrolling/selection
		autoScrollTimer.ticksToWait -= timer.tickSize;
		if (autoScrollTimer.ticksToWait > 0)
			return;
		autoScrollTimer.ticksToWait = autoScrollDelay;

		// Adjust selection
		if (posDrag.IsValid()) {
			SetDragPosition(movePos);
		} else {
			if (selectionType == selChar) {
				if (sel.IsRectangular()) {
					sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor);
					SetSelection(movePos, sel.RangeMain().anchor);
				} else if (sel.Count() > 1) {
					SelectionRange range(movePos, sel.RangeMain().anchor);
					sel.TentativeSelection(range);
					InvalidateSelection(range, true);
				} else {
					SetSelection(movePos, sel.RangeMain().anchor);
				}
			} else if (selectionType == selWord) {
				// Continue selecting by word
				if (movePos.Position() == wordSelectInitialCaretPos) {  // Didn't move
					// No need to do anything. Previously this case was lumped
					// in with "Moved forward", but that can be harmful in this
					// case: a handler for the NotifyDoubleClick re-adjusts
					// the selection for a fancier definition of "word" (for
					// example, in Perl it is useful to include the leading
					// '$', '%' or '@' on variables for word selection). In this
					// the ButtonMove() called via Tick() for auto-scrolling
					// could result in the fancier word selection adjustment
					// being unmade.
				} else {
					wordSelectInitialCaretPos = -1;
					WordSelection(movePos.Position());
				}
			} else {
				// Continue selecting by line
				LineSelection(movePos.Position(), lineAnchorPos, selectionType == selWholeLine);
			}
		}

		// Autoscroll
		PRectangle rcClient = GetClientRectangle();
		Point ptOrigin = GetVisibleOriginInMain();
		rcClient.Move(0, -ptOrigin.y);
		int lineMove = DisplayFromPosition(movePos.Position());
		if (pt.y > rcClient.bottom) {
			ScrollTo(lineMove - LinesOnScreen() + 1);
			Redraw();
		} else if (pt.y < rcClient.top) {
			ScrollTo(lineMove);
			Redraw();
		}
		EnsureCaretVisible(false, false, true);

		if (hsStart != -1 && !PositionIsHotspot(movePos.Position()))
			SetHotSpotRange(NULL);

		if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,false) != hotSpotClickPos) {
			if (inDragDrop == ddNone) {
				DisplayCursor(Window::cursorText);
			}
			hotSpotClickPos = INVALID_POSITION;
		}

	} else {
		if (vs.fixedColumnWidth > 0) {	// There is a margin
			if (PointInSelMargin(pt)) {
				DisplayCursor(GetMarginCursor(pt));
				SetHotSpotRange(NULL);
				return; 	// No need to test for selection
			}
		}
		// Display regular (drag) cursor over selection
		if (PointInSelection(pt) && !SelectionEmpty()) {
			DisplayCursor(Window::cursorArrow);
		} else if (PointIsHotspot(pt)) {
			DisplayCursor(Window::cursorHand);
			SetHotSpotRange(&pt);
		} else {
			DisplayCursor(Window::cursorText);
			SetHotSpotRange(NULL);
		}
	}
}

void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
	//Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
	SelectionPosition newPos = SPositionFromLocation(pt, false, false,
		AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
	newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
	if (inDragDrop == ddInitial) {
		inDragDrop = ddNone;
		SetEmptySelection(newPos);
		selectionType = selChar;
		originalAnchorPos = sel.MainCaret();
	}
	if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) {
		hotSpotClickPos = INVALID_POSITION;
		NotifyHotSpotReleaseClick(newPos.Position(), false, ctrl, false);
	}
	if (HaveMouseCapture()) {
		if (PointInSelMargin(pt)) {
			DisplayCursor(GetMarginCursor(pt));
		} else {
			DisplayCursor(Window::cursorText);
			SetHotSpotRange(NULL);
		}
		ptMouseLast = pt;
		SetMouseCapture(false);
		NotifyIndicatorClick(false, newPos.Position(), false, false, false);
		if (inDragDrop == ddDragging) {
			SelectionPosition selStart = SelectionStart();
			SelectionPosition selEnd = SelectionEnd();
			if (selStart < selEnd) {
				if (drag.len) {
					if (ctrl) {
						if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
							SetSelection(newPos.Position(), newPos.Position() + drag.len);
						}
					} else if (newPos < selStart) {
						pdoc->DeleteChars(selStart.Position(), drag.len);
						if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
							SetSelection(newPos.Position(), newPos.Position() + drag.len);
						}
					} else if (newPos > selEnd) {
						pdoc->DeleteChars(selStart.Position(), drag.len);
						newPos.Add(-drag.len);
						if (pdoc->InsertString(newPos.Position(), drag.s, drag.len)) {
							SetSelection(newPos.Position(), newPos.Position() + drag.len);
						}
					} else {
						SetEmptySelection(newPos.Position());
					}
					drag.Free();
				}
				selectionType = selChar;
			}
		} else {
			if (selectionType == selChar) {
				if (sel.Count() > 1) {
					sel.RangeMain() =
						SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor);
					InvalidateSelection(sel.RangeMain(), true);
				} else {
					SetSelection(newPos, sel.RangeMain().anchor);
				}
			}
			sel.CommitTentative();
		}
		SetRectangularRange();
		lastClickTime = curTime;
		lastClick = pt;
		lastXChosen = pt.x + xOffset;
		if (sel.selType == Selection::selStream) {
			SetLastXChosen();
		}
		inDragDrop = ddNone;
		EnsureCaretVisible(false);
	}
}

// Called frequently to perform background UI including
// caret blinking and automatic scrolling.
void Editor::Tick() {
	if (HaveMouseCapture()) {
		// Auto scroll
		ButtonMove(ptMouseLast);
	}
	if (caret.period > 0) {
		timer.ticksToWait -= timer.tickSize;
		if (timer.ticksToWait <= 0) {
			caret.on = !caret.on;
			timer.ticksToWait = caret.period;
			if (caret.active) {
				InvalidateCaret();
			}
		}
	}
	if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
		scrollWidth = lineWidthMaxSeen;
		SetScrollBars();
	}
	if ((dwellDelay < SC_TIME_FOREVER) &&
	        (ticksToDwell > 0) &&
	        (!HaveMouseCapture()) &&
	        (ptMouseLast.y >= 0)) {
		ticksToDwell -= timer.tickSize;
		if (ticksToDwell <= 0) {
			dwelling = true;
			NotifyDwelling(ptMouseLast, dwelling);
		}
	}
}

bool Editor::Idle() {

	bool idleDone;

	bool wrappingDone = wrapState == eWrapNone;

	if (!wrappingDone) {
		// Wrap lines during idle.
		WrapLines(false, -1);
		// No more wrapping
		if (wrapStart == wrapEnd)
			wrappingDone = true;
	}

	// Add more idle things to do here, but make sure idleDone is
	// set correctly before the function returns. returning
	// false will stop calling this idle funtion until SetIdle() is
	// called again.

	idleDone = wrappingDone; // && thatDone && theOtherThingDone...

	return !idleDone;
}

void Editor::SetFocusState(bool focusState) {
	hasFocus = focusState;
	NotifyFocus(hasFocus);
	if (hasFocus) {
		ShowCaretAtCurrentPosition();
	} else {
		CancelModes();
		DropCaret();
	}
}

int Editor::PositionAfterArea(PRectangle rcArea) {
	// The start of the document line after the display line after the area
	// This often means that the line after a modification is restyled which helps
	// detect multiline comment additions and heals single line comments
	int lineAfter = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1;
	if (lineAfter < cs.LinesDisplayed())
		return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1);
	else
		return pdoc->Length();
}

// Style to a position within the view. If this causes a change at end of last line then
// affects later lines so style all the viewed text.
void Editor::StyleToPositionInView(Position pos) {
	int endWindow = (vs.marginInside) ? (PositionAfterArea(GetClientRectangle())) : (pdoc->Length());
	if (pos > endWindow)
		pos = endWindow;
	int styleAtEnd = pdoc->StyleAt(pos-1);
	pdoc->EnsureStyledTo(pos);
	if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) {
		// Style at end of line changed so is multi-line change like starting a comment
		// so require rest of window to be styled.
		pdoc->EnsureStyledTo(endWindow);
	}
}

void Editor::IdleWork() {
	// Style the line after the modification as this allows modifications that change just the
	// line of the modification to heal instead of propagating to the rest of the window.
	if (workNeeded.items & WorkNeeded::workStyle)
		StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));

	NotifyUpdateUI();
	workNeeded.Reset();
}

void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
	workNeeded.Need(items, upTo);
}

bool Editor::PaintContains(PRectangle rc) {
	if (rc.Empty()) {
		return true;
	} else {
		return rcPaint.Contains(rc);
	}
}

bool Editor::PaintContainsMargin() {
	if (wMargin.GetID()) {
		// With separate margin view, paint of text view
		// never contains margin.
		return false;
	}
	PRectangle rcSelMargin = GetClientRectangle();
	rcSelMargin.right = vs.textStart;
	return PaintContains(rcSelMargin);
}

void Editor::CheckForChangeOutsidePaint(Range r) {
	if (paintState == painting && !paintingAllText) {
		//Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
		if (!r.Valid())
			return;

		PRectangle rcRange = RectangleFromRange(r.start, r.end);
		PRectangle rcText = GetTextRectangle();
		if (rcRange.top < rcText.top) {
			rcRange.top = rcText.top;
		}
		if (rcRange.bottom > rcText.bottom) {
			rcRange.bottom = rcText.bottom;
		}

		if (!PaintContains(rcRange)) {
			AbandonPaint();
		}
	}
}

void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
	if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
		if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
			CheckForChangeOutsidePaint(Range(braces[0]));
			CheckForChangeOutsidePaint(Range(pos0));
			braces[0] = pos0;
		}
		if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
			CheckForChangeOutsidePaint(Range(braces[1]));
			CheckForChangeOutsidePaint(Range(pos1));
			braces[1] = pos1;
		}
		bracesMatchStyle = matchStyle;
		if (paintState == notPainting) {
			Redraw();
		}
	}
}

void Editor::SetAnnotationHeights(int start, int end) {
	if (vs.annotationVisible) {
		bool changedHeight = false;
		for (int line=start; line<end && line<pdoc->LinesTotal(); line++) {
			int linesWrapped = 1;
			if (wrapState != eWrapNone) {
				AutoSurface surface(this);
				AutoLineLayout ll(llc, RetrieveLineLayout(line));
				if (surface && ll) {
					LayoutLine(line, surface, vs, ll, wrapWidth);
					linesWrapped = ll->lines;
				}
			}
			if (cs.SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped))
				changedHeight = true;
		}
		if (changedHeight) {
			Redraw();
		}
	}
}

void Editor::SetDocPointer(Document *document) {
	//Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
	pdoc->RemoveWatcher(this, 0);
	pdoc->Release();
	if (document == NULL) {
		pdoc = new Document();
	} else {
		pdoc = document;
	}
	pdoc->AddRef();

	// Ensure all positions within document
	sel.Clear();
	targetStart = 0;
	targetEnd = 0;

	braces[0] = invalidPosition;
	braces[1] = invalidPosition;

	vs.ReleaseAllExtendedStyles();

	// Reset the contraction state to fully shown.
	cs.Clear();
	cs.InsertLines(0, pdoc->LinesTotal() - 1);
	SetAnnotationHeights(0, pdoc->LinesTotal());
	llc.Deallocate();
	NeedWrapping();

	pdoc->AddWatcher(this, 0);
	SetScrollBars();
	Redraw();
}

void Editor::SetAnnotationVisible(int visible) {
	if (vs.annotationVisible != visible) {
		bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
		vs.annotationVisible = visible;
		if (changedFromOrToHidden) {
			int dir = vs.annotationVisible ? 1 : -1;
			for (int line=0; line<pdoc->LinesTotal(); line++) {
				int annotationLines = pdoc->AnnotationLines(line);
				if (annotationLines > 0) {
					cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir);
				}
			}
		}
		Redraw();
	}
}

/**
 * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
 */
void Editor::Expand(int &line, bool doExpand) {
	int lineMaxSubord = pdoc->GetLastChild(line);
	line++;
	while (line <= lineMaxSubord) {
		if (doExpand)
			cs.SetVisible(line, line, true);
		int level = pdoc->GetLevel(line);
		if (level & SC_FOLDLEVELHEADERFLAG) {
			if (doExpand && cs.GetExpanded(line)) {
				Expand(line, true);
			} else {
				Expand(line, false);
			}
		} else {
			line++;
		}
	}
}

void Editor::ToggleContraction(int line) {
	if (line >= 0) {
		if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
			line = pdoc->GetFoldParent(line);
			if (line < 0)
				return;
		}

		if (cs.GetExpanded(line)) {
			int lineMaxSubord = pdoc->GetLastChild(line);
			if (lineMaxSubord > line) {
				cs.SetExpanded(line, 0);
				cs.SetVisible(line + 1, lineMaxSubord, false);

				int lineCurrent = pdoc->LineFromPosition(sel.MainCaret());
				if (lineCurrent > line && lineCurrent <= lineMaxSubord) {
					// This does not re-expand the fold
					EnsureCaretVisible();
				}

				SetScrollBars();
				Redraw();
			}

		} else {
			if (!(cs.GetVisible(line))) {
				EnsureLineVisible(line, false);
				GoToLine(line);
			}
			cs.SetExpanded(line, 1);
			Expand(line, true);
			SetScrollBars();
			Redraw();
		}
	}
}

int Editor::ContractedFoldNext(int lineStart) {
	for (int line = lineStart; line<pdoc->LinesTotal();) {
		if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG))
			return line;
		line = cs.ContractedNext(line+1);
		if (line < 0)
			return -1;
	}

	return -1;
}

/**
 * Recurse up from this line to find any folds that prevent this line from being visible
 * and unfold them all.
 */
void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {

	// In case in need of wrapping to ensure DisplayFromDoc works.
	if (lineDoc >= wrapStart)
		WrapLines(true, -1);

	if (!cs.GetVisible(lineDoc)) {
		// Back up to find a non-blank line 
		int lookLine = lineDoc;
		int lookLineLevel = pdoc->GetLevel(lookLine);
		while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
			lookLineLevel = pdoc->GetLevel(--lookLine);
		}
		int lineParent = pdoc->GetFoldParent(lookLine);
		if (lineParent < 0) {
			// Backed up to a top level line, so try to find parent of initial line 
			lineParent = pdoc->GetFoldParent(lineDoc);
		}
		if (lineParent >= 0) {
			if (lineDoc != lineParent)
				EnsureLineVisible(lineParent, enforcePolicy);
			if (!cs.GetExpanded(lineParent)) {
				cs.SetExpanded(lineParent, 1);
				Expand(lineParent, true);
			}
		}
		SetScrollBars();
		Redraw();
	}
	if (enforcePolicy) {
		int lineDisplay = cs.DisplayFromDoc(lineDoc);
		if (visiblePolicy & VISIBLE_SLOP) {
			if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) {
				SetTopLine(Platform::Clamp(lineDisplay - visibleSlop, 0, MaxScrollPos()));
				SetVerticalScrollPos();
				Redraw();
			} else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
			        ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
				SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos()));
				SetVerticalScrollPos();
				Redraw();
			}
		} else {
			if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) {
				SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
				SetVerticalScrollPos();
				Redraw();
			}
		}
	}
}

int Editor::GetTag(char *tagValue, int tagNumber) {
	const char *text = 0;
	int length = 0;
	if ((tagNumber >= 1) && (tagNumber <= 9)) {
		char name[3] = "\\?";
		name[1] = static_cast<char>(tagNumber + '0');
		length = 2;
		text = pdoc->SubstituteByPosition(name, &length);
	}
	if (tagValue) {
		if (text)
			memcpy(tagValue, text, length + 1);
		else
			*tagValue = '\0';
	}
	return length;
}

int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
	UndoGroup ug(pdoc);
	if (length == -1)
		length = istrlen(text);
	if (replacePatterns) {
		text = pdoc->SubstituteByPosition(text, &length);
		if (!text) {
			return 0;
		}
	}
	if (targetStart != targetEnd)
		pdoc->DeleteChars(targetStart, targetEnd - targetStart);
	targetEnd = targetStart;
	pdoc->InsertString(targetStart, text, length);
	targetEnd = targetStart + length;
	return length;
}

bool Editor::IsUnicodeMode() const {
	return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage);
}

int Editor::CodePage() const {
	if (pdoc)
		return pdoc->dbcsCodePage;
	else
		return 0;
}

int Editor::WrapCount(int line) {
	AutoSurface surface(this);
	AutoLineLayout ll(llc, RetrieveLineLayout(line));

	if (surface && ll) {
		LayoutLine(line, surface, vs, ll, wrapWidth);
		return ll->lines;
	} else {
		return 1;
	}
}

void Editor::AddStyledText(char *buffer, int appendLength) {
	// The buffer consists of alternating character bytes and style bytes
	int textLength = appendLength / 2;
	char *text = new char[textLength];
	int i;
	for (i = 0; i < textLength; i++) {
		text[i] = buffer[i*2];
	}
	pdoc->InsertString(CurrentPosition(), text, textLength);
	for (i = 0; i < textLength; i++) {
		text[i] = buffer[i*2+1];
	}
	pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
	pdoc->SetStyles(textLength, text);
	delete []text;
	SetEmptySelection(sel.MainCaret() + textLength);
}

static bool ValidMargin(unsigned long wParam) {
	return wParam <= SC_MAX_MARGIN;
}

static char *CharPtrFromSPtr(sptr_t lParam) {
	return reinterpret_cast<char *>(lParam);
}

void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	vs.EnsureStyle(wParam);
	switch (iMessage) {
	case SCI_STYLESETFORE:
		vs.styles[wParam].fore = ColourDesired(lParam);
		break;
	case SCI_STYLESETBACK:
		vs.styles[wParam].back = ColourDesired(lParam);
		break;
	case SCI_STYLESETBOLD:
		vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL;
		break;
	case SCI_STYLESETWEIGHT:
		vs.styles[wParam].weight = lParam;
		break;
	case SCI_STYLESETITALIC:
		vs.styles[wParam].italic = lParam != 0;
		break;
	case SCI_STYLESETEOLFILLED:
		vs.styles[wParam].eolFilled = lParam != 0;
		break;
	case SCI_STYLESETSIZE:
		vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER;
		break;
	case SCI_STYLESETSIZEFRACTIONAL:
		vs.styles[wParam].size = lParam;
		break;
	case SCI_STYLESETFONT:
		if (lParam != 0) {
			vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
		}
		break;
	case SCI_STYLESETUNDERLINE:
		vs.styles[wParam].underline = lParam != 0;
		break;
	case SCI_STYLESETCASE:
		vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
		break;
	case SCI_STYLESETCHARACTERSET:
		vs.styles[wParam].characterSet = lParam;
		pdoc->SetCaseFolder(NULL);
		break;
	case SCI_STYLESETVISIBLE:
		vs.styles[wParam].visible = lParam != 0;
		break;
	case SCI_STYLESETCHANGEABLE:
		vs.styles[wParam].changeable = lParam != 0;
		break;
	case SCI_STYLESETHOTSPOT:
		vs.styles[wParam].hotspot = lParam != 0;
		break;
	}
	InvalidateStyleRedraw();
}

sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	vs.EnsureStyle(wParam);
	switch (iMessage) {
	case SCI_STYLEGETFORE:
		return vs.styles[wParam].fore.AsLong();
	case SCI_STYLEGETBACK:
		return vs.styles[wParam].back.AsLong();
	case SCI_STYLEGETBOLD:
		return vs.styles[wParam].weight > SC_WEIGHT_NORMAL;
	case SCI_STYLEGETWEIGHT:
		return vs.styles[wParam].weight;
	case SCI_STYLEGETITALIC:
		return vs.styles[wParam].italic ? 1 : 0;
	case SCI_STYLEGETEOLFILLED:
		return vs.styles[wParam].eolFilled ? 1 : 0;
	case SCI_STYLEGETSIZE:
		return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER;
	case SCI_STYLEGETSIZEFRACTIONAL:
		return vs.styles[wParam].size;
	case SCI_STYLEGETFONT:
		if (!vs.styles[wParam].fontName)
			return 0;
		if (lParam != 0)
			strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
		return strlen(vs.styles[wParam].fontName);
	case SCI_STYLEGETUNDERLINE:
		return vs.styles[wParam].underline ? 1 : 0;
	case SCI_STYLEGETCASE:
		return static_cast<int>(vs.styles[wParam].caseForce);
	case SCI_STYLEGETCHARACTERSET:
		return vs.styles[wParam].characterSet;
	case SCI_STYLEGETVISIBLE:
		return vs.styles[wParam].visible ? 1 : 0;
	case SCI_STYLEGETCHANGEABLE:
		return vs.styles[wParam].changeable ? 1 : 0;
	case SCI_STYLEGETHOTSPOT:
		return vs.styles[wParam].hotspot ? 1 : 0;
	}
	return 0;
}

sptr_t Editor::StringResult(sptr_t lParam, const char *val) {
	const size_t n = strlen(val);
	if (lParam != 0) {
		char *ptr = reinterpret_cast<char *>(lParam);
		strcpy(ptr, val);
	}
	return n;	// Not including NUL
}

sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);

	// Optional macro recording hook
	if (recordingMacro)
		NotifyMacroRecord(iMessage, wParam, lParam);

	switch (iMessage) {

	case SCI_GETTEXT: {
			if (lParam == 0)
				return pdoc->Length() + 1;
			if (wParam == 0)
				return 0;
			char *ptr = CharPtrFromSPtr(lParam);
			unsigned int iChar = 0;
			for (; iChar < wParam - 1; iChar++)
				ptr[iChar] = pdoc->CharAt(iChar);
			ptr[iChar] = '\0';
			return iChar;
		}

	case SCI_SETTEXT: {
			if (lParam == 0)
				return 0;
			UndoGroup ug(pdoc);
			pdoc->DeleteChars(0, pdoc->Length());
			SetEmptySelection(0);
			pdoc->InsertCString(0, CharPtrFromSPtr(lParam));
			return 1;
		}

	case SCI_GETTEXTLENGTH:
		return pdoc->Length();

	case SCI_CUT:
		Cut();
		SetLastXChosen();
		break;

	case SCI_COPY:
		Copy();
		break;

	case SCI_COPYALLOWLINE:
		CopyAllowLine();
		break;

	case SCI_VERTICALCENTRECARET:
		VerticalCentreCaret();
		break;

	case SCI_MOVESELECTEDLINESUP:
		MoveSelectedLinesUp();
		break;

	case SCI_MOVESELECTEDLINESDOWN:
		MoveSelectedLinesDown();
		break;

	case SCI_COPYRANGE:
		CopyRangeToClipboard(wParam, lParam);
		break;

	case SCI_COPYTEXT:
		CopyText(wParam, CharPtrFromSPtr(lParam));
		break;

	case SCI_PASTE:
		Paste();
		if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
			SetLastXChosen();
		}
		EnsureCaretVisible();
		break;

	case SCI_CLEAR:
		Clear();
		SetLastXChosen();
		EnsureCaretVisible();
		break;

	case SCI_UNDO:
		Undo();
		SetLastXChosen();
		break;

	case SCI_CANUNDO:
		return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;

	case SCI_EMPTYUNDOBUFFER:
		pdoc->DeleteUndoHistory();
		return 0;

	case SCI_GETFIRSTVISIBLELINE:
		return topLine;

	case SCI_SETFIRSTVISIBLELINE:
		ScrollTo(wParam);
		break;

	case SCI_GETLINE: {	// Risk of overwriting the end of the buffer
			int lineStart = pdoc->LineStart(wParam);
			int lineEnd = pdoc->LineStart(wParam + 1);
			if (lParam == 0) {
				return lineEnd - lineStart;
			}
			char *ptr = CharPtrFromSPtr(lParam);
			int iPlace = 0;
			for (int iChar = lineStart; iChar < lineEnd; iChar++) {
				ptr[iPlace++] = pdoc->CharAt(iChar);
			}
			return iPlace;
		}

	case SCI_GETLINECOUNT:
		if (pdoc->LinesTotal() == 0)
			return 1;
		else
			return pdoc->LinesTotal();

	case SCI_GETMODIFY:
		return !pdoc->IsSavePoint();

	case SCI_SETSEL: {
			int nStart = static_cast<int>(wParam);
			int nEnd = static_cast<int>(lParam);
			if (nEnd < 0)
				nEnd = pdoc->Length();
			if (nStart < 0)
				nStart = nEnd; 	// Remove selection
			InvalidateSelection(SelectionRange(nStart, nEnd));
			sel.Clear();
			sel.selType = Selection::selStream;
			SetSelection(nEnd, nStart);
			EnsureCaretVisible();
		}
		break;

	case SCI_GETSELTEXT: {
			SelectionText selectedText;
			CopySelectionRange(&selectedText);
			if (lParam == 0) {
				return selectedText.len ? selectedText.len : 1;
			} else {
				char *ptr = CharPtrFromSPtr(lParam);
				int iChar = 0;
				if (selectedText.len) {
					for (; iChar < selectedText.len; iChar++)
						ptr[iChar] = selectedText.s[iChar];
				} else {
					ptr[0] = '\0';
				}
				return iChar;
			}
		}

	case SCI_LINEFROMPOSITION:
		if (static_cast<int>(wParam) < 0)
			return 0;
		return pdoc->LineFromPosition(wParam);

	case SCI_POSITIONFROMLINE:
		if (static_cast<int>(wParam) < 0)
			wParam = pdoc->LineFromPosition(SelectionStart().Position());
		if (wParam == 0)
			return 0; 	// Even if there is no text, there is a first line that starts at 0
		if (static_cast<int>(wParam) > pdoc->LinesTotal())
			return -1;
		//if (wParam > pdoc->LineFromPosition(pdoc->Length()))	// Useful test, anyway...
		//	return -1;
		return pdoc->LineStart(wParam);

		// Replacement of the old Scintilla interpretation of EM_LINELENGTH
	case SCI_LINELENGTH:
		if ((static_cast<int>(wParam) < 0) ||
		        (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
			return 0;
		return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);

	case SCI_REPLACESEL: {
			if (lParam == 0)
				return 0;
			UndoGroup ug(pdoc);
			ClearSelection();
			char *replacement = CharPtrFromSPtr(lParam);
			pdoc->InsertCString(sel.MainCaret(), replacement);
			SetEmptySelection(sel.MainCaret() + istrlen(replacement));
			EnsureCaretVisible();
		}
		break;

	case SCI_SETTARGETSTART:
		targetStart = wParam;
		break;

	case SCI_GETTARGETSTART:
		return targetStart;

	case SCI_SETTARGETEND:
		targetEnd = wParam;
		break;

	case SCI_GETTARGETEND:
		return targetEnd;

	case SCI_TARGETFROMSELECTION:
		if (sel.MainCaret() < sel.MainAnchor()) {
			targetStart = sel.MainCaret();
			targetEnd = sel.MainAnchor();
		} else {
			targetStart = sel.MainAnchor();
			targetEnd = sel.MainCaret();
		}
		break;

	case SCI_REPLACETARGET:
		PLATFORM_ASSERT(lParam);
		return ReplaceTarget(false, CharPtrFromSPtr(lParam), wParam);

	case SCI_REPLACETARGETRE:
		PLATFORM_ASSERT(lParam);
		return ReplaceTarget(true, CharPtrFromSPtr(lParam), wParam);

	case SCI_SEARCHINTARGET:
		PLATFORM_ASSERT(lParam);
		return SearchInTarget(CharPtrFromSPtr(lParam), wParam);

	case SCI_SETSEARCHFLAGS:
		searchFlags = wParam;
		break;

	case SCI_GETSEARCHFLAGS:
		return searchFlags;

	case SCI_GETTAG:
		return GetTag(CharPtrFromSPtr(lParam), wParam);

	case SCI_POSITIONBEFORE:
		return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);

	case SCI_POSITIONAFTER:
		return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);

	case SCI_LINESCROLL:
		ScrollTo(topLine + lParam);
		HorizontalScrollTo(xOffset + static_cast<int>(wParam) * vs.spaceWidth);
		return 1;

	case SCI_SETXOFFSET:
		xOffset = wParam;
		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
		SetHorizontalScrollPos();
		Redraw();
		break;

	case SCI_GETXOFFSET:
		return xOffset;

	case SCI_CHOOSECARETX:
		SetLastXChosen();
		break;

	case SCI_SCROLLCARET:
		EnsureCaretVisible();
		break;

	case SCI_SETREADONLY:
		pdoc->SetReadOnly(wParam != 0);
		return 1;

	case SCI_GETREADONLY:
		return pdoc->IsReadOnly();

	case SCI_CANPASTE:
		return CanPaste();

	case SCI_POINTXFROMPOSITION:
		if (lParam < 0) {
			return 0;
		} else {
			Point pt = LocationFromPosition(lParam);
			// Convert to view-relative
			return pt.x - vs.textStart + vs.fixedColumnWidth;
		}

	case SCI_POINTYFROMPOSITION:
		if (lParam < 0) {
			return 0;
		} else {
			Point pt = LocationFromPosition(lParam);
			return pt.y;
		}

	case SCI_FINDTEXT:
		return FindText(wParam, lParam);

	case SCI_GETTEXTRANGE: {
			if (lParam == 0)
				return 0;
			Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
			int cpMax = tr->chrg.cpMax;
			if (cpMax == -1)
				cpMax = pdoc->Length();
			PLATFORM_ASSERT(cpMax <= pdoc->Length());
			int len = cpMax - tr->chrg.cpMin; 	// No -1 as cpMin and cpMax are referring to inter character positions
			pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
			// Spec says copied text is terminated with a NUL
			tr->lpstrText[len] = '\0';
			return len; 	// Not including NUL
		}

	case SCI_HIDESELECTION:
		hideSelection = wParam != 0;
		Redraw();
		break;

	case SCI_FORMATRANGE:
		return FormatRange(wParam != 0, reinterpret_cast<Sci_RangeToFormat *>(lParam));

	case SCI_GETMARGINLEFT:
		return vs.leftMarginWidth;

	case SCI_GETMARGINRIGHT:
		return vs.rightMarginWidth;

	case SCI_SETMARGINLEFT:
		vs.leftMarginWidth = lParam;
		InvalidateStyleRedraw();
		break;

	case SCI_SETMARGINRIGHT:
		vs.rightMarginWidth = lParam;
		InvalidateStyleRedraw();
		break;

		// Control specific mesages

	case SCI_ADDTEXT: {
			if (lParam == 0)
				return 0;
			pdoc->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam), wParam);
			SetEmptySelection(sel.MainCaret() + wParam);
			return 0;
		}

	case SCI_ADDSTYLEDTEXT:
		if (lParam)
			AddStyledText(CharPtrFromSPtr(lParam), wParam);
		return 0;

	case SCI_INSERTTEXT: {
			if (lParam == 0)
				return 0;
			int insertPos = wParam;
			if (static_cast<int>(wParam) == -1)
				insertPos = CurrentPosition();
			int newCurrent = CurrentPosition();
			char *sz = CharPtrFromSPtr(lParam);
			pdoc->InsertCString(insertPos, sz);
			if (newCurrent > insertPos)
				newCurrent += istrlen(sz);
			SetEmptySelection(newCurrent);
			return 0;
		}

	case SCI_APPENDTEXT:
		pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), wParam);
		return 0;

	case SCI_CLEARALL:
		ClearAll();
		return 0;

	case SCI_DELETERANGE:
		pdoc->DeleteChars(wParam, lParam);
		return 0;

	case SCI_CLEARDOCUMENTSTYLE:
		ClearDocumentStyle();
		return 0;

	case SCI_SETUNDOCOLLECTION:
		pdoc->SetUndoCollection(wParam != 0);
		return 0;

	case SCI_GETUNDOCOLLECTION:
		return pdoc->IsCollectingUndo();

	case SCI_BEGINUNDOACTION:
		pdoc->BeginUndoAction();
		return 0;

	case SCI_ENDUNDOACTION:
		pdoc->EndUndoAction();
		return 0;

	case SCI_GETCARETPERIOD:
		return caret.period;

	case SCI_SETCARETPERIOD:
		caret.period = wParam;
		break;

	case SCI_GETWORDCHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccWord, reinterpret_cast<unsigned char *>(lParam));

	case SCI_SETWORDCHARS: {
			pdoc->SetDefaultCharClasses(false);
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccWord);
		}
		break;

	case SCI_GETWHITESPACECHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccSpace, reinterpret_cast<unsigned char *>(lParam));

	case SCI_SETWHITESPACECHARS: {
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccSpace);
		}
		break;

	case SCI_GETPUNCTUATIONCHARS:
		return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, reinterpret_cast<unsigned char *>(lParam));

	case SCI_SETPUNCTUATIONCHARS: {
			if (lParam == 0)
				return 0;
			pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccPunctuation);
		}
		break;

	case SCI_SETCHARSDEFAULT:
		pdoc->SetDefaultCharClasses(true);
		break;

	case SCI_GETLENGTH:
		return pdoc->Length();

	case SCI_ALLOCATE:
		pdoc->Allocate(wParam);
		break;

	case SCI_GETCHARAT:
		return pdoc->CharAt(wParam);

	case SCI_SETCURRENTPOS:
		if (sel.IsRectangular()) {
			sel.Rectangular().caret.SetPosition(wParam);
			SetRectangularRange();
			Redraw();
		} else {
			SetSelection(wParam, sel.MainAnchor());
		}
		break;

	case SCI_GETCURRENTPOS:
		return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();

	case SCI_SETANCHOR:
		if (sel.IsRectangular()) {
			sel.Rectangular().anchor.SetPosition(wParam);
			SetRectangularRange();
			Redraw();
		} else {
			SetSelection(sel.MainCaret(), wParam);
		}
		break;

	case SCI_GETANCHOR:
		return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();

	case SCI_SETSELECTIONSTART:
		SetSelection(Platform::Maximum(sel.MainCaret(), wParam), wParam);
		break;

	case SCI_GETSELECTIONSTART:
		return sel.LimitsForRectangularElseMain().start.Position();

	case SCI_SETSELECTIONEND:
		SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam));
		break;

	case SCI_GETSELECTIONEND:
		return sel.LimitsForRectangularElseMain().end.Position();

	case SCI_SETEMPTYSELECTION:
		SetEmptySelection(wParam);
		break;

	case SCI_SETPRINTMAGNIFICATION:
		printMagnification = wParam;
		break;

	case SCI_GETPRINTMAGNIFICATION:
		return printMagnification;

	case SCI_SETPRINTCOLOURMODE:
		printColourMode = wParam;
		break;

	case SCI_GETPRINTCOLOURMODE:
		return printColourMode;

	case SCI_SETPRINTWRAPMODE:
		printWrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
		break;

	case SCI_GETPRINTWRAPMODE:
		return printWrapState;

	case SCI_GETSTYLEAT:
		if (static_cast<int>(wParam) >= pdoc->Length())
			return 0;
		else
			return pdoc->StyleAt(wParam);

	case SCI_REDO:
		Redo();
		break;

	case SCI_SELECTALL:
		SelectAll();
		break;

	case SCI_SETSAVEPOINT:
		pdoc->SetSavePoint();
		break;

	case SCI_GETSTYLEDTEXT: {
			if (lParam == 0)
				return 0;
			Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
			int iPlace = 0;
			for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
				tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
				tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
			}
			tr->lpstrText[iPlace] = '\0';
			tr->lpstrText[iPlace + 1] = '\0';
			return iPlace;
		}

	case SCI_CANREDO:
		return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;

	case SCI_MARKERLINEFROMHANDLE:
		return pdoc->LineFromHandle(wParam);

	case SCI_MARKERDELETEHANDLE:
		pdoc->DeleteMarkFromHandle(wParam);
		break;

	case SCI_GETVIEWWS:
		return vs.viewWhitespace;

	case SCI_SETVIEWWS:
		vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
		Redraw();
		break;

	case SCI_GETWHITESPACESIZE:
		return vs.whitespaceSize;

	case SCI_SETWHITESPACESIZE:
		vs.whitespaceSize = static_cast<int>(wParam);
		Redraw();
		break;

	case SCI_POSITIONFROMPOINT:
		return PositionFromLocation(Point(wParam, lParam), false, false);

	case SCI_POSITIONFROMPOINTCLOSE:
		return PositionFromLocation(Point(wParam, lParam), true, false);

	case SCI_CHARPOSITIONFROMPOINT:
		return PositionFromLocation(Point(wParam, lParam), false, true);

	case SCI_CHARPOSITIONFROMPOINTCLOSE:
		return PositionFromLocation(Point(wParam, lParam), true, true);

	case SCI_GOTOLINE:
		GoToLine(wParam);
		break;

	case SCI_GOTOPOS:
		SetEmptySelection(wParam);
		EnsureCaretVisible();
		break;

	case SCI_GETCURLINE: {
			int lineCurrentPos = pdoc->LineFromPosition(sel.MainCaret());
			int lineStart = pdoc->LineStart(lineCurrentPos);
			unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
			if (lParam == 0) {
				return 1 + lineEnd - lineStart;
			}
			PLATFORM_ASSERT(wParam > 0);
			char *ptr = CharPtrFromSPtr(lParam);
			unsigned int iPlace = 0;
			for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
				ptr[iPlace++] = pdoc->CharAt(iChar);
			}
			ptr[iPlace] = '\0';
			return sel.MainCaret() - lineStart;
		}

	case SCI_GETENDSTYLED:
		return pdoc->GetEndStyled();

	case SCI_GETEOLMODE:
		return pdoc->eolMode;

	case SCI_SETEOLMODE:
		pdoc->eolMode = wParam;
		break;

	case SCI_SETLINEENDTYPESALLOWED:
		if (pdoc->SetLineEndTypesAllowed(wParam)) {
			cs.Clear();
			cs.InsertLines(0, pdoc->LinesTotal() - 1);
			SetAnnotationHeights(0, pdoc->LinesTotal());
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETLINEENDTYPESALLOWED:
		return pdoc->GetLineEndTypesAllowed();
		
	case SCI_GETLINEENDTYPESACTIVE:
		return pdoc->GetLineEndTypesActive();
		
	case SCI_STARTSTYLING:
		pdoc->StartStyling(wParam, static_cast<char>(lParam));
		break;

	case SCI_SETSTYLING:
		pdoc->SetStyleFor(wParam, static_cast<char>(lParam));
		break;

	case SCI_SETSTYLINGEX:             // Specify a complete styling buffer
		if (lParam == 0)
			return 0;
		pdoc->SetStyles(wParam, CharPtrFromSPtr(lParam));
		break;

	case SCI_SETBUFFEREDDRAW:
		bufferedDraw = wParam != 0;
		break;

	case SCI_GETBUFFEREDDRAW:
		return bufferedDraw;

	case SCI_GETTWOPHASEDRAW:
		return twoPhaseDraw;

	case SCI_SETTWOPHASEDRAW:
		twoPhaseDraw = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_SETFONTQUALITY:
		vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
		vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
		InvalidateStyleRedraw();
		break;

	case SCI_GETFONTQUALITY:
		return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);

	case SCI_SETTABWIDTH:
		if (wParam > 0) {
			pdoc->tabInChars = wParam;
			if (pdoc->indentInChars == 0)
				pdoc->actualIndentInChars = pdoc->tabInChars;
		}
		InvalidateStyleRedraw();
		break;

	case SCI_GETTABWIDTH:
		return pdoc->tabInChars;

	case SCI_SETINDENT:
		pdoc->indentInChars = wParam;
		if (pdoc->indentInChars != 0)
			pdoc->actualIndentInChars = pdoc->indentInChars;
		else
			pdoc->actualIndentInChars = pdoc->tabInChars;
		InvalidateStyleRedraw();
		break;

	case SCI_GETINDENT:
		return pdoc->indentInChars;

	case SCI_SETUSETABS:
		pdoc->useTabs = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETUSETABS:
		return pdoc->useTabs;

	case SCI_SETLINEINDENTATION:
		pdoc->SetLineIndentation(wParam, lParam);
		break;

	case SCI_GETLINEINDENTATION:
		return pdoc->GetLineIndentation(wParam);

	case SCI_GETLINEINDENTPOSITION:
		return pdoc->GetLineIndentPosition(wParam);

	case SCI_SETTABINDENTS:
		pdoc->tabIndents = wParam != 0;
		break;

	case SCI_GETTABINDENTS:
		return pdoc->tabIndents;

	case SCI_SETBACKSPACEUNINDENTS:
		pdoc->backspaceUnindents = wParam != 0;
		break;

	case SCI_GETBACKSPACEUNINDENTS:
		return pdoc->backspaceUnindents;

	case SCI_SETMOUSEDWELLTIME:
		dwellDelay = wParam;
		ticksToDwell = dwellDelay;
		break;

	case SCI_GETMOUSEDWELLTIME:
		return dwellDelay;

	case SCI_WORDSTARTPOSITION:
		return pdoc->ExtendWordSelect(wParam, -1, lParam != 0);

	case SCI_WORDENDPOSITION:
		return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);

	case SCI_SETWRAPMODE:
		switch (wParam) {
		case SC_WRAP_WORD:
			wrapState = eWrapWord;
			break;
		case SC_WRAP_CHAR:
			wrapState = eWrapChar;
			break;
		default:
			wrapState = eWrapNone;
			break;
		}
		xOffset = 0;
		ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
		InvalidateStyleRedraw();
		ReconfigureScrollBars();
		break;

	case SCI_GETWRAPMODE:
		return wrapState;

	case SCI_SETWRAPVISUALFLAGS:
		if (wrapVisualFlags != static_cast<int>(wParam)) {
			wrapVisualFlags = wParam;
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPVISUALFLAGS:
		return wrapVisualFlags;

	case SCI_SETWRAPVISUALFLAGSLOCATION:
		wrapVisualFlagsLocation = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETWRAPVISUALFLAGSLOCATION:
		return wrapVisualFlagsLocation;

	case SCI_SETWRAPSTARTINDENT:
		if (wrapVisualStartIndent != static_cast<int>(wParam)) {
			wrapVisualStartIndent = wParam;
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPSTARTINDENT:
		return wrapVisualStartIndent;

	case SCI_SETWRAPINDENTMODE:
		if (wrapIndentMode != static_cast<int>(wParam)) {
			wrapIndentMode = wParam;
			InvalidateStyleRedraw();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETWRAPINDENTMODE:
		return wrapIndentMode;

	case SCI_SETLAYOUTCACHE:
		llc.SetLevel(wParam);
		break;

	case SCI_GETLAYOUTCACHE:
		return llc.GetLevel();

	case SCI_SETPOSITIONCACHE:
		posCache.SetSize(wParam);
		break;

	case SCI_GETPOSITIONCACHE:
		return posCache.GetSize();

	case SCI_SETSCROLLWIDTH:
		PLATFORM_ASSERT(wParam > 0);
		if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
			lineWidthMaxSeen = 0;
			scrollWidth = wParam;
			SetScrollBars();
		}
		break;

	case SCI_GETSCROLLWIDTH:
		return scrollWidth;

	case SCI_SETSCROLLWIDTHTRACKING:
		trackLineWidth = wParam != 0;
		break;

	case SCI_GETSCROLLWIDTHTRACKING:
		return trackLineWidth;

	case SCI_LINESJOIN:
		LinesJoin();
		break;

	case SCI_LINESSPLIT:
		LinesSplit(wParam);
		break;

	case SCI_TEXTWIDTH:
		PLATFORM_ASSERT(wParam < vs.stylesSize);
		PLATFORM_ASSERT(lParam);
		return TextWidth(wParam, CharPtrFromSPtr(lParam));

	case SCI_TEXTHEIGHT:
		return vs.lineHeight;

	case SCI_SETENDATLASTLINE:
		PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
		if (endAtLastLine != (wParam != 0)) {
			endAtLastLine = wParam != 0;
			SetScrollBars();
		}
		break;

	case SCI_GETENDATLASTLINE:
		return endAtLastLine;

	case SCI_SETCARETSTICKY:
		PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE);
		if (wParam <= SC_CARETSTICKY_WHITESPACE) {
			caretSticky = wParam;
		}
		break;

	case SCI_GETCARETSTICKY:
		return caretSticky;

	case SCI_TOGGLECARETSTICKY:
		caretSticky = !caretSticky;
		break;

	case SCI_GETCOLUMN:
		return pdoc->GetColumn(wParam);

	case SCI_FINDCOLUMN:
		return pdoc->FindColumn(wParam, lParam);

	case SCI_SETHSCROLLBAR :
		if (horizontalScrollBarVisible != (wParam != 0)) {
			horizontalScrollBarVisible = wParam != 0;
			SetScrollBars();
			ReconfigureScrollBars();
		}
		break;

	case SCI_GETHSCROLLBAR:
		return horizontalScrollBarVisible;

	case SCI_SETVSCROLLBAR:
		if (verticalScrollBarVisible != (wParam != 0)) {
			verticalScrollBarVisible = wParam != 0;
			SetScrollBars();
			ReconfigureScrollBars();
			if (verticalScrollBarVisible)
				SetVerticalScrollPos();
		}
		break;

	case SCI_GETVSCROLLBAR:
		return verticalScrollBarVisible;

	case SCI_SETINDENTATIONGUIDES:
		vs.viewIndentationGuides = IndentView(wParam);
		Redraw();
		break;

	case SCI_GETINDENTATIONGUIDES:
		return vs.viewIndentationGuides;

	case SCI_SETHIGHLIGHTGUIDE:
		if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
			highlightGuideColumn = wParam;
			Redraw();
		}
		break;

	case SCI_GETHIGHLIGHTGUIDE:
		return highlightGuideColumn;

	case SCI_GETLINEENDPOSITION:
		return pdoc->LineEnd(wParam);

	case SCI_SETCODEPAGE:
		if (ValidCodePage(wParam)) {
			if (pdoc->SetDBCSCodePage(wParam)) {
				cs.Clear();
				cs.InsertLines(0, pdoc->LinesTotal() - 1);
				SetAnnotationHeights(0, pdoc->LinesTotal());
				InvalidateStyleRedraw();
			}
		}
		break;

	case SCI_GETCODEPAGE:
		return pdoc->dbcsCodePage;

#ifdef INCLUDE_DEPRECATED_FEATURES
	case SCI_SETUSEPALETTE:
		InvalidateStyleRedraw();
		break;

	case SCI_GETUSEPALETTE:
		return 0;
#endif

		// Marker definition and setting
	case SCI_MARKERDEFINE:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].markType = lParam;
			vs.CalcLargestMarkerHeight();
		}
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_MARKERSYMBOLDEFINED:
		if (wParam <= MARKER_MAX)
			return vs.markers[wParam].markType;
		else
			return 0;

	case SCI_MARKERSETFORE:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].fore = ColourDesired(lParam);
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERSETBACKSELECTED:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].backSelected = ColourDesired(lParam);
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERENABLEHIGHLIGHT:
		highlightDelimiter.isEnabled = wParam == 1;
		RedrawSelMargin();
		break;
	case SCI_MARKERSETBACK:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].back = ColourDesired(lParam);
		InvalidateStyleData();
		RedrawSelMargin();
		break;
	case SCI_MARKERSETALPHA:
		if (wParam <= MARKER_MAX)
			vs.markers[wParam].alpha = lParam;
		InvalidateStyleRedraw();
		break;
	case SCI_MARKERADD: {
			int markerID = pdoc->AddMark(wParam, lParam);
			return markerID;
		}
	case SCI_MARKERADDSET:
		if (lParam != 0)
			pdoc->AddMarkSet(wParam, lParam);
		break;

	case SCI_MARKERDELETE:
		pdoc->DeleteMark(wParam, lParam);
		break;

	case SCI_MARKERDELETEALL:
		pdoc->DeleteAllMarks(static_cast<int>(wParam));
		break;

	case SCI_MARKERGET:
		return pdoc->GetMark(wParam);

	case SCI_MARKERNEXT: 
		return pdoc->MarkerNext(wParam, lParam);

	case SCI_MARKERPREVIOUS: {
			for (int iLine = wParam; iLine >= 0; iLine--) {
				if ((pdoc->GetMark(iLine) & lParam) != 0)
					return iLine;
			}
		}
		return -1;

	case SCI_MARKERDEFINEPIXMAP:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
			vs.CalcLargestMarkerHeight();
		};
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_RGBAIMAGESETWIDTH:
		sizeRGBAImage.x = wParam;
		break;

	case SCI_RGBAIMAGESETHEIGHT:
		sizeRGBAImage.y = wParam;
		break;

	case SCI_RGBAIMAGESETSCALE:
		scaleRGBAImage = wParam;
		break;

	case SCI_MARKERDEFINERGBAIMAGE:
		if (wParam <= MARKER_MAX) {
			vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0, reinterpret_cast<unsigned char *>(lParam));
			vs.CalcLargestMarkerHeight();
		};
		InvalidateStyleData();
		RedrawSelMargin();
		break;

	case SCI_SETMARGINTYPEN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].style = lParam;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINTYPEN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].style;
		else
			return 0;

	case SCI_SETMARGINWIDTHN:
		if (ValidMargin(wParam)) {
			// Short-circuit if the width is unchanged, to avoid unnecessary redraw.
			if (vs.ms[wParam].width != lParam) {
				vs.ms[wParam].width = lParam;
				InvalidateStyleRedraw();
			}
		}
		break;

	case SCI_GETMARGINWIDTHN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].width;
		else
			return 0;

	case SCI_SETMARGINMASKN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].mask = lParam;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINMASKN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].mask;
		else
			return 0;

	case SCI_SETMARGINSENSITIVEN:
		if (ValidMargin(wParam)) {
			vs.ms[wParam].sensitive = lParam != 0;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_GETMARGINSENSITIVEN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].sensitive ? 1 : 0;
		else
			return 0;

	case SCI_SETMARGINCURSORN:
		if (ValidMargin(wParam))
			vs.ms[wParam].cursor = lParam;
		break;

	case SCI_GETMARGINCURSORN:
		if (ValidMargin(wParam))
			return vs.ms[wParam].cursor;
		else
			return 0;

	case SCI_STYLECLEARALL:
		vs.ClearStyles();
		InvalidateStyleRedraw();
		break;

	case SCI_STYLESETFORE:
	case SCI_STYLESETBACK:
	case SCI_STYLESETBOLD:
	case SCI_STYLESETWEIGHT:
	case SCI_STYLESETITALIC:
	case SCI_STYLESETEOLFILLED:
	case SCI_STYLESETSIZE:
	case SCI_STYLESETSIZEFRACTIONAL:
	case SCI_STYLESETFONT:
	case SCI_STYLESETUNDERLINE:
	case SCI_STYLESETCASE:
	case SCI_STYLESETCHARACTERSET:
	case SCI_STYLESETVISIBLE:
	case SCI_STYLESETCHANGEABLE:
	case SCI_STYLESETHOTSPOT:
		StyleSetMessage(iMessage, wParam, lParam);
		break;

	case SCI_STYLEGETFORE:
	case SCI_STYLEGETBACK:
	case SCI_STYLEGETBOLD:
	case SCI_STYLEGETWEIGHT:
	case SCI_STYLEGETITALIC:
	case SCI_STYLEGETEOLFILLED:
	case SCI_STYLEGETSIZE:
	case SCI_STYLEGETSIZEFRACTIONAL:
	case SCI_STYLEGETFONT:
	case SCI_STYLEGETUNDERLINE:
	case SCI_STYLEGETCASE:
	case SCI_STYLEGETCHARACTERSET:
	case SCI_STYLEGETVISIBLE:
	case SCI_STYLEGETCHANGEABLE:
	case SCI_STYLEGETHOTSPOT:
		return StyleGetMessage(iMessage, wParam, lParam);

	case SCI_STYLERESETDEFAULT:
		vs.ResetDefaultStyle();
		InvalidateStyleRedraw();
		break;
	case SCI_SETSTYLEBITS:
		vs.EnsureStyle((1 << wParam) - 1);
		pdoc->SetStylingBits(wParam);
		break;

	case SCI_GETSTYLEBITS:
		return pdoc->stylingBits;

	case SCI_SETLINESTATE:
		return pdoc->SetLineState(wParam, lParam);

	case SCI_GETLINESTATE:
		return pdoc->GetLineState(wParam);

	case SCI_GETMAXLINESTATE:
		return pdoc->GetMaxLineState();

	case SCI_GETCARETLINEVISIBLE:
		return vs.showCaretLineBackground;
	case SCI_SETCARETLINEVISIBLE:
		vs.showCaretLineBackground = wParam != 0;
		InvalidateStyleRedraw();
		break;
	case SCI_GETCARETLINEVISIBLEALWAYS:
		return vs.alwaysShowCaretLineBackground;
	case SCI_SETCARETLINEVISIBLEALWAYS:
		vs.alwaysShowCaretLineBackground = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETLINEBACK:
		return vs.caretLineBackground.AsLong();
	case SCI_SETCARETLINEBACK:
		vs.caretLineBackground = wParam;
		InvalidateStyleRedraw();
		break;
	case SCI_GETCARETLINEBACKALPHA:
		return vs.caretLineAlpha;
	case SCI_SETCARETLINEBACKALPHA:
		vs.caretLineAlpha = wParam;
		InvalidateStyleRedraw();
		break;

		// Folding messages

	case SCI_VISIBLEFROMDOCLINE:
		return cs.DisplayFromDoc(wParam);

	case SCI_DOCLINEFROMVISIBLE:
		return cs.DocFromDisplay(wParam);

	case SCI_WRAPCOUNT:
		return WrapCount(wParam);

	case SCI_SETFOLDLEVEL: {
			int prev = pdoc->SetLevel(wParam, lParam);
			if (prev != lParam)
				RedrawSelMargin();
			return prev;
		}

	case SCI_GETFOLDLEVEL:
		return pdoc->GetLevel(wParam);

	case SCI_GETLASTCHILD:
		return pdoc->GetLastChild(wParam, lParam);

	case SCI_GETFOLDPARENT:
		return pdoc->GetFoldParent(wParam);

	case SCI_SHOWLINES:
		cs.SetVisible(wParam, lParam, true);
		SetScrollBars();
		Redraw();
		break;

	case SCI_HIDELINES:
		if (wParam > 0)
			cs.SetVisible(wParam, lParam, false);
		SetScrollBars();
		Redraw();
		break;

	case SCI_GETLINEVISIBLE:
		return cs.GetVisible(wParam);

	case SCI_GETALLLINESVISIBLE:
		return cs.HiddenLines() ? 0 : 1;

	case SCI_SETFOLDEXPANDED:
		if (cs.SetExpanded(wParam, lParam != 0)) {
			RedrawSelMargin();
		}
		break;

	case SCI_GETFOLDEXPANDED:
		return cs.GetExpanded(wParam);

	case SCI_SETFOLDFLAGS:
		foldFlags = wParam;
		Redraw();
		break;

	case SCI_TOGGLEFOLD:
		ToggleContraction(wParam);
		break;

	case SCI_CONTRACTEDFOLDNEXT:
		return ContractedFoldNext(wParam);

	case SCI_ENSUREVISIBLE:
		EnsureLineVisible(wParam, false);
		break;

	case SCI_ENSUREVISIBLEENFORCEPOLICY:
		EnsureLineVisible(wParam, true);
		break;

	case SCI_SCROLLRANGE: 
		ScrollRange(SelectionRange(lParam, wParam));
		break;

	case SCI_SEARCHANCHOR:
		SearchAnchor();
		break;

	case SCI_SEARCHNEXT:
	case SCI_SEARCHPREV:
		return SearchText(iMessage, wParam, lParam);

	case SCI_SETXCARETPOLICY:
		caretXPolicy = wParam;
		caretXSlop = lParam;
		break;

	case SCI_SETYCARETPOLICY:
		caretYPolicy = wParam;
		caretYSlop = lParam;
		break;

	case SCI_SETVISIBLEPOLICY:
		visiblePolicy = wParam;
		visibleSlop = lParam;
		break;

	case SCI_LINESONSCREEN:
		return LinesOnScreen();

	case SCI_SETSELFORE:
		vs.selforeset = wParam != 0;
		vs.selforeground = ColourDesired(lParam);
		vs.selAdditionalForeground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETSELBACK:
		vs.selbackset = wParam != 0;
		vs.selbackground = ColourDesired(lParam);
		vs.selAdditionalBackground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETSELALPHA:
		vs.selAlpha = wParam;
		vs.selAdditionalAlpha = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETSELALPHA:
		return vs.selAlpha;

	case SCI_GETSELEOLFILLED:
		return vs.selEOLFilled;

	case SCI_SETSELEOLFILLED:
		vs.selEOLFilled = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_SETWHITESPACEFORE:
		vs.whitespaceForegroundSet = wParam != 0;
		vs.whitespaceForeground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETWHITESPACEBACK:
		vs.whitespaceBackgroundSet = wParam != 0;
		vs.whitespaceBackground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETCARETFORE:
		vs.caretcolour = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETFORE:
		return vs.caretcolour.AsLong();

	case SCI_SETCARETSTYLE:
		if (wParam <= CARETSTYLE_BLOCK)
			vs.caretStyle = wParam;
		else
			/* Default to the line caret */
			vs.caretStyle = CARETSTYLE_LINE;
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETSTYLE:
		return vs.caretStyle;

	case SCI_SETCARETWIDTH:
		if (static_cast<int>(wParam) <= 0)
			vs.caretWidth = 0;
		else if (wParam >= 3)
			vs.caretWidth = 3;
		else
			vs.caretWidth = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETCARETWIDTH:
		return vs.caretWidth;

	case SCI_ASSIGNCMDKEY:
		kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
		        Platform::HighShortFromLong(wParam), lParam);
		break;

	case SCI_CLEARCMDKEY:
		kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
		        Platform::HighShortFromLong(wParam), SCI_NULL);
		break;

	case SCI_CLEARALLCMDKEYS:
		kmap.Clear();
		break;

	case SCI_INDICSETSTYLE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].style = lParam;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETSTYLE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;

	case SCI_INDICSETFORE:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].fore = ColourDesired(lParam);
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETFORE:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0;

	case SCI_INDICSETUNDER:
		if (wParam <= INDIC_MAX) {
			vs.indicators[wParam].under = lParam != 0;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETUNDER:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;

	case SCI_INDICSETALPHA:
		if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
			vs.indicators[wParam].fillAlpha = lParam;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETALPHA:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0;

	case SCI_INDICSETOUTLINEALPHA:
		if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
			vs.indicators[wParam].outlineAlpha = lParam;
			InvalidateStyleRedraw();
		}
		break;

	case SCI_INDICGETOUTLINEALPHA:
		return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0;

	case SCI_SETINDICATORCURRENT:
		pdoc->decorations.SetCurrentIndicator(wParam);
		break;
	case SCI_GETINDICATORCURRENT:
		return pdoc->decorations.GetCurrentIndicator();
	case SCI_SETINDICATORVALUE:
		pdoc->decorations.SetCurrentValue(wParam);
		break;
	case SCI_GETINDICATORVALUE:
		return pdoc->decorations.GetCurrentValue();

	case SCI_INDICATORFILLRANGE:
		pdoc->DecorationFillRange(wParam, pdoc->decorations.GetCurrentValue(), lParam);
		break;

	case SCI_INDICATORCLEARRANGE:
		pdoc->DecorationFillRange(wParam, 0, lParam);
		break;

	case SCI_INDICATORALLONFOR:
		return pdoc->decorations.AllOnFor(wParam);

	case SCI_INDICATORVALUEAT:
		return pdoc->decorations.ValueAt(wParam, lParam);

	case SCI_INDICATORSTART:
		return pdoc->decorations.Start(wParam, lParam);

	case SCI_INDICATOREND:
		return pdoc->decorations.End(wParam, lParam);

	case SCI_LINEDOWN:
	case SCI_LINEDOWNEXTEND:
	case SCI_PARADOWN:
	case SCI_PARADOWNEXTEND:
	case SCI_LINEUP:
	case SCI_LINEUPEXTEND:
	case SCI_PARAUP:
	case SCI_PARAUPEXTEND:
	case SCI_CHARLEFT:
	case SCI_CHARLEFTEXTEND:
	case SCI_CHARRIGHT:
	case SCI_CHARRIGHTEXTEND:
	case SCI_WORDLEFT:
	case SCI_WORDLEFTEXTEND:
	case SCI_WORDRIGHT:
	case SCI_WORDRIGHTEXTEND:
	case SCI_WORDLEFTEND:
	case SCI_WORDLEFTENDEXTEND:
	case SCI_WORDRIGHTEND:
	case SCI_WORDRIGHTENDEXTEND:
	case SCI_HOME:
	case SCI_HOMEEXTEND:
	case SCI_LINEEND:
	case SCI_LINEENDEXTEND:
	case SCI_HOMEWRAP:
	case SCI_HOMEWRAPEXTEND:
	case SCI_LINEENDWRAP:
	case SCI_LINEENDWRAPEXTEND:
	case SCI_DOCUMENTSTART:
	case SCI_DOCUMENTSTARTEXTEND:
	case SCI_DOCUMENTEND:
	case SCI_DOCUMENTENDEXTEND:
	case SCI_SCROLLTOSTART:
	case SCI_SCROLLTOEND:

	case SCI_STUTTEREDPAGEUP:
	case SCI_STUTTEREDPAGEUPEXTEND:
	case SCI_STUTTEREDPAGEDOWN:
	case SCI_STUTTEREDPAGEDOWNEXTEND:

	case SCI_PAGEUP:
	case SCI_PAGEUPEXTEND:
	case SCI_PAGEDOWN:
	case SCI_PAGEDOWNEXTEND:
	case SCI_EDITTOGGLEOVERTYPE:
	case SCI_CANCEL:
	case SCI_DELETEBACK:
	case SCI_TAB:
	case SCI_BACKTAB:
	case SCI_NEWLINE:
	case SCI_FORMFEED:
	case SCI_VCHOME:
	case SCI_VCHOMEEXTEND:
	case SCI_VCHOMEWRAP:
	case SCI_VCHOMEWRAPEXTEND:
	case SCI_VCHOMEDISPLAY:
	case SCI_VCHOMEDISPLAYEXTEND:
	case SCI_ZOOMIN:
	case SCI_ZOOMOUT:
	case SCI_DELWORDLEFT:
	case SCI_DELWORDRIGHT:
	case SCI_DELWORDRIGHTEND:
	case SCI_DELLINELEFT:
	case SCI_DELLINERIGHT:
	case SCI_LINECOPY:
	case SCI_LINECUT:
	case SCI_LINEDELETE:
	case SCI_LINETRANSPOSE:
	case SCI_LINEDUPLICATE:
	case SCI_LOWERCASE:
	case SCI_UPPERCASE:
	case SCI_LINESCROLLDOWN:
	case SCI_LINESCROLLUP:
	case SCI_WORDPARTLEFT:
	case SCI_WORDPARTLEFTEXTEND:
	case SCI_WORDPARTRIGHT:
	case SCI_WORDPARTRIGHTEXTEND:
	case SCI_DELETEBACKNOTLINE:
	case SCI_HOMEDISPLAY:
	case SCI_HOMEDISPLAYEXTEND:
	case SCI_LINEENDDISPLAY:
	case SCI_LINEENDDISPLAYEXTEND:
	case SCI_LINEDOWNRECTEXTEND:
	case SCI_LINEUPRECTEXTEND:
	case SCI_CHARLEFTRECTEXTEND:
	case SCI_CHARRIGHTRECTEXTEND:
	case SCI_HOMERECTEXTEND:
	case SCI_VCHOMERECTEXTEND:
	case SCI_LINEENDRECTEXTEND:
	case SCI_PAGEUPRECTEXTEND:
	case SCI_PAGEDOWNRECTEXTEND:
	case SCI_SELECTIONDUPLICATE:
		return KeyCommand(iMessage);

	case SCI_BRACEHIGHLIGHT:
		SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
		break;

	case SCI_BRACEHIGHLIGHTINDICATOR:
		if (lParam >= 0 && lParam <= INDIC_MAX) {
			vs.braceHighlightIndicatorSet = wParam != 0;
			vs.braceHighlightIndicator = lParam;
		}
		break;

	case SCI_BRACEBADLIGHT:
		SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
		break;

	case SCI_BRACEBADLIGHTINDICATOR:
		if (lParam >= 0 && lParam <= INDIC_MAX) {
			vs.braceBadLightIndicatorSet = wParam != 0;
			vs.braceBadLightIndicator = lParam;
		}
		break;

	case SCI_BRACEMATCH:
		// wParam is position of char to find brace for,
		// lParam is maximum amount of text to restyle to find it
		return pdoc->BraceMatch(wParam, lParam);

	case SCI_GETVIEWEOL:
		return vs.viewEOL;

	case SCI_SETVIEWEOL:
		vs.viewEOL = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_SETZOOM:
		vs.zoomLevel = wParam;
		InvalidateStyleRedraw();
		NotifyZoom();
		break;

	case SCI_GETZOOM:
		return vs.zoomLevel;

	case SCI_GETEDGECOLUMN:
		return theEdge;

	case SCI_SETEDGECOLUMN:
		theEdge = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETEDGEMODE:
		return vs.edgeState;

	case SCI_SETEDGEMODE:
		vs.edgeState = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETEDGECOLOUR:
		return vs.edgecolour.AsLong();

	case SCI_SETEDGECOLOUR:
		vs.edgecolour = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETDOCPOINTER:
		return reinterpret_cast<sptr_t>(pdoc);

	case SCI_SETDOCPOINTER:
		CancelModes();
		SetDocPointer(reinterpret_cast<Document *>(lParam));
		return 0;

	case SCI_CREATEDOCUMENT: {
			Document *doc = new Document();
			if (doc) {
				doc->AddRef();
			}
			return reinterpret_cast<sptr_t>(doc);
		}

	case SCI_ADDREFDOCUMENT:
		(reinterpret_cast<Document *>(lParam))->AddRef();
		break;

	case SCI_RELEASEDOCUMENT:
		(reinterpret_cast<Document *>(lParam))->Release();
		break;

	case SCI_CREATELOADER: {
			Document *doc = new Document();
			if (doc) {
				doc->AddRef();
				doc->Allocate(wParam);
				doc->SetUndoCollection(false);
			}
			return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
		}

	case SCI_SETMODEVENTMASK:
		modEventMask = wParam;
		return 0;

	case SCI_GETMODEVENTMASK:
		return modEventMask;

	case SCI_CONVERTEOLS:
		pdoc->ConvertLineEnds(wParam);
		SetSelection(sel.MainCaret(), sel.MainAnchor());	// Ensure selection inside document
		return 0;

	case SCI_SETLENGTHFORENCODE:
		lengthForEncode = wParam;
		return 0;

	case SCI_SELECTIONISRECTANGLE:
		return sel.selType == Selection::selRectangle ? 1 : 0;

	case SCI_SETSELECTIONMODE: {
			switch (wParam) {
			case SC_SEL_STREAM:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
				sel.selType = Selection::selStream;
				break;
			case SC_SEL_RECTANGLE:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
				sel.selType = Selection::selRectangle;
				break;
			case SC_SEL_LINES:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
				sel.selType = Selection::selLines;
				break;
			case SC_SEL_THIN:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
				sel.selType = Selection::selThin;
				break;
			default:
				sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
				sel.selType = Selection::selStream;
			}
			InvalidateSelection(sel.RangeMain(), true);
		}
	case SCI_GETSELECTIONMODE:
		switch (sel.selType) {
		case Selection::selStream:
			return SC_SEL_STREAM;
		case Selection::selRectangle:
			return SC_SEL_RECTANGLE;
		case Selection::selLines:
			return SC_SEL_LINES;
		case Selection::selThin:
			return SC_SEL_THIN;
		default:	// ?!
			return SC_SEL_STREAM;
		}
	case SCI_GETLINESELSTARTPOSITION:
	case SCI_GETLINESELENDPOSITION: {
			SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(wParam)),
				SelectionPosition(pdoc->LineEnd(wParam)));
			for (size_t r=0; r<sel.Count(); r++) {
				SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
				if (portion.start.IsValid()) {
					return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
				}
			}
			return INVALID_POSITION;
		}

	case SCI_SETOVERTYPE:
		inOverstrike = wParam != 0;
		break;

	case SCI_GETOVERTYPE:
		return inOverstrike ? 1 : 0;

	case SCI_SETFOCUS:
		SetFocusState(wParam != 0);
		break;

	case SCI_GETFOCUS:
		return hasFocus;

	case SCI_SETSTATUS:
		errorStatus = wParam;
		break;

	case SCI_GETSTATUS:
		return errorStatus;

	case SCI_SETMOUSEDOWNCAPTURES:
		mouseDownCaptures = wParam != 0;
		break;

	case SCI_GETMOUSEDOWNCAPTURES:
		return mouseDownCaptures;

	case SCI_SETCURSOR:
		cursorMode = wParam;
		DisplayCursor(Window::cursorText);
		break;

	case SCI_GETCURSOR:
		return cursorMode;

	case SCI_SETCONTROLCHARSYMBOL:
		controlCharSymbol = wParam;
		break;

	case SCI_GETCONTROLCHARSYMBOL:
		return controlCharSymbol;

	case SCI_STARTRECORD:
		recordingMacro = true;
		return 0;

	case SCI_STOPRECORD:
		recordingMacro = false;
		return 0;

	case SCI_MOVECARETINSIDEVIEW:
		MoveCaretInsideView();
		break;

	case SCI_SETFOLDMARGINCOLOUR:
		vs.foldmarginColourSet = wParam != 0;
		vs.foldmarginColour = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETFOLDMARGINHICOLOUR:
		vs.foldmarginHighlightColourSet = wParam != 0;
		vs.foldmarginHighlightColour = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETHOTSPOTACTIVEFORE:
		vs.hotspotForegroundSet = wParam != 0;
		vs.hotspotForeground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEFORE:
		return vs.hotspotForeground.AsLong();

	case SCI_SETHOTSPOTACTIVEBACK:
		vs.hotspotBackgroundSet = wParam != 0;
		vs.hotspotBackground = ColourDesired(lParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEBACK:
		return vs.hotspotBackground.AsLong();

	case SCI_SETHOTSPOTACTIVEUNDERLINE:
		vs.hotspotUnderline = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTACTIVEUNDERLINE:
		return vs.hotspotUnderline ? 1 : 0;

	case SCI_SETHOTSPOTSINGLELINE:
		vs.hotspotSingleLine = wParam != 0;
		InvalidateStyleRedraw();
		break;

	case SCI_GETHOTSPOTSINGLELINE:
		return vs.hotspotSingleLine ? 1 : 0;

	case SCI_SETPASTECONVERTENDINGS:
		convertPastes = wParam != 0;
		break;

	case SCI_GETPASTECONVERTENDINGS:
		return convertPastes ? 1 : 0;

	case SCI_GETCHARACTERPOINTER:
		return reinterpret_cast<sptr_t>(pdoc->BufferPointer());

	case SCI_GETRANGEPOINTER:
		return reinterpret_cast<sptr_t>(pdoc->RangePointer(wParam, lParam));

	case SCI_GETGAPPOSITION:
		return pdoc->GapPosition();

	case SCI_SETEXTRAASCENT:
		vs.extraAscent = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETEXTRAASCENT:
		return vs.extraAscent;

	case SCI_SETEXTRADESCENT:
		vs.extraDescent = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETEXTRADESCENT:
		return vs.extraDescent;

	case SCI_MARGINSETSTYLEOFFSET:
		vs.marginStyleOffset = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_MARGINGETSTYLEOFFSET:
		return vs.marginStyleOffset;

	case SCI_SETMARGINOPTIONS:
		marginOptions = wParam;
		break;

	case SCI_GETMARGINOPTIONS:
		return marginOptions;

	case SCI_MARGINSETTEXT:
		pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam));
		break;

	case SCI_MARGINGETTEXT: {
			const StyledText st = pdoc->MarginStyledText(wParam);
			if (lParam) {
				if (st.text)
					memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
				else
					strcpy(CharPtrFromSPtr(lParam), "");
			}
			return st.length;
		}

	case SCI_MARGINSETSTYLE:
		pdoc->MarginSetStyle(wParam, lParam);
		break;

	case SCI_MARGINGETSTYLE: {
			const StyledText st = pdoc->MarginStyledText(wParam);
			return st.style;
		}

	case SCI_MARGINSETSTYLES:
		pdoc->MarginSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
		break;

	case SCI_MARGINGETSTYLES: {
			const StyledText st = pdoc->MarginStyledText(wParam);
			if (lParam) {
				if (st.styles)
					memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
				else
					strcpy(CharPtrFromSPtr(lParam), "");
			}
			return st.styles ? st.length : 0;
		}

	case SCI_MARGINTEXTCLEARALL:
		pdoc->MarginClearAll();
		break;

	case SCI_ANNOTATIONSETTEXT:
		pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam));
		break;

	case SCI_ANNOTATIONGETTEXT: {
			const StyledText st = pdoc->AnnotationStyledText(wParam);
			if (lParam) {
				if (st.text)
					memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
				else
					strcpy(CharPtrFromSPtr(lParam), "");
			}
			return st.length;
		}

	case SCI_ANNOTATIONGETSTYLE: {
			const StyledText st = pdoc->AnnotationStyledText(wParam);
			return st.style;
		}

	case SCI_ANNOTATIONSETSTYLE:
		pdoc->AnnotationSetStyle(wParam, lParam);
		break;

	case SCI_ANNOTATIONSETSTYLES:
		pdoc->AnnotationSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
		break;

	case SCI_ANNOTATIONGETSTYLES: {
			const StyledText st = pdoc->AnnotationStyledText(wParam);
			if (lParam) {
				if (st.styles)
					memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
				else
					strcpy(CharPtrFromSPtr(lParam), "");
			}
			return st.styles ? st.length : 0;
		}

	case SCI_ANNOTATIONGETLINES:
		return pdoc->AnnotationLines(wParam);

	case SCI_ANNOTATIONCLEARALL:
		pdoc->AnnotationClearAll();
		break;

	case SCI_ANNOTATIONSETVISIBLE:
		SetAnnotationVisible(wParam);
		break;

	case SCI_ANNOTATIONGETVISIBLE:
		return vs.annotationVisible;

	case SCI_ANNOTATIONSETSTYLEOFFSET:
		vs.annotationStyleOffset = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_ANNOTATIONGETSTYLEOFFSET:
		return vs.annotationStyleOffset;

	case SCI_RELEASEALLEXTENDEDSTYLES:
		vs.ReleaseAllExtendedStyles();
		break;

	case SCI_ALLOCATEEXTENDEDSTYLES:
		return vs.AllocateExtendedStyles(wParam);

	case SCI_ADDUNDOACTION:
		pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
		break;

	case SCI_SETMULTIPLESELECTION:
		multipleSelection = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETMULTIPLESELECTION:
		return multipleSelection;

	case SCI_SETADDITIONALSELECTIONTYPING:
		additionalSelectionTyping = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALSELECTIONTYPING:
		return additionalSelectionTyping;

	case SCI_SETMULTIPASTE:
		multiPasteMode = wParam;
		break;

	case SCI_GETMULTIPASTE:
		return multiPasteMode;

	case SCI_SETADDITIONALCARETSBLINK:
		additionalCaretsBlink = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALCARETSBLINK:
		return additionalCaretsBlink;

	case SCI_SETADDITIONALCARETSVISIBLE:
		additionalCaretsVisible = wParam != 0;
		InvalidateCaret();
		break;

	case SCI_GETADDITIONALCARETSVISIBLE:
		return additionalCaretsVisible;

	case SCI_GETSELECTIONS:
		return sel.Count();

	case SCI_GETSELECTIONEMPTY:
		return sel.Empty();

	case SCI_CLEARSELECTIONS:
		sel.Clear();
		Redraw();
		break;

	case SCI_SETSELECTION:
		sel.SetSelection(SelectionRange(wParam, lParam));
		Redraw();
		break;

	case SCI_ADDSELECTION:
		sel.AddSelection(SelectionRange(wParam, lParam));
		Redraw();
		break;

	case SCI_SETMAINSELECTION:
		sel.SetMain(wParam);
		Redraw();
		break;

	case SCI_GETMAINSELECTION:
		return sel.Main();

	case SCI_SETSELECTIONNCARET:
		sel.Range(wParam).caret.SetPosition(lParam);
		Redraw();
		break;

	case SCI_GETSELECTIONNCARET:
		return sel.Range(wParam).caret.Position();

	case SCI_SETSELECTIONNANCHOR:
		sel.Range(wParam).anchor.SetPosition(lParam);
		Redraw();
		break;
	case SCI_GETSELECTIONNANCHOR:
		return sel.Range(wParam).anchor.Position();

	case SCI_SETSELECTIONNCARETVIRTUALSPACE:
		sel.Range(wParam).caret.SetVirtualSpace(lParam);
		Redraw();
		break;

	case SCI_GETSELECTIONNCARETVIRTUALSPACE:
		return sel.Range(wParam).caret.VirtualSpace();

	case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
		sel.Range(wParam).anchor.SetVirtualSpace(lParam);
		Redraw();
		break;

	case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
		return sel.Range(wParam).anchor.VirtualSpace();

	case SCI_SETSELECTIONNSTART:
		sel.Range(wParam).anchor.SetPosition(lParam);
		Redraw();
		break;

	case SCI_GETSELECTIONNSTART:
		return sel.Range(wParam).Start().Position();

	case SCI_SETSELECTIONNEND:
		sel.Range(wParam).caret.SetPosition(lParam);
		Redraw();
		break;

	case SCI_GETSELECTIONNEND:
		return sel.Range(wParam).End().Position();

	case SCI_SETRECTANGULARSELECTIONCARET:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().caret.SetPosition(wParam);
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONCARET:
		return sel.Rectangular().caret.Position();

	case SCI_SETRECTANGULARSELECTIONANCHOR:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().anchor.SetPosition(wParam);
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONANCHOR:
		return sel.Rectangular().anchor.Position();

	case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().caret.SetVirtualSpace(wParam);
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
		return sel.Rectangular().caret.VirtualSpace();

	case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
		if (!sel.IsRectangular())
			sel.Clear();
		sel.selType = Selection::selRectangle;
		sel.Rectangular().anchor.SetVirtualSpace(wParam);
		SetRectangularRange();
		Redraw();
		break;

	case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
		return sel.Rectangular().anchor.VirtualSpace();

	case SCI_SETVIRTUALSPACEOPTIONS:
		virtualSpaceOptions = wParam;
		break;

	case SCI_GETVIRTUALSPACEOPTIONS:
		return virtualSpaceOptions;

	case SCI_SETADDITIONALSELFORE:
		vs.selAdditionalForeground = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETADDITIONALSELBACK:
		vs.selAdditionalBackground = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_SETADDITIONALSELALPHA:
		vs.selAdditionalAlpha = wParam;
		InvalidateStyleRedraw();
		break;

	case SCI_GETADDITIONALSELALPHA:
		return vs.selAdditionalAlpha;

	case SCI_SETADDITIONALCARETFORE:
		vs.additionalCaretColour = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_GETADDITIONALCARETFORE:
		return vs.additionalCaretColour.AsLong();

	case SCI_ROTATESELECTION:
		sel.RotateMain();
		InvalidateSelection(sel.RangeMain(), true);
		break;

	case SCI_SWAPMAINANCHORCARET:
		InvalidateSelection(sel.RangeMain());
		sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret);
		break;

	case SCI_CHANGELEXERSTATE:
		pdoc->ChangeLexerState(wParam, lParam);
		break;
	
	case SCI_SETIDENTIFIER:
		SetCtrlID(wParam);
		break;
	
	case SCI_GETIDENTIFIER:
		return GetCtrlID();

	case SCI_SETTECHNOLOGY:
		// No action by default
		break;
	
	case SCI_GETTECHNOLOGY:
		return technology;

	case SCI_COUNTCHARACTERS:
		return pdoc->CountCharacters(wParam, lParam);

	default:
		return DefWndProc(iMessage, wParam, lParam);
	}
	//Platform::DebugPrintf("end wnd proc\n");
	return 0l;
}

Added src/Editor.h.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
// Scintilla source code edit control
/** @file Editor.h
 ** Defines the main editor class.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef EDITOR_H
#define EDITOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class Caret {
public:
	bool active;
	bool on;
	int period;

	Caret();
};

/**
 */
class Timer {
public:
	bool ticking;
	int ticksToWait;
	enum {tickSize = 100};
	TickerID tickerID;

	Timer();
};

/**
 */
class Idler {
public:
	bool state;
	IdlerID idlerID;

	Idler();
};

/**
 * When platform has a way to generate an event before painting,
 * accumulate needed styling range and other work items in 
 * WorkNeeded to avoid unnecessary work inside paint handler
 */
class WorkNeeded {
public:
	enum workItems {
		workNone=0,
		workStyle=1,
		workUpdateUI=2
	};
	bool active;
	enum workItems items;
	Position upTo;

	WorkNeeded() : active(false), items(workNone), upTo(0) {}
	void Reset() {
		active = false;
		items = workNone;
		upTo = 0;
	}
	void Need(workItems items_, Position pos) {
		if ((items_ & workStyle) && (upTo < pos))
			upTo = pos;
		items = static_cast<workItems>(items | items_);
	}
};

/**
 * Hold a piece of text selected for copying or dragging.
 * The text is expected to hold a terminating '\0' and this is counted in len.
 */
class SelectionText {
public:
	char *s;
	int len;
	bool rectangular;
	bool lineCopy;
	int codePage;
	int characterSet;
	SelectionText() : s(0), len(0), rectangular(false), lineCopy(false), codePage(0), characterSet(0) {}
	~SelectionText() {
		Free();
	}
	void Free() {
		Set(0, 0, 0, 0, false, false);
	}
	void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
		delete []s;
		s = s_;
		if (s)
			len = len_;
		else
			len = 0;
		codePage = codePage_;
		characterSet = characterSet_;
		rectangular = rectangular_;
		lineCopy = lineCopy_;
		FixSelectionForClipboard();
	}
	void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
		delete []s;
		s = 0;
		s = new char[len_];
		len = len_;
		for (int i = 0; i < len_; i++) {
			s[i] = s_[i];
		}
		codePage = codePage_;
		characterSet = characterSet_;
		rectangular = rectangular_;
		lineCopy = lineCopy_;
		FixSelectionForClipboard();
	}
	void Copy(const SelectionText &other) {
		Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
	}
	
private:
	void FixSelectionForClipboard() {
		// Replace null characters by spaces.
		// To avoid that the content of the clipboard is truncated in the paste operation 
		// when the clipboard contains null characters.
		for (int i = 0; i < len - 1; ++i) {
			if (s[i] == '\0')
				s[i] = ' ';
		}
	}
};

/**
 */
class Editor : public DocWatcher {
	// Private so Editor objects can not be copied
	Editor(const Editor &);
	Editor &operator=(const Editor &);

protected:	// ScintillaBase subclass needs access to much of Editor

	/** On GTK+, Scintilla is a container widget holding two scroll bars
	 * whereas on Windows there is just one window with both scroll bars turned on. */
	Window wMain;	///< The Scintilla parent window
	Window wMargin;	///< May be separate when using a scroll view for wMain

	/** Style resources may be expensive to allocate so are cached between uses.
	 * When a style attribute is changed, this cache is flushed. */
	bool stylesValid;
	ViewStyle vs;
	int technology;
	Point sizeRGBAImage;
	float scaleRGBAImage;

	int printMagnification;
	int printColourMode;
	int printWrapState;
	int cursorMode;
	int controlCharSymbol;

	// Highlight current folding block
	HighlightDelimiter highlightDelimiter;

	bool hasFocus;
	bool hideSelection;
	bool inOverstrike;
	bool mouseDownCaptures;

	/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
	 * the screen. This avoids flashing but is about 30% slower. */
	bool bufferedDraw;
	/** In twoPhaseDraw mode, drawing is performed in two phases, first the background
	* and then the foreground. This avoids chopping off characters that overlap the next run. */
	bool twoPhaseDraw;

	int xOffset;		///< Horizontal scrolled amount in pixels
	int xCaretMargin;	///< Ensure this many pixels visible on both sides of caret
	bool horizontalScrollBarVisible;
	int scrollWidth;
	bool trackLineWidth;
	int lineWidthMaxSeen;
	bool verticalScrollBarVisible;
	bool endAtLastLine;
	int caretSticky;
	int marginOptions;
	bool multipleSelection;
	bool additionalSelectionTyping;
	int multiPasteMode;
	bool additionalCaretsBlink;
	bool additionalCaretsVisible;

	int virtualSpaceOptions;

	Surface *pixmapLine;
	Surface *pixmapSelMargin;
	Surface *pixmapSelPattern;
	Surface *pixmapSelPatternOffset1;
	Surface *pixmapIndentGuide;
	Surface *pixmapIndentGuideHighlight;

	LineLayoutCache llc;
	PositionCache posCache;

	KeyMap kmap;

	Caret caret;
	Timer timer;
	Timer autoScrollTimer;
	enum { autoScrollDelay = 200 };

	Idler idler;

	Point lastClick;
	unsigned int lastClickTime;
	int dwellDelay;
	int ticksToDwell;
	bool dwelling;
	enum { selChar, selWord, selSubLine, selWholeLine } selectionType;
	Point ptMouseLast;
	enum { ddNone, ddInitial, ddDragging } inDragDrop;
	bool dropWentOutside;
	SelectionPosition posDrag;
	SelectionPosition posDrop;
	int hotSpotClickPos;
	int lastXChosen;
	int lineAnchorPos;
	int originalAnchorPos;
	int wordSelectAnchorStartPos;
	int wordSelectAnchorEndPos;
	int wordSelectInitialCaretPos;
	int targetStart;
	int targetEnd;
	int searchFlags;
	int topLine;
	int posTopLine;
	int lengthForEncode;

	int needUpdateUI;
	Position braces[2];
	int bracesMatchStyle;
	int highlightGuideColumn;

	int theEdge;

	enum { notPainting, painting, paintAbandoned } paintState;
	PRectangle rcPaint;
	bool paintingAllText;
	bool willRedrawAll;
	WorkNeeded workNeeded;

	int modEventMask;

	SelectionText drag;
	Selection sel;
	bool primarySelection;

	int caretXPolicy;
	int caretXSlop;	///< Ensure this many pixels visible on both sides of caret

	int caretYPolicy;
	int caretYSlop;	///< Ensure this many lines visible on both sides of caret

	int visiblePolicy;
	int visibleSlop;

	int searchAnchor;

	bool recordingMacro;

	int foldFlags;
	ContractionState cs;

	// Hotspot support
	int hsStart;
	int hsEnd;

	// Wrapping support
	enum { eWrapNone, eWrapWord, eWrapChar } wrapState;
	enum { wrapLineLarge = 0x7ffffff };
	int wrapWidth;
	int wrapStart;
	int wrapEnd;
	int wrapVisualFlags;
	int wrapVisualFlagsLocation;
	int wrapVisualStartIndent;
	int wrapIndentMode; // SC_WRAPINDENT_FIXED, _SAME, _INDENT

	bool convertPastes;

	int marginNumberPadding; // the right-side padding of the number margin
	int ctrlCharPadding; // the padding around control character text blobs
	int lastSegItalicsOffset; // the offset so as not to clip italic characters at EOLs

	Document *pdoc;

	Editor();
	virtual ~Editor();
	virtual void Initialise() = 0;
	virtual void Finalise();

	void InvalidateStyleData();
	void InvalidateStyleRedraw();
	void RefreshStyleData();
	void DropGraphics(bool freeObjects);
	void AllocateGraphics();

	// The top left visible point in main window coordinates. Will be 0,0 except for
	// scroll views where it will be equivalent to the current scroll position.
	virtual Point GetVisibleOriginInMain();
	Point DocumentPointFromView(Point ptView);  // Convert a point from view space to document
	int TopLineOfMain();   // Return the line at Main's y coordinate 0
	virtual PRectangle GetClientRectangle();
	PRectangle GetTextRectangle();

	int LinesOnScreen();
	int LinesToScroll();
	int MaxScrollPos();
	SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const;
	Point LocationFromPosition(SelectionPosition pos);
	Point LocationFromPosition(int pos);
	int XFromPosition(int pos);
	int XFromPosition(SelectionPosition sp);
	SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true);
	int PositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false);
	SelectionPosition SPositionFromLineX(int lineDoc, int x);
	int PositionFromLineX(int line, int x);
	int LineFromLocation(Point pt);
	void SetTopLine(int topLineNew);

	bool AbandonPaint();
	void RedrawRect(PRectangle rc);
	void Redraw();
	void RedrawSelMargin(int line=-1, bool allAfter=false);
	PRectangle RectangleFromRange(int start, int end);
	void InvalidateRange(int start, int end);

	bool UserVirtualSpace() const {
		return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0);
	}
	int CurrentPosition();
	bool SelectionEmpty();
	SelectionPosition SelectionStart();
	SelectionPosition SelectionEnd();
	void SetRectangularRange();
	void ThinRectangularRange();
	void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
	void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
	void SetSelection(int currentPos_, int anchor_);
	void SetSelection(SelectionPosition currentPos_);
	void SetSelection(int currentPos_);
	void SetEmptySelection(SelectionPosition currentPos_);
	void SetEmptySelection(int currentPos_);
	bool RangeContainsProtected(int start, int end) const;
	bool SelectionContainsProtected();
	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const;
	SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const;
	int MovePositionTo(SelectionPosition newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
	int MovePositionTo(int newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
	SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir);
	SelectionPosition MovePositionSoVisible(int pos, int moveDir);
	Point PointMainCaret();
	void SetLastXChosen();

	void ScrollTo(int line, bool moveThumb=true);
	virtual void ScrollText(int linesToMove);
	void HorizontalScrollTo(int xPos);
	void VerticalCentreCaret();
	void MoveSelectedLines(int lineDelta);
	void MoveSelectedLinesUp();
	void MoveSelectedLinesDown();
	void MoveCaretInsideView(bool ensureVisible=true);
	int DisplayFromPosition(int pos);

	struct XYScrollPosition {
		int xOffset;
		int topLine;
		XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {}
		bool operator==(const XYScrollPosition &other) const {
			return (xOffset == other.xOffset) && (topLine == other.topLine);
		}
	};
	enum XYScrollOptions {
		xysUseMargin=0x1,
		xysVertical=0x2,
		xysHorizontal=0x4,
		xysDefault=xysUseMargin|xysVertical|xysHorizontal};
	XYScrollPosition XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options);
	void SetXYScroll(XYScrollPosition newXY);
	void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
	void ScrollRange(SelectionRange range);
	void ShowCaretAtCurrentPosition();
	void DropCaret();
	void InvalidateCaret();
	virtual void UpdateSystemCaret();

	void NeedWrapping(int docLineStart = 0, int docLineEnd = wrapLineLarge);
	bool WrapOneLine(Surface *surface, int lineToWrap);
	bool WrapLines(bool fullWrap, int priorityWrapLineStart);
	void LinesJoin();
	void LinesSplit(int pixelWidth);

	int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault);
	void PaintSelMargin(Surface *surface, PRectangle &rc);
	LineLayout *RetrieveLineLayout(int lineNumber);
	void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll,
		int width=LineLayout::wrapWidthInfinite);
	ColourDesired SelectionBackground(ViewStyle &vsDraw, bool main);
	ColourDesired TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll);
	void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
	void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
	void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
		int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
		bool overrideBackground, ColourDesired background,
		bool drawWrapMark, ColourDesired wrapColour);
	void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw,
		int xStart, PRectangle rcLine, LineLayout *ll, int subLine);
	void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
		PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under);
	void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
        PRectangle rcLine, LineLayout *ll, int subLine);
	void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
		PRectangle rcLine, LineLayout *ll, int subLine);
	void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
		int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour);
	void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
		PRectangle rcLine, LineLayout *ll, int subLine);
	void RefreshPixMaps(Surface *surfaceWindow);
	void Paint(Surface *surfaceWindow, PRectangle rcArea);
	long FormatRange(bool draw, Sci_RangeToFormat *pfr);
	int TextWidth(int style, const char *text);

	virtual void SetVerticalScrollPos() = 0;
	virtual void SetHorizontalScrollPos() = 0;
	virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
	virtual void ReconfigureScrollBars();
	void SetScrollBars();
	void ChangeSize();

	void FilterSelections();
	int InsertSpace(int position, unsigned int spaces);
	void AddChar(char ch);
	virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
	void InsertPaste(SelectionPosition selStart, const char *text, int len);
	void ClearSelection(bool retainMultipleSelections=false);
	void ClearAll();
	void ClearDocumentStyle();
	void Cut();
	void PasteRectangular(SelectionPosition pos, const char *ptr, int len);
	virtual void Copy() = 0;
	virtual void CopyAllowLine();
	virtual bool CanPaste();
	virtual void Paste() = 0;
	void Clear();
	void SelectAll();
	void Undo();
	void Redo();
	void DelChar();
	void DelCharBack(bool allowLineStartDeletion);
	virtual void ClaimSelection() = 0;

	virtual void NotifyChange() = 0;
	virtual void NotifyFocus(bool focus);
	virtual void SetCtrlID(int identifier);
	virtual int GetCtrlID() { return ctrlID; }
	virtual void NotifyParent(SCNotification scn) = 0;
	virtual void NotifyStyleToNeeded(int endStyleNeeded);
	void NotifyChar(int ch);
	void NotifySavePoint(bool isSavePoint);
	void NotifyModifyAttempt();
	virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
	void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
	void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
	void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt);
	bool NotifyUpdateUI();
	void NotifyPainted();
	void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt);
	bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
	void NotifyNeedShown(int pos, int len);
	void NotifyDwelling(Point pt, bool state);
	void NotifyZoom();

	void NotifyModifyAttempt(Document *document, void *userData);
	void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
	void CheckModificationForWrap(DocModification mh);
	void NotifyModified(Document *document, DocModification mh, void *userData);
	void NotifyDeleted(Document *document, void *userData);
	void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
	void NotifyLexerChanged(Document *doc, void *userData);
	void NotifyErrorOccurred(Document *doc, void *userData, int status);
	void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

	void ContainerNeedsUpdate(int flags);
	void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false);
	enum { cmSame, cmUpper, cmLower } caseMap;
	virtual std::string CaseMapString(const std::string &s, int caseMapping);
	void ChangeCaseOfSelection(int caseMapping);
	void LineTranspose();
	void Duplicate(bool forLine);
	virtual void CancelModes();
	void NewLine();
	void CursorUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
	void ParaUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
	int StartEndDisplayLine(int pos, bool start);
	virtual int KeyCommand(unsigned int iMessage);
	virtual int KeyDefault(int /* key */, int /*modifiers*/);
	int KeyDownWithModifiers(int key, int modifiers, bool *consumed);
	int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0);

	void Indent(bool forwards);

	virtual CaseFolder *CaseFolderForEncoding();
	long FindText(uptr_t wParam, sptr_t lParam);
	void SearchAnchor();
	long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	long SearchInTarget(const char *text, int length);
	void GoToLine(int lineNo);

	virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
	char *CopyRange(int start, int end);
	std::string RangeText(int start, int end) const;
	void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
	void CopyRangeToClipboard(int start, int end);
	void CopyText(int length, const char *text);
	void SetDragPosition(SelectionPosition newPos);
	virtual void DisplayCursor(Window::Cursor c);
	virtual bool DragThreshold(Point ptStart, Point ptNow);
	virtual void StartDrag();
	void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular);
	/** PositionInSelection returns true if position in selection. */
	bool PositionInSelection(int pos);
	bool PointInSelection(Point pt);
	bool PointInSelMargin(Point pt);
	Window::Cursor GetMarginCursor(Point pt);
	void TrimAndSetSelection(int currentPos_, int anchor_);
	void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine);
	void WordSelection(int pos);
	void DwellEnd(bool mouseMoved);
	void MouseLeave();
	virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
	void ButtonMove(Point pt);
	void ButtonUp(Point pt, unsigned int curTime, bool ctrl);

	void Tick();
	bool Idle();
	virtual void SetTicking(bool on) = 0;
	virtual bool SetIdle(bool) { return false; }
	virtual void SetMouseCapture(bool on) = 0;
	virtual bool HaveMouseCapture() = 0;
	void SetFocusState(bool focusState);

	int PositionAfterArea(PRectangle rcArea);
	void StyleToPositionInView(Position pos);
	virtual void IdleWork();
	virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0);

	virtual bool PaintContains(PRectangle rc);
	bool PaintContainsMargin();
	void CheckForChangeOutsidePaint(Range r);
	void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);

	void SetAnnotationHeights(int start, int end);
	void SetDocPointer(Document *document);

	void SetAnnotationVisible(int visible);

	void Expand(int &line, bool doExpand);
	void ToggleContraction(int line);
	int ContractedFoldNext(int lineStart);
	void EnsureLineVisible(int lineDoc, bool enforcePolicy);
	int GetTag(char *tagValue, int tagNumber);
	int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);

	bool PositionIsHotspot(int position);
	bool PointIsHotspot(Point pt);
	void SetHotSpotRange(Point *pt);
	void GetHotSpotRange(int &hsStart, int &hsEnd);

	int CodePage() const;
	virtual bool ValidCodePage(int /* codePage */) const { return true; }
	int WrapCount(int line);
	void AddStyledText(char *buffer, int appendLength);

	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
	void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

	static const char *StringFromEOLMode(int eolMode);

	static sptr_t StringResult(sptr_t lParam, const char *val);

public:
	// Public so the COM thunks can access it.
	bool IsUnicodeMode() const;
	// Public so scintilla_send_message can use it.
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	// Public so scintilla_set_id can use it.
	int ctrlID;
	// Public so COM methods for drag and drop can set it.
	int errorStatus;
	friend class AutoSurface;
	friend class SelectionLineIterator;
};

/**
 * A smart pointer class to ensure Surfaces are set up and deleted correctly.
 */
class AutoSurface {
private:
	Surface *surf;
public:
	AutoSurface(Editor *ed, int technology = -1) : surf(0) {
		if (ed->wMain.GetID()) {
			surf = Surface::Allocate(technology != -1 ? technology : ed->technology);
			if (surf) {
				surf->Init(ed->wMain.GetID());
				surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
				surf->SetDBCSMode(ed->CodePage());
			}
		}
	}
	AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) : surf(0) {
		if (ed->wMain.GetID()) {
			surf = Surface::Allocate(technology != -1 ? technology : ed->technology);
			if (surf) {
				surf->Init(sid, ed->wMain.GetID());
				surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
				surf->SetDBCSMode(ed->CodePage());
			}
		}
	}
	~AutoSurface() {
		delete surf;
	}
	Surface *operator->() const {
		return surf;
	}
	operator Surface *() const {
		return surf;
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/ExternalLexer.cxx.



































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include <string>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "LexerModule.h"
#include "Catalogue.h"
#include "ExternalLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerManager *LexerManager::theInstance = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
	fneFactory = fFactory;
	fnFactory = fFactory(index);
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(const char *ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	lib = DynamicLibrary::Load(ModuleName);
	if (lib->IsValid()) {
		m_sModuleName = ModuleName;
		//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
			GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
				Catalogue::AddLexerModule(lex);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here.
				lex->SetExternal(fnFactory, i);
			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
	delete lib;
}

void LexerLibrary::Release() {
	LexerMinder *lm;
	LexerMinder *lmNext;
	lm = first;
	while (NULL != lm) {
		lmNext = lm->next;
		delete lm->self;
		delete lm;
		lm = lmNext;
	}

	first = NULL;
	last = NULL;
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
	if (!theInstance)
		theInstance = new LexerManager;
	return theInstance;
}

/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
	delete theInstance;
	theInstance = NULL;
}

/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
	first = NULL;
	last = NULL;
}

LexerManager::~LexerManager() {
	Clear();
}

void LexerManager::Load(const char *path) {
	LoadLexerLibrary(path);
}

void LexerManager::LoadLexerLibrary(const char *module) {
	for (LexerLibrary *ll = first; ll; ll= ll->next) {
		if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
			return;
	}
	LexerLibrary *lib = new LexerLibrary(module);
	if (NULL != first) {
		last->next = lib;
		last = lib;
	} else {
		first = lib;
		last = lib;
	}
}

void LexerManager::Clear() {
	if (NULL != first) {
		LexerLibrary *cur = first;
		LexerLibrary *next;
		while (cur) {
			next = cur->next;
			delete cur;
			cur = next;
		}
		first = NULL;
		last = NULL;
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

LMMinder::~LMMinder() {
	LexerManager::DeleteInstance();
}

LMMinder minder;

Added src/ExternalLexer.h.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ExternalLexer.h
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef EXTERNALLEXER_H
#define EXTERNALLEXER_H

#if PLAT_WIN
#define EXT_LEXER_DECL __stdcall
#else
#define EXT_LEXER_DECL
#endif

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);
typedef int (EXT_LEXER_DECL *GetLexerCountFn)();
typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength);
typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index);

/// Sub-class of LexerModule to use an external lexer.
class ExternalLexerModule : public LexerModule {
protected:
	GetLexerFactoryFunction fneFactory;
	char name[100];
public:
	ExternalLexerModule(int language_, LexerFunction fnLexer_,
		const char *languageName_=0, LexerFunction fnFolder_=0) :
		LexerModule(language_, fnLexer_, 0, fnFolder_),
		fneFactory(0) {
		strncpy(name, languageName_, sizeof(name));
		name[sizeof(name)-1] = '\0';
		languageName = name;
	}
	virtual void SetExternal(GetLexerFactoryFunction fFactory, int index);
};

/// LexerMinder points to an ExternalLexerModule - so we don't leak them.
class LexerMinder {
public:
	ExternalLexerModule *self;
	LexerMinder *next;
};

/// LexerLibrary exists for every External Lexer DLL, contains LexerMinders.
class LexerLibrary {
	DynamicLibrary	*lib;
	LexerMinder		*first;
	LexerMinder		*last;

public:
	LexerLibrary(const char *ModuleName);
	~LexerLibrary();
	void Release();

	LexerLibrary	*next;
	std::string			m_sModuleName;
};

/// LexerManager manages external lexers, contains LexerLibrarys.
class LexerManager {
public:
	~LexerManager();

	static LexerManager *GetInstance();
	static void DeleteInstance();

	void Load(const char *path);
	void Clear();

private:
	LexerManager();
	static LexerManager *theInstance;

	void LoadLexerLibrary(const char *module);
	LexerLibrary *first;
	LexerLibrary *last;
};

class LMMinder {
public:
	~LMMinder();
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/FontQuality.h.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Scintilla source code edit control
/** @file FontQuality.h
 ** Definitions to control font anti-aliasing.
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#define SC_EFF_QUALITY_MASK            0xF
#define SC_EFF_QUALITY_DEFAULT           0
#define SC_EFF_QUALITY_NON_ANTIALIASED   1
#define SC_EFF_QUALITY_ANTIALIASED       2
#define SC_EFF_QUALITY_LCD_OPTIMIZED     3

#define SCWIN_TECH_GDI 0
#define SCWIN_TECH_DIRECTWRITE 1

Added src/Indicator.cxx.

































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Indicator.cxx
 ** Defines the style of indicators which are text decorations such as underlining.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "Indicator.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static PRectangle PixelGridAlign(const PRectangle &rc) {
	// Move left and right side to nearest pixel to avoid blurry visuals
	return PRectangle(int(rc.left + 0.5), rc.top, int(rc.right + 0.5), rc.bottom);
}

void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
	surface->PenColour(fore);
	int ymid = (rc.bottom + rc.top) / 2;
	if (style == INDIC_SQUIGGLE) {
		int x = int(rc.left+0.5);
		int xLast = int(rc.right+0.5);
		int y = 0;
		surface->MoveTo(x, rc.top + y);
		while (x < xLast) {
			if ((x + 2) > xLast) {
				if (xLast > x)
					y = 1;
				x = xLast;
			} else {
				x += 2;
				y = 2 - y;
			}
			surface->LineTo(x, rc.top + y);
		}
	} else if (style == INDIC_SQUIGGLEPIXMAP) {
		PRectangle rcSquiggle = PixelGridAlign(rc);

		int width = Platform::Minimum(4000, rcSquiggle.Width());
		RGBAImage image(width, 3, 1.0, 0);
		enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
		for (int x = 0; x < width; x++) {
			if (x%2) {
				// Two halfway columns have a full pixel in middle flanked by light pixels
				image.SetPixel(x, 0, fore, alphaSide);
				image.SetPixel(x, 1, fore, alphaFull);
				image.SetPixel(x, 2, fore, alphaSide);
			} else {
				// Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
				image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
				image.SetPixel(x, 1, fore, alphaSide2);
			}
		}
		surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_SQUIGGLELOW) {
		surface->MoveTo(rc.left, rc.top);
		int x = rc.left + 3;
		int y = 0;
		while (x < rc.right) {
			surface->LineTo(x-1, rc.top + y);
			y = 1 - y;
        	surface->LineTo(x, rc.top + y);
			x += 3;
		}
		surface->LineTo(rc.right, rc.top + y);	// Finish the line
	} else if (style == INDIC_TT) {
		surface->MoveTo(rc.left, ymid);
		int x = rc.left + 5;
		while (x < rc.right) {
			surface->LineTo(x, ymid);
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
			x++;
			surface->MoveTo(x, ymid);
			x += 5;
		}
		surface->LineTo(rc.right, ymid);	// Finish the line
		if (x - 3 <= rc.right) {
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
		}
	} else if (style == INDIC_DIAGONAL) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, rc.top+2);
			int endX = x+3;
			int endY = rc.top - 1;
			if (endX > rc.right) {
				endY += endX - rc.right;
				endX = rc.right;
			}
			surface->LineTo(endX, endY);
			x += 4;
		}
	} else if (style == INDIC_STRIKE) {
		surface->MoveTo(rc.left, rc.top - 4);
		surface->LineTo(rc.right, rc.top - 4);
	} else if (style == INDIC_HIDDEN) {
		// Draw nothing
	} else if (style == INDIC_BOX) {
		surface->MoveTo(rc.left, ymid+1);
		surface->LineTo(rc.right, ymid+1);
		surface->LineTo(rc.right, rcLine.top+1);
		surface->LineTo(rc.left, rcLine.top+1);
		surface->LineTo(rc.left, ymid+1);
	} else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
		PRectangle rcBox = rcLine;
		rcBox.top = rcLine.top + 1;
		rcBox.left = rc.left;
		rcBox.right = rc.right;
		surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
	} else if (style == INDIC_DOTBOX) {
		PRectangle rcBox = PixelGridAlign(rc);
		rcBox.top = rcLine.top + 1;
		rcBox.bottom = rcLine.bottom;
		// Cap width at 4000 to avoid large allocations when mistakes made
		int width = Platform::Minimum(rcBox.Width(), 4000);
		RGBAImage image(width, rcBox.Height(), 1.0, 0);
		// Draw horizontal lines top and bottom
		for (int x=0; x<width; x++) {
			for (int y=0; y<rcBox.Height(); y += rcBox.Height()-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		// Draw vertical lines left and right
		for (int y=1; y<rcBox.Height(); y++) {
			for (int x=0; x<width; x += width-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_DASH) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, ymid);
			surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid);
			x += 7;
		}
	} else if (style == INDIC_DOTS) {
		int x = rc.left;
		while (x < rc.right) {
			PRectangle rcDot(x, ymid, x+1, ymid+1);
			surface->FillRectangle(rcDot, fore);
			x += 2;
		}
	} else {	// Either INDIC_PLAIN or unknown
		surface->MoveTo(rc.left, ymid);
		surface->LineTo(rc.right, ymid);
	}
}

Added src/Indicator.h.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Indicator.h
 ** Defines the style of indicators which are text decorations such as underlining.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef INDICATOR_H
#define INDICATOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class Indicator {
public:
	int style;
	bool under;
	ColourDesired fore;
	int fillAlpha;
	int outlineAlpha;
	Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30), outlineAlpha(50) {
	}
	void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/KeyMap.cxx.











































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file KeyMap.cxx
 ** Defines a mapping between keystrokes and commands.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include "Platform.h"

#include "Scintilla.h"

#include "KeyMap.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

KeyMap::KeyMap() : kmap(0), len(0), alloc(0) {
	for (int i = 0; MapDefault[i].key; i++) {
		AssignCmdKey(MapDefault[i].key,
			MapDefault[i].modifiers,
			MapDefault[i].msg);
	}
}

KeyMap::~KeyMap() {
	Clear();
}

void KeyMap::Clear() {
	delete []kmap;
	kmap = 0;
	len = 0;
	alloc = 0;
}

void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) {
	if ((len+1) >= alloc) {
		KeyToCommand *ktcNew = new KeyToCommand[alloc + 5];
		if (!ktcNew)
			return;
		for (int k = 0; k < len; k++)
			ktcNew[k] = kmap[k];
		alloc += 5;
		delete []kmap;
		kmap = ktcNew;
	}
	for (int keyIndex = 0; keyIndex < len; keyIndex++) {
		if ((key == kmap[keyIndex].key) && (modifiers == kmap[keyIndex].modifiers)) {
			kmap[keyIndex].msg = msg;
			return;
		}
	}
	kmap[len].key = key;
	kmap[len].modifiers = modifiers;
	kmap[len].msg = msg;
	len++;
}

unsigned int KeyMap::Find(int key, int modifiers) {
	for (int i = 0; i < len; i++) {
		if ((key == kmap[i].key) && (modifiers == kmap[i].modifiers)) {
			return kmap[i].msg;
		}
	}
	return 0;
}

#if PLAT_GTK_MACOSX
#define OS_X_KEYS 1
#else
#define OS_X_KEYS 0
#endif

// Define a modifier that is exactly Ctrl key on all platforms
// Most uses of Ctrl map to Cmd on OS X but some can't so use SCI_[S]CTRL_META
#if OS_X_KEYS
#define SCI_CTRL_META SCI_META
#define SCI_SCTRL_META (SCI_META | SCI_SHIFT)
#else
#define SCI_CTRL_META SCI_CTRL
#define SCI_SCTRL_META (SCI_CTRL | SCI_SHIFT)
#endif

const KeyToCommand KeyMap::MapDefault[] = {

#if OS_X_KEYS
    {SCK_DOWN,		SCI_CTRL,	SCI_DOCUMENTEND},
    {SCK_DOWN,		SCI_CSHIFT,	SCI_DOCUMENTENDEXTEND},
    {SCK_UP,		SCI_CTRL,	SCI_DOCUMENTSTART},
    {SCK_UP,		SCI_CSHIFT,	SCI_DOCUMENTSTARTEXTEND},
    {SCK_LEFT,		SCI_CTRL,	SCI_VCHOME},
    {SCK_LEFT,		SCI_CSHIFT,	SCI_VCHOMEEXTEND},
    {SCK_RIGHT,		SCI_CTRL,	SCI_LINEEND},
    {SCK_RIGHT,		SCI_CSHIFT,	SCI_LINEENDEXTEND},
#endif

    {SCK_DOWN,		SCI_NORM,	SCI_LINEDOWN},
    {SCK_DOWN,		SCI_SHIFT,	SCI_LINEDOWNEXTEND},
    {SCK_DOWN,		SCI_CTRL_META,	SCI_LINESCROLLDOWN},
    {SCK_DOWN,		SCI_ASHIFT,	SCI_LINEDOWNRECTEXTEND},
    {SCK_UP,		SCI_NORM,	SCI_LINEUP},
    {SCK_UP,			SCI_SHIFT,	SCI_LINEUPEXTEND},
    {SCK_UP,			SCI_CTRL_META,	SCI_LINESCROLLUP},
    {SCK_UP,		SCI_ASHIFT,	SCI_LINEUPRECTEXTEND},
    {'[',			SCI_CTRL,		SCI_PARAUP},
    {'[',			SCI_CSHIFT,	SCI_PARAUPEXTEND},
    {']',			SCI_CTRL,		SCI_PARADOWN},
    {']',			SCI_CSHIFT,	SCI_PARADOWNEXTEND},
    {SCK_LEFT,		SCI_NORM,	SCI_CHARLEFT},
    {SCK_LEFT,		SCI_SHIFT,	SCI_CHARLEFTEXTEND},
    {SCK_LEFT,		SCI_CTRL_META,	SCI_WORDLEFT},
    {SCK_LEFT,		SCI_SCTRL_META,	SCI_WORDLEFTEXTEND},
    {SCK_LEFT,		SCI_ASHIFT,	SCI_CHARLEFTRECTEXTEND},
    {SCK_RIGHT,		SCI_NORM,	SCI_CHARRIGHT},
    {SCK_RIGHT,		SCI_SHIFT,	SCI_CHARRIGHTEXTEND},
    {SCK_RIGHT,		SCI_CTRL_META,	SCI_WORDRIGHT},
    {SCK_RIGHT,		SCI_SCTRL_META,	SCI_WORDRIGHTEXTEND},
    {SCK_RIGHT,		SCI_ASHIFT,	SCI_CHARRIGHTRECTEXTEND},
    {'/',		SCI_CTRL,		SCI_WORDPARTLEFT},
    {'/',		SCI_CSHIFT,	SCI_WORDPARTLEFTEXTEND},
    {'\\',		SCI_CTRL,		SCI_WORDPARTRIGHT},
    {'\\',		SCI_CSHIFT,	SCI_WORDPARTRIGHTEXTEND},
    {SCK_HOME,		SCI_NORM,	SCI_VCHOME},
    {SCK_HOME, 		SCI_SHIFT, 	SCI_VCHOMEEXTEND},
    {SCK_HOME, 		SCI_CTRL, 	SCI_DOCUMENTSTART},
    {SCK_HOME, 		SCI_CSHIFT, 	SCI_DOCUMENTSTARTEXTEND},
    {SCK_HOME, 		SCI_ALT, 	SCI_HOMEDISPLAY},
    {SCK_HOME,		SCI_ASHIFT,	SCI_VCHOMERECTEXTEND},
    {SCK_END,	 	SCI_NORM,	SCI_LINEEND},
    {SCK_END,	 	SCI_SHIFT, 	SCI_LINEENDEXTEND},
    {SCK_END, 		SCI_CTRL, 	SCI_DOCUMENTEND},
    {SCK_END, 		SCI_CSHIFT, 	SCI_DOCUMENTENDEXTEND},
    {SCK_END, 		SCI_ALT, 	SCI_LINEENDDISPLAY},
    {SCK_END,		SCI_ASHIFT,	SCI_LINEENDRECTEXTEND},
    {SCK_PRIOR,		SCI_NORM,	SCI_PAGEUP},
    {SCK_PRIOR,		SCI_SHIFT, 	SCI_PAGEUPEXTEND},
    {SCK_PRIOR,		SCI_ASHIFT,	SCI_PAGEUPRECTEXTEND},
    {SCK_NEXT, 		SCI_NORM, 	SCI_PAGEDOWN},
    {SCK_NEXT, 		SCI_SHIFT, 	SCI_PAGEDOWNEXTEND},
    {SCK_NEXT,		SCI_ASHIFT,	SCI_PAGEDOWNRECTEXTEND},
    {SCK_DELETE, 	SCI_NORM,	SCI_CLEAR},
    {SCK_DELETE, 	SCI_SHIFT,	SCI_CUT},
    {SCK_DELETE, 	SCI_CTRL,	SCI_DELWORDRIGHT},
    {SCK_DELETE,	SCI_CSHIFT,	SCI_DELLINERIGHT},
    {SCK_INSERT, 		SCI_NORM,	SCI_EDITTOGGLEOVERTYPE},
    {SCK_INSERT, 		SCI_SHIFT,	SCI_PASTE},
    {SCK_INSERT, 		SCI_CTRL,	SCI_COPY},
    {SCK_ESCAPE,  	SCI_NORM,	SCI_CANCEL},
    {SCK_BACK,		SCI_NORM, 	SCI_DELETEBACK},
    {SCK_BACK,		SCI_SHIFT, 	SCI_DELETEBACK},
    {SCK_BACK,		SCI_CTRL, 	SCI_DELWORDLEFT},
    {SCK_BACK, 		SCI_ALT,	SCI_UNDO},
    {SCK_BACK,		SCI_CSHIFT,	SCI_DELLINELEFT},
    {'Z', 			SCI_CTRL,	SCI_UNDO},
#if OS_X_KEYS
    {'Z', 			SCI_CSHIFT,	SCI_REDO},
#else
    {'Y', 			SCI_CTRL,	SCI_REDO},
#endif
    {'X', 			SCI_CTRL,	SCI_CUT},
    {'C', 			SCI_CTRL,	SCI_COPY},
    {'V', 			SCI_CTRL,	SCI_PASTE},
    {'A', 			SCI_CTRL,	SCI_SELECTALL},
    {SCK_TAB,		SCI_NORM,	SCI_TAB},
    {SCK_TAB,		SCI_SHIFT,	SCI_BACKTAB},
    {SCK_RETURN, 	SCI_NORM,	SCI_NEWLINE},
    {SCK_RETURN, 	SCI_SHIFT,	SCI_NEWLINE},
    {SCK_ADD, 		SCI_CTRL,	SCI_ZOOMIN},
    {SCK_SUBTRACT,	SCI_CTRL,	SCI_ZOOMOUT},
    {SCK_DIVIDE,	SCI_CTRL,	SCI_SETZOOM},
    {'L', 			SCI_CTRL,	SCI_LINECUT},
    {'L', 			SCI_CSHIFT,	SCI_LINEDELETE},
    {'T', 			SCI_CSHIFT,	SCI_LINECOPY},
    {'T', 			SCI_CTRL,	SCI_LINETRANSPOSE},
    {'D', 			SCI_CTRL,	SCI_SELECTIONDUPLICATE},
    {'U', 			SCI_CTRL,	SCI_LOWERCASE},
    {'U', 			SCI_CSHIFT,	SCI_UPPERCASE},
    {0,0,0},
};

Added src/KeyMap.h.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file KeyMap.h
 ** Defines a mapping between keystrokes and commands.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef KEYTOCOMMAND_H
#define KEYTOCOMMAND_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

#define SCI_NORM 0
#define SCI_SHIFT SCMOD_SHIFT
#define SCI_CTRL SCMOD_CTRL
#define SCI_ALT SCMOD_ALT
#define SCI_META SCMOD_META
#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT)

/**
 */
class KeyToCommand {
public:
	int key;
	int modifiers;
	unsigned int msg;
};

/**
 */
class KeyMap {
	KeyToCommand *kmap;
	int len;
	int alloc;
	static const KeyToCommand MapDefault[];

public:
	KeyMap();
	~KeyMap();
	void Clear();
	void AssignCmdKey(int key, int modifiers, unsigned int msg);
	unsigned int Find(int key, int modifiers);	// 0 returned on failure
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/LexGen.py.





























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#!/usr/bin/env python
# LexGen.py - implemented 2002 by Neil Hodgson neilh@scintilla.org
# Released to the public domain.

# Regenerate the Scintilla and SciTE source files that list
# all the lexers and all the properties files.
# Should be run whenever a new lexer is added or removed.
# Requires Python 2.4 or later
# Most files are regenerated in place with templates stored in comments.
# The VS .NET project file is generated into a different file as the
# VS .NET environment will not retain comments when modifying the file.
# The files are copied to a string apart from sections between a
# ++Autogenerated comment and a --Autogenerated comment which is
# generated by the CopyWithInsertion function. After the whole
# string is instantiated, it is compared with the target file and
# if different the file is rewritten.
# Does not regenerate the Visual C++ 6 project files but does the VS .NET
# project file.

import string
import sys
import os
import glob

# EOL constants
CR = "\r"
LF = "\n"
CRLF = "\r\n"
if sys.platform == "win32":
    NATIVE = CRLF
else:
    # Yes, LF is the native EOL even on Mac OS X. CR is just for
    # Mac OS <=9 (a.k.a. "Mac Classic")
    NATIVE = LF

# Automatically generated sections contain start and end comments,
# a definition line and the results.
# The results are replaced by regenerating based on the definition line.
# The definition line is a comment prefix followed by "**".
# If there is a digit after the ** then this indicates which list to use
# and the digit and next character are not part of the definition
# Backslash is used as an escape within the definition line.
# The part between \( and \) is repeated for each item in the list.
# \* is replaced by each list item. \t, and \n are tab and newline.
def CopyWithInsertion(input, commentPrefix, retainDefs, eolType, *lists):
    copying = 1
    listid = 0
    output = []
    for line in input.splitlines(0):
        isStartGenerated = line.startswith(commentPrefix + "++Autogenerated")
        if copying and not isStartGenerated:
            output.append(line)
        if isStartGenerated:
            if retainDefs:
                output.append(line)
            copying = 0
            definition = ""
        elif not copying and line.startswith(commentPrefix + "**"):
            if retainDefs:
                output.append(line)
            definition = line[len(commentPrefix + "**"):]
            if (commentPrefix == "<!--") and (" -->" in definition):
                definition = definition.replace(" -->", "")
            listid = 0
            if definition[0] in string.digits:
                listid = int(definition[:1])
                definition = definition[2:]
            # Hide double slashes as a control character
            definition = definition.replace("\\\\", "\001")
            # Do some normal C style transforms
            definition = definition.replace("\\n", "\n")
            definition = definition.replace("\\t", "\t")
            # Get the doubled backslashes back as single backslashes
            definition = definition.replace("\001", "\\")
            startRepeat = definition.find("\\(")
            endRepeat = definition.find("\\)")
            intro = definition[:startRepeat]
            out = ""
            if intro.endswith("\n"):
                pos = 0
            else:
                pos = len(intro)
            out += intro
            middle = definition[startRepeat+2:endRepeat]
            for i in lists[listid]:
                item = middle.replace("\\*", i)
                if pos and (pos + len(item) >= 80):
                    out += "\\\n"
                    pos = 0
                out += item
                pos += len(item)
                if item.endswith("\n"):
                    pos = 0
            outro = definition[endRepeat+2:]
            out += outro
            out = out.replace("\n", eolType) # correct EOLs in generated content
            output.append(out)
        elif line.startswith(commentPrefix + "--Autogenerated"):
            copying = 1
            if retainDefs:
                output.append(line)
    output = [line.rstrip(" \t") for line in output] # trim trailing whitespace
    return eolType.join(output) + eolType

def UpdateFile(filename, updated):
    """ If the file is different to updated then copy updated
    into the file else leave alone so CVS and make don't treat
    it as modified. """
    try:
        infile = open(filename, "rb")
    except IOError:	# File is not there yet
        out = open(filename, "wb")
        out.write(updated.encode('utf-8'))
        out.close()
        print("New %s" % filename)
        return
    original = infile.read()
    infile.close()
    original = original.decode('utf-8')
    if updated != original:
        os.unlink(filename)
        out = open(filename, "wb")
        out.write(updated.encode('utf-8'))
        out.close()
        print("Changed %s " % filename)
    #~ else:
        #~ print "Unchanged", filename

def Generate(inpath, outpath, commentPrefix, eolType, *lists):
    """Generate 'outpath' from 'inpath'.

        "eolType" indicates the type of EOLs to use in the generated
            file. It should be one of following constants: LF, CRLF,
            CR, or NATIVE.
    """
    #print "generate '%s' -> '%s' (comment prefix: %r, eols: %r)"\
    #      % (inpath, outpath, commentPrefix, eolType)
    try:
        infile = open(inpath, "rb")
    except IOError:
        print("Can not open %s" % inpath)
        return
    original = infile.read()
    infile.close()
    original = original.decode('utf-8')
    updated = CopyWithInsertion(original, commentPrefix,
        inpath == outpath, eolType, *lists)
    UpdateFile(outpath, updated)

def Regenerate(filename, commentPrefix, eolType, *lists):
    """Regenerate the given file.

        "eolType" indicates the type of EOLs to use in the generated
            file. It should be one of following constants: LF, CRLF,
            CR, or NATIVE.
    """
    Generate(filename, filename, commentPrefix, eolType, *lists)

def FindModules(lexFile):
    modules = []
    f = open(lexFile)
    for l in f.readlines():
        if l.startswith("LexerModule"):
            l = l.replace("(", " ")
            modules.append(l.split()[1])
    return modules

# Properties that start with lexer. or fold. are automatically found but there are some
# older properties that don't follow this pattern so must be explicitly listed.
knownIrregularProperties = [
    "fold",
    "styling.within.preprocessor",
    "tab.timmy.whinge.level",
    "asp.default.language",
    "html.tags.case.sensitive",
    "ps.level",
    "ps.tokenize",
    "sql.backslash.escapes",
    "nsis.uservars",
    "nsis.ignorecase"
]

def FindProperties(lexFile):
    properties = {}
    f = open(lexFile)
    for l in f.readlines():
        if ("GetProperty" in l or "DefineProperty" in l) and "\"" in l:
            l = l.strip()
            if not l.startswith("//"):	# Drop comments
                propertyName = l.split("\"")[1]
                if propertyName.lower() == propertyName:
                    # Only allow lower case property names
                    if propertyName in knownIrregularProperties or \
                        propertyName.startswith("fold.") or \
                        propertyName.startswith("lexer."):
                        properties[propertyName] = 1
    return properties

def FindPropertyDocumentation(lexFile):
    documents = {}
    f = open(lexFile)
    name = ""
    for l in f.readlines():
        l = l.strip()
        if "// property " in l:
            propertyName = l.split()[2]
            if propertyName.lower() == propertyName:
                # Only allow lower case property names
                name = propertyName
                documents[name] = ""
        elif "DefineProperty" in l and "\"" in l:
            propertyName = l.split("\"")[1]
            if propertyName.lower() == propertyName:
                # Only allow lower case property names
                name = propertyName
                documents[name] = ""
        elif name:
            if l.startswith("//"):
                if documents[name]:
                    documents[name] += " "
                documents[name] += l[2:].strip()
            elif l.startswith("\""):
                l = l[1:].strip()
                if l.endswith(";"):
                    l = l[:-1].strip()
                if l.endswith(")"):
                    l = l[:-1].strip()
                if l.endswith("\""):
                    l = l[:-1]
                # Fix escaped double quotes
                l = l.replace("\\\"", "\"")
                documents[name] += l
            else:
                name = ""
    for name in list(documents.keys()):
        if documents[name] == "":
            del documents[name]
    return documents

def ciCompare(a,b):
    return cmp(a.lower(), b.lower())

def ciKey(a):
    return a.lower()

def sortListInsensitive(l):
    try:    # Try key function
        l.sort(key=ciKey)
    except TypeError:    # Earlier version of Python, so use comparison function
        l.sort(ciCompare)

def UpdateLineInFile(path, linePrefix, lineReplace):
    lines = []
    with open(path, "r") as f:
        for l in f.readlines():
            l = l.rstrip()
            if l.startswith(linePrefix):
                lines.append(lineReplace)
            else:
                lines.append(l)
    contents = NATIVE.join(lines) + NATIVE
    UpdateFile(path, contents)

def UpdateVersionNumbers(root):
    with open(root + "scintilla/version.txt") as f:
        version = f.read()
    versionDotted = version[0] + '.' + version[1] + '.' + version[2]
    versionCommad = version[0] + ', ' + version[1] + ', ' + version[2] + ', 0'

    UpdateLineInFile(root + "scintilla/win32/ScintRes.rc", "#define VERSION_SCINTILLA",
        "#define VERSION_SCINTILLA \"" + versionDotted + "\"")
    UpdateLineInFile(root + "scintilla/win32/ScintRes.rc", "#define VERSION_WORDS", 
        "#define VERSION_WORDS " + versionCommad)
    UpdateLineInFile(root + "scintilla/qt/ScintillaEditBase/ScintillaEditBase.pro",
        "VERSION =", 
        "VERSION = " + versionDotted)
    UpdateLineInFile(root + "scintilla/qt/ScintillaEdit/ScintillaEdit.pro",
        "VERSION =", 
        "VERSION = " + versionDotted)
    UpdateLineInFile(root + "scintilla/doc/ScintillaDownload.html", "       Release", 
        "       Release " + versionDotted)
    UpdateLineInFile(root + "scintilla/doc/index.html",
        '          <font color="#FFCC99" size="3"> Release version', 
        '          <font color="#FFCC99" size="3"> Release version ' + versionDotted + '<br />') 

    if os.path.exists(root + "scite"):
        UpdateLineInFile(root + "scite/src/SciTE.h", "#define VERSION_SCITE", 
            "#define VERSION_SCITE \"" + versionDotted + "\"")
        UpdateLineInFile(root + "scite/src/SciTE.h", "#define VERSION_WORDS", 
            "#define VERSION_WORDS " + versionCommad)
        UpdateLineInFile(root + "scite/doc/SciTEDownload.html", "       Release", 
            "       Release " + versionDotted)
        UpdateLineInFile(root + "scite/doc/SciTE.html",
            '          <font color="#FFCC99" size="3"> Release version', 
            '          <font color="#FFCC99" size="3"> Release version ' + versionDotted + '<br />') 

def RegenerateAll():
    root="../../"

    # Find all the lexer source code files
    lexFilePaths = glob.glob(root + "scintilla/lexers/Lex*.cxx")
    sortListInsensitive(lexFilePaths)
    lexFiles = [os.path.basename(f)[:-4] for f in lexFilePaths]
    print(lexFiles)
    lexerModules = []
    lexerProperties = {}
    propertyDocuments = {}
    for lexFile in lexFilePaths:
        lexerModules.extend(FindModules(lexFile))
        for k in FindProperties(lexFile).keys():
            lexerProperties[k] = 1
        documents = FindPropertyDocumentation(lexFile)
        for k in documents.keys():
            propertyDocuments[k] = documents[k]
    sortListInsensitive(lexerModules)
    lexerProperties = list(lexerProperties.keys())
    sortListInsensitive(lexerProperties)

    # Generate HTML to document each property
    # This is done because tags can not be safely put inside comments in HTML
    documentProperties = list(propertyDocuments.keys())
    sortListInsensitive(documentProperties)
    propertiesHTML = []
    for k in documentProperties:
        propertiesHTML.append("\t<tr id='property-%s'>\n\t<td>%s</td>\n\t<td>%s</td>\n\t</tr>" %
            (k, k, propertyDocuments[k]))

    # Find all the SciTE properties files
    otherProps = ["abbrev.properties", "Embedded.properties", "SciTEGlobal.properties", "SciTE.properties"]
    if os.path.exists(root + "scite"):
        propFilePaths = glob.glob(root + "scite/src/*.properties")
        sortListInsensitive(propFilePaths)
        propFiles = [os.path.basename(f) for f in propFilePaths if os.path.basename(f) not in otherProps]
        sortListInsensitive(propFiles)
        print(propFiles)

    Regenerate(root + "scintilla/src/Catalogue.cxx", "//", NATIVE, lexerModules)
    Regenerate(root + "scintilla/win32/scintilla.mak", "#", NATIVE, lexFiles)
    Regenerate(root + "scintilla/win32/scintilla_vc6.mak", "#", NATIVE, lexFiles)
    if os.path.exists(root + "scite"):
        Regenerate(root + "scite/win32/makefile", "#", NATIVE, propFiles)
        Regenerate(root + "scite/win32/scite.mak", "#", NATIVE, propFiles)
        Regenerate(root + "scite/src/SciTEProps.cxx", "//", NATIVE, lexerProperties)
        Regenerate(root + "scite/doc/SciTEDoc.html", "<!--", NATIVE, propertiesHTML)
        Generate(root + "scite/boundscheck/vcproj.gen",
         root + "scite/boundscheck/SciTE.vcproj", "#", NATIVE, lexFiles)

    UpdateVersionNumbers(root)

RegenerateAll()

Added src/LineMarker.cxx.

































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
// Scintilla source code edit control
/** @file LineMarker.cxx
 ** Defines the look of a line marker in the margin .
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>
#include <math.h>

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "LineMarker.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void LineMarker::SetXPM(const char *textForm) {
	delete pxpm;
	pxpm = new XPM(textForm);
	markType = SC_MARK_PIXMAP;
}

void LineMarker::SetXPM(const char *const *linesForm) {
	delete pxpm;
	pxpm = new XPM(linesForm);
	markType = SC_MARK_PIXMAP;
}

void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) {
	delete image;
	image = new RGBAImage(sizeRGBAImage.x, sizeRGBAImage.y, scale, pixelsRGBAImage);
	markType = SC_MARK_RGBAIMAGE;
}

static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
	PRectangle rc;
	rc.left = centreX - armSize;
	rc.top = centreY - armSize;
	rc.right = centreX + armSize + 1;
	rc.bottom = centreY + armSize + 1;
	surface->RectangleDraw(rc, back, fore);
}

static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
	PRectangle rcCircle;
	rcCircle.left = centreX - armSize;
	rcCircle.top = centreY - armSize;
	rcCircle.right = centreX + armSize + 1;
	rcCircle.bottom = centreY + armSize + 1;
	surface->Ellipse(rcCircle, back, fore);
}

static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
	PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
	surface->FillRectangle(rcV, fore);
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) {
	ColourDesired head = back;
	ColourDesired body = back;
	ColourDesired tail = back;

	switch (tFold) {
	case LineMarker::head :
	case LineMarker::headWithTail :
		head = backSelected;
		tail = backSelected;
		break;
	case LineMarker::body :
		head = backSelected;
		body = backSelected;
		break;
	case LineMarker::tail :
		body = backSelected;
		tail = backSelected;
		break;
	default :
		// LineMarker::undefined
		break;
	}

	if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
		pxpm->Draw(surface, rcWhole);
		return;
	}
	if ((markType == SC_MARK_RGBAIMAGE) && (image)) {
		// Make rectangle just large enough to fit image centred on centre of rcWhole
		PRectangle rcImage;
		rcImage.top = static_cast<int>(((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2);
		rcImage.bottom = rcImage.top + image->GetScaledHeight();
		rcImage.left = static_cast<int>(((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2);
		rcImage.right = rcImage.left + image->GetScaledWidth();
		surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels());
		return;
	}
	// Restrict most shapes a bit
	PRectangle rc = rcWhole;
	rc.top++;
	rc.bottom--;
	int minDim = Platform::Minimum(rc.Width(), rc.Height());
	minDim--;	// Ensure does not go beyond edge
	int centreX = floor((rc.right + rc.left) / 2.0);
	int centreY = floor((rc.bottom + rc.top) / 2.0);
	int dimOn2 = minDim / 2;
	int dimOn4 = minDim / 4;
	int blobSize = dimOn2-1;
	int armSize = dimOn2-2;
	if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) {
		// On textual margins move marker to the left to try to avoid overlapping the text
		centreX = rc.left + dimOn2 + 1;
	}
	if (markType == SC_MARK_ROUNDRECT) {
		PRectangle rcRounded = rc;
		rcRounded.left = rc.left + 1;
		rcRounded.right = rc.right - 1;
		surface->RoundedRectangle(rcRounded, fore, back);
	} else if (markType == SC_MARK_CIRCLE) {
		PRectangle rcCircle;
		rcCircle.left = centreX - dimOn2;
		rcCircle.top = centreY - dimOn2;
		rcCircle.right = centreX + dimOn2;
		rcCircle.bottom = centreY + dimOn2;
		surface->Ellipse(rcCircle, fore, back);
	} else if (markType == SC_MARK_ARROW) {
		Point pts[] = {
    		Point(centreX - dimOn4, centreY - dimOn2),
    		Point(centreX - dimOn4, centreY + dimOn2),
    		Point(centreX + dimOn2 - dimOn4, centreY),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore, back);

	} else if (markType == SC_MARK_ARROWDOWN) {
		Point pts[] = {
    		Point(centreX - dimOn2, centreY - dimOn4),
    		Point(centreX + dimOn2, centreY - dimOn4),
    		Point(centreX, centreY + dimOn2 - dimOn4),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore, back);

	} else if (markType == SC_MARK_PLUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX - 1, centreY - 1),
    		Point(centreX - 1, centreY - armSize),
    		Point(centreX + 1, centreY - armSize),
    		Point(centreX + 1, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX + 1, centreY + 1),
    		Point(centreX + 1, centreY + armSize),
    		Point(centreX - 1, centreY + armSize),
    		Point(centreX - 1, centreY + 1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore, back);

	} else if (markType == SC_MARK_MINUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore, back);

	} else if (markType == SC_MARK_SMALLRECT) {
		PRectangle rcSmall;
		rcSmall.left = rc.left + 1;
		rcSmall.top = rc.top + 2;
		rcSmall.right = rc.right - 1;
		rcSmall.bottom = rc.bottom - 2;
		surface->RectangleDraw(rcSmall, fore, back);

	} else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
		markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
		// An invisible marker so don't draw anything

	} else if (markType == SC_MARK_VLINE) {
		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_LCORNER) {
		surface->PenColour(tail);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY);
		surface->LineTo(rc.right - 1, centreY);

	} else if (markType == SC_MARK_TCORNER) {
		surface->PenColour(tail);
		surface->MoveTo(centreX, centreY);
		surface->LineTo(rc.right - 1, centreY);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY + 1);

		surface->PenColour(head);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_LCORNERCURVE) {
		surface->PenColour(tail);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY-3);
		surface->LineTo(centreX+3, centreY);
		surface->LineTo(rc.right - 1, centreY);

	} else if (markType == SC_MARK_TCORNERCURVE) {
		surface->PenColour(tail);
		surface->MoveTo(centreX, centreY-3);
		surface->LineTo(centreX+3, centreY);
		surface->LineTo(rc.right - 1, centreY);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY-2);

		surface->PenColour(head);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_BOXPLUS) {
		DrawBox(surface, centreX, centreY, blobSize, fore, head);
		DrawPlus(surface, centreX, centreY, blobSize, tail);

	} else if (markType == SC_MARK_BOXPLUSCONNECTED) {
		if (tFold == LineMarker::headWithTail)
			surface->PenColour(tail);
		else
			surface->PenColour(body);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

		DrawBox(surface, centreX, centreY, blobSize, fore, head);
		DrawPlus(surface, centreX, centreY, blobSize, tail);

		if (tFold == LineMarker::body) {
			surface->PenColour(tail);
			surface->MoveTo(centreX + 1, centreY + blobSize);
			surface->LineTo(centreX + blobSize + 1, centreY + blobSize);

			surface->MoveTo(centreX + blobSize, centreY + blobSize);
			surface->LineTo(centreX + blobSize, centreY - blobSize);

			surface->MoveTo(centreX + 1, centreY - blobSize);
			surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
		}
	} else if (markType == SC_MARK_BOXMINUS) {
		DrawBox(surface, centreX, centreY, blobSize, fore, head);
		DrawMinus(surface, centreX, centreY, blobSize, tail);

		surface->PenColour(head);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_BOXMINUSCONNECTED) {
		DrawBox(surface, centreX, centreY, blobSize, fore, head);
		DrawMinus(surface, centreX, centreY, blobSize, tail);

		surface->PenColour(head);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

		if (tFold == LineMarker::body) {
			surface->PenColour(tail);
			surface->MoveTo(centreX + 1, centreY + blobSize);
			surface->LineTo(centreX + blobSize + 1, centreY + blobSize);

			surface->MoveTo(centreX + blobSize, centreY + blobSize);
			surface->LineTo(centreX + blobSize, centreY - blobSize);

			surface->MoveTo(centreX + 1, centreY - blobSize);
			surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
		}
	} else if (markType == SC_MARK_CIRCLEPLUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore, head);
		DrawPlus(surface, centreX, centreY, blobSize, tail);

	} else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
		if (tFold == LineMarker::headWithTail)
			surface->PenColour(tail);
		else
			surface->PenColour(body);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

		DrawCircle(surface, centreX, centreY, blobSize, fore, head);
		DrawPlus(surface, centreX, centreY, blobSize, tail);

	} else if (markType == SC_MARK_CIRCLEMINUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore, head);
		DrawMinus(surface, centreX, centreY, blobSize, tail);

		surface->PenColour(head);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
		DrawCircle(surface, centreX, centreY, blobSize, fore, head);
		DrawMinus(surface, centreX, centreY, blobSize, tail);

		surface->PenColour(head);
		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->PenColour(body);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

	} else if (markType >= SC_MARK_CHARACTER) {
		char character[1];
		character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
		XYPOSITION width = surface->WidthText(fontForCharacter, character, 1);
		rc.left += (rc.Width() - width) / 2;
		rc.right = rc.left + width;
		surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
			character, 1, fore, back);

	} else if (markType == SC_MARK_DOTDOTDOT) {
		int right = centreX - 6;
		for (int b=0; b<3; b++) {
			PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
			surface->FillRectangle(rcBlob, fore);
			right += 5;
		}
	} else if (markType == SC_MARK_ARROWS) {
		surface->PenColour(fore);
		int right = centreX - 2;
		for (int b=0; b<3; b++) {
			surface->MoveTo(right - 4, centreY - 4);
			surface->LineTo(right, centreY);
			surface->LineTo(right - 5, centreY + 5);
			right += 4;
		}
	} else if (markType == SC_MARK_SHORTARROW) {
		Point pts[] = {
			Point(centreX, centreY + dimOn2),
			Point(centreX + dimOn2, centreY),
			Point(centreX, centreY - dimOn2),
			Point(centreX, centreY - dimOn4),
			Point(centreX - dimOn4, centreY - dimOn4),
			Point(centreX - dimOn4, centreY + dimOn4),
			Point(centreX, centreY + dimOn4),
			Point(centreX, centreY + dimOn2),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
				fore, back);
	} else if (markType == SC_MARK_LEFTRECT) {
		PRectangle rcLeft = rcWhole;
		rcLeft.right = rcLeft.left + 4;
		surface->FillRectangle(rcLeft, back);
	} else { // SC_MARK_FULLRECT
		surface->FillRectangle(rcWhole, back);
	}
}

Added src/LineMarker.h.



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file LineMarker.h
 ** Defines the look of a line marker in the margin .
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef LINEMARKER_H
#define LINEMARKER_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif


/**
 */
class LineMarker {
public:
	enum typeOfFold { undefined, head, body, tail, headWithTail };

	int markType;
	ColourDesired fore;
	ColourDesired back;
	ColourDesired backSelected;
	int alpha;
	XPM *pxpm;
	RGBAImage *image;
	LineMarker() {
		markType = SC_MARK_CIRCLE;
		fore = ColourDesired(0,0,0);
		back = ColourDesired(0xff,0xff,0xff);
		backSelected = ColourDesired(0xff,0x00,0x00);
		alpha = SC_ALPHA_NOALPHA;
		pxpm = NULL;
		image = NULL;
	}
	LineMarker(const LineMarker &) {
		// Defined to avoid pxpm being blindly copied, not as a complete copy constructor
		markType = SC_MARK_CIRCLE;
		fore = ColourDesired(0,0,0);
		back = ColourDesired(0xff,0xff,0xff);
		backSelected = ColourDesired(0xff,0x00,0x00);
		alpha = SC_ALPHA_NOALPHA;
		pxpm = NULL;
		image = NULL;
	}
	~LineMarker() {
		delete pxpm;
		delete image;
	}
	LineMarker &operator=(const LineMarker &other) {
		// Defined to avoid pxpm being blindly copied, not as a complete assignment operator
		if (this != &other) {
			markType = SC_MARK_CIRCLE;
			fore = ColourDesired(0,0,0);
			back = ColourDesired(0xff,0xff,0xff);
			backSelected = ColourDesired(0xff,0x00,0x00);
			alpha = SC_ALPHA_NOALPHA;
			delete pxpm;
			pxpm = NULL;
			delete image;
			image = NULL;
		}
		return *this;
	}
	void SetXPM(const char *textForm);
	void SetXPM(const char *const *linesForm);
	void SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage);
	void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Partitioning.h.



























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Partitioning.h
 ** Data structure used to partition an interval. Used for holding line start/end positions.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef PARTITIONING_H
#define PARTITIONING_H

/// A split vector of integers with a method for adding a value to all elements
/// in a range.
/// Used by the Partitioning class.

class SplitVectorWithRangeAdd : public SplitVector<int> {
public:
	SplitVectorWithRangeAdd(int growSize_) {
		SetGrowSize(growSize_);
		ReAllocate(growSize_);
	}
	~SplitVectorWithRangeAdd() {
	}
	void RangeAddDelta(int start, int end, int delta) {
		// end is 1 past end, so end-start is number of elements to change
		int i = 0;
		int rangeLength = end - start;
		int range1Length = rangeLength;
		int part1Left = part1Length - start;
		if (range1Length > part1Left)
			range1Length = part1Left;
		while (i < range1Length) {
			body[start++] += delta;
			i++;
		}
		start += gapLength;
		while (i < rangeLength) {
			body[start++] += delta;
			i++;
		}
	}
};

/// Divide an interval into multiple partitions.
/// Useful for breaking a document down into sections such as lines.
/// A 0 length interval has a single 0 length partition, numbered 0
/// If interval not 0 length then each partition non-zero length
/// When needed, positions after the interval are considered part of the last partition
/// but the end of the last partition can be found with PositionFromPartition(last+1).

class Partitioning {
private:
	// To avoid calculating all the partition positions whenever any text is inserted
	// there may be a step somewhere in the list.
	int stepPartition;
	int stepLength;
	SplitVectorWithRangeAdd *body;

	// Move step forward
	void ApplyStep(int partitionUpTo) {
		if (stepLength != 0) {
			body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength);
		}
		stepPartition = partitionUpTo;
		if (stepPartition >= body->Length()-1) {
			stepPartition = body->Length()-1;
			stepLength = 0;
		}
	}

	// Move step backward
	void BackStep(int partitionDownTo) {
		if (stepLength != 0) {
			body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength);
		}
		stepPartition = partitionDownTo;
	}

	void Allocate(int growSize) {
		body = new SplitVectorWithRangeAdd(growSize);
		stepPartition = 0;
		stepLength = 0;
		body->Insert(0, 0);	// This value stays 0 for ever
		body->Insert(1, 0);	// This is the end of the first partition and will be the start of the second
	}

public:
	Partitioning(int growSize) {
		Allocate(growSize);
	}

	~Partitioning() {
		delete body;
		body = 0;
	}

	int Partitions() const {
		return body->Length()-1;
	}

	void InsertPartition(int partition, int pos) {
		if (stepPartition < partition) {
			ApplyStep(partition);
		}
		body->Insert(partition, pos);
		stepPartition++;
	}

	void SetPartitionStartPosition(int partition, int pos) {
		ApplyStep(partition+1);
		if ((partition < 0) || (partition > body->Length())) {
			return;
		}
		body->SetValueAt(partition, pos);
	}

	void InsertText(int partitionInsert, int delta) {
		// Point all the partitions after the insertion point further along in the buffer
		if (stepLength != 0) {
			if (partitionInsert >= stepPartition) {
				// Fill in up to the new insertion point
				ApplyStep(partitionInsert);
				stepLength += delta;
			} else if (partitionInsert >= (stepPartition - body->Length() / 10)) {
				// Close to step but before so move step back
				BackStep(partitionInsert);
				stepLength += delta;
			} else {
				ApplyStep(body->Length()-1);
				stepPartition = partitionInsert;
				stepLength = delta;
			}
		} else {
			stepPartition = partitionInsert;
			stepLength = delta;
		}
	}

	void RemovePartition(int partition) {
		if (partition > stepPartition) {
			ApplyStep(partition);
			stepPartition--;
		} else {
			stepPartition--;
		}
		body->Delete(partition);
	}

	int PositionFromPartition(int partition) const {
		PLATFORM_ASSERT(partition >= 0);
		PLATFORM_ASSERT(partition < body->Length());
		if ((partition < 0) || (partition >= body->Length())) {
			return 0;
		}
		int pos = body->ValueAt(partition);
		if (partition > stepPartition)
			pos += stepLength;
		return pos;
	}

	/// Return value in range [0 .. Partitions() - 1] even for arguments outside interval
	int PartitionFromPosition(int pos) const {
		if (body->Length() <= 1)
			return 0;
		if (pos >= (PositionFromPartition(body->Length()-1)))
			return body->Length() - 1 - 1;
		int lower = 0;
		int upper = body->Length()-1;
		do {
			int middle = (upper + lower + 1) / 2; 	// Round high
			int posMiddle = body->ValueAt(middle);
			if (middle > stepPartition)
				posMiddle += stepLength;
			if (pos < posMiddle) {
				upper = middle - 1;
			} else {
				lower = middle;
			}
		} while (lower < upper);
		return lower;
	}

	void DeleteAll() {
		int growSize = body->GetGrowSize();
		delete body;
		Allocate(growSize);
	}
};

#endif

Added src/PerLine.cxx.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
// Scintilla source code edit control
/** @file PerLine.cxx
 ** Manages data associated with each line of the document
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
#include "PerLine.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

MarkerHandleSet::MarkerHandleSet() {
	root = 0;
}

MarkerHandleSet::~MarkerHandleSet() {
	MarkerHandleNumber *mhn = root;
	while (mhn) {
		MarkerHandleNumber *mhnToFree = mhn;
		mhn = mhn->next;
		delete mhnToFree;
	}
	root = 0;
}

int MarkerHandleSet::Length() const {
	int c = 0;
	MarkerHandleNumber *mhn = root;
	while (mhn) {
		c++;
		mhn = mhn->next;
	}
	return c;
}

int MarkerHandleSet::NumberFromHandle(int handle) const {
	MarkerHandleNumber *mhn = root;
	while (mhn) {
		if (mhn->handle == handle) {
			return mhn->number;
		}
		mhn = mhn->next;
	}
	return - 1;
}

int MarkerHandleSet::MarkValue() const {
	unsigned int m = 0;
	MarkerHandleNumber *mhn = root;
	while (mhn) {
		m |= (1 << mhn->number);
		mhn = mhn->next;
	}
	return m;
}

bool MarkerHandleSet::Contains(int handle) const {
	MarkerHandleNumber *mhn = root;
	while (mhn) {
		if (mhn->handle == handle) {
			return true;
		}
		mhn = mhn->next;
	}
	return false;
}

bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
	MarkerHandleNumber *mhn = new MarkerHandleNumber;
	if (!mhn)
		return false;
	mhn->handle = handle;
	mhn->number = markerNum;
	mhn->next = root;
	root = mhn;
	return true;
}

void MarkerHandleSet::RemoveHandle(int handle) {
	MarkerHandleNumber **pmhn = &root;
	while (*pmhn) {
		MarkerHandleNumber *mhn = *pmhn;
		if (mhn->handle == handle) {
			*pmhn = mhn->next;
			delete mhn;
			return;
		}
		pmhn = &((*pmhn)->next);
	}
}

bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) {
	bool performedDeletion = false;
	MarkerHandleNumber **pmhn = &root;
	while (*pmhn) {
		MarkerHandleNumber *mhn = *pmhn;
		if (mhn->number == markerNum) {
			*pmhn = mhn->next;
			delete mhn;
			performedDeletion = true;
			if (!all)
				break; 
		} else {
			pmhn = &((*pmhn)->next);
		}
	}
	return performedDeletion;
}

void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
	MarkerHandleNumber **pmhn = &root;
	while (*pmhn) {
		pmhn = &((*pmhn)->next);
	}
	*pmhn = other->root;
	other->root = 0;
}

LineMarkers::~LineMarkers() {
	Init();
}

void LineMarkers::Init() {
	for (int line = 0; line < markers.Length(); line++) {
		delete markers[line];
		markers[line] = 0;
	}
	markers.DeleteAll();
}

void LineMarkers::InsertLine(int line) {
	if (markers.Length()) {
		markers.Insert(line, 0);
	}
}

void LineMarkers::RemoveLine(int line) {
	// Retain the markers from the deleted line by oring them into the previous line
	if (markers.Length()) {
		if (line > 0) {
			MergeMarkers(line - 1);
		}
		markers.Delete(line);
	}
}

int LineMarkers::LineFromHandle(int markerHandle) {
	if (markers.Length()) {
		for (int line = 0; line < markers.Length(); line++) {
			if (markers[line]) {
				if (markers[line]->Contains(markerHandle)) {
					return line;
				}
			}
		}
	}
	return -1;
}

void LineMarkers::MergeMarkers(int pos) {
	if (markers[pos + 1] != NULL) {
		if (markers[pos] == NULL)
			markers[pos] = new MarkerHandleSet;
		markers[pos]->CombineWith(markers[pos + 1]);
		delete markers[pos + 1];
		markers[pos + 1] = NULL;
	}
}

int LineMarkers::MarkValue(int line) {
	if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
		return markers[line]->MarkValue();
	else
		return 0;
}

int LineMarkers::MarkerNext(int lineStart, int mask) const {
	if (lineStart < 0)
		lineStart = 0;
	int length = markers.Length();
	for (int iLine = lineStart; iLine < length; iLine++) {
		MarkerHandleSet *onLine = markers[iLine];
		if (onLine && ((onLine->MarkValue() & mask) != 0))
		//if ((pdoc->GetMark(iLine) & lParam) != 0)
			return iLine;
	}
	return -1;
}

int LineMarkers::AddMark(int line, int markerNum, int lines) {
	handleCurrent++;
	if (!markers.Length()) {
		// No existing markers so allocate one element per line
		markers.InsertValue(0, lines, 0);
	}
	if (line >= markers.Length()) {
		return -1;
	}
	if (!markers[line]) {
		// Need new structure to hold marker handle
		markers[line] = new MarkerHandleSet();
		if (!markers[line])
			return -1;
	}
	markers[line]->InsertHandle(handleCurrent, markerNum);

	return handleCurrent;
}

bool LineMarkers::DeleteMark(int line, int markerNum, bool all) {
	bool someChanges = false;
	if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
		if (markerNum == -1) {
			someChanges = true;
			delete markers[line];
			markers[line] = NULL;
		} else {
			someChanges = markers[line]->RemoveNumber(markerNum, all);
			if (markers[line]->Length() == 0) {
				delete markers[line];
				markers[line] = NULL;
			}
		}
	}
	return someChanges;
}

void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
	int line = LineFromHandle(markerHandle);
	if (line >= 0) {
		markers[line]->RemoveHandle(markerHandle);
		if (markers[line]->Length() == 0) {
			delete markers[line];
			markers[line] = NULL;
		}
	}
}

LineLevels::~LineLevels() {
}

void LineLevels::Init() {
	levels.DeleteAll();
}

void LineLevels::InsertLine(int line) {
	if (levels.Length()) {
		int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
		levels.InsertValue(line, 1, level);
	}
}

void LineLevels::RemoveLine(int line) {
	if (levels.Length()) {
		// Move up following lines but merge header flag from this line
		// to line before to avoid a temporary disappearence causing expansion.
		int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
		levels.Delete(line);
		if (line == levels.Length()-1) // Last line loses the header flag
			levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
		else if (line > 0)
			levels[line-1] |= firstHeader;
	}
}

void LineLevels::ExpandLevels(int sizeNew) {
	levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
}

void LineLevels::ClearLevels() {
	levels.DeleteAll();
}

int LineLevels::SetLevel(int line, int level, int lines) {
	int prev = 0;
	if ((line >= 0) && (line < lines)) {
		if (!levels.Length()) {
			ExpandLevels(lines + 1);
		}
		prev = levels[line];
		if (prev != level) {
			levels[line] = level;
		}
	}
	return prev;
}

int LineLevels::GetLevel(int line) {
	if (levels.Length() && (line >= 0) && (line < levels.Length())) {
		return levels[line];
	} else {
		return SC_FOLDLEVELBASE;
	}
}

LineState::~LineState() {
}

void LineState::Init() {
	lineStates.DeleteAll();
}

void LineState::InsertLine(int line) {
	if (lineStates.Length()) {
		lineStates.EnsureLength(line);
		int val = (line < lineStates.Length()) ? lineStates[line] : 0;
		lineStates.Insert(line, val);
	}
}

void LineState::RemoveLine(int line) {
	if (lineStates.Length() > line) {
		lineStates.Delete(line);
	}
}

int LineState::SetLineState(int line, int state) {
	lineStates.EnsureLength(line + 1);
	int stateOld = lineStates[line];
	lineStates[line] = state;
	return stateOld;
}

int LineState::GetLineState(int line) {
	if (line < 0)
		return 0;
	lineStates.EnsureLength(line + 1);
	return lineStates[line];
}

int LineState::GetMaxLineState() {
	return lineStates.Length();
}

static int NumberLines(const char *text) {
	if (text) {
		int newLines = 0;
		while (*text) {
			if (*text == '\n')
				newLines++;
			text++;
		}
		return newLines+1;
	} else {
		return 0;
	}
}

// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
// and then has text and optional styles.

static const int IndividualStyles = 0x100;

struct AnnotationHeader {
	short style;	// Style IndividualStyles implies array of styles
	short lines;
	int length;
};

LineAnnotation::~LineAnnotation() {
	ClearAll();
}

void LineAnnotation::Init() {
	ClearAll();
}

void LineAnnotation::InsertLine(int line) {
	if (annotations.Length()) {
		annotations.EnsureLength(line);
		annotations.Insert(line, 0);
	}
}

void LineAnnotation::RemoveLine(int line) {
	if (annotations.Length() && (line < annotations.Length())) {
		delete []annotations[line];
		annotations.Delete(line);
	}
}

bool LineAnnotation::AnySet() const {
	return annotations.Length() > 0;
}

bool LineAnnotation::MultipleStyles(int line) const {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
		return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
	else
		return 0;
}

int LineAnnotation::Style(int line) {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
		return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
	else
		return 0;
}

const char *LineAnnotation::Text(int line) const {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
		return annotations[line]+sizeof(AnnotationHeader);
	else
		return 0;
}

const unsigned char *LineAnnotation::Styles(int line) const {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
		return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
	else
		return 0;
}

static char *AllocateAnnotation(int length, int style) {
	size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
	char *ret = new char[len];
	memset(ret, 0, len);
	return ret;
}

void LineAnnotation::SetText(int line, const char *text) {
	if (text && (line >= 0)) {
		annotations.EnsureLength(line+1);
		int style = Style(line);
		if (annotations[line]) {
			delete []annotations[line];
		}
		annotations[line] = AllocateAnnotation(static_cast<int>(strlen(text)), style);
		AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
		pah->style = static_cast<short>(style);
		pah->length = static_cast<int>(strlen(text));
		pah->lines = static_cast<short>(NumberLines(text));
		memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
	} else {
		if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) {
			delete []annotations[line];
			annotations[line] = 0;
		}
	}
}

void LineAnnotation::ClearAll() {
	for (int line = 0; line < annotations.Length(); line++) {
		delete []annotations[line];
		annotations[line] = 0;
	}
	annotations.DeleteAll();
}

void LineAnnotation::SetStyle(int line, int style) {
	annotations.EnsureLength(line+1);
	if (!annotations[line]) {
		annotations[line] = AllocateAnnotation(0, style);
	}
	reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
}

void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
	if (line >= 0) {
		annotations.EnsureLength(line+1);
		if (!annotations[line]) {
			annotations[line] = AllocateAnnotation(0, IndividualStyles);
		} else {
			AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
			if (pahSource->style != IndividualStyles) {
				char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
				AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
				pahAlloc->length = pahSource->length;
				pahAlloc->lines = pahSource->lines;
				memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
				delete []annotations[line];
				annotations[line] = allocation;
			}
		}
		AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
		pah->style = IndividualStyles;
		memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
	}
}

int LineAnnotation::Length(int line) const {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
		return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
	else
		return 0;
}

int LineAnnotation::Lines(int line) const {
	if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
		return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
	else
		return 0;
}

Added src/PerLine.h.



















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file PerLine.h
 ** Manages data associated with each line of the document
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef PERLINE_H
#define PERLINE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 * This holds the marker identifier and the marker type to display.
 * MarkerHandleNumbers are members of lists.
 */
struct MarkerHandleNumber {
	int handle;
	int number;
	MarkerHandleNumber *next;
};

/**
 * A marker handle set contains any number of MarkerHandleNumbers.
 */
class MarkerHandleSet {
	MarkerHandleNumber *root;

public:
	MarkerHandleSet();
	~MarkerHandleSet();
	int Length() const;
	int NumberFromHandle(int handle) const;
	int MarkValue() const;	///< Bit set of marker numbers.
	bool Contains(int handle) const;
	bool InsertHandle(int handle, int markerNum);
	void RemoveHandle(int handle);
	bool RemoveNumber(int markerNum, bool all);
	void CombineWith(MarkerHandleSet *other);
};

class LineMarkers : public PerLine {
	SplitVector<MarkerHandleSet *> markers;
	/// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
	int handleCurrent;
public:
	LineMarkers() : handleCurrent(0) {
	}
	virtual ~LineMarkers();
	virtual void Init();
	virtual void InsertLine(int line);
	virtual void RemoveLine(int line);

	int MarkValue(int line);
	int MarkerNext(int lineStart, int mask) const;
	int AddMark(int line, int marker, int lines);
	void MergeMarkers(int pos);
	bool DeleteMark(int line, int markerNum, bool all);
	void DeleteMarkFromHandle(int markerHandle);
	int LineFromHandle(int markerHandle);
};

class LineLevels : public PerLine {
	SplitVector<int> levels;
public:
	virtual ~LineLevels();
	virtual void Init();
	virtual void InsertLine(int line);
	virtual void RemoveLine(int line);

	void ExpandLevels(int sizeNew=-1);
	void ClearLevels();
	int SetLevel(int line, int level, int lines);
	int GetLevel(int line);
};

class LineState : public PerLine {
	SplitVector<int> lineStates;
public:
	LineState() {
	}
	virtual ~LineState();
	virtual void Init();
	virtual void InsertLine(int line);
	virtual void RemoveLine(int line);

	int SetLineState(int line, int state);
	int GetLineState(int line);
	int GetMaxLineState();
};

class LineAnnotation : public PerLine {
	SplitVector<char *> annotations;
public:
	LineAnnotation() {
	}
	virtual ~LineAnnotation();
	virtual void Init();
	virtual void InsertLine(int line);
	virtual void RemoveLine(int line);

	bool AnySet() const;
	bool MultipleStyles(int line) const;
	int Style(int line);
	const char *Text(int line) const;
	const unsigned char *Styles(int line) const;
	void SetText(int line, const char *text);
	void ClearAll();
	void SetStyle(int line, int style);
	void SetStyles(int line, const unsigned char *styles);
	int Length(int line) const;
	int Lines(int line) const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/PositionCache.cxx.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
// Scintilla source code edit control
/** @file PositionCache.cxx
 ** Classes for caching layout information.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include <string>
#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "ILexer.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static inline bool IsControlCharacter(int ch) {
	// iscntrl returns true for lots of chars > 127 which are displayable
	return ch >= 0 && ch < ' ';
}

LineLayout::LineLayout(int maxLineLength_) :
	lineStarts(0),
	lenLineStarts(0),
	lineNumber(-1),
	inCache(false),
	maxLineLength(-1),
	numCharsInLine(0),
	numCharsBeforeEOL(0),
	validity(llInvalid),
	xHighlightGuide(0),
	highlightColumn(0),
	psel(NULL),
	containsCaret(false),
	edgeColumn(0),
	chars(0),
	styles(0),
	styleBitsSet(0),
	indicators(0),
	positions(0),
	hsStart(0),
	hsEnd(0),
	widthLine(wrapWidthInfinite),
	lines(1),
	wrapIndent(0) {
	bracePreviousStyles[0] = 0;
	bracePreviousStyles[1] = 0;
	Resize(maxLineLength_);
}

LineLayout::~LineLayout() {
	Free();
}

void LineLayout::Resize(int maxLineLength_) {
	if (maxLineLength_ > maxLineLength) {
		Free();
		chars = new char[maxLineLength_ + 1];
		styles = new unsigned char[maxLineLength_ + 1];
		indicators = new char[maxLineLength_ + 1];
		// Extra position allocated as sometimes the Windows
		// GetTextExtentExPoint API writes an extra element.
		positions = new XYPOSITION[maxLineLength_ + 1 + 1];
		maxLineLength = maxLineLength_;
	}
}

void LineLayout::Free() {
	delete []chars;
	chars = 0;
	delete []styles;
	styles = 0;
	delete []indicators;
	indicators = 0;
	delete []positions;
	positions = 0;
	delete []lineStarts;
	lineStarts = 0;
}

void LineLayout::Invalidate(validLevel validity_) {
	if (validity > validity_)
		validity = validity_;
}

int LineLayout::LineStart(int line) const {
	if (line <= 0) {
		return 0;
	} else if ((line >= lines) || !lineStarts) {
		return numCharsInLine;
	} else {
		return lineStarts[line];
	}
}

int LineLayout::LineLastVisible(int line) const {
	if (line < 0) {
		return 0;
	} else if ((line >= lines-1) || !lineStarts) {
		return numCharsBeforeEOL;
	} else {
		return lineStarts[line+1];
	}
}

bool LineLayout::InLine(int offset, int line) const {
	return ((offset >= LineStart(line)) && (offset < LineStart(line + 1))) ||
		((offset == numCharsInLine) && (line == (lines-1)));
}

void LineLayout::SetLineStart(int line, int start) {
	if ((line >= lenLineStarts) && (line != 0)) {
		int newMaxLines = line + 20;
		int *newLineStarts = new int[newMaxLines];
		for (int i = 0; i < newMaxLines; i++) {
			if (i < lenLineStarts)
				newLineStarts[i] = lineStarts[i];
			else
				newLineStarts[i] = 0;
		}
		delete []lineStarts;
		lineStarts = newLineStarts;
		lenLineStarts = newMaxLines;
	}
	lineStarts[line] = start;
}

void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[],
                                    char bracesMatchStyle, int xHighlight, bool ignoreStyle) {
	if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
		int braceOffset = braces[0] - rangeLine.start;
		if (braceOffset < numCharsInLine) {
			bracePreviousStyles[0] = styles[braceOffset];
			styles[braceOffset] = bracesMatchStyle;
		}
	}
	if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
		int braceOffset = braces[1] - rangeLine.start;
		if (braceOffset < numCharsInLine) {
			bracePreviousStyles[1] = styles[braceOffset];
			styles[braceOffset] = bracesMatchStyle;
		}
	}
	if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) ||
	        (braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) {
		xHighlightGuide = xHighlight;
	}
}

void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle) {
	if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
		int braceOffset = braces[0] - rangeLine.start;
		if (braceOffset < numCharsInLine) {
			styles[braceOffset] = bracePreviousStyles[0];
		}
	}
	if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
		int braceOffset = braces[1] - rangeLine.start;
		if (braceOffset < numCharsInLine) {
			styles[braceOffset] = bracePreviousStyles[1];
		}
	}
	xHighlightGuide = 0;
}

int LineLayout::FindBefore(XYPOSITION x, int lower, int upper) const {
	do {
		int middle = (upper + lower + 1) / 2; 	// Round high
		XYPOSITION posMiddle = positions[middle];
		if (x < posMiddle) {
			upper = middle - 1;
		} else {
			lower = middle;
		}
	} while (lower < upper);
	return lower;
}

int LineLayout::EndLineStyle() const {
	return styles[numCharsBeforeEOL > 0 ? numCharsBeforeEOL-1 : 0];
}

LineLayoutCache::LineLayoutCache() :
	level(0), length(0), size(0), cache(0),
	allInvalidated(false), styleClock(-1), useCount(0) {
	Allocate(0);
}

LineLayoutCache::~LineLayoutCache() {
	Deallocate();
}

void LineLayoutCache::Allocate(int length_) {
	PLATFORM_ASSERT(cache == NULL);
	allInvalidated = false;
	length = length_;
	size = length;
	if (size > 1) {
		size = (size / 16 + 1) * 16;
	}
	if (size > 0) {
		cache = new LineLayout * [size];
	}
	for (int i = 0; i < size; i++)
		cache[i] = 0;
}

void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
	PLATFORM_ASSERT(useCount == 0);
	int lengthForLevel = 0;
	if (level == llcCaret) {
		lengthForLevel = 1;
	} else if (level == llcPage) {
		lengthForLevel = linesOnScreen + 1;
	} else if (level == llcDocument) {
		lengthForLevel = linesInDoc;
	}
	if (lengthForLevel > size) {
		Deallocate();
		Allocate(lengthForLevel);
	} else {
		if (lengthForLevel < length) {
			for (int i = lengthForLevel; i < length; i++) {
				delete cache[i];
				cache[i] = 0;
			}
		}
		length = lengthForLevel;
	}
	PLATFORM_ASSERT(length == lengthForLevel);
	PLATFORM_ASSERT(cache != NULL || length == 0);
}

void LineLayoutCache::Deallocate() {
	PLATFORM_ASSERT(useCount == 0);
	for (int i = 0; i < length; i++)
		delete cache[i];
	delete []cache;
	cache = 0;
	length = 0;
	size = 0;
}

void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
	if (cache && !allInvalidated) {
		for (int i = 0; i < length; i++) {
			if (cache[i]) {
				cache[i]->Invalidate(validity_);
			}
		}
		if (validity_ == LineLayout::llInvalid) {
			allInvalidated = true;
		}
	}
}

void LineLayoutCache::SetLevel(int level_) {
	allInvalidated = false;
	if ((level_ != -1) && (level != level_)) {
		level = level_;
		Deallocate();
	}
}

LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
                                      int linesOnScreen, int linesInDoc) {
	AllocateForLevel(linesOnScreen, linesInDoc);
	if (styleClock != styleClock_) {
		Invalidate(LineLayout::llCheckTextAndStyle);
		styleClock = styleClock_;
	}
	allInvalidated = false;
	int pos = -1;
	LineLayout *ret = 0;
	if (level == llcCaret) {
		pos = 0;
	} else if (level == llcPage) {
		if (lineNumber == lineCaret) {
			pos = 0;
		} else if (length > 1) {
			pos = 1 + (lineNumber % (length - 1));
		}
	} else if (level == llcDocument) {
		pos = lineNumber;
	}
	if (pos >= 0) {
		PLATFORM_ASSERT(useCount == 0);
		if (cache && (pos < length)) {
			if (cache[pos]) {
				if ((cache[pos]->lineNumber != lineNumber) ||
				        (cache[pos]->maxLineLength < maxChars)) {
					delete cache[pos];
					cache[pos] = 0;
				}
			}
			if (!cache[pos]) {
				cache[pos] = new LineLayout(maxChars);
			}
			if (cache[pos]) {
				cache[pos]->lineNumber = lineNumber;
				cache[pos]->inCache = true;
				ret = cache[pos];
				useCount++;
			}
		}
	}

	if (!ret) {
		ret = new LineLayout(maxChars);
		ret->lineNumber = lineNumber;
	}

	return ret;
}

void LineLayoutCache::Dispose(LineLayout *ll) {
	allInvalidated = false;
	if (ll) {
		if (!ll->inCache) {
			delete ll;
		} else {
			useCount--;
		}
	}
}

void BreakFinder::Insert(int val) {
	// Expand if needed
	if (saeLen >= saeSize) {
		saeSize *= 2;
		int *selAndEdgeNew = new int[saeSize];
		for (unsigned int j = 0; j<saeLen; j++) {
			selAndEdgeNew[j] = selAndEdge[j];
		}
		delete []selAndEdge;
		selAndEdge = selAndEdgeNew;
	}

	if (val >= nextBreak) {
		for (unsigned int j = 0; j<saeLen; j++) {
			if (val == selAndEdge[j]) {
				return;
			}
			if (val < selAndEdge[j]) {
				for (unsigned int k = saeLen; k>j; k--) {
					selAndEdge[k] = selAndEdge[k-1];
				}
				saeLen++;
				selAndEdge[j] = val;
				return;
			}
		}
		// Not less than any so append
		selAndEdge[saeLen++] = val;
	}
}

extern bool BadUTF(const char *s, int len, int &trailBytes);

static int NextBadU(const char *s, int p, int len, int &trailBytes) {
	while (p < len) {
		p++;
		if (BadUTF(s + p, len - p, trailBytes))
			return p;
	}
	return -1;
}

BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_,
	int xStart, bool breakForSelection, Document *pdoc_) :
	ll(ll_),
	lineStart(lineStart_),
	lineEnd(lineEnd_),
	posLineStart(posLineStart_),
	nextBreak(lineStart_),
	saeSize(0),
	saeLen(0),
	saeCurrentPos(0),
	saeNext(0),
	subBreak(-1),
	pdoc(pdoc_) {
	saeSize = 8;
	selAndEdge = new int[saeSize];
	for (unsigned int j=0; j < saeSize; j++) {
		selAndEdge[j] = 0;
	}

	// Search for first visible break
	// First find the first visible character
	nextBreak = ll->FindBefore(xStart, lineStart, lineEnd);
	// Now back to a style break
	while ((nextBreak > lineStart) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) {
		nextBreak--;
	}

	if (breakForSelection) {
		SelectionPosition posStart(posLineStart);
		SelectionPosition posEnd(posLineStart + lineEnd);
		SelectionSegment segmentLine(posStart, posEnd);
		for (size_t r=0; r<ll->psel->Count(); r++) {
			SelectionSegment portion = ll->psel->Range(r).Intersect(segmentLine);
			if (!(portion.start == portion.end)) {
				if (portion.start.IsValid())
					Insert(portion.start.Position() - posLineStart - 1);
				if (portion.end.IsValid())
					Insert(portion.end.Position() - posLineStart - 1);
			}
		}
	}

	Insert(ll->edgeColumn - 1);
	Insert(lineEnd - 1);

	if (pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage)) {
		int trailBytes=0;
		for (int pos = -1;;) {
			pos = NextBadU(ll->chars, pos, lineEnd, trailBytes);
			if (pos < 0)
				break;
			Insert(pos-1);
			Insert(pos);
		}
	}
	saeNext = (saeLen > 0) ? selAndEdge[0] : -1;
}

BreakFinder::~BreakFinder() {
	delete []selAndEdge;
}

int BreakFinder::First() const {
	return nextBreak;
}

int BreakFinder::Next() {
	if (subBreak == -1) {
		int prev = nextBreak;
		while (nextBreak < lineEnd) {
			if ((ll->styles[nextBreak] != ll->styles[nextBreak + 1]) ||
					(nextBreak == saeNext) ||
					IsControlCharacter(ll->chars[nextBreak]) || IsControlCharacter(ll->chars[nextBreak + 1])) {
				if (nextBreak == saeNext) {
					saeCurrentPos++;
					saeNext = (saeLen > saeCurrentPos) ? selAndEdge[saeCurrentPos] : -1;
				}
				nextBreak++;
				if ((nextBreak - prev) < lengthStartSubdivision) {
					return nextBreak;
				}
				break;
			}
			nextBreak++;
		}
		if ((nextBreak - prev) < lengthStartSubdivision) {
			return nextBreak;
		}
		subBreak = prev;
	}
	// Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision.
	// For very long runs add extra breaks after spaces or if no spaces before low punctuation.
	if ((nextBreak - subBreak) <= lengthEachSubdivision) {
		subBreak = -1;
		return nextBreak;
	} else {
		subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision);
		if (subBreak >= nextBreak) {
			subBreak = -1;
			return nextBreak;
		} else {
			return subBreak;
		}
	}
}

PositionCacheEntry::PositionCacheEntry() :
	styleNumber(0), len(0), clock(0), positions(0) {
}

void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
	unsigned int len_, XYPOSITION *positions_, unsigned int clock_) {
	Clear();
	styleNumber = styleNumber_;
	len = len_;
	clock = clock_;
	if (s_ && positions_) {
		positions = new XYPOSITION[len + (len + 1) / 2];
		for (unsigned int i=0; i<len; i++) {
			positions[i] = static_cast<XYPOSITION>(positions_[i]);
		}
		memcpy(reinterpret_cast<char *>(positions + len), s_, len);
	}
}

PositionCacheEntry::~PositionCacheEntry() {
	Clear();
}

void PositionCacheEntry::Clear() {
	delete []positions;
	positions = 0;
	styleNumber = 0;
	len = 0;
	clock = 0;
}

bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_,
	unsigned int len_, XYPOSITION *positions_) const {
	if ((styleNumber == styleNumber_) && (len == len_) &&
		(memcmp(reinterpret_cast<char *>(positions + len), s_, len)== 0)) {
		for (unsigned int i=0; i<len; i++) {
			positions_[i] = positions[i];
		}
		return true;
	} else {
		return false;
	}
}

int PositionCacheEntry::Hash(unsigned int styleNumber_, const char *s, unsigned int len_) {
	unsigned int ret = s[0] << 7;
	for (unsigned int i=0; i<len_; i++) {
		ret *= 1000003;
		ret ^= s[i];
	}
	ret *= 1000003;
	ret ^= len_;
	ret *= 1000003;
	ret ^= styleNumber_;
	return ret;
}

bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) const {
	return clock > other.clock;
}

void PositionCacheEntry::ResetClock() {
	if (clock > 0) {
		clock = 1;
	}
}

PositionCache::PositionCache() {
	size = 0x400;
	clock = 1;
	pces = new PositionCacheEntry[size];
	allClear = true;
}

PositionCache::~PositionCache() {
	Clear();
	delete []pces;
}

void PositionCache::Clear() {
	if (!allClear) {
		for (size_t i=0; i<size; i++) {
			pces[i].Clear();
		}
	}
	clock = 1;
	allClear = true;
}

void PositionCache::SetSize(size_t size_) {
	Clear();
	delete []pces;
	size = size_;
	pces = new PositionCacheEntry[size];
}

void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
	const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc) {

	allClear = false;
	int probe = -1;
	if ((size > 0) && (len < 30)) {
		// Only store short strings in the cache so it doesn't churn with
		// long comments with only a single comment.

		// Two way associative: try two probe positions.
		int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
		probe = static_cast<int>(hashValue % size);
		if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
			return;
		}
		int probe2 = static_cast<int>((hashValue * 37) % size);
		if (pces[probe2].Retrieve(styleNumber, s, len, positions)) {
			return;
		}
		// Not found. Choose the oldest of the two slots to replace
		if (pces[probe].NewerThan(pces[probe2])) {
			probe = probe2;
		}
	}
	if (len > BreakFinder::lengthStartSubdivision) {
		// Break up into segments
		unsigned int startSegment = 0;
		XYPOSITION xStartSegment = 0;
		while (startSegment < len) {
			unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision);
			surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment);
			for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) {
				positions[startSegment + inSeg] += xStartSegment;
			}
			xStartSegment = positions[startSegment + lenSegment - 1];
			startSegment += lenSegment;
		}
	} else {
		surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions);
	}
	if (probe >= 0) {
		clock++;
		if (clock > 60000) {
			// Since there are only 16 bits for the clock, wrap it round and
			// reset all cache entries so none get stuck with a high clock.
			for (size_t i=0; i<size; i++) {
				pces[i].ResetClock();
			}
			clock = 2;
		}
		pces[probe].Set(styleNumber, s, len, positions, clock);
	}
}

Added src/PositionCache.h.



























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file PositionCache.h
 ** Classes for caching layout information.
 **/
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef POSITIONCACHE_H
#define POSITIONCACHE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

static inline bool IsEOLChar(char ch) {
	return (ch == '\r') || (ch == '\n');
}

/**
 */
class LineLayout {
private:
	friend class LineLayoutCache;
	int *lineStarts;
	int lenLineStarts;
	/// Drawing is only performed for @a maxLineLength characters on each line.
	int lineNumber;
	bool inCache;
public:
	enum { wrapWidthInfinite = 0x7ffffff };
	int maxLineLength;
	int numCharsInLine;
	int numCharsBeforeEOL;
	enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
	int xHighlightGuide;
	bool highlightColumn;
	Selection *psel;
	bool containsCaret;
	int edgeColumn;
	char *chars;
	unsigned char *styles;
	int styleBitsSet;
	char *indicators;
	XYPOSITION *positions;
	char bracePreviousStyles[2];

	// Hotspot support
	int hsStart;
	int hsEnd;

	// Wrapped line support
	int widthLine;
	int lines;
	XYPOSITION wrapIndent; // In pixels

	LineLayout(int maxLineLength_);
	virtual ~LineLayout();
	void Resize(int maxLineLength_);
	void Free();
	void Invalidate(validLevel validity_);
	int LineStart(int line) const;
	int LineLastVisible(int line) const;
	bool InLine(int offset, int line) const;
	void SetLineStart(int line, int start);
	void SetBracesHighlight(Range rangeLine, Position braces[],
		char bracesMatchStyle, int xHighlight, bool ignoreStyle);
	void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle);
	int FindBefore(XYPOSITION x, int lower, int upper) const;
	int EndLineStyle() const;
};

/**
 */
class LineLayoutCache {
	int level;
	int length;
	int size;
	LineLayout **cache;
	bool allInvalidated;
	int styleClock;
	int useCount;
	void Allocate(int length_);
	void AllocateForLevel(int linesOnScreen, int linesInDoc);
public:
	LineLayoutCache();
	virtual ~LineLayoutCache();
	void Deallocate();
	enum {
		llcNone=SC_CACHE_NONE,
		llcCaret=SC_CACHE_CARET,
		llcPage=SC_CACHE_PAGE,
		llcDocument=SC_CACHE_DOCUMENT
	};
	void Invalidate(LineLayout::validLevel validity_);
	void SetLevel(int level_);
	int GetLevel() const { return level; }
	LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
		int linesOnScreen, int linesInDoc);
	void Dispose(LineLayout *ll);
};

class PositionCacheEntry {
	unsigned int styleNumber:8;
	unsigned int len:8;
	unsigned int clock:16;
	XYPOSITION *positions;
public:
	PositionCacheEntry();
	~PositionCacheEntry();
	void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock);
	void Clear();
	bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const;
	static int Hash(unsigned int styleNumber_, const char *s, unsigned int len);
	bool NewerThan(const PositionCacheEntry &other) const;
	void ResetClock();
};

// Class to break a line of text into shorter runs at sensible places.
class BreakFinder {
	LineLayout *ll;
	int lineStart;
	int lineEnd;
	int posLineStart;
	int nextBreak;
	int *selAndEdge;
	unsigned int saeSize;
	unsigned int saeLen;
	unsigned int saeCurrentPos;
	int saeNext;
	int subBreak;
	Document *pdoc;
	void Insert(int val);
	// Private so BreakFinder objects can not be copied
	BreakFinder(const BreakFinder &);
public:
	// If a whole run is longer than lengthStartSubdivision then subdivide
	// into smaller runs at spaces or punctuation.
	enum { lengthStartSubdivision = 300 };
	// Try to make each subdivided run lengthEachSubdivision or shorter.
	enum { lengthEachSubdivision = 100 };
	BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_,
		int xStart, bool breakForSelection, Document *pdoc_);
	~BreakFinder();
	int First() const;
	int Next();
};

class PositionCache {
	PositionCacheEntry *pces;
	size_t size;
	unsigned int clock;
	bool allClear;
	// Private so PositionCache objects can not be copied
	PositionCache(const PositionCache &);
public:
	PositionCache();
	~PositionCache();
	void Clear();
	void SetSize(size_t size_);
	size_t GetSize() const { return size; }
	void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
		const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc);
};

inline bool IsSpaceOrTab(int ch) {
	return ch == ' ' || ch == '\t';
}

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/RESearch.cxx.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
// Scintilla source code edit control
/** @file RESearch.cxx
 ** Regular expression search library.
 **/

/*
 * regex - Regular expression pattern matching and replacement
 *
 * By:  Ozan S. Yigit (oz)
 *      Dept. of Computer Science
 *      York University
 *
 * Original code available from http://www.cs.yorku.ca/~oz/
 * Translation to C++ by Neil Hodgson neilh@scintilla.org
 * Removed all use of register.
 * Converted to modern function prototypes.
 * Put all global/static variables into an object so this code can be
 * used from multiple threads, etc.
 * Some extensions by Philippe Lhoste PhiLho(a)GMX.net
 * '?' extensions by Michael Mullin masmullin@gmail.com
 *
 * These routines are the PUBLIC DOMAIN equivalents of regex
 * routines as found in 4.nBSD UN*X, with minor extensions.
 *
 * These routines are derived from various implementations found
 * in software tools books, and Conroy's grep. They are NOT derived
 * from licensed/restricted software.
 * For more interesting/academic/complicated implementations,
 * see Henry Spencer's regexp routines, or GNU Emacs pattern
 * matching module.
 *
 * Modification history removed.
 *
 * Interfaces:
 *  RESearch::Compile:      compile a regular expression into a NFA.
 *
 *          const char *RESearch::Compile(const char *pattern, int length,
 *                                        bool caseSensitive, bool posix)
 *
 * Returns a short error string if they fail.
 *
 *  RESearch::Execute:      execute the NFA to match a pattern.
 *
 *          int RESearch::Execute(characterIndexer &ci, int lp, int endp)
 *
 *  RESearch::Substitute:   substitute the matched portions in a new string.
 *
 *          int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst)
 *
 *  re_fail:                failure routine for RESearch::Execute. (no longer used)
 *
 *          void re_fail(char *msg, char op)
 *
 * Regular Expressions:
 *
 *      [1]     char    matches itself, unless it is a special
 *                      character (metachar): . \ [ ] * + ? ^ $
 *                      and ( ) if posix option.
 *
 *      [2]     .       matches any character.
 *
 *      [3]     \       matches the character following it, except:
 *                      - \a, \b, \f, \n, \r, \t, \v match the corresponding C
 *                      escape char, respectively BEL, BS, FF, LF, CR, TAB and VT;
 *                      Note that \r and \n are never matched because Scintilla
 *                      regex searches are made line per line
 *                      (stripped of end-of-line chars).
 *                      - if not in posix mode, when followed by a
 *                      left or right round bracket (see [8]);
 *                      - when followed by a digit 1 to 9 (see [9]);
 *                      - when followed by a left or right angle bracket
 *                      (see [10]);
 *                      - when followed by d, D, s, S, w or W (see [11]);
 *                      - when followed by x and two hexa digits (see [12].
 *                      Backslash is used as an escape character for all
 *                      other meta-characters, and itself.
 *
 *      [4]     [set]   matches one of the characters in the set.
 *                      If the first character in the set is "^",
 *                      it matches the characters NOT in the set, i.e.
 *                      complements the set. A shorthand S-E (start dash end)
 *                      is used to specify a set of characters S up to
 *                      E, inclusive. S and E must be characters, otherwise
 *                      the dash is taken literally (eg. in expression [\d-a]).
 *                      The special characters "]" and "-" have no special
 *                      meaning if they appear as the first chars in the set.
 *                      To include both, put - first: [-]A-Z]
 *                      (or just backslash them).
 *                      examples:        match:
 *
 *                              [-]|]    matches these 3 chars,
 *
 *                              []-|]    matches from ] to | chars
 *
 *                              [a-z]    any lowercase alpha
 *
 *                              [^-]]    any char except - and ]
 *
 *                              [^A-Z]   any char except uppercase
 *                                       alpha
 *
 *                              [a-zA-Z] any alpha
 *
 *      [5]     *       any regular expression form [1] to [4]
 *                      (except [8], [9] and [10] forms of [3]),
 *                      followed by closure char (*)
 *                      matches zero or more matches of that form.
 *
 *      [6]     +       same as [5], except it matches one or more.
 *
 *      [5-6]           Both [5] and [6] are greedy (they match as much as possible).
 *                      Unless they are followed by the 'lazy' quantifier (?)
 *                      In which case both [5] and [6] try to match as little as possible
 *
 *      [7]     ?       same as [5] except it matches zero or one.
 *
 *      [8]             a regular expression in the form [1] to [13], enclosed
 *                      as \(form\) (or (form) with posix flag) matches what
 *                      form matches. The enclosure creates a set of tags,
 *                      used for [9] and for pattern substitution.
 *                      The tagged forms are numbered starting from 1.
 *
 *      [9]             a \ followed by a digit 1 to 9 matches whatever a
 *                      previously tagged regular expression ([8]) matched.
 *
 *      [10]    \<      a regular expression starting with a \< construct
 *              \>      and/or ending with a \> construct, restricts the
 *                      pattern matching to the beginning of a word, and/or
 *                      the end of a word. A word is defined to be a character
 *                      string beginning and/or ending with the characters
 *                      A-Z a-z 0-9 and _. Scintilla extends this definition
 *                      by user setting. The word must also be preceded and/or
 *                      followed by any character outside those mentioned.
 *
 *      [11]    \l      a backslash followed by d, D, s, S, w or W,
 *                      becomes a character class (both inside and
 *                      outside sets []).
 *                        d: decimal digits
 *                        D: any char except decimal digits
 *                        s: whitespace (space, \t \n \r \f \v)
 *                        S: any char except whitespace (see above)
 *                        w: alphanumeric & underscore (changed by user setting)
 *                        W: any char except alphanumeric & underscore (see above)
 *
 *      [12]    \xHH    a backslash followed by x and two hexa digits,
 *                      becomes the character whose Ascii code is equal
 *                      to these digits. If not followed by two digits,
 *                      it is 'x' char itself.
 *
 *      [13]            a composite regular expression xy where x and y
 *                      are in the form [1] to [12] matches the longest
 *                      match of x followed by a match for y.
 *
 *      [14]    ^       a regular expression starting with a ^ character
 *              $       and/or ending with a $ character, restricts the
 *                      pattern matching to the beginning of the line,
 *                      or the end of line. [anchors] Elsewhere in the
 *                      pattern, ^ and $ are treated as ordinary characters.
 *
 *
 * Acknowledgements:
 *
 *  HCR's Hugh Redelmeier has been most helpful in various
 *  stages of development. He convinced me to include BOW
 *  and EOW constructs, originally invented by Rob Pike at
 *  the University of Toronto.
 *
 * References:
 *              Software tools                  Kernighan & Plauger
 *              Software tools in Pascal        Kernighan & Plauger
 *              Grep [rsx-11 C dist]            David Conroy
 *              ed - text editor                Un*x Programmer's Manual
 *              Advanced editing on Un*x        B. W. Kernighan
 *              RegExp routines                 Henry Spencer
 *
 * Notes:
 *
 *  This implementation uses a bit-set representation for character
 *  classes for speed and compactness. Each character is represented
 *  by one bit in a 256-bit block. Thus, CCL always takes a
 *	constant 32 bytes in the internal nfa, and RESearch::Execute does a single
 *  bit comparison to locate the character in the set.
 *
 * Examples:
 *
 *  pattern:    foo*.*
 *  compile:    CHR f CHR o CLO CHR o END CLO ANY END END
 *  matches:    fo foo fooo foobar fobar foxx ...
 *
 *  pattern:    fo[ob]a[rz]
 *  compile:    CHR f CHR o CCL bitset CHR a CCL bitset END
 *  matches:    fobar fooar fobaz fooaz
 *
 *  pattern:    foo\\+
 *  compile:    CHR f CHR o CHR o CHR \ CLO CHR \ END END
 *  matches:    foo\ foo\\ foo\\\  ...
 *
 *  pattern:    \(foo\)[1-3]\1  (same as foo[1-3]foo)
 *  compile:    BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
 *  matches:    foo1foo foo2foo foo3foo
 *
 *  pattern:    \(fo.*\)-\1
 *  compile:    BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
 *  matches:    foo-foo fo-fo fob-fob foobar-foobar ...
 */

#include <stdlib.h>

#include "CharClassify.h"
#include "RESearch.h"

// Shut up annoying Visual C++ warnings:
#ifdef _MSC_VER
#pragma warning(disable: 4514)
#endif

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

#define OKP     1
#define NOP     0

#define CHR     1
#define ANY     2
#define CCL     3
#define BOL     4
#define EOL     5
#define BOT     6
#define EOT     7
#define BOW     8
#define EOW     9
#define REF     10
#define CLO     11
#define CLQ     12 /* 0 to 1 closure */
#define LCLO    13 /* lazy closure */

#define END     0

/*
 * The following defines are not meant to be changeable.
 * They are for readability only.
 */
#define BLKIND  0370
#define BITIND  07

const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, '\200' };

#define badpat(x)	(*nfa = END, x)

/*
 * Character classification table for word boundary operators BOW
 * and EOW is passed in by the creator of this object (Scintilla
 * Document). The Document default state is that word chars are:
 * 0-9, a-z, A-Z and _
 */

RESearch::RESearch(CharClassify *charClassTable) {
	failure = 0;
	charClass = charClassTable;
	Init();
}

RESearch::~RESearch() {
	Clear();
}

void RESearch::Init() {
	sta = NOP;                  /* status of lastpat */
	bol = 0;
	for (int i = 0; i < MAXTAG; i++)
		pat[i] = 0;
	for (int j = 0; j < BITBLK; j++)
		bittab[j] = 0;
}

void RESearch::Clear() {
	for (int i = 0; i < MAXTAG; i++) {
		delete []pat[i];
		pat[i] = 0;
		bopat[i] = NOTFOUND;
		eopat[i] = NOTFOUND;
	}
}

bool RESearch::GrabMatches(CharacterIndexer &ci) {
	bool success = true;
	for (unsigned int i = 0; i < MAXTAG; i++) {
		if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
			unsigned int len = eopat[i] - bopat[i];
			pat[i] = new char[len + 1];
			if (pat[i]) {
				for (unsigned int j = 0; j < len; j++)
					pat[i][j] = ci.CharAt(bopat[i] + j);
				pat[i][len] = '\0';
			} else {
				success = false;
			}
		}
	}
	return success;
}

void RESearch::ChSet(unsigned char c) {
	bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
}

void RESearch::ChSetWithCase(unsigned char c, bool caseSensitive) {
	if (caseSensitive) {
		ChSet(c);
	} else {
		if ((c >= 'a') && (c <= 'z')) {
			ChSet(c);
			ChSet(static_cast<unsigned char>(c - 'a' + 'A'));
		} else if ((c >= 'A') && (c <= 'Z')) {
			ChSet(c);
			ChSet(static_cast<unsigned char>(c - 'A' + 'a'));
		} else {
			ChSet(c);
		}
	}
}

unsigned char escapeValue(unsigned char ch) {
	switch (ch) {
	case 'a':	return '\a';
	case 'b':	return '\b';
	case 'f':	return '\f';
	case 'n':	return '\n';
	case 'r':	return '\r';
	case 't':	return '\t';
	case 'v':	return '\v';
	}
	return 0;
}

static int GetHexaChar(unsigned char hd1, unsigned char hd2) {
	int hexValue = 0;
	if (hd1 >= '0' && hd1 <= '9') {
		hexValue += 16 * (hd1 - '0');
	} else if (hd1 >= 'A' && hd1 <= 'F') {
		hexValue += 16 * (hd1 - 'A' + 10);
	} else if (hd1 >= 'a' && hd1 <= 'f') {
		hexValue += 16 * (hd1 - 'a' + 10);
	} else
		return -1;
	if (hd2 >= '0' && hd2 <= '9') {
		hexValue += hd2 - '0';
	} else if (hd2 >= 'A' && hd2 <= 'F') {
		hexValue += hd2 - 'A' + 10;
	} else if (hd2 >= 'a' && hd2 <= 'f') {
		hexValue += hd2 - 'a' + 10;
	} else
		return -1;
	return hexValue;
}

/**
 * Called when the parser finds a backslash not followed
 * by a valid expression (like \( in non-Posix mode).
 * @param pattern: pointer on the char after the backslash.
 * @param incr: (out) number of chars to skip after expression evaluation.
 * @return the char if it resolves to a simple char,
 * or -1 for a char class. In this case, bittab is changed.
 */
int RESearch::GetBackslashExpression(
    const char *pattern,
    int &incr) {
	// Since error reporting is primitive and messages are not used anyway,
	// I choose to interpret unexpected syntax in a logical way instead
	// of reporting errors. Otherwise, we can stick on, eg., PCRE behavior.
	incr = 0;	// Most of the time, will skip the char "naturally".
	int c;
	int result = -1;
	unsigned char bsc = *pattern;
	if (!bsc) {
		// Avoid overrun
		result = '\\';	// \ at end of pattern, take it literally
		return result;
	}

	switch (bsc) {
	case 'a':
	case 'b':
	case 'n':
	case 'f':
	case 'r':
	case 't':
	case 'v':
		result = escapeValue(bsc);
		break;
	case 'x': {
			unsigned char hd1 = *(pattern + 1);
			unsigned char hd2 = *(pattern + 2);
			int hexValue = GetHexaChar(hd1, hd2);
			if (hexValue >= 0) {
				result = hexValue;
				incr = 2;	// Must skip the digits
			} else {
				result = 'x';	// \x without 2 digits: see it as 'x'
			}
		}
		break;
	case 'd':
		for (c = '0'; c <= '9'; c++) {
			ChSet(static_cast<unsigned char>(c));
		}
		break;
	case 'D':
		for (c = 0; c < MAXCHR; c++) {
			if (c < '0' || c > '9') {
				ChSet(static_cast<unsigned char>(c));
			}
		}
		break;
	case 's':
		ChSet(' ');
		ChSet('\t');
		ChSet('\n');
		ChSet('\r');
		ChSet('\f');
		ChSet('\v');
		break;
	case 'S':
		for (c = 0; c < MAXCHR; c++) {
			if (c != ' ' && !(c >= 0x09 && c <= 0x0D)) {
				ChSet(static_cast<unsigned char>(c));
			}
		}
		break;
	case 'w':
		for (c = 0; c < MAXCHR; c++) {
			if (iswordc(static_cast<unsigned char>(c))) {
				ChSet(static_cast<unsigned char>(c));
			}
		}
		break;
	case 'W':
		for (c = 0; c < MAXCHR; c++) {
			if (!iswordc(static_cast<unsigned char>(c))) {
				ChSet(static_cast<unsigned char>(c));
			}
		}
		break;
	default:
		result = bsc;
	}
	return result;
}

const char *RESearch::Compile(const char *pattern, int length, bool caseSensitive, bool posix) {
	char *mp=nfa;          /* nfa pointer       */
	char *lp;              /* saved pointer     */
	char *sp=nfa;          /* another one       */
	char *mpMax = mp + MAXNFA - BITBLK - 10;

	int tagi = 0;          /* tag stack index   */
	int tagc = 1;          /* actual tag count  */

	int n;
	char mask;             /* xor mask -CCL/NCL */
	int c1, c2, prevChar;

	if (!pattern || !length) {
		if (sta)
			return 0;
		else
			return badpat("No previous regular expression");
	}
	sta = NOP;

	const char *p=pattern;     /* pattern pointer   */
	for (int i=0; i<length; i++, p++) {
		if (mp > mpMax)
			return badpat("Pattern too long");
		lp = mp;
		switch (*p) {

		case '.':               /* match any char  */
			*mp++ = ANY;
			break;

		case '^':               /* match beginning */
			if (p == pattern)
				*mp++ = BOL;
			else {
				*mp++ = CHR;
				*mp++ = *p;
			}
			break;

		case '$':               /* match endofline */
			if (!*(p+1))
				*mp++ = EOL;
			else {
				*mp++ = CHR;
				*mp++ = *p;
			}
			break;

		case '[':               /* match char class */
			*mp++ = CCL;
			prevChar = 0;

			i++;
			if (*++p == '^') {
				mask = '\377';
				i++;
				p++;
			} else
				mask = 0;

			if (*p == '-') {	/* real dash */
				i++;
				prevChar = *p;
				ChSet(*p++);
			}
			if (*p == ']') {	/* real brace */
				i++;
				prevChar = *p;
				ChSet(*p++);
			}
			while (*p && *p != ']') {
				if (*p == '-') {
					if (prevChar < 0) {
						// Previous def. was a char class like \d, take dash literally
						prevChar = *p;
						ChSet(*p);
					} else if (*(p+1)) {
						if (*(p+1) != ']') {
							c1 = prevChar + 1;
							i++;
							c2 = static_cast<unsigned char>(*++p);
							if (c2 == '\\') {
								if (!*(p+1))	// End of RE
									return badpat("Missing ]");
								else {
									i++;
									p++;
									int incr;
									c2 = GetBackslashExpression(p, incr);
									i += incr;
									p += incr;
									if (c2 >= 0) {
										// Convention: \c (c is any char) is case sensitive, whatever the option
										ChSet(static_cast<unsigned char>(c2));
										prevChar = c2;
									} else {
										// bittab is already changed
										prevChar = -1;
									}
								}
							}
							if (prevChar < 0) {
								// Char after dash is char class like \d, take dash literally
								prevChar = '-';
								ChSet('-');
							} else {
								// Put all chars between c1 and c2 included in the char set
								while (c1 <= c2) {
									ChSetWithCase(static_cast<unsigned char>(c1++), caseSensitive);
								}
							}
						} else {
							// Dash before the ], take it literally
							prevChar = *p;
							ChSet(*p);
						}
					} else {
						return badpat("Missing ]");
					}
				} else if (*p == '\\' && *(p+1)) {
					i++;
					p++;
					int incr;
					int c = GetBackslashExpression(p, incr);
					i += incr;
					p += incr;
					if (c >= 0) {
						// Convention: \c (c is any char) is case sensitive, whatever the option
						ChSet(static_cast<unsigned char>(c));
						prevChar = c;
					} else {
						// bittab is already changed
						prevChar = -1;
					}
				} else {
					prevChar = static_cast<unsigned char>(*p);
					ChSetWithCase(*p, caseSensitive);
				}
				i++;
				p++;
			}
			if (!*p)
				return badpat("Missing ]");

			for (n = 0; n < BITBLK; bittab[n++] = 0)
				*mp++ = static_cast<char>(mask ^ bittab[n]);

			break;

		case '*':               /* match 0 or more... */
		case '+':               /* match 1 or more... */
		case '?':
			if (p == pattern)
				return badpat("Empty closure");
			lp = sp;		/* previous opcode */
			if (*lp == CLO || *lp == LCLO)		/* equivalence... */
				break;
			switch (*lp) {

			case BOL:
			case BOT:
			case EOT:
			case BOW:
			case EOW:
			case REF:
				return badpat("Illegal closure");
			default:
				break;
			}

			if (*p == '+')
				for (sp = mp; lp < sp; lp++)
					*mp++ = *lp;

			*mp++ = END;
			*mp++ = END;
			sp = mp;

			while (--mp > lp)
				*mp = mp[-1];
			if (*p == '?')          *mp = CLQ;
			else if (*(p+1) == '?') *mp = LCLO;
			else                    *mp = CLO;

			mp = sp;
			break;

		case '\\':              /* tags, backrefs... */
			i++;
			switch (*++p) {
			case '<':
				*mp++ = BOW;
				break;
			case '>':
				if (*sp == BOW)
					return badpat("Null pattern inside \\<\\>");
				*mp++ = EOW;
				break;
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				n = *p-'0';
				if (tagi > 0 && tagstk[tagi] == n)
					return badpat("Cyclical reference");
				if (tagc > n) {
					*mp++ = static_cast<char>(REF);
					*mp++ = static_cast<char>(n);
				} else
					return badpat("Undetermined reference");
				break;
			default:
				if (!posix && *p == '(') {
					if (tagc < MAXTAG) {
						tagstk[++tagi] = tagc;
						*mp++ = BOT;
						*mp++ = static_cast<char>(tagc++);
					} else
						return badpat("Too many \\(\\) pairs");
				} else if (!posix && *p == ')') {
					if (*sp == BOT)
						return badpat("Null pattern inside \\(\\)");
					if (tagi > 0) {
						*mp++ = static_cast<char>(EOT);
						*mp++ = static_cast<char>(tagstk[tagi--]);
					} else
						return badpat("Unmatched \\)");
				} else {
					int incr;
					int c = GetBackslashExpression(p, incr);
					i += incr;
					p += incr;
					if (c >= 0) {
						*mp++ = CHR;
						*mp++ = static_cast<unsigned char>(c);
					} else {
						*mp++ = CCL;
						mask = 0;
						for (n = 0; n < BITBLK; bittab[n++] = 0)
							*mp++ = static_cast<char>(mask ^ bittab[n]);
					}
				}
			}
			break;

		default :               /* an ordinary char */
			if (posix && *p == '(') {
				if (tagc < MAXTAG) {
					tagstk[++tagi] = tagc;
					*mp++ = BOT;
					*mp++ = static_cast<char>(tagc++);
				} else
					return badpat("Too many () pairs");
			} else if (posix && *p == ')') {
				if (*sp == BOT)
					return badpat("Null pattern inside ()");
				if (tagi > 0) {
					*mp++ = static_cast<char>(EOT);
					*mp++ = static_cast<char>(tagstk[tagi--]);
				} else
					return badpat("Unmatched )");
			} else {
				unsigned char c = *p;
				if (!c)	// End of RE
					c = '\\';	// We take it as raw backslash
				if (caseSensitive || !iswordc(c)) {
					*mp++ = CHR;
					*mp++ = c;
				} else {
					*mp++ = CCL;
					mask = 0;
					ChSetWithCase(c, false);
					for (n = 0; n < BITBLK; bittab[n++] = 0)
						*mp++ = static_cast<char>(mask ^ bittab[n]);
				}
			}
			break;
		}
		sp = lp;
	}
	if (tagi > 0)
		return badpat((posix ? "Unmatched (" : "Unmatched \\("));
	*mp = END;
	sta = OKP;
	return 0;
}

/*
 * RESearch::Execute:
 *   execute nfa to find a match.
 *
 *  special cases: (nfa[0])
 *      BOL
 *          Match only once, starting from the
 *          beginning.
 *      CHR
 *          First locate the character without
 *          calling PMatch, and if found, call
 *          PMatch for the remaining string.
 *      END
 *          RESearch::Compile failed, poor luser did not
 *          check for it. Fail fast.
 *
 *  If a match is found, bopat[0] and eopat[0] are set
 *  to the beginning and the end of the matched fragment,
 *  respectively.
 *
 */
int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) {
	unsigned char c;
	int ep = NOTFOUND;
	char *ap = nfa;

	bol = lp;
	failure = 0;

	Clear();

	switch (*ap) {

	case BOL:			/* anchored: match from BOL only */
		ep = PMatch(ci, lp, endp, ap);
		break;
	case EOL:			/* just searching for end of line normal path doesn't work */
		if (*(ap+1) == END) {
			lp = endp;
			ep = lp;
			break;
		} else {
			return 0;
		}
	case CHR:			/* ordinary char: locate it fast */
		c = *(ap+1);
		while ((lp < endp) && (static_cast<unsigned char>(ci.CharAt(lp)) != c))
			lp++;
		if (lp >= endp)	/* if EOS, fail, else fall thru. */
			return 0;
	default:			/* regular matching all the way. */
		while (lp < endp) {
			ep = PMatch(ci, lp, endp, ap);
			if (ep != NOTFOUND)
				break;
			lp++;
		}
		break;
	case END:			/* munged automaton. fail always */
		return 0;
	}
	if (ep == NOTFOUND)
		return 0;

	bopat[0] = lp;
	eopat[0] = ep;
	return 1;
}

/*
 * PMatch: internal routine for the hard part
 *
 *  This code is partly snarfed from an early grep written by
 *  David Conroy. The backref and tag stuff, and various other
 *  innovations are by oz.
 *
 *  special case optimizations: (nfa[n], nfa[n+1])
 *      CLO ANY
 *          We KNOW .* will match everything upto the
 *          end of line. Thus, directly go to the end of
 *          line, without recursive PMatch calls. As in
 *          the other closure cases, the remaining pattern
 *          must be matched by moving backwards on the
 *          string recursively, to find a match for xy
 *          (x is ".*" and y is the remaining pattern)
 *          where the match satisfies the LONGEST match for
 *          x followed by a match for y.
 *      CLO CHR
 *          We can again scan the string forward for the
 *          single char and at the point of failure, we
 *          execute the remaining nfa recursively, same as
 *          above.
 *
 *  At the end of a successful match, bopat[n] and eopat[n]
 *  are set to the beginning and end of subpatterns matched
 *  by tagged expressions (n = 1 to 9).
 */

extern void re_fail(char *,char);

#define isinset(x,y)	((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])

/*
 * skip values for CLO XXX to skip past the closure
 */

#define ANYSKIP 2 	/* [CLO] ANY END          */
#define CHRSKIP 3	/* [CLO] CHR chr END      */
#define CCLSKIP 34	/* [CLO] CCL 32 bytes END */

int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) {
	int op, c, n;
	int e;		/* extra pointer for CLO  */
	int bp;		/* beginning of subpat... */
	int ep;		/* ending of subpat...    */
	int are;	/* to save the line ptr.  */
	int llp;	/* lazy lp for LCLO       */

	while ((op = *ap++) != END)
		switch (op) {

		case CHR:
			if (ci.CharAt(lp++) != *ap++)
				return NOTFOUND;
			break;
		case ANY:
			if (lp++ >= endp)
				return NOTFOUND;
			break;
		case CCL:
			if (lp >= endp)
				return NOTFOUND;
			c = ci.CharAt(lp++);
			if (!isinset(ap,c))
				return NOTFOUND;
			ap += BITBLK;
			break;
		case BOL:
			if (lp != bol)
				return NOTFOUND;
			break;
		case EOL:
			if (lp < endp)
				return NOTFOUND;
			break;
		case BOT:
			bopat[static_cast<int>(*ap++)] = lp;
			break;
		case EOT:
			eopat[static_cast<int>(*ap++)] = lp;
			break;
		case BOW:
			if ((lp!=bol && iswordc(ci.CharAt(lp-1))) || !iswordc(ci.CharAt(lp)))
				return NOTFOUND;
			break;
		case EOW:
			if (lp==bol || !iswordc(ci.CharAt(lp-1)) || iswordc(ci.CharAt(lp)))
				return NOTFOUND;
			break;
		case REF:
			n = *ap++;
			bp = bopat[n];
			ep = eopat[n];
			while (bp < ep)
				if (ci.CharAt(bp++) != ci.CharAt(lp++))
					return NOTFOUND;
			break;
		case LCLO:
		case CLQ:
		case CLO:
			are = lp;
			switch (*ap) {

			case ANY:
				if (op == CLO || op == LCLO)
					while (lp < endp)
						lp++;
				else if (lp < endp)
					lp++;

				n = ANYSKIP;
				break;
			case CHR:
				c = *(ap+1);
				if (op == CLO || op == LCLO)
					while ((lp < endp) && (c == ci.CharAt(lp)))
						lp++;
				else if ((lp < endp) && (c == ci.CharAt(lp)))
					lp++;
				n = CHRSKIP;
				break;
			case CCL:
				while ((lp < endp) && isinset(ap+1,ci.CharAt(lp)))
					lp++;
				n = CCLSKIP;
				break;
			default:
				failure = true;
				//re_fail("closure: bad nfa.", *ap);
				return NOTFOUND;
			}
			ap += n;

			llp = lp;
			e = NOTFOUND;
			while (llp >= are) {
				int q;
				if ((q = PMatch(ci, llp, endp, ap)) != NOTFOUND) {
					e = q;
					lp = llp;
					if (op != LCLO) return e;
				}
				if (*ap == END) return e;
				--llp;
			}
			if (*ap == EOT)
				PMatch(ci, lp, endp, ap);
			return e;
		default:
			//re_fail("RESearch::Execute: bad nfa.", static_cast<char>(op));
			return NOTFOUND;
		}
	return lp;
}

/*
 * RESearch::Substitute:
 *  substitute the matched portions of the src in dst.
 *
 *  &    substitute the entire matched pattern.
 *
 *  \digit  substitute a subpattern, with the given tag number.
 *      Tags are numbered from 1 to 9. If the particular
 *      tagged subpattern does not exist, null is substituted.
 */
int RESearch::Substitute(CharacterIndexer &ci, char *src, char *dst) {
	unsigned char c;
	int  pin;
	int bp;
	int ep;

	if (!*src || !bopat[0])
		return 0;

	while ((c = *src++) != 0) {
		switch (c) {

		case '&':
			pin = 0;
			break;

		case '\\':
			c = *src++;
			if (c >= '0' && c <= '9') {
				pin = c - '0';
				break;
			}

		default:
			*dst++ = c;
			continue;
		}

		if ((bp = bopat[pin]) != 0 && (ep = eopat[pin]) != 0) {
			while (ci.CharAt(bp) && bp < ep)
				*dst++ = ci.CharAt(bp++);
			if (bp < ep)
				return 0;
		}
	}
	*dst = '\0';
	return 1;
}

Added src/RESearch.h.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file RESearch.h
 ** Interface to the regular expression search library.
 **/
// Written by Neil Hodgson <neilh@scintilla.org>
// Based on the work of Ozan S. Yigit.
// This file is in the public domain.

#ifndef RESEARCH_H
#define RESEARCH_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/*
 * The following defines are not meant to be changeable.
 * They are for readability only.
 */
#define MAXCHR	256
#define CHRBIT	8
#define BITBLK	MAXCHR/CHRBIT

class CharacterIndexer {
public:
	virtual char CharAt(int index)=0;
	virtual ~CharacterIndexer() {
	}
};

class RESearch {

public:
	RESearch(CharClassify *charClassTable);
	~RESearch();
	bool GrabMatches(CharacterIndexer &ci);
	const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
	int Execute(CharacterIndexer &ci, int lp, int endp);
	int Substitute(CharacterIndexer &ci, char *src, char *dst);

	enum { MAXTAG=10 };
	enum { MAXNFA=2048 };
	enum { NOTFOUND=-1 };

	int bopat[MAXTAG];
	int eopat[MAXTAG];
	char *pat[MAXTAG];

private:
	void Init();
	void Clear();
	void ChSet(unsigned char c);
	void ChSetWithCase(unsigned char c, bool caseSensitive);
	int GetBackslashExpression(const char *pattern, int &incr);

	int PMatch(CharacterIndexer &ci, int lp, int endp, char *ap);

	int bol;
	int tagstk[MAXTAG];  /* subpat tag stack */
	char nfa[MAXNFA];    /* automaton */
	int sta;
	unsigned char bittab[BITBLK]; /* bit table for CCL pre-set bits */
	int failure;
	CharClassify *charClass;
	bool iswordc(unsigned char x) {
		return charClass->IsWord(x);
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/RunStyles.cxx.























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
/** @file RunStyles.cxx
 ** Data structure used to store sparse styles.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "Platform.h"

#include "Scintilla.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Find the first run at a position
int RunStyles::RunFromPosition(int position) const {
	int run = starts->PartitionFromPosition(position);
	// Go to first element with this position
	while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
		run--;
	}
	return run;
}

// If there is no run boundary at position, insert one continuing style.
int RunStyles::SplitRun(int position) {
	int run = RunFromPosition(position);
	int posRun = starts->PositionFromPartition(run);
	if (posRun < position) {
		int runStyle = ValueAt(position);
		run++;
		starts->InsertPartition(run, position);
		styles->InsertValue(run, 1, runStyle);
	}
	return run;
}

void RunStyles::RemoveRun(int run) {
	starts->RemovePartition(run);
	styles->DeleteRange(run, 1);
}

void RunStyles::RemoveRunIfEmpty(int run) {
	if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
		if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
			RemoveRun(run);
		}
	}
}

void RunStyles::RemoveRunIfSameAsPrevious(int run) {
	if ((run > 0) && (run < starts->Partitions())) {
		if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
			RemoveRun(run);
		}
	}
}

RunStyles::RunStyles() {
	starts = new Partitioning(8);
	styles = new SplitVector<int>();
	styles->InsertValue(0, 2, 0);
}

RunStyles::~RunStyles() {
	delete starts;
	starts = NULL;
	delete styles;
	styles = NULL;
}

int RunStyles::Length() const {
	return starts->PositionFromPartition(starts->Partitions());
}

int RunStyles::ValueAt(int position) const {
	return styles->ValueAt(starts->PartitionFromPosition(position));
}

int RunStyles::FindNextChange(int position, int end) {
	int run = starts->PartitionFromPosition(position);
	if (run < starts->Partitions()) {
		int runChange = starts->PositionFromPartition(run);
		if (runChange > position)
			return runChange;
		int nextChange = starts->PositionFromPartition(run + 1);
		if (nextChange > position) {
			return nextChange;
		} else if (position < end) {
			return end;
		} else {
			return end + 1;
		}
	} else {
		return end + 1;
	}
}

int RunStyles::StartRun(int position) {
	return starts->PositionFromPartition(starts->PartitionFromPosition(position));
}

int RunStyles::EndRun(int position) {
	return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
}

bool RunStyles::FillRange(int &position, int value, int &fillLength) {
	int end = position + fillLength;
	int runEnd = RunFromPosition(end);
	if (styles->ValueAt(runEnd) == value) {
		// End already has value so trim range.
		end = starts->PositionFromPartition(runEnd);
		if (position >= end) {
			// Whole range is already same as value so no action
			return false;
		}
		fillLength = end - position;
	} else {
		runEnd = SplitRun(end);
	}
	int runStart = RunFromPosition(position);
	if (styles->ValueAt(runStart) == value) {
		// Start is in expected value so trim range.
		runStart++;
		position = starts->PositionFromPartition(runStart);
		fillLength = end - position;
	} else {
		if (starts->PositionFromPartition(runStart) < position) {
			runStart = SplitRun(position);
			runEnd++;
		}
	}
	if (runStart < runEnd) {
		styles->SetValueAt(runStart, value);
		// Remove each old run over the range
		for (int run=runStart+1; run<runEnd; run++) {
			RemoveRun(runStart+1);
		}
		runEnd = RunFromPosition(end);
		RemoveRunIfSameAsPrevious(runEnd);
		RemoveRunIfSameAsPrevious(runStart);
		runEnd = RunFromPosition(end);
		RemoveRunIfEmpty(runEnd);
		return true;
	} else {
		return false;
	}
}

void RunStyles::SetValueAt(int position, int value) {
	int len = 1;
	FillRange(position, value, len);
}

void RunStyles::InsertSpace(int position, int insertLength) {
	int runStart = RunFromPosition(position);
	if (starts->PositionFromPartition(runStart) == position) {
		int runStyle = ValueAt(position);
		// Inserting at start of run so make previous longer
		if (runStart == 0) {
			// Inserting at start of document so ensure 0
			if (runStyle) {
				styles->SetValueAt(0, 0);
				starts->InsertPartition(1, 0);
				styles->InsertValue(1, 1, runStyle);
				starts->InsertText(0, insertLength);
			} else {
				starts->InsertText(runStart, insertLength);
			}
		} else {
			if (runStyle) {
				starts->InsertText(runStart-1, insertLength);
			} else {
				// Insert at end of run so do not extend style
				starts->InsertText(runStart, insertLength);
			}
		}
	} else {
		starts->InsertText(runStart, insertLength);
	}
}

void RunStyles::DeleteAll() {
	delete starts;
	starts = NULL;
	delete styles;
	styles = NULL;
	starts = new Partitioning(8);
	styles = new SplitVector<int>();
	styles->InsertValue(0, 2, 0);
}

void RunStyles::DeleteRange(int position, int deleteLength) {
	int end = position + deleteLength;
	int runStart = RunFromPosition(position);
	int runEnd = RunFromPosition(end);
	if (runStart == runEnd) {
		// Deleting from inside one run
		starts->InsertText(runStart, -deleteLength);
		RemoveRunIfEmpty(runStart);
	} else {
		runStart = SplitRun(position);
		runEnd = SplitRun(end);
		starts->InsertText(runStart, -deleteLength);
		// Remove each old run over the range
		for (int run=runStart; run<runEnd; run++) {
			RemoveRun(runStart);
		}
		RemoveRunIfEmpty(runStart);
		RemoveRunIfSameAsPrevious(runStart);
	}
}

int RunStyles::Runs() const {
	return starts->Partitions();
}

bool RunStyles::AllSame() const {
	for (int run = 1; run < starts->Partitions(); run++) {
		if (styles->ValueAt(run) != styles->ValueAt(run - 1))
			return false;
	}
	return true;
}

bool RunStyles::AllSameAs(int value) const {
	return AllSame() && (styles->ValueAt(0) == value);
}

int RunStyles::Find(int value, int start) const {
	if (start < Length()) {
		int run = start ? RunFromPosition(start) : 0;
		if (styles->ValueAt(run) == value)
			return start;
		run++;
		while (run < starts->Partitions()) {
			if (styles->ValueAt(run) == value)
				return starts->PositionFromPartition(run);
			run++;
		}
	}
	return -1;
}

Added src/RunStyles.h.









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/** @file RunStyles.h
 ** Data structure used to store sparse styles.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

/// Styling buffer using one element for each run rather than using
/// a filled buffer.

#ifndef RUNSTYLES_H
#define RUNSTYLES_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class RunStyles {
private:
	Partitioning *starts;
	SplitVector<int> *styles;
	int RunFromPosition(int position) const;
	int SplitRun(int position);
	void RemoveRun(int run);
	void RemoveRunIfEmpty(int run);
	void RemoveRunIfSameAsPrevious(int run);
	// Private so RunStyles objects can not be copied
	RunStyles(const RunStyles &);
public:
	RunStyles();
	~RunStyles();
	int Length() const;
	int ValueAt(int position) const;
	int FindNextChange(int position, int end);
	int StartRun(int position);
	int EndRun(int position);
	// Returns true if some values may have changed
	bool FillRange(int &position, int value, int &fillLength);
	void SetValueAt(int position, int value);
	void InsertSpace(int position, int insertLength);
	void DeleteAll();
	void DeleteRange(int position, int deleteLength);
	int Runs() const;
	bool AllSame() const;
	bool AllSameAs(int value) const;
	int Find(int value, int start) const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/SVector.h.























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file SVector.h
 ** A simple expandable vector.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@hare.net.au>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SVECTOR_H
#define SVECTOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 * A simple expandable integer vector.
 * Storage not allocated for elements until an element is used.
 * This makes it very lightweight unless used so is a good match for optional features.
 */
class SVector {
	enum { allocSize = 4000 };

	int *v;				///< The vector
	unsigned int size;	///< Number of elements allocated
	unsigned int len;	///< Number of elements used in vector

	/** Internally allocate more elements than the user wants
	 * to avoid thrashing the memory allocator. */
	void SizeTo(int newSize) {
		if (newSize < allocSize)
			newSize += allocSize;
		else
			newSize = (newSize * 3) / 2;
		int *newv = new int[newSize];
		size = newSize;
        unsigned int i=0;
		for (; i<len; i++) {
			newv[i] = v[i];
		}
		for (; i<size; i++) {
			newv[i] = 0;
		}
		delete []v;
		v = newv;
	}

public:
	SVector() {
		v = 0;
		len = 0;
		size = 0;
	}
	~SVector() {
		Free();
	}
	/// Constructor from another vector.
	SVector(const SVector &other) {
		v = 0;
		len = 0;
		size = 0;
		if (other.Length() > 0) {
			SizeTo(other.Length());
			for (int i=0; i<other.Length(); i++)
				v[i] = other.v[i];
			len = other.Length();
		}
	}
	/// Copy constructor.
	SVector &operator=(const SVector &other) {
		if (this != &other) {
			delete []v;
			v = 0;
			len = 0;
			size = 0;
			if (other.Length() > 0) {
				SizeTo(other.Length());
				for (int i=0; i<other.Length(); i++)
					v[i] = other.v[i];
				len = other.Length();
			}
		}
		return *this;
	}
	/** @brief Accessor.
	 * Allows to access values from the list, and grows it if accessing
	 * outside the current bounds. The returned value in this case is 0. */
	int &operator[](unsigned int i) {
		if (i >= len) {
			if (i >= size) {
				SizeTo(i);
			}
			len = i+1;
		}
		return v[i];
	}
	/// Reset vector.
	void Free() {
		delete []v;
		v = 0;
		size = 0;
		len = 0;
	}
	/** @brief Grow vector size.
	 * Doesn't allow a vector to be shrinked. */
	void SetLength(unsigned int newLength) {
		if (newLength > len) {
			if (newLength >= size) {
				SizeTo(newLength);
			}
		}
		len = newLength;
	}
	/// Get the current length (number of used elements) of the vector.
	int Length() const {
		return len;
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/SciTE.properties.













>
>
>
>
>
>
1
2
3
4
5
6
# SciTE.properties is the per directory local options file and can be used to override
# settings made in SciTEGlobal.properties
command.build.directory.*.cxx=..\win32
command.build.directory.*.h=..\win32
command.build.*.cxx=nmake -f scintilla.mak QUIET=1
command.build.*.h=nmake -f scintilla.mak QUIET=1

Added src/ScintillaBase.cxx.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
// Scintilla source code edit control
/** @file ScintillaBase.cxx
 ** An enhanced subclass of Editor with calltips, autocomplete and context menu.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>

#include <string>
#include <vector>
#include <map>

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"

#include "PropSetSimple.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
#include "LexerModule.h"
#include "Catalogue.h"
#endif
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "AutoComplete.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

ScintillaBase::ScintillaBase() {
	displayPopupMenu = true;
	listType = 0;
	maxListWidth = 0;
}

ScintillaBase::~ScintillaBase() {
}

void ScintillaBase::Finalise() {
	Editor::Finalise();
	popup.Destroy();
}

void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
	bool isFillUp = ac.Active() && ac.IsFillUpChar(*s);
	if (!isFillUp) {
		Editor::AddCharUTF(s, len, treatAsDBCS);
	}
	if (ac.Active()) {
		AutoCompleteCharacterAdded(s[0]);
		// For fill ups add the character after the autocompletion has
		// triggered so containers see the key so can display a calltip.
		if (isFillUp) {
			Editor::AddCharUTF(s, len, treatAsDBCS);
		}
	}
}

void ScintillaBase::Command(int cmdId) {

	switch (cmdId) {

	case idAutoComplete:  	// Nothing to do

		break;

	case idCallTip:  	// Nothing to do

		break;

	case idcmdUndo:
		WndProc(SCI_UNDO, 0, 0);
		break;

	case idcmdRedo:
		WndProc(SCI_REDO, 0, 0);
		break;

	case idcmdCut:
		WndProc(SCI_CUT, 0, 0);
		break;

	case idcmdCopy:
		WndProc(SCI_COPY, 0, 0);
		break;

	case idcmdPaste:
		WndProc(SCI_PASTE, 0, 0);
		break;

	case idcmdDelete:
		WndProc(SCI_CLEAR, 0, 0);
		break;

	case idcmdSelectAll:
		WndProc(SCI_SELECTALL, 0, 0);
		break;
	}
}

int ScintillaBase::KeyCommand(unsigned int iMessage) {
	// Most key commands cancel autocompletion mode
	if (ac.Active()) {
		switch (iMessage) {
			// Except for these
		case SCI_LINEDOWN:
			AutoCompleteMove(1);
			return 0;
		case SCI_LINEUP:
			AutoCompleteMove(-1);
			return 0;
		case SCI_PAGEDOWN:
			AutoCompleteMove(ac.lb->GetVisibleRows());
			return 0;
		case SCI_PAGEUP:
			AutoCompleteMove(-ac.lb->GetVisibleRows());
			return 0;
		case SCI_VCHOME:
			AutoCompleteMove(-5000);
			return 0;
		case SCI_LINEEND:
			AutoCompleteMove(5000);
			return 0;
		case SCI_DELETEBACK:
			DelCharBack(true);
			AutoCompleteCharacterDeleted();
			EnsureCaretVisible();
			return 0;
		case SCI_DELETEBACKNOTLINE:
			DelCharBack(false);
			AutoCompleteCharacterDeleted();
			EnsureCaretVisible();
			return 0;
		case SCI_TAB:
			AutoCompleteCompleted();
			return 0;
		case SCI_NEWLINE:
			AutoCompleteCompleted();
			return 0;

		default:
			AutoCompleteCancel();
		}
	}

	if (ct.inCallTipMode) {
		if (
		    (iMessage != SCI_CHARLEFT) &&
		    (iMessage != SCI_CHARLEFTEXTEND) &&
		    (iMessage != SCI_CHARRIGHT) &&
		    (iMessage != SCI_CHARRIGHTEXTEND) &&
		    (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
		    (iMessage != SCI_DELETEBACK) &&
		    (iMessage != SCI_DELETEBACKNOTLINE)
		) {
			ct.CallTipCancel();
		}
		if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) {
			if (sel.MainCaret() <= ct.posStartCallTip) {
				ct.CallTipCancel();
			}
		}
	}
	return Editor::KeyCommand(iMessage);
}

void ScintillaBase::AutoCompleteDoubleClick(void *p) {
	ScintillaBase *sci = reinterpret_cast<ScintillaBase *>(p);
	sci->AutoCompleteCompleted();
}

void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
	//Platform::DebugPrintf("AutoComplete %s\n", list);
	ct.CallTipCancel();

	if (ac.chooseSingle && (listType == 0)) {
		if (list && !strchr(list, ac.GetSeparator())) {
			const char *typeSep = strchr(list, ac.GetTypesep());
			int lenInsert = typeSep ? 
				static_cast<int>(typeSep-list) : static_cast<int>(strlen(list));
			UndoGroup ug(pdoc);
			if (ac.ignoreCase) {
				SetEmptySelection(sel.MainCaret() - lenEntered);
				pdoc->DeleteChars(sel.MainCaret(), lenEntered);
				SetEmptySelection(sel.MainCaret());
				pdoc->InsertString(sel.MainCaret(), list, lenInsert);
				SetEmptySelection(sel.MainCaret() + lenInsert);
			} else {
				SetEmptySelection(sel.MainCaret());
				pdoc->InsertString(sel.MainCaret(), list + lenEntered, lenInsert - lenEntered);
				SetEmptySelection(sel.MainCaret() + lenInsert - lenEntered);
			}
			ac.Cancel();
			return;
		}
	}
	ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(),
				lenEntered, vs.lineHeight, IsUnicodeMode(), technology);

	PRectangle rcClient = GetClientRectangle();
	Point pt = LocationFromPosition(sel.MainCaret() - lenEntered);
	PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
	if (rcPopupBounds.Height() == 0)
		rcPopupBounds = rcClient;

	int heightLB = ac.heightLBDefault;
	int widthLB = ac.widthLBDefault;
	if (pt.x >= rcClient.right - widthLB) {
		HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB);
		Redraw();
		pt = PointMainCaret();
	}
	PRectangle rcac;
	rcac.left = pt.x - ac.lb->CaretFromEdge();
	if (pt.y >= rcPopupBounds.bottom - heightLB &&  // Wont fit below.
	        pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above.
		rcac.top = pt.y - heightLB;
		if (rcac.top < rcPopupBounds.top) {
			heightLB -= (rcPopupBounds.top - rcac.top);
			rcac.top = rcPopupBounds.top;
		}
	} else {
		rcac.top = pt.y + vs.lineHeight;
	}
	rcac.right = rcac.left + widthLB;
	rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcPopupBounds.bottom);
	ac.lb->SetPositionRelative(rcac, wMain);
	ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
	unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
	ac.lb->SetAverageCharWidth(aveCharWidth);
	ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);

	ac.SetList(list);

	// Fiddle the position of the list so it is right next to the target and wide enough for all its strings
	PRectangle rcList = ac.lb->GetDesiredRect();
	int heightAlloced = rcList.bottom - rcList.top;
	widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left);
	if (maxListWidth != 0)
		widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth);
	// Make an allowance for large strings in list
	rcList.left = pt.x - ac.lb->CaretFromEdge();
	rcList.right = rcList.left + widthLB;
	if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) &&  // Wont fit below.
	        ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above.
		rcList.top = pt.y - heightAlloced;
	} else {
		rcList.top = pt.y + vs.lineHeight;
	}
	rcList.bottom = rcList.top + heightAlloced;
	ac.lb->SetPositionRelative(rcList, wMain);
	ac.Show(true);
	if (lenEntered != 0) {
		AutoCompleteMoveToCurrentWord();
	}
}

void ScintillaBase::AutoCompleteCancel() {
	if (ac.Active()) {
		SCNotification scn = {0};
		scn.nmhdr.code = SCN_AUTOCCANCELLED;
		scn.wParam = 0;
		scn.listType = 0;
		NotifyParent(scn);
	}
	ac.Cancel();
}

void ScintillaBase::AutoCompleteMove(int delta) {
	ac.Move(delta);
}

void ScintillaBase::AutoCompleteMoveToCurrentWord() {
	std::string wordCurrent = RangeText(ac.posStart - ac.startLen, sel.MainCaret());
	ac.Select(wordCurrent.c_str());
}

void ScintillaBase::AutoCompleteCharacterAdded(char ch) {
	if (ac.IsFillUpChar(ch)) {
		AutoCompleteCompleted();
	} else if (ac.IsStopChar(ch)) {
		AutoCompleteCancel();
	} else {
		AutoCompleteMoveToCurrentWord();
	}
}

void ScintillaBase::AutoCompleteCharacterDeleted() {
	if (sel.MainCaret() < ac.posStart - ac.startLen) {
		AutoCompleteCancel();
	} else if (ac.cancelAtStartPos && (sel.MainCaret() <= ac.posStart)) {
		AutoCompleteCancel();
	} else {
		AutoCompleteMoveToCurrentWord();
	}
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_AUTOCCHARDELETED;
	scn.wParam = 0;
	scn.listType = 0;
	NotifyParent(scn);
}

void ScintillaBase::AutoCompleteCompleted() {
	int item = ac.GetSelection();
	if (item == -1) {
		AutoCompleteCancel();
		return;
	}
	const std::string selected = ac.GetValue(item);

	ac.Show(false);

	SCNotification scn = {0};
	scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
	scn.message = 0;
	scn.wParam = listType;
	scn.listType = listType;
	Position firstPos = ac.posStart - ac.startLen;
	scn.position = firstPos;
	scn.lParam = firstPos;
	scn.text = selected.c_str();
	NotifyParent(scn);

	if (!ac.Active())
		return;
	ac.Cancel();

	if (listType > 0)
		return;

	Position endPos = sel.MainCaret();
	if (ac.dropRestOfWord)
		endPos = pdoc->ExtendWordSelect(endPos, 1, true);
	if (endPos < firstPos)
		return;
	UndoGroup ug(pdoc);
	if (endPos != firstPos) {
		pdoc->DeleteChars(firstPos, endPos - firstPos);
	}
	SetEmptySelection(ac.posStart);
	if (item != -1) {
		pdoc->InsertCString(firstPos, selected.c_str());
		SetEmptySelection(firstPos + static_cast<int>(selected.length()));
	}
	SetLastXChosen();
}

int ScintillaBase::AutoCompleteGetCurrent() {
	if (!ac.Active())
		return -1;
	return ac.GetSelection();
}

int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) {
	if (ac.Active()) {
		int item = ac.GetSelection();
		if (item != -1) {
			const std::string selected = ac.GetValue(item);
			if (buffer != NULL)
				strcpy(buffer, selected.c_str());
			return static_cast<int>(selected.length());
		}
	}
	if (buffer != NULL)
		*buffer = '\0';
	return 0;
}

void ScintillaBase::CallTipShow(Point pt, const char *defn) {
	ac.Cancel();
	// If container knows about STYLE_CALLTIP then use it in place of the
	// STYLE_DEFAULT for the face name, size and character set. Also use it
	// for the foreground and background colour.
	int ctStyle = ct.UseStyleCallTip() ? STYLE_CALLTIP : STYLE_DEFAULT;
	if (ct.UseStyleCallTip()) {
		ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back);
	}
	PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
		vs.lineHeight,
		defn,
		vs.styles[ctStyle].fontName,
		vs.styles[ctStyle].sizeZoomed,
		CodePage(),
		vs.styles[ctStyle].characterSet,
		vs.technology,
		wMain);
	// If the call-tip window would be out of the client
	// space
	PRectangle rcClient = GetClientRectangle();
	int offset = vs.lineHeight + rc.Height();
	// adjust so it displays below the text.
	if (rc.top < rcClient.top) {
		rc.top += offset;
		rc.bottom += offset;
	}
	// adjust so it displays above the text.
	if (rc.bottom > rcClient.bottom) {
		rc.top -= offset;
		rc.bottom -= offset;
	}
	// Now display the window.
	CreateCallTipWindow(rc);
	ct.wCallTip.SetPositionRelative(rc, wMain);
	ct.wCallTip.Show();
}

void ScintillaBase::CallTipClick() {
	SCNotification scn = {0};
	scn.nmhdr.code = SCN_CALLTIPCLICK;
	scn.position = ct.clickPlace;
	NotifyParent(scn);
}

void ScintillaBase::ContextMenu(Point pt) {
	if (displayPopupMenu) {
		bool writable = !WndProc(SCI_GETREADONLY, 0, 0);
		popup.CreatePopUp();
		AddToPopUp("Undo", idcmdUndo, writable && pdoc->CanUndo());
		AddToPopUp("Redo", idcmdRedo, writable && pdoc->CanRedo());
		AddToPopUp("");
		AddToPopUp("Cut", idcmdCut, writable && !sel.Empty());
		AddToPopUp("Copy", idcmdCopy, !sel.Empty());
		AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0));
		AddToPopUp("Delete", idcmdDelete, writable && !sel.Empty());
		AddToPopUp("");
		AddToPopUp("Select All", idcmdSelectAll);
		popup.Show(pt, wMain);
	}
}

void ScintillaBase::CancelModes() {
	AutoCompleteCancel();
	ct.CallTipCancel();
	Editor::CancelModes();
}

void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
	CancelModes();
	Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
}

#ifdef SCI_LEXER

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class LexState : public LexInterface {
	const LexerModule *lexCurrent;
	void SetLexerModule(const LexerModule *lex);
	PropSetSimple props;
	int interfaceVersion;
public:
	int lexLanguage;

	LexState(Document *pdoc_);
	virtual ~LexState();
	void SetLexer(uptr_t wParam);
	void SetLexerLanguage(const char *languageName);
	const char *DescribeWordListSets();
	void SetWordList(int n, const char *wl);
	int GetStyleBitsNeeded() const;
	const char *GetName() const;
	void *PrivateCall(int operation, void *pointer);
	const char *PropertyNames();
	int PropertyType(const char *name);
	const char *DescribeProperty(const char *name);
	void PropSet(const char *key, const char *val);
	const char *PropGet(const char *key) const;
	int PropGetInt(const char *key, int defaultValue=0) const;
	int PropGetExpanded(const char *key, char *result) const;

	int LineEndTypesSupported();
	int AllocateSubStyles(int styleBase, int numberStyles);
	int SubStylesStart(int styleBase);
	int SubStylesLength(int styleBase);
	void FreeSubStyles();
	void SetIdentifiers(int style, const char *identifiers);
	int DistanceToSecondaryStyles();
	const char *GetSubStyleBases();
};

#ifdef SCI_NAMESPACE
}
#endif

LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) {
	lexCurrent = 0;
	performingStyle = false;
	interfaceVersion = lvOriginal;
	lexLanguage = SCLEX_CONTAINER;
}

LexState::~LexState() {
	if (instance) {
		instance->Release();
		instance = 0;
	}
}

LexState *ScintillaBase::DocumentLexState() {
	if (!pdoc->pli) {
		pdoc->pli = new LexState(pdoc);
	}
	return static_cast<LexState *>(pdoc->pli);
}

void LexState::SetLexerModule(const LexerModule *lex) {
	if (lex != lexCurrent) {
		if (instance) {
			instance->Release();
			instance = 0;
		}
		interfaceVersion = lvOriginal;
		lexCurrent = lex;
		if (lexCurrent) {
			instance = lexCurrent->Create();
			interfaceVersion = instance->Version();
		}
		pdoc->LexerChanged();
	}
}

void LexState::SetLexer(uptr_t wParam) {
	lexLanguage = wParam;
	if (lexLanguage == SCLEX_CONTAINER) {
		SetLexerModule(0);
	} else {
		const LexerModule *lex = Catalogue::Find(lexLanguage);
		if (!lex)
			lex = Catalogue::Find(SCLEX_NULL);
		SetLexerModule(lex);
	}
}

void LexState::SetLexerLanguage(const char *languageName) {
	const LexerModule *lex = Catalogue::Find(languageName);
	if (!lex)
		lex = Catalogue::Find(SCLEX_NULL);
	if (lex)
		lexLanguage = lex->GetLanguage();
	SetLexerModule(lex);
}

const char *LexState::DescribeWordListSets() {
	if (instance) {
		return instance->DescribeWordListSets();
	} else {
		return 0;
	}
}

void LexState::SetWordList(int n, const char *wl) {
	if (instance) {
		int firstModification = instance->WordListSet(n, wl);
		if (firstModification >= 0) {
			pdoc->ModifiedAt(firstModification);
		}
	}
}

int LexState::GetStyleBitsNeeded() const {
	return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
}

const char *LexState::GetName() const {
	return lexCurrent ? lexCurrent->languageName : "";
}

void *LexState::PrivateCall(int operation, void *pointer) {
	if (pdoc && instance) {
		return instance->PrivateCall(operation, pointer);
	} else {
		return 0;
	}
}

const char *LexState::PropertyNames() {
	if (instance) {
		return instance->PropertyNames();
	} else {
		return 0;
	}
}

int LexState::PropertyType(const char *name) {
	if (instance) {
		return instance->PropertyType(name);
	} else {
		return SC_TYPE_BOOLEAN;
	}
}

const char *LexState::DescribeProperty(const char *name) {
	if (instance) {
		return instance->DescribeProperty(name);
	} else {
		return 0;
	}
}

void LexState::PropSet(const char *key, const char *val) {
	props.Set(key, val);
	if (instance) {
		int firstModification = instance->PropertySet(key, val);
		if (firstModification >= 0) {
			pdoc->ModifiedAt(firstModification);
		}
	}
}

const char *LexState::PropGet(const char *key) const {
	return props.Get(key);
}

int LexState::PropGetInt(const char *key, int defaultValue) const {
	return props.GetInt(key, defaultValue);
}

int LexState::PropGetExpanded(const char *key, char *result) const {
	return props.GetExpanded(key, result);
}

int LexState::LineEndTypesSupported() {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->LineEndTypesSupported();
	}
	return 0;
}

int LexState::AllocateSubStyles(int styleBase, int numberStyles) {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->AllocateSubStyles(styleBase, numberStyles);
	}
	return -1;
}

int LexState::SubStylesStart(int styleBase) {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->SubStylesStart(styleBase);
	}
	return -1;
}

int LexState::SubStylesLength(int styleBase) {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->SubStylesLength(styleBase);
	}
	return 0;
}

void LexState::FreeSubStyles() {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		static_cast<ILexerWithSubStyles *>(instance)->FreeSubStyles();
	}
}

void LexState::SetIdentifiers(int style, const char *identifiers) {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		static_cast<ILexerWithSubStyles *>(instance)->SetIdentifiers(style, identifiers);
	}
}

int LexState::DistanceToSecondaryStyles() {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->DistanceToSecondaryStyles();
	}
	return 0;
}

const char *LexState::GetSubStyleBases() {
	if (instance && (interfaceVersion >= lvSubStyles)) {
		return static_cast<ILexerWithSubStyles *>(instance)->GetSubStyleBases();
	}
	return "";
}

#endif

void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
#ifdef SCI_LEXER
	if (DocumentLexState()->lexLanguage != SCLEX_CONTAINER) {
		int lineEndStyled = pdoc->LineFromPosition(pdoc->GetEndStyled());
		int endStyled = pdoc->LineStart(lineEndStyled);
		DocumentLexState()->Colourise(endStyled, endStyleNeeded);
		return;
	}
#endif
	Editor::NotifyStyleToNeeded(endStyleNeeded);
}

void ScintillaBase::NotifyLexerChanged(Document *, void *) {
#ifdef SCI_LEXER
	int bits = DocumentLexState()->GetStyleBitsNeeded();
	vs.EnsureStyle((1 << bits) - 1);
#endif
}

sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	switch (iMessage) {
	case SCI_AUTOCSHOW:
		listType = 0;
		AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
		break;

	case SCI_AUTOCCANCEL:
		ac.Cancel();
		break;

	case SCI_AUTOCACTIVE:
		return ac.Active();

	case SCI_AUTOCPOSSTART:
		return ac.posStart;

	case SCI_AUTOCCOMPLETE:
		AutoCompleteCompleted();
		break;

	case SCI_AUTOCSETSEPARATOR:
		ac.SetSeparator(static_cast<char>(wParam));
		break;

	case SCI_AUTOCGETSEPARATOR:
		return ac.GetSeparator();

	case SCI_AUTOCSTOPS:
		ac.SetStopChars(reinterpret_cast<char *>(lParam));
		break;

	case SCI_AUTOCSELECT:
		ac.Select(reinterpret_cast<char *>(lParam));
		break;

	case SCI_AUTOCGETCURRENT:
		return AutoCompleteGetCurrent();

	case SCI_AUTOCGETCURRENTTEXT:
		return AutoCompleteGetCurrentText(reinterpret_cast<char *>(lParam));

	case SCI_AUTOCSETCANCELATSTART:
		ac.cancelAtStartPos = wParam != 0;
		break;

	case SCI_AUTOCGETCANCELATSTART:
		return ac.cancelAtStartPos;

	case SCI_AUTOCSETFILLUPS:
		ac.SetFillUpChars(reinterpret_cast<char *>(lParam));
		break;

	case SCI_AUTOCSETCHOOSESINGLE:
		ac.chooseSingle = wParam != 0;
		break;

	case SCI_AUTOCGETCHOOSESINGLE:
		return ac.chooseSingle;

	case SCI_AUTOCSETIGNORECASE:
		ac.ignoreCase = wParam != 0;
		break;

	case SCI_AUTOCGETIGNORECASE:
		return ac.ignoreCase;

	case SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR:
		ac.ignoreCaseBehaviour = wParam;
		break;

	case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR:
		return ac.ignoreCaseBehaviour;

	case SCI_USERLISTSHOW:
		listType = wParam;
		AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
		break;

	case SCI_AUTOCSETAUTOHIDE:
		ac.autoHide = wParam != 0;
		break;

	case SCI_AUTOCGETAUTOHIDE:
		return ac.autoHide;

	case SCI_AUTOCSETDROPRESTOFWORD:
		ac.dropRestOfWord = wParam != 0;
		break;

	case SCI_AUTOCGETDROPRESTOFWORD:
		return ac.dropRestOfWord;

	case SCI_AUTOCSETMAXHEIGHT:
		ac.lb->SetVisibleRows(wParam);
		break;

	case SCI_AUTOCGETMAXHEIGHT:
		return ac.lb->GetVisibleRows();

	case SCI_AUTOCSETMAXWIDTH:
		maxListWidth = wParam;
		break;

	case SCI_AUTOCGETMAXWIDTH:
		return maxListWidth;

	case SCI_REGISTERIMAGE:
		ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
		break;

	case SCI_REGISTERRGBAIMAGE:
		ac.lb->RegisterRGBAImage(wParam, sizeRGBAImage.x, sizeRGBAImage.y, reinterpret_cast<unsigned char *>(lParam));
		break;

	case SCI_CLEARREGISTEREDIMAGES:
		ac.lb->ClearRegisteredImages();
		break;

	case SCI_AUTOCSETTYPESEPARATOR:
		ac.SetTypesep(static_cast<char>(wParam));
		break;

	case SCI_AUTOCGETTYPESEPARATOR:
		return ac.GetTypesep();

	case SCI_CALLTIPSHOW:
		CallTipShow(LocationFromPosition(wParam),
			reinterpret_cast<const char *>(lParam));
		break;

	case SCI_CALLTIPCANCEL:
		ct.CallTipCancel();
		break;

	case SCI_CALLTIPACTIVE:
		return ct.inCallTipMode;

	case SCI_CALLTIPPOSSTART:
		return ct.posStartCallTip;

	case SCI_CALLTIPSETHLT:
		ct.SetHighlight(wParam, lParam);
		break;

	case SCI_CALLTIPSETBACK:
		ct.colourBG = ColourDesired(wParam);
		vs.styles[STYLE_CALLTIP].back = ct.colourBG;
		InvalidateStyleRedraw();
		break;

	case SCI_CALLTIPSETFORE:
		ct.colourUnSel = ColourDesired(wParam);
		vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel;
		InvalidateStyleRedraw();
		break;

	case SCI_CALLTIPSETFOREHLT:
		ct.colourSel = ColourDesired(wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_CALLTIPUSESTYLE:
		ct.SetTabSize((int)wParam);
		InvalidateStyleRedraw();
		break;

	case SCI_CALLTIPSETPOSITION:
		ct.SetPosition(wParam != 0);
		InvalidateStyleRedraw();
		break;

	case SCI_USEPOPUP:
		displayPopupMenu = wParam != 0;
		break;

#ifdef SCI_LEXER
	case SCI_SETLEXER:
		DocumentLexState()->SetLexer(wParam);
		break;

	case SCI_GETLEXER:
		return DocumentLexState()->lexLanguage;

	case SCI_COLOURISE:
		if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) {
			pdoc->ModifiedAt(wParam);
			NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
		} else {
			DocumentLexState()->Colourise(wParam, lParam);
		}
		Redraw();
		break;

	case SCI_SETPROPERTY:
		DocumentLexState()->PropSet(reinterpret_cast<const char *>(wParam),
		          reinterpret_cast<const char *>(lParam));
		break;

	case SCI_GETPROPERTY:
		return StringResult(lParam, DocumentLexState()->PropGet(reinterpret_cast<const char *>(wParam)));

	case SCI_GETPROPERTYEXPANDED:
		return DocumentLexState()->PropGetExpanded(reinterpret_cast<const char *>(wParam),
			reinterpret_cast<char *>(lParam));

	case SCI_GETPROPERTYINT:
		return DocumentLexState()->PropGetInt(reinterpret_cast<const char *>(wParam), lParam);

	case SCI_SETKEYWORDS:
		DocumentLexState()->SetWordList(wParam, reinterpret_cast<const char *>(lParam));
		break;

	case SCI_SETLEXERLANGUAGE:
		DocumentLexState()->SetLexerLanguage(reinterpret_cast<const char *>(lParam));
		break;

	case SCI_GETLEXERLANGUAGE:
		return StringResult(lParam, DocumentLexState()->GetName());

	case SCI_PRIVATELEXERCALL:
		return reinterpret_cast<sptr_t>(
			DocumentLexState()->PrivateCall(wParam, reinterpret_cast<void *>(lParam)));

	case SCI_GETSTYLEBITSNEEDED:
		return DocumentLexState()->GetStyleBitsNeeded();

	case SCI_PROPERTYNAMES:
		return StringResult(lParam, DocumentLexState()->PropertyNames());

	case SCI_PROPERTYTYPE:
		return DocumentLexState()->PropertyType(reinterpret_cast<const char *>(wParam));

	case SCI_DESCRIBEPROPERTY:
		return StringResult(lParam, DocumentLexState()->DescribeProperty(reinterpret_cast<const char *>(wParam)));

	case SCI_DESCRIBEKEYWORDSETS:
		return StringResult(lParam, DocumentLexState()->DescribeWordListSets());

	case SCI_GETLINEENDTYPESSUPPORTED:
		return DocumentLexState()->LineEndTypesSupported();

	case SCI_ALLOCATESUBSTYLES:
		return DocumentLexState()->AllocateSubStyles(wParam, lParam);

	case SCI_GETSUBSTYLESSTART:
		return DocumentLexState()->SubStylesStart(wParam);

	case SCI_GETSUBSTYLESLENGTH:
		return DocumentLexState()->SubStylesLength(wParam);

	case SCI_FREESUBSTYLES:
		DocumentLexState()->FreeSubStyles();
		break;

	case SCI_SETIDENTIFIERS:
		DocumentLexState()->SetIdentifiers(wParam, reinterpret_cast<const char *>(lParam));
		break;

	case SCI_DISTANCETOSECONDARYSTYLES:
		return DocumentLexState()->DistanceToSecondaryStyles();

	case SCI_GETSUBSTYLEBASES:
		return StringResult(lParam, DocumentLexState()->GetSubStyleBases());
#endif

	default:
		return Editor::WndProc(iMessage, wParam, lParam);
	}
	return 0l;
}

Added src/ScintillaBase.h.







































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ScintillaBase.h
 ** Defines an enhanced subclass of Editor with calltips, autocomplete and context menu.
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SCINTILLABASE_H
#define SCINTILLABASE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

#ifdef SCI_LEXER
class LexState;
#endif

/**
 */
class ScintillaBase : public Editor {
	// Private so ScintillaBase objects can not be copied
	ScintillaBase(const ScintillaBase &);
	ScintillaBase &operator=(const ScintillaBase &);

protected:
	/** Enumeration of commands and child windows. */
	enum {
		idCallTip=1,
		idAutoComplete=2,

		idcmdUndo=10,
		idcmdRedo=11,
		idcmdCut=12,
		idcmdCopy=13,
		idcmdPaste=14,
		idcmdDelete=15,
		idcmdSelectAll=16
	};

	bool displayPopupMenu;
	Menu popup;
	AutoComplete ac;

	CallTip ct;

	int listType;			///< 0 is an autocomplete list
	int maxListWidth;		/// Maximum width of list, in average character widths

#ifdef SCI_LEXER
	LexState *DocumentLexState();
	void SetLexer(uptr_t wParam);
	void SetLexerLanguage(const char *languageName);
	void Colourise(int start, int end);
#endif

	ScintillaBase();
	virtual ~ScintillaBase();
	virtual void Initialise() = 0;
	virtual void Finalise() = 0;

	virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
	void Command(int cmdId);
	virtual void CancelModes();
	virtual int KeyCommand(unsigned int iMessage);

	void AutoCompleteStart(int lenEntered, const char *list);
	void AutoCompleteCancel();
	void AutoCompleteMove(int delta);
	int AutoCompleteGetCurrent();
	int AutoCompleteGetCurrentText(char *buffer);
	void AutoCompleteCharacterAdded(char ch);
	void AutoCompleteCharacterDeleted();
	void AutoCompleteCompleted();
	void AutoCompleteMoveToCurrentWord();
	static void AutoCompleteDoubleClick(void *p);

	void CallTipClick();
	void CallTipShow(Point pt, const char *defn);
	virtual void CreateCallTipWindow(PRectangle rc) = 0;

	virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0;
	void ContextMenu(Point pt);

	virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);

	void NotifyStyleToNeeded(int endStyleNeeded);
	void NotifyLexerChanged(Document *doc, void *userData);

public:
	// Public so scintilla_send_message can use it
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/Selection.cxx.















































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
// Scintilla source code edit control
/** @file Selection.cxx
 ** Classes maintaining the selection.
 **/
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>

#include <vector>

#include "Platform.h"

#include "Scintilla.h"

#include "Selection.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
	if (position == startChange) {
		virtualSpace = 0;
	}
	if (insertion) {
		if (position > startChange) {
			position += length;
		}
	} else {
		if (position > startChange) {
			int endDeletion = startChange + length;
			if (position > endDeletion) {
				position -= length;
			} else {
				position = startChange;
				virtualSpace = 0;
			}
		}
	}
}

bool SelectionPosition::operator <(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace < other.virtualSpace;
	else
		return position < other.position;
}

bool SelectionPosition::operator >(const SelectionPosition &other) const {
	if (position == other.position)
		return virtualSpace > other.virtualSpace;
	else
		return position > other.position;
}

bool SelectionPosition::operator <=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return other > *this;
}

bool SelectionPosition::operator >=(const SelectionPosition &other) const {
	if (position == other.position && virtualSpace == other.virtualSpace)
		return true;
	else
		return *this > other;
}

int SelectionRange::Length() const {
	if (anchor > caret) {
		return anchor.Position() - caret.Position();
	} else {
		return caret.Position() - anchor.Position();
	}
}

bool SelectionRange::Contains(int pos) const {
	if (anchor > caret)
		return (pos >= caret.Position()) && (pos <= anchor.Position());
	else
		return (pos >= anchor.Position()) && (pos <= caret.Position());
}

bool SelectionRange::Contains(SelectionPosition sp) const {
	if (anchor > caret)
		return (sp >= caret) && (sp <= anchor);
	else
		return (sp >= anchor) && (sp <= caret);
}

bool SelectionRange::ContainsCharacter(int posCharacter) const {
	if (anchor > caret)
		return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
	else
		return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
}

SelectionSegment SelectionRange::Intersect(SelectionSegment check) const {
	SelectionSegment inOrder(caret, anchor);
	if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
		SelectionSegment portion = check;
		if (portion.start < inOrder.start)
			portion.start = inOrder.start;
		if (portion.end > inOrder.end)
			portion.end = inOrder.end;
		if (portion.start > portion.end)
			return SelectionSegment();
		else
			return portion;
	} else {
		return SelectionSegment();
	}
}

bool SelectionRange::Trim(SelectionRange range) {
	SelectionPosition startRange = range.Start();
	SelectionPosition endRange = range.End();
	SelectionPosition start = Start();
	SelectionPosition end = End();
	PLATFORM_ASSERT(start <= end);
	PLATFORM_ASSERT(startRange <= endRange);
	if ((startRange <= end) && (endRange >= start)) {
		if ((start > startRange) && (end < endRange)) {
			// Completely covered by range -> empty at start
			end = start;
		} else if ((start < startRange) && (end > endRange)) {
			// Completely covers range -> empty at start
			end = start;
		} else if (start <= startRange) {
			// Trim end
			end = startRange;
		} else { //
			PLATFORM_ASSERT(end >= endRange);
			// Trim start
			start = endRange;
		}
		if (anchor > caret) {
			caret = start;
			anchor = end;
		} else {
			anchor = start;
			caret = end;
		}
		return Empty();
	} else {
		return false;
	}
}

// If range is all virtual collapse to start of virtual space
void SelectionRange::MinimizeVirtualSpace() {
	if (caret.Position() == anchor.Position()) {
		int virtualSpace = caret.VirtualSpace();
		if (virtualSpace > anchor.VirtualSpace())
			virtualSpace = anchor.VirtualSpace();
		caret.SetVirtualSpace(virtualSpace);
		anchor.SetVirtualSpace(virtualSpace);
	}
}

Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
	AddSelection(SelectionPosition(0));
}

Selection::~Selection() {
}

bool Selection::IsRectangular() const {
	return (selType == selRectangle) || (selType == selThin);
}

int Selection::MainCaret() const {
	return ranges[mainRange].caret.Position();
}

int Selection::MainAnchor() const {
	return ranges[mainRange].anchor.Position();
}

SelectionRange &Selection::Rectangular() {
	return rangeRectangular;
}

SelectionSegment Selection::Limits() const {
	if (ranges.empty()) {
		return SelectionSegment();
	} else {
		SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
		for (size_t i=1; i<ranges.size(); i++) {
			sr.Extend(ranges[i].anchor);
			sr.Extend(ranges[i].caret);
		}
		return sr;
	}
}

SelectionSegment Selection::LimitsForRectangularElseMain() const {
	if (IsRectangular()) {
		return Limits();
	} else {
		return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
	}
}

size_t Selection::Count() const {
	return ranges.size();
}

size_t Selection::Main() const {
	return mainRange;
}

void Selection::SetMain(size_t r) {
	PLATFORM_ASSERT(r < ranges.size());
	mainRange = r;
}

SelectionRange &Selection::Range(size_t r) {
	return ranges[r];
}

SelectionRange &Selection::RangeMain() {
	return ranges[mainRange];
}

bool Selection::MoveExtends() const {
	return moveExtends;
}

void Selection::SetMoveExtends(bool moveExtends_) {
	moveExtends = moveExtends_;
}

bool Selection::Empty() const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty())
			return false;
	}
	return true;
}

SelectionPosition Selection::Last() const {
	SelectionPosition lastPosition;
	for (size_t i=0; i<ranges.size(); i++) {
		if (lastPosition < ranges[i].caret)
			lastPosition = ranges[i].caret;
		if (lastPosition < ranges[i].anchor)
			lastPosition = ranges[i].anchor;
	}
	return lastPosition;
}

int Selection::Length() const {
	int len = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		len += ranges[i].Length();
	}
	return len;
}

void Selection::MovePositions(bool insertion, int startChange, int length) {
	for (size_t i=0; i<ranges.size(); i++) {
		ranges[i].caret.MoveForInsertDelete(insertion, startChange, length);
		ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length);
	}
}

void Selection::TrimSelection(SelectionRange range) {
	for (size_t i=0; i<ranges.size();) {
		if ((i != mainRange) && (ranges[i].Trim(range))) {
			// Trimmed to empty so remove
			for (size_t j=i; j<ranges.size()-1; j++) {
				ranges[j] = ranges[j+1];
				if (j == mainRange-1)
					mainRange--;
			}
			ranges.pop_back();
		} else {
			i++;
		}
	}
}

void Selection::SetSelection(SelectionRange range) {
	ranges.clear();
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelection(SelectionRange range) {
	TrimSelection(range);
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::AddSelectionWithoutTrim(SelectionRange range) {
	ranges.push_back(range);
	mainRange = ranges.size() - 1;
}

void Selection::TentativeSelection(SelectionRange range) {
	if (!tentativeMain) {
		rangesSaved = ranges;
	}
	ranges = rangesSaved;
	AddSelection(range);
	TrimSelection(ranges[mainRange]);
	tentativeMain = true;
}

void Selection::CommitTentative() {
	rangesSaved.clear();
	tentativeMain = false;
}

int Selection::CharacterInSelection(int posCharacter) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (ranges[i].ContainsCharacter(posCharacter))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::InSelectionForEOL(int pos) const {
	for (size_t i=0; i<ranges.size(); i++) {
		if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
			return i == mainRange ? 1 : 2;
	}
	return 0;
}

int Selection::VirtualSpaceFor(int pos) const {
	int virtualSpace = 0;
	for (size_t i=0; i<ranges.size(); i++) {
		if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace()))
			virtualSpace = ranges[i].caret.VirtualSpace();
		if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace()))
			virtualSpace = ranges[i].anchor.VirtualSpace();
	}
	return virtualSpace;
}

void Selection::Clear() {
	ranges.clear();
	ranges.push_back(SelectionRange());
	mainRange = ranges.size() - 1;
	selType = selStream;
	moveExtends = false;
	ranges[mainRange].Reset();
	rangeRectangular.Reset();
}

void Selection::RemoveDuplicates() {
	for (size_t i=0; i<ranges.size()-1; i++) {
		if (ranges[i].Empty()) {
			size_t j=i+1;
			while (j<ranges.size()) {
				if (ranges[i] == ranges[j]) {
					ranges.erase(ranges.begin() + j);
					if (mainRange >= j)
						mainRange--;
				} else {
					j++;
				}
			}
		}
	}
}

void Selection::RotateMain() {
	mainRange = (mainRange + 1) % ranges.size();
}

Added src/Selection.h.

























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Selection.h
 ** Classes maintaining the selection.
 **/
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SELECTION_H
#define SELECTION_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class SelectionPosition {
	int position;
	int virtualSpace;
public:
	explicit SelectionPosition(int position_=INVALID_POSITION, int virtualSpace_=0) : position(position_), virtualSpace(virtualSpace_) {
		PLATFORM_ASSERT(virtualSpace < 800000);
		if (virtualSpace < 0)
			virtualSpace = 0;
	}
	void Reset() {
		position = 0;
		virtualSpace = 0;
	}
	void MoveForInsertDelete(bool insertion, int startChange, int length);
	bool operator ==(const SelectionPosition &other) const {
		return position == other.position && virtualSpace == other.virtualSpace;
	}
	bool operator <(const SelectionPosition &other) const;
	bool operator >(const SelectionPosition &other) const;
	bool operator <=(const SelectionPosition &other) const;
	bool operator >=(const SelectionPosition &other) const;
	int Position() const {
		return position;
	}
	void SetPosition(int position_) {
		position = position_;
		virtualSpace = 0;
	}
	int VirtualSpace() const {
		return virtualSpace;
	}
	void SetVirtualSpace(int virtualSpace_) {
		PLATFORM_ASSERT(virtualSpace_ < 800000);
		if (virtualSpace_ >= 0)
			virtualSpace = virtualSpace_;
	}
	void Add(int increment) {
		position = position + increment;
	}
	bool IsValid() const {
		return position >= 0;
	}
};

// Ordered range to make drawing simpler
struct SelectionSegment {
	SelectionPosition start;
	SelectionPosition end;
	SelectionSegment() : start(), end() {
	}
	SelectionSegment(SelectionPosition a, SelectionPosition b) {
		if (a < b) {
			start = a;
			end = b;
		} else {
			start = b;
			end = a;
		}
	}
	bool Empty() const {
		return start == end;
	}
	void Extend(SelectionPosition p) {
		if (start > p)
			start = p;
		if (end < p)
			end = p;
	}
};

struct SelectionRange {
	SelectionPosition caret;
	SelectionPosition anchor;

	SelectionRange() : caret(), anchor() {
	}
	SelectionRange(SelectionPosition single) : caret(single), anchor(single) {
	}
	SelectionRange(int single) : caret(single), anchor(single) {
	}
	SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) {
	}
	SelectionRange(int caret_, int anchor_) : caret(caret_), anchor(anchor_) {
	}
	bool Empty() const {
		return anchor == caret;
	}
	int Length() const;
	// int Width() const;	// Like Length but takes virtual space into account
	bool operator ==(const SelectionRange &other) const {
		return caret == other.caret && anchor == other.anchor;
	}
	bool operator <(const SelectionRange &other) const {
		return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor));
	}
	void Reset() {
		anchor.Reset();
		caret.Reset();
	}
	void ClearVirtualSpace() {
		anchor.SetVirtualSpace(0);
		caret.SetVirtualSpace(0);
	}
	bool Contains(int pos) const;
	bool Contains(SelectionPosition sp) const;
	bool ContainsCharacter(int posCharacter) const;
	SelectionSegment Intersect(SelectionSegment check) const;
	SelectionPosition Start() const {
		return (anchor < caret) ? anchor : caret;
	}
	SelectionPosition End() const {
		return (anchor < caret) ? caret : anchor;
	}
	bool Trim(SelectionRange range);
	// If range is all virtual collapse to start of virtual space
	void MinimizeVirtualSpace();
};

class Selection {
	std::vector<SelectionRange> ranges;
	std::vector<SelectionRange> rangesSaved;
	SelectionRange rangeRectangular;
	size_t mainRange;
	bool moveExtends;
	bool tentativeMain;
public:
	enum selTypes { noSel, selStream, selRectangle, selLines, selThin };
	selTypes selType;

	Selection();
	~Selection();
	bool IsRectangular() const;
	int MainCaret() const;
	int MainAnchor() const;
	SelectionRange &Rectangular();
	SelectionSegment Limits() const;
	// This is for when you want to move the caret in response to a
	// user direction command - for rectangular selections, use the range
	// that covers all selected text otherwise return the main selection.
	SelectionSegment LimitsForRectangularElseMain() const;
	size_t Count() const;
	size_t Main() const;
	void SetMain(size_t r);
	SelectionRange &Range(size_t r);
	SelectionRange &RangeMain();
	bool MoveExtends() const;
	void SetMoveExtends(bool moveExtends_);
	bool Empty() const;
	SelectionPosition Last() const;
	int Length() const;
	void MovePositions(bool insertion, int startChange, int length);
	void TrimSelection(SelectionRange range);
	void SetSelection(SelectionRange range);
	void AddSelection(SelectionRange range);
	void AddSelectionWithoutTrim(SelectionRange range);
	void TentativeSelection(SelectionRange range);
	void CommitTentative();
	int CharacterInSelection(int posCharacter) const;
	int InSelectionForEOL(int pos) const;
	int VirtualSpaceFor(int pos) const;
	void Clear();
	void RemoveDuplicates();
	void RotateMain();
	bool Tentative() const { return tentativeMain; }
	std::vector<SelectionRange> RangesCopy() const {
		return ranges;
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/SplitVector.h.

























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// Scintilla source code edit control
/** @file SplitVector.h
 ** Main data structure for holding arrays that handle insertions
 ** and deletions efficiently.
 **/
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SPLITVECTOR_H
#define SPLITVECTOR_H

template <typename T>
class SplitVector {
protected:
	T *body;
	int size;
	int lengthBody;
	int part1Length;
	int gapLength;	/// invariant: gapLength == size - lengthBody
	int growSize;

	/// Move the gap to a particular position so that insertion and
	/// deletion at that point will not require much copying and
	/// hence be fast.
	void GapTo(int position) {
		if (position != part1Length) {
			if (position < part1Length) {
				memmove(
					body + position + gapLength,
					body + position,
					sizeof(T) * (part1Length - position));
			} else {	// position > part1Length
				memmove(
					body + part1Length,
					body + part1Length + gapLength,
					sizeof(T) * (position - part1Length));
			}
			part1Length = position;
		}
	}

	/// Check that there is room in the buffer for an insertion,
	/// reallocating if more space needed.
	void RoomFor(int insertionLength) {
		if (gapLength <= insertionLength) {
			while (growSize < size / 6)
				growSize *= 2;
			ReAllocate(size + insertionLength + growSize);
		}
	}

	void Init() {
		body = NULL;
		growSize = 8;
		size = 0;
		lengthBody = 0;
		part1Length = 0;
		gapLength = 0;
	}

public:
	/// Construct a split buffer.
	SplitVector() {
		Init();
	}

	~SplitVector() {
		delete []body;
		body = 0;
	}

	int GetGrowSize() const {
		return growSize;
	}

	void SetGrowSize(int growSize_) {
		growSize = growSize_;
	}

	/// Reallocate the storage for the buffer to be newSize and
	/// copy exisiting contents to the new buffer.
	/// Must not be used to decrease the size of the buffer.
	void ReAllocate(int newSize) {
		if (newSize > size) {
			// Move the gap to the end
			GapTo(lengthBody);
			T *newBody = new T[newSize];
			if ((size != 0) && (body != 0)) {
				memmove(newBody, body, sizeof(T) * lengthBody);
				delete []body;
			}
			body = newBody;
			gapLength += newSize - size;
			size = newSize;
		}
	}

	/// Retrieve the character at a particular position.
	/// Retrieving positions outside the range of the buffer returns 0.
	/// The assertions here are disabled since calling code can be
	/// simpler if out of range access works and returns 0.
	T ValueAt(int position) const {
		if (position < part1Length) {
			//PLATFORM_ASSERT(position >= 0);
			if (position < 0) {
				return 0;
			} else {
				return body[position];
			}
		} else {
			//PLATFORM_ASSERT(position < lengthBody);
			if (position >= lengthBody) {
				return 0;
			} else {
				return body[gapLength + position];
			}
		}
	}

	void SetValueAt(int position, T v) {
		if (position < part1Length) {
			PLATFORM_ASSERT(position >= 0);
			if (position < 0) {
				;
			} else {
				body[position] = v;
			}
		} else {
			PLATFORM_ASSERT(position < lengthBody);
			if (position >= lengthBody) {
				;
			} else {
				body[gapLength + position] = v;
			}
		}
	}

	T &operator[](int position) const {
		PLATFORM_ASSERT(position >= 0 && position < lengthBody);
		if (position < part1Length) {
			return body[position];
		} else {
			return body[gapLength + position];
		}
	}

	/// Retrieve the length of the buffer.
	int Length() const {
		return lengthBody;
	}

	/// Insert a single value into the buffer.
	/// Inserting at positions outside the current range fails.
	void Insert(int position, T v) {
		PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
		if ((position < 0) || (position > lengthBody)) {
			return;
		}
		RoomFor(1);
		GapTo(position);
		body[part1Length] = v;
		lengthBody++;
		part1Length++;
		gapLength--;
	}

	/// Insert a number of elements into the buffer setting their value.
	/// Inserting at positions outside the current range fails.
	void InsertValue(int position, int insertLength, T v) {
		PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
		if (insertLength > 0) {
			if ((position < 0) || (position > lengthBody)) {
				return;
			}
			RoomFor(insertLength);
			GapTo(position);
			for (int i = 0; i < insertLength; i++)
				body[part1Length + i] = v;
			lengthBody += insertLength;
			part1Length += insertLength;
			gapLength -= insertLength;
		}
	}

	/// Ensure at least length elements allocated,
	/// appending zero valued elements if needed.
	void EnsureLength(int wantedLength) {
		if (Length() < wantedLength) {
			InsertValue(Length(), wantedLength - Length(), 0);
		}
	}

	/// Insert text into the buffer from an array.
	void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) {
		PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody));
		if (insertLength > 0) {
			if ((positionToInsert < 0) || (positionToInsert > lengthBody)) {
				return;
			}
			RoomFor(insertLength);
			GapTo(positionToInsert);
			memmove(body + part1Length, s + positionFrom, sizeof(T) * insertLength);
			lengthBody += insertLength;
			part1Length += insertLength;
			gapLength -= insertLength;
		}
	}

	/// Delete one element from the buffer.
	void Delete(int position) {
		PLATFORM_ASSERT((position >= 0) && (position < lengthBody));
		if ((position < 0) || (position >= lengthBody)) {
			return;
		}
		DeleteRange(position, 1);
	}

	/// Delete a range from the buffer.
	/// Deleting positions outside the current range fails.
	void DeleteRange(int position, int deleteLength) {
		PLATFORM_ASSERT((position >= 0) && (position + deleteLength <= lengthBody));
		if ((position < 0) || ((position + deleteLength) > lengthBody)) {
			return;
		}
		if ((position == 0) && (deleteLength == lengthBody)) {
			// Full deallocation returns storage and is faster
			delete []body;
			Init();
		} else if (deleteLength > 0) {
			GapTo(position);
			lengthBody -= deleteLength;
			gapLength += deleteLength;
		}
	}

	/// Delete all the buffer contents.
	void DeleteAll() {
		DeleteRange(0, lengthBody);
	}

	// Retrieve a range of elements into an array
	void GetRange(T *buffer, int position, int retrieveLength) const {
		// Split into up to 2 ranges, before and after the split then use memcpy on each.
		int range1Length = 0;
		if (position < part1Length) {
			int part1AfterPosition = part1Length - position;
			range1Length = retrieveLength;
			if (range1Length > part1AfterPosition)
				range1Length = part1AfterPosition;
		}
		memcpy(buffer, body + position, range1Length * sizeof(T));
		buffer += range1Length;
		position = position + range1Length + gapLength;
		int range2Length = retrieveLength - range1Length;
		memcpy(buffer, body + position, range2Length * sizeof(T));
	}

	T *BufferPointer() {
		RoomFor(1);
		GapTo(lengthBody);
		body[lengthBody] = 0;
		return body;
	}

	T *RangePointer(int position, int rangeLength) {
		if (position < part1Length) {
			if ((position + rangeLength) > part1Length) {
				// Range overlaps gap, so move gap to start of range.
				GapTo(position);
				return body + position + gapLength;
			} else {
				return body + position ;
			}
		} else {
			return body + position + gapLength;
		}
	}

	int GapPosition() const {
		return part1Length; 
	}
};

#endif

Added src/Style.cxx.







































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Style.cxx
 ** Defines the font and colour style for a class of text.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "Style.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

FontAlias::FontAlias() {
}

FontAlias::~FontAlias() {
	SetID(0);
	// ~Font will not release the actual font resource sine it is now 0
}

void FontAlias::MakeAlias(Font &fontOrigin) {
	SetID(fontOrigin.GetID());
}

void FontAlias::ClearFont() {
	SetID(0);
}

bool FontSpecification::EqualTo(const FontSpecification &other) const {
	return weight == other.weight &&
	       italic == other.italic &&
	       size == other.size &&
	       characterSet == other.characterSet &&
	       fontName == other.fontName;
}

FontMeasurements::FontMeasurements() {
	Clear();
}

void FontMeasurements::Clear() {
	ascent = 1;
	descent = 1;
	aveCharWidth = 1;
	spaceWidth = 1;
	sizeZoomed = 2;
}

Style::Style() : FontSpecification() {
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, 0, SC_CHARSET_DEFAULT,
	      SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
}

Style::Style(const Style &source) : FontSpecification(), FontMeasurements() {
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, 0,
	      SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
	fore = source.fore;
	back = source.back;
	characterSet = source.characterSet;
	weight = source.weight;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	hotspot = source.hotspot;
}

Style::~Style() {
}

Style &Style::operator=(const Style &source) {
	if (this == &source)
		return * this;
	Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
	      0, 0, SC_CHARSET_DEFAULT,
	      SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
	fore = source.fore;
	back = source.back;
	characterSet = source.characterSet;
	weight = source.weight;
	italic = source.italic;
	size = source.size;
	eolFilled = source.eolFilled;
	underline = source.underline;
	caseForce = source.caseForce;
	visible = source.visible;
	changeable = source.changeable;
	return *this;
}

void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
        const char *fontName_, int characterSet_,
        int weight_, bool italic_, bool eolFilled_,
        bool underline_, ecaseForced caseForce_,
        bool visible_, bool changeable_, bool hotspot_) {
	fore = fore_;
	back = back_;
	characterSet = characterSet_;
	weight = weight_;
	italic = italic_;
	size = size_;
	fontName = fontName_;
	eolFilled = eolFilled_;
	underline = underline_;
	caseForce = caseForce_;
	visible = visible_;
	changeable = changeable_;
	hotspot = hotspot_;
	font.ClearFont();
	FontMeasurements::Clear();
}

void Style::ClearTo(const Style &source) {
	Clear(
	    source.fore,
	    source.back,
	    source.size,
	    source.fontName,
	    source.characterSet,
	    source.weight,
	    source.italic,
	    source.eolFilled,
	    source.underline,
	    source.caseForce,
	    source.visible,
	    source.changeable,
	    source.hotspot);
}

void Style::Copy(Font &font_, const FontMeasurements &fm_) {
	font.MakeAlias(font_);
#if PLAT_WX
	font.SetAscent(fm_.ascent);
#endif
	(FontMeasurements &)(*this) = fm_;
}

Added src/Style.h.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file Style.h
 ** Defines the font and colour style for a class of text.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef STYLE_H
#define STYLE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

struct FontSpecification {
	const char *fontName;
	int weight;
	bool italic;
	int size;
	int characterSet;
	int extraFontFlag;
	FontSpecification() :
		fontName(0),
		weight(SC_WEIGHT_NORMAL),
		italic(false),
		size(10 * SC_FONT_SIZE_MULTIPLIER),
		characterSet(0),
		extraFontFlag(0) {
	}
	bool EqualTo(const FontSpecification &other) const;
};

// Just like Font but only has a copy of the FontID so should not delete it
class FontAlias : public Font {
	// Private so FontAlias objects can not be copied
	FontAlias(const FontAlias &);
	FontAlias &operator=(const FontAlias &);
public:
	FontAlias();
	virtual ~FontAlias();
	void MakeAlias(Font &fontOrigin);
	void ClearFont();
};

struct FontMeasurements {
	unsigned int ascent;
	unsigned int descent;
	XYPOSITION aveCharWidth;
	XYPOSITION spaceWidth;
	int sizeZoomed;
	FontMeasurements();
	void Clear();
};

/**
 */
class Style : public FontSpecification, public FontMeasurements {
public:
	ColourDesired fore;
	ColourDesired back;
	bool eolFilled;
	bool underline;
	enum ecaseForced {caseMixed, caseUpper, caseLower};
	ecaseForced caseForce;
	bool visible;
	bool changeable;
	bool hotspot;

	FontAlias font;

	Style();
	Style(const Style &source);
	~Style();
	Style &operator=(const Style &source);
	void Clear(ColourDesired fore_, ColourDesired back_,
	           int size_,
	           const char *fontName_, int characterSet_,
	           int weight_, bool italic_, bool eolFilled_,
	           bool underline_, ecaseForced caseForce_,
		   bool visible_, bool changeable_, bool hotspot_);
	void ClearTo(const Style &source);
	void Copy(Font &font_, const FontMeasurements &fm_);
	bool IsProtected() const { return !(changeable && visible);}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/UniConversion.cxx.

















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
// Scintilla source code edit control
/** @file UniConversion.cxx
 ** Functions to handle UTF-8 and UTF-16 strings.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>

#include "UniConversion.h"

enum { SURROGATE_LEAD_FIRST = 0xD800 };
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
enum { SURROGATE_TRAIL_LAST = 0xDFFF };

unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) {
	unsigned int len = 0;
	for (unsigned int i = 0; i < tlen && uptr[i];) {
		unsigned int uch = uptr[i];
		if (uch < 0x80) {
			len++;
		} else if (uch < 0x800) {
			len += 2;
		} else if ((uch >= SURROGATE_LEAD_FIRST) &&
			(uch <= SURROGATE_TRAIL_LAST)) {
			len += 4;
			i++;
		} else {
			len += 3;
		}
		i++;
	}
	return len;
}

void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) {
	int k = 0;
	for (unsigned int i = 0; i < tlen && uptr[i];) {
		unsigned int uch = uptr[i];
		if (uch < 0x80) {
			putf[k++] = static_cast<char>(uch);
		} else if (uch < 0x800) {
			putf[k++] = static_cast<char>(0xC0 | (uch >> 6));
			putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
		} else if ((uch >= SURROGATE_LEAD_FIRST) &&
			(uch <= SURROGATE_TRAIL_LAST)) {
			// Half a surrogate pair
			i++;
			unsigned int xch = 0x10000 + ((uch & 0x3ff) << 10) + (uptr[i] & 0x3ff);
			putf[k++] = static_cast<char>(0xF0 | (xch >> 18));
			putf[k++] = static_cast<char>(0x80 | ((xch >> 12) & 0x3f));
			putf[k++] = static_cast<char>(0x80 | ((xch >> 6) & 0x3f));
			putf[k++] = static_cast<char>(0x80 | (xch & 0x3f));
		} else {
			putf[k++] = static_cast<char>(0xE0 | (uch >> 12));
			putf[k++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
			putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
		}
		i++;
	}
	putf[len] = '\0';
}

unsigned int UTF8CharLength(unsigned char ch) {
	if (ch < 0x80) {
		return 1;
	} else if (ch < 0x80 + 0x40 + 0x20) {
		return 2;
	} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
		return 3;
	} else {
		return 4;
	}
}

unsigned int UTF16Length(const char *s, unsigned int len) {
	unsigned int ulen = 0;
	unsigned int charLen;
	for (unsigned int i=0; i<len;) {
		unsigned char ch = static_cast<unsigned char>(s[i]);
		if (ch < 0x80) {
			charLen = 1;
		} else if (ch < 0x80 + 0x40 + 0x20) {
			charLen = 2;
		} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
			charLen = 3;
		} else {
			charLen = 4;
			ulen++;
		}
		i += charLen;
		ulen++;
	}
	return ulen;
}

unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) {
	unsigned int ui=0;
	const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
	unsigned int i=0;
	while ((i<len) && (ui<tlen)) {
		unsigned char ch = us[i++];
		if (ch < 0x80) {
			tbuf[ui] = ch;
		} else if (ch < 0x80 + 0x40 + 0x20) {
			tbuf[ui] = static_cast<wchar_t>((ch & 0x1F) << 6);
			ch = us[i++];
			tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
		} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
			tbuf[ui] = static_cast<wchar_t>((ch & 0xF) << 12);
			ch = us[i++];
			tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + ((ch & 0x7F) << 6));
			ch = us[i++];
			tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
		} else {
			// Outside the BMP so need two surrogates
			int val = (ch & 0x7) << 18;
			ch = us[i++];
			val += (ch & 0x3F) << 12;
			ch = us[i++];
			val += (ch & 0x3F) << 6;
			ch = us[i++];
			val += (ch & 0x3F);
			tbuf[ui] = static_cast<wchar_t>(((val - 0x10000) >> 10) + SURROGATE_LEAD_FIRST);
			ui++;
			tbuf[ui] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST);
		}
		ui++;
	}
	return ui;
}

int UTF8BytesOfLead[256];
static bool initialisedBytesOfLead = false;

static int BytesFromLead(int leadByte) {
	if (leadByte < 0xC2) {
		// Single byte or invalid
		return 1;
	} else if (leadByte < 0xE0) {
		return 2;
	} else if (leadByte < 0xF0) {
		return 3;
	} else if (leadByte < 0xF5) {
		return 4;
	} else {
		// Characters longer than 4 bytes not possible in current UTF-8
		return 1;
	}
}

void UTF8BytesOfLeadInitialise() {
	if (!initialisedBytesOfLead) {
		for (int i=0;i<256;i++) {
			UTF8BytesOfLead[i] = BytesFromLead(i);
		}
		initialisedBytesOfLead = true;
	}
}

// Return both the width of the first character in the string and a status
// saying whether it is valid or invalid.
// Most invalid sequences return a width of 1 so are treated as isolated bytes but
// the non-characters *FFFE, *FFFF and FDD0 .. FDEF return 3 or 4 as they can be
// reasonably treated as code points in some circumstances. They will, however,
// not have associated glyphs.
int UTF8Classify(const unsigned char *us, int len) {
	// For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
	if (*us < 0x80) {
		// Single bytes easy
		return 1;
	} else if (*us > 0xf4) {
		// Characters longer than 4 bytes not possible in current UTF-8
		return UTF8MaskInvalid | 1;
	} else if (*us >= 0xf0) {
		// 4 bytes
		if (len < 4)
			return UTF8MaskInvalid | 1;
		if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2]) && UTF8IsTrailByte(us[3])) {
			if (((us[1] & 0xf) == 0xf) && (us[2] == 0xbf) && ((us[3] == 0xbe) || (us[3] == 0xbf))) {
				// *FFFE or *FFFF non-character
				return UTF8MaskInvalid | 4;
			}
			if (*us == 0xf4) {
				// Check if encoding a value beyond the last Unicode character 10FFFF
				if (us[1] > 0x8f) {
					return UTF8MaskInvalid | 1;
				} else if (us[1] == 0x8f) {
					if (us[2] > 0xbf) {
						return UTF8MaskInvalid | 1;
					} else if (us[2] == 0xbf) {
						if (us[3] > 0xbf) {
							return UTF8MaskInvalid | 1;
						}
					}
				}
			} else if ((*us == 0xf0) && ((us[1] & 0xf0) == 0x80)) {
				// Overlong
				return UTF8MaskInvalid | 1;
			}
			return 4;
		} else {
			return UTF8MaskInvalid | 1;
		}
	} else if (*us >= 0xe0) {
		// 3 bytes
		if (len < 3)
			return UTF8MaskInvalid | 1;
		if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2])) {
			if ((*us == 0xe0) && ((us[1] & 0xe0) == 0x80)) {
				// Overlong
				return UTF8MaskInvalid | 1;
			}
			if ((*us == 0xed) && ((us[1] & 0xe0) == 0xa0)) {
				// Surrogate
				return UTF8MaskInvalid | 1;
			}
			if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbe)) {
				// U+FFFE non-character - 3 bytes long
				return UTF8MaskInvalid | 3;
			}
			if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbf)) {
				// U+FFFF non-character - 3 bytes long
				return UTF8MaskInvalid | 3;
			}
			if ((*us == 0xef) && (us[1] == 0xb7) && (((us[2] & 0xf0) == 0x90) || ((us[2] & 0xf0) == 0xa0))) {
				// U+FDD0 .. U+FDEF
				return UTF8MaskInvalid | 3;
			}
			return 3;
		} else {
			return UTF8MaskInvalid | 1;
		}
	} else if (*us >= 0xc2) {
		// 2 bytes
		if (len < 2)
			return UTF8MaskInvalid | 1;
		if (UTF8IsTrailByte(us[1])) {
			return 2;
		} else {
			return UTF8MaskInvalid | 1;
		}
	} else {
		// 0xc0 .. 0xc1 is overlong encoding
		// 0x80 .. 0xbf is trail byte
		return UTF8MaskInvalid | 1;
	}
}

Added src/UniConversion.h.



















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file UniConversion.h
 ** Functions to handle UTF-8 and UTF-16 strings.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

const int UTF8MaxBytes = 4;

unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
unsigned int UTF8CharLength(unsigned char ch);
unsigned int UTF16Length(const char *s, unsigned int len);
unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);

extern int UTF8BytesOfLead[256];
void UTF8BytesOfLeadInitialise();

inline bool UTF8IsTrailByte(int ch) {
	return (ch >= 0x80) && (ch < 0xc0);
}

inline bool UTF8IsAscii(int ch) {
	return ch < 0x80;
}

enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 };
int UTF8Classify(const unsigned char *us, int len);

// Line separator is U+2028 \xe2\x80\xa8
// Paragraph separator is U+2029 \xe2\x80\xa9
const int UTF8SeparatorLength = 3;
inline bool UTF8IsSeparator(const unsigned char *us) {
	return (us[0] == 0xe2) && (us[1] == 0x80) && ((us[2] == 0xa8) || (us[2] == 0xa9));
}

// NEL is U+0085 \xc2\x85
const int UTF8NELLength = 2;
inline bool UTF8IsNEL(const unsigned char *us) {
	return (us[0] == 0xc2) && (us[1] == 0x85);
}

Added src/ViewStyle.cxx.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
// Scintilla source code edit control
/** @file ViewStyle.cxx
 ** Store information on how the document is to be viewed.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>
#include <assert.h>

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

MarginStyle::MarginStyle() :
	style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
}

// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
	size = 8;
	names = new char *[size];
	max = 0;
}

FontNames::~FontNames() {
	Clear();
	delete []names;
	names = 0;
}

void FontNames::Clear() {
	for (int i=0; i<max; i++) {
		delete []names[i];
	}
	max = 0;
}

const char *FontNames::Save(const char *name) {
	if (!name)
		return 0;
	for (int i=0; i<max; i++) {
		if (strcmp(names[i], name) == 0) {
			return names[i];
		}
	}
	if (max >= size) {
		// Grow array
		int sizeNew = size * 2;
		char **namesNew = new char *[sizeNew];
		for (int j=0; j<max; j++) {
			namesNew[j] = names[j];
		}
		delete []names;
		names = namesNew;
		size = sizeNew;
	}
	names[max] = new char[strlen(name) + 1];
	strcpy(names[max], name);
	max++;
	return names[max-1];
}

FontRealised::FontRealised(const FontSpecification &fs) {
	frNext = NULL;
	(FontSpecification &)(*this) = fs;
}

FontRealised::~FontRealised() {
	font.Release();
	delete frNext;
	frNext = 0;
}

void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) {
	PLATFORM_ASSERT(fontName);
	sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
	if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER)	// Hangs if sizeZoomed <= 1
		sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;

	float deviceHeight = surface.DeviceHeightFont(sizeZoomed);
	FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet);
	font.Create(fp);

	ascent = surface.Ascent(font);
	descent = surface.Descent(font);
	aveCharWidth = surface.AverageCharWidth(font);
	spaceWidth = surface.WidthChar(font, ' ');
	if (frNext) {
		frNext->Realise(surface, zoomLevel, technology);
	}
}

FontRealised *FontRealised::Find(const FontSpecification &fs) {
	if (!fs.fontName)
		return this;
	FontRealised *fr = this;
	while (fr) {
		if (fr->EqualTo(fs))
			return fr;
		fr = fr->frNext;
	}
	return 0;
}

void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) {
	FontRealised *fr = this;
	while (fr) {
		if (maxAscent < fr->ascent)
			maxAscent = fr->ascent;
		if (maxDescent < fr->descent)
			maxDescent = fr->descent;
		fr = fr->frNext;
	}
}

ViewStyle::ViewStyle() {
	Init();
}

ViewStyle::ViewStyle(const ViewStyle &source) {
	frFirst = NULL;
	Init(source.stylesSize);
	for (unsigned int sty=0; sty<source.stylesSize; sty++) {
		styles[sty] = source.styles[sty];
		// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
		styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
	}
	nextExtendedStyle = source.nextExtendedStyle;
	for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
		markers[mrk] = source.markers[mrk];
	}
	CalcLargestMarkerHeight();
	for (int ind=0; ind<=INDIC_MAX; ind++) {
		indicators[ind] = source.indicators[ind];
	}

	selforeset = source.selforeset;
	selforeground = source.selforeground;
	selAdditionalForeground = source.selAdditionalForeground;
	selbackset = source.selbackset;
	selbackground = source.selbackground;
	selAdditionalBackground = source.selAdditionalBackground;
	selbackground2 = source.selbackground2;
	selAlpha = source.selAlpha;
	selAdditionalAlpha = source.selAdditionalAlpha;
	selEOLFilled = source.selEOLFilled;

	foldmarginColourSet = source.foldmarginColourSet;
	foldmarginColour = source.foldmarginColour;
	foldmarginHighlightColourSet = source.foldmarginHighlightColourSet;
	foldmarginHighlightColour = source.foldmarginHighlightColour;

	hotspotForegroundSet = source.hotspotForegroundSet;
	hotspotForeground = source.hotspotForeground;
	hotspotBackgroundSet = source.hotspotBackgroundSet;
	hotspotBackground = source.hotspotBackground;
	hotspotUnderline = source.hotspotUnderline;
	hotspotSingleLine = source.hotspotSingleLine;

	whitespaceForegroundSet = source.whitespaceForegroundSet;
	whitespaceForeground = source.whitespaceForeground;
	whitespaceBackgroundSet = source.whitespaceBackgroundSet;
	whitespaceBackground = source.whitespaceBackground;
	selbar = source.selbar;
	selbarlight = source.selbarlight;
	caretcolour = source.caretcolour;
	additionalCaretColour = source.additionalCaretColour;
	showCaretLineBackground = source.showCaretLineBackground;
	alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
	caretLineBackground = source.caretLineBackground;
	caretLineAlpha = source.caretLineAlpha;
	edgecolour = source.edgecolour;
	edgeState = source.edgeState;
	caretStyle = source.caretStyle;
	caretWidth = source.caretWidth;
	someStylesProtected = false;
	someStylesForceCase = false;
	leftMarginWidth = source.leftMarginWidth;
	rightMarginWidth = source.rightMarginWidth;
	for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
		ms[margin] = source.ms[margin];
	}
	maskInLine = source.maskInLine;
	fixedColumnWidth = source.fixedColumnWidth;
	marginInside = source.marginInside;
	textStart = source.textStart;
	zoomLevel = source.zoomLevel;
	viewWhitespace = source.viewWhitespace;
	whitespaceSize = source.whitespaceSize;
	viewIndentationGuides = source.viewIndentationGuides;
	viewEOL = source.viewEOL;
	extraFontFlag = source.extraFontFlag;
	extraAscent = source.extraAscent;
	extraDescent = source.extraDescent;
	marginStyleOffset = source.marginStyleOffset;
	annotationVisible = source.annotationVisible;
	annotationStyleOffset = source.annotationStyleOffset;
	braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;
	braceHighlightIndicator = source.braceHighlightIndicator;
	braceBadLightIndicatorSet = source.braceBadLightIndicatorSet;
	braceBadLightIndicator = source.braceBadLightIndicator;
}

ViewStyle::~ViewStyle() {
	delete []styles;
	styles = NULL;
	delete frFirst;
	frFirst = NULL;
}

void ViewStyle::Init(size_t stylesSize_) {
	frFirst = NULL;
	stylesSize = 0;
	styles = NULL;
	AllocStyles(stylesSize_);
	nextExtendedStyle = 256;
	fontNames.Clear();
	ResetDefaultStyle();

	// There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
	largestMarkerHeight = 0;

	indicators[0].style = INDIC_SQUIGGLE;
	indicators[0].under = false;
	indicators[0].fore = ColourDesired(0, 0x7f, 0);
	indicators[1].style = INDIC_TT;
	indicators[1].under = false;
	indicators[1].fore = ColourDesired(0, 0, 0xff);
	indicators[2].style = INDIC_PLAIN;
	indicators[2].under = false;
	indicators[2].fore = ColourDesired(0xff, 0, 0);

	technology = SC_TECHNOLOGY_DEFAULT;
	lineHeight = 1;
	maxAscent = 1;
	maxDescent = 1;
	aveCharWidth = 8;
	spaceWidth = 8;

	selforeset = false;
	selforeground = ColourDesired(0xff, 0, 0);
	selAdditionalForeground = ColourDesired(0xff, 0, 0);
	selbackset = true;
	selbackground = ColourDesired(0xc0, 0xc0, 0xc0);
	selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7);
	selbackground2 = ColourDesired(0xb0, 0xb0, 0xb0);
	selAlpha = SC_ALPHA_NOALPHA;
	selAdditionalAlpha = SC_ALPHA_NOALPHA;
	selEOLFilled = false;

	foldmarginColourSet = false;
	foldmarginColour = ColourDesired(0xff, 0, 0);
	foldmarginHighlightColourSet = false;
	foldmarginHighlightColour = ColourDesired(0xc0, 0xc0, 0xc0);

	whitespaceForegroundSet = false;
	whitespaceForeground = ColourDesired(0, 0, 0);
	whitespaceBackgroundSet = false;
	whitespaceBackground = ColourDesired(0xff, 0xff, 0xff);
	selbar = Platform::Chrome();
	selbarlight = Platform::ChromeHighlight();
	styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0);
	styles[STYLE_LINENUMBER].back = Platform::Chrome();
	caretcolour = ColourDesired(0, 0, 0);
	additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
	showCaretLineBackground = false;
	alwaysShowCaretLineBackground = false;
	caretLineBackground = ColourDesired(0xff, 0xff, 0);
	caretLineAlpha = SC_ALPHA_NOALPHA;
	edgecolour = ColourDesired(0xc0, 0xc0, 0xc0);
	edgeState = EDGE_NONE;
	caretStyle = CARETSTYLE_LINE;
	caretWidth = 1;
	someStylesProtected = false;
	someStylesForceCase = false;

	hotspotForegroundSet = false;
	hotspotForeground = ColourDesired(0, 0, 0xff);
	hotspotBackgroundSet = false;
	hotspotBackground = ColourDesired(0xff, 0xff, 0xff);
	hotspotUnderline = true;
	hotspotSingleLine = true;

	leftMarginWidth = 1;
	rightMarginWidth = 1;
	ms[0].style = SC_MARGIN_NUMBER;
	ms[0].width = 0;
	ms[0].mask = 0;
	ms[1].style = SC_MARGIN_SYMBOL;
	ms[1].width = 16;
	ms[1].mask = ~SC_MASK_FOLDERS;
	ms[2].style = SC_MARGIN_SYMBOL;
	ms[2].width = 0;
	ms[2].mask = 0;
	marginInside = true;
	fixedColumnWidth = marginInside ? leftMarginWidth : 0;
	maskInLine = 0xffffffff;
	for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
		fixedColumnWidth += ms[margin].width;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
	textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
	zoomLevel = 0;
	viewWhitespace = wsInvisible;
	whitespaceSize = 1;
	viewIndentationGuides = ivNone;
	viewEOL = false;
	extraFontFlag = 0;
	extraAscent = 0;
	extraDescent = 0;
	marginStyleOffset = 0;
	annotationVisible = ANNOTATION_HIDDEN;
	annotationStyleOffset = 0;
	braceHighlightIndicatorSet = false;
	braceHighlightIndicator = 0;
	braceBadLightIndicatorSet = false;
	braceBadLightIndicator = 0;
}

void ViewStyle::CreateFont(const FontSpecification &fs) {
	if (fs.fontName) {
		for (FontRealised *cur=frFirst; cur; cur=cur->frNext) {
			if (cur->EqualTo(fs))
				return;
			if (!cur->frNext) {
				cur->frNext = new FontRealised(fs);
				return;
			}
		}
		frFirst = new FontRealised(fs);
	}
}

void ViewStyle::Refresh(Surface &surface) {
	delete frFirst;
	frFirst = NULL;
	selbar = Platform::Chrome();
	selbarlight = Platform::ChromeHighlight();

	for (unsigned int i=0; i<stylesSize; i++) {
		styles[i].extraFontFlag = extraFontFlag;
	}

	CreateFont(styles[STYLE_DEFAULT]);
	for (unsigned int j=0; j<stylesSize; j++) {
		CreateFont(styles[j]);
	}

	assert(frFirst);
	frFirst->Realise(surface, zoomLevel, technology);

	for (unsigned int k=0; k<stylesSize; k++) {
		FontRealised *fr = frFirst->Find(styles[k]);
		styles[k].Copy(fr->font, *fr);
	}
	maxAscent = 1;
	maxDescent = 1;
	frFirst->FindMaxAscentDescent(maxAscent, maxDescent);
	maxAscent += extraAscent;
	maxDescent += extraDescent;
	lineHeight = maxAscent + maxDescent;

	someStylesProtected = false;
	someStylesForceCase = false;
	for (unsigned int l=0; l<stylesSize; l++) {
		if (styles[l].IsProtected()) {
			someStylesProtected = true;
		}
		if (styles[l].caseForce != Style::caseMixed) {
			someStylesForceCase = true;
		}
	}

	aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
	spaceWidth = styles[STYLE_DEFAULT].spaceWidth;

	fixedColumnWidth = marginInside ? leftMarginWidth : 0;
	maskInLine = 0xffffffff;
	for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
		fixedColumnWidth += ms[margin].width;
		if (ms[margin].width > 0)
			maskInLine &= ~ms[margin].mask;
	}
	textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
}

void ViewStyle::AllocStyles(size_t sizeNew) {
	Style *stylesNew = new Style[sizeNew];
	size_t i=0;
	for (; i<stylesSize; i++) {
		stylesNew[i] = styles[i];
		stylesNew[i].fontName = styles[i].fontName;
	}
	if (stylesSize > STYLE_DEFAULT) {
		for (; i<sizeNew; i++) {
			if (i != STYLE_DEFAULT) {
				stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
			}
		}
	}
	delete []styles;
	styles = stylesNew;
	stylesSize = sizeNew;
}

void ViewStyle::ReleaseAllExtendedStyles() {
	nextExtendedStyle = 256;
}

int ViewStyle::AllocateExtendedStyles(int numberStyles) {
	int startRange = static_cast<int>(nextExtendedStyle);
	nextExtendedStyle += numberStyles;
	return startRange;
}

void ViewStyle::EnsureStyle(size_t index) {
	if (index >= stylesSize) {
		size_t sizeNew = stylesSize * 2;
		while (sizeNew <= index)
			sizeNew *= 2;
		AllocStyles(sizeNew);
	}
}

void ViewStyle::ResetDefaultStyle() {
	styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
	        ColourDesired(0xff,0xff,0xff),
	        Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
	        SC_CHARSET_DEFAULT,
	        SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
}

void ViewStyle::ClearStyles() {
	// Reset all styles to be like the default style
	for (unsigned int i=0; i<stylesSize; i++) {
		if (i != STYLE_DEFAULT) {
			styles[i].ClearTo(styles[STYLE_DEFAULT]);
		}
	}
	styles[STYLE_LINENUMBER].back = Platform::Chrome();

	// Set call tip fore/back to match the values previously set for call tips
	styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff);
	styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80);
}

void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
	styles[styleIndex].fontName = fontNames.Save(name);
}

bool ViewStyle::ProtectionActive() const {
	return someStylesProtected;
}

bool ViewStyle::ValidStyle(size_t styleIndex) const {
	return styleIndex < stylesSize;
}

void ViewStyle::CalcLargestMarkerHeight() {
	largestMarkerHeight = 0;
	for (int m = 0; m <= MARKER_MAX; ++m) {
		switch (markers[m].markType) {
		case SC_MARK_PIXMAP:
			if (markers[m].pxpm->GetHeight() > largestMarkerHeight)
				largestMarkerHeight = markers[m].pxpm->GetHeight();
			break;
		case SC_MARK_RGBAIMAGE:
			if (markers[m].image->GetHeight() > largestMarkerHeight)
				largestMarkerHeight = markers[m].image->GetHeight();
			break;
		}
	}
}

Added src/ViewStyle.h.









































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file ViewStyle.h
 ** Store information on how the document is to be viewed.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef VIEWSTYLE_H
#define VIEWSTYLE_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 */
class MarginStyle {
public:
	int style;
	int width;
	int mask;
	bool sensitive;
	int cursor;
	MarginStyle();
};

/**
 */
class FontNames {
private:
	char **names;
	int size;
	int max;

	// Private so FontNames objects can not be copied
	FontNames(const FontNames &);
public:
	FontNames();
	~FontNames();
	void Clear();
	const char *Save(const char *name);
};

class FontRealised : public FontSpecification, public FontMeasurements {
	// Private so FontRealised objects can not be copied
	FontRealised(const FontRealised &);
	FontRealised &operator=(const FontRealised &);
public:
	Font font;
	FontRealised *frNext;
	FontRealised(const FontSpecification &fs);
	virtual ~FontRealised();
	void Realise(Surface &surface, int zoomLevel, int technology);
	FontRealised *Find(const FontSpecification &fs);
	void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
};

enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};

enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};

/**
 */
class ViewStyle {
public:
	FontNames fontNames;
	FontRealised *frFirst;
	size_t stylesSize;
	Style *styles;
	size_t nextExtendedStyle;
	LineMarker markers[MARKER_MAX + 1];
	int largestMarkerHeight;
	Indicator indicators[INDIC_MAX + 1];
	int technology;
	int lineHeight;
	unsigned int maxAscent;
	unsigned int maxDescent;
	XYPOSITION aveCharWidth;
	XYPOSITION spaceWidth;
	bool selforeset;
	ColourDesired selforeground;
	ColourDesired selAdditionalForeground;
	bool selbackset;
	ColourDesired selbackground;
	ColourDesired selAdditionalBackground;
	ColourDesired selbackground2;
	int selAlpha;
	int selAdditionalAlpha;
	bool selEOLFilled;
	bool whitespaceForegroundSet;
	ColourDesired whitespaceForeground;
	bool whitespaceBackgroundSet;
	ColourDesired whitespaceBackground;
	ColourDesired selbar;
	ColourDesired selbarlight;
	bool foldmarginColourSet;
	ColourDesired foldmarginColour;
	bool foldmarginHighlightColourSet;
	ColourDesired foldmarginHighlightColour;
	bool hotspotForegroundSet;
	ColourDesired hotspotForeground;
	bool hotspotBackgroundSet;
	ColourDesired hotspotBackground;
	bool hotspotUnderline;
	bool hotspotSingleLine;
	/// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
	int leftMarginWidth;	///< Spacing margin on left of text
	int rightMarginWidth;	///< Spacing margin on right of text
	int maskInLine;	///< Mask for markers to be put into text because there is nowhere for them to go in margin
	MarginStyle ms[SC_MAX_MARGIN+1];
	int fixedColumnWidth;	///< Total width of margins
	bool marginInside;	///< true: margin included in text view, false: separate views
	int textStart;	///< Starting x position of text within the view
	int zoomLevel;
	WhiteSpaceVisibility viewWhitespace;
	int whitespaceSize;
	IndentView viewIndentationGuides;
	bool viewEOL;
	ColourDesired caretcolour;
	ColourDesired additionalCaretColour;
	bool showCaretLineBackground;
	bool alwaysShowCaretLineBackground;
	ColourDesired caretLineBackground;
	int caretLineAlpha;
	ColourDesired edgecolour;
	int edgeState;
	int caretStyle;
	int caretWidth;
	bool someStylesProtected;
	bool someStylesForceCase;
	int extraFontFlag;
	int extraAscent;
	int extraDescent;
	int marginStyleOffset;
	int annotationVisible;
	int annotationStyleOffset;
	bool braceHighlightIndicatorSet;
	int braceHighlightIndicator;
	bool braceBadLightIndicatorSet;
	int braceBadLightIndicator;

	ViewStyle();
	ViewStyle(const ViewStyle &source);
	~ViewStyle();
	void Init(size_t stylesSize_=64);
	void CreateFont(const FontSpecification &fs);
	void Refresh(Surface &surface);
	void AllocStyles(size_t sizeNew);
	void ReleaseAllExtendedStyles();
	int AllocateExtendedStyles(int numberStyles);
	void EnsureStyle(size_t index);
	void ResetDefaultStyle();
	void ClearStyles();
	void SetStyleFontName(int styleIndex, const char *name);
	bool ProtectionActive() const;
	bool ValidStyle(size_t styleIndex) const;
	void CalcLargestMarkerHeight();
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added src/XPM.cxx.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
// Scintilla source code edit control
/** @file XPM.cxx
 ** Define a class that holds data in the X Pixmap (XPM) format.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>
#include <stdlib.h>

#include <vector>
#include <map>

#include "Platform.h"

#include "XPM.h"

#ifdef _WIN32
#   define strcasecmp stricmp
#endif

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static const char *NextField(const char *s) {
	// In case there are leading spaces in the string
	while (*s && *s == ' ') {
		s++;
	}
	while (*s && *s != ' ') {
		s++;
	}
	while (*s && *s == ' ') {
		s++;
	}
	return s;
}

// Data lines in XPM can be terminated either with NUL or "
static size_t MeasureLength(const char *s) {
	size_t i = 0;
	while (s[i] && (s[i] != '\"'))
		i++;
	return i;
}

ColourDesired XPM::ColourDesiredFromCode(const std::string & ch) const {
    ColourCodeMap::const_iterator it = colourCodeTable.find(ch);
    ColourDesired *cd = it->second;
    return (cd ? *cd: ColourDesired(0xff, 0xff, 0xff));
}

ColourDesired XPM::ColourFromCode(const std::string &ch) const {
    ColourCodeMap::const_iterator it = colourCodeTable.find(ch);
    ColourDesired *cd = it->second;
    return (cd ? *cd: ColourDesired(0xff, 0xff, 0xff));
}

void XPM::FillRun(Surface *surface, const std::string &code, int startX, int y, int x) {
	if ((code.compare(*codeTransparent) != 0) && (startX != x)) {
		PRectangle rc(startX, y, x, y+1);
		surface->FillRectangle(rc, ColourFromCode(code));
	}
}

XPM::XPM(const char *textForm) :
	data(0), codeTransparent(NULL), codes(0), colours(0), lines(0) {
	Init(textForm);
}

XPM::XPM(const char *const *linesForm) :
	data(0), codeTransparent(NULL), codes(0), colours(0), lines(0) {
	Init(linesForm);
}

XPM::~XPM() {
	Clear();
}

void XPM::Init(const char *textForm) {
	Clear();
	// Test done is two parts to avoid possibility of overstepping the memory
	// if memcmp implemented strangely. Must be 4 bytes at least at destination.
	if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
		// Build the lines form out of the text form
		const char **linesForm = LinesFormFromTextForm(textForm);
		if (linesForm != 0) {
			Init(linesForm);
			delete []linesForm;
		}
	} else {
		// It is really in line form
		Init(reinterpret_cast<const char * const *>(textForm));
	}
}

void XPM::Init(const char *const *linesForm) {
	Clear();
	height = 1;
	width = 1;
	nColours = 1;
	data = NULL;
	codeTransparent = new std::string;
	codes = NULL;
	colours = NULL;
	lines = NULL;
	if (!linesForm)
		return;

	const char *line0 = linesForm[0];
	width = atoi(line0);
	line0 = NextField(line0);
	height = atoi(line0);
	line0 = NextField(line0);
	nColours = atoi(line0);
	line0 = NextField(line0);
	ncpp = atoi(line0);
	if (ncpp < 1 || 4 < ncpp) {
	     // Only 1-4 char per pixel is supported
	     return;
	}
	codes = new std::string[nColours];
	colours = new ColourDesired[nColours];

	int strings = 1+height+nColours;
	lines = new char *[strings];
	size_t allocation = 0;
	for (int i=0; i<strings; i++) {
		allocation += MeasureLength(linesForm[i]) + 1;
	}
	data = new char[allocation];
	char *nextBit = data;
	for (int j=0; j<strings; j++) {
		lines[j] = nextBit;
		size_t len = MeasureLength(linesForm[j]);
		memcpy(nextBit, linesForm[j], len);
		nextBit += len;
		*nextBit++ = '\0';
	}

	for (int c=0; c<nColours; c++) {
		const char *colourDef = lines[c+1];
		std::string *ch = new std::string(colourDef, 0, ncpp);
		codes[c] = *ch;
		colourDef += ncpp;
		while (*colourDef == ' ' && *colourDef != '\0') colourDef++;
		while (*colourDef != '\0') {
			 switch (*colourDef) {
			 case 'c':
				  colourDef += 2;
				  if (*colourDef == '#') {
					   colours[c].Set(colourDef);
				  } else if (strcasecmp(colourDef,"none")==0) {
					   colours[c] = ColourDesired(0xff, 0xff, 0xff);
					   codeTransparent = &codes[c];
				  } else {
					   // Symbolic name for color - not supported
					   // use white for now
					   colours[c] = ColourDesired(0xff, 0xff, 0xff);
				  }
				  break;
			 case 's':
				  // Skip symbolic name
			 case 'm':
				  // Skip monochrome spec
			 case 'g':
				  // Skip grayscale spec
				  while (*colourDef != ' ' && *colourDef != '\0') colourDef++;
				  while (*colourDef == ' ' && *colourDef != '\0') colourDef++;
				  break;
			 default:
				  // Unexpected key!
				  return;
			 }
			 while (*colourDef != ' ' && *colourDef != '\0') colourDef++;
			 while (*colourDef == ' ' && *colourDef != '\0') colourDef++;
		}
		colourCodeTable[codes[c]] = &(colours[c]);
	}
}

void XPM::Clear() {
	delete []data;
	data = 0;
	delete []codes;
	codes = 0;
	delete []colours;
	colours = 0;
	delete []lines;
	lines = 0;
}

void XPM::Draw(Surface *surface, PRectangle &rc) {
	if (!data || !codes || !colours || !lines) {
		return;
	}
	// Centre the pixmap
	int startY = rc.top + (rc.Height() - height) / 2;
	int startX = rc.left + (rc.Width() - width) / 2;
	for (int y=0; y<height; y++) {
		char prevCode[5] = {'\0','\0','\0','\0','\0'};
		int xStartRun = 0;
		for (int x=0; x<width; x++) {
			char code[5];
			strncpy(code, &lines[y+nColours+1][(x*ncpp)], ncpp);
			code[ncpp] = '\0';
			if (strcmp(code, prevCode) != 0) {
				FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x);
				xStartRun = x;
				strcpy(prevCode, code);
			}
		}
		FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + width);
	}
}

void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const {
	if (!data || !codes || !colours || !lines || (x<0) || (x >= width) || (y<0) || (y >= height)) {
		colour = 0;
		transparent = true;
		return;
	}
	std::string const code(&lines[y+nColours+1][x],0,ncpp);
	transparent = (code.compare(*codeTransparent) == 0);
	if (transparent) {
		colour = 0;
	} else {
		colour = ColourDesiredFromCode(code).AsLong();
	}
}

const char **XPM::LinesFormFromTextForm(const char *textForm) {
	// Build the lines form out of the text form
	const char **linesForm = 0;
	int countQuotes = 0;
	int strings=1;
	int j=0;
	for (; countQuotes < (2*strings) && textForm[j] != '\0'; j++) {
		if (textForm[j] == '\"') {
			if (countQuotes == 0) {
				// First field: width, height, number of colors, chars per pixel
				const char *line0 = textForm + j + 1;
				// Skip width
				line0 = NextField(line0);
				// Add 1 line for each pixel of height
				strings += atoi(line0);
				line0 = NextField(line0);
				// Add 1 line for each colour
				strings += atoi(line0);
				linesForm = new const char *[strings];
				if (linesForm == 0) {
					break;	// Memory error!
				}
			}
			if (countQuotes / 2 >= strings) {
				break;	// Bad height or number of colors!
			}
			if ((countQuotes & 1) == 0) {
				linesForm[countQuotes / 2] = textForm + j + 1;
			}
			countQuotes++;
		}
	}
	if (textForm[j] == '\0' || countQuotes / 2 > strings) {
		// Malformed XPM! Height + number of colors too high or too low
		delete []linesForm;
		linesForm = 0;
	}
	return linesForm;
}

// In future, may want to minimize search time by sorting and using a binary search.

XPMSet::XPMSet() : set(0), len(0), maximum(0), height(-1), width(-1) {
}

XPMSet::~XPMSet() {
	Clear();
}

void XPMSet::Clear() {
	for (int i = 0; i < len; i++) {
		delete set[i];
	}
	delete []set;
	set = 0;
	len = 0;
	maximum = 0;
	height = -1;
	width = -1;
}

void XPMSet::Add(int ident, const char *textForm) {
	// Invalidate cached dimensions
	height = -1;
	width = -1;

	// Replace if this id already present
	for (int i = 0; i < len; i++) {
		if (set[i]->GetId() == ident) {
			set[i]->Init(textForm);
			return;
		}
	}

	// Not present, so add to end
	XPM *pxpm = new XPM(textForm);
	if (pxpm) {
		pxpm->SetId(ident);
		if (len == maximum) {
			maximum += 64;
			XPM **setNew = new XPM *[maximum];
			for (int i = 0; i < len; i++) {
				setNew[i] = set[i];
			}
			delete []set;
			set = setNew;
		}
		set[len] = pxpm;
		len++;
	}
}

XPM *XPMSet::Get(int ident) {
	for (int i = 0; i < len; i++) {
		if (set[i]->GetId() == ident) {
			return set[i];
		}
	}
	return 0;
}

int XPMSet::GetHeight() {
	if (height < 0) {
		for (int i = 0; i < len; i++) {
			if (height < set[i]->GetHeight()) {
				height = set[i]->GetHeight();
			}
		}
	}
	return (height > 0) ? height : 0;
}

int XPMSet::GetWidth() {
	if (width < 0) {
		for (int i = 0; i < len; i++) {
			if (width < set[i]->GetWidth()) {
				width = set[i]->GetWidth();
			}
		}
	}
	return (width > 0) ? width : 0;
}

RGBAImage::RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_) :
	height(height_), width(width_), scale(scale_) {
	if (pixels_) {
		pixelBytes.assign(pixels_, pixels_ + CountBytes());
	} else {
		pixelBytes.resize(CountBytes());
	}
}

RGBAImage::RGBAImage(const XPM &xpm) {
	height = xpm.GetHeight();
	width = xpm.GetWidth();
	scale = 1;
	pixelBytes.resize(CountBytes());
	for (int y=0; y<height; y++) {
		for (int x=0; x<width; x++) {
			ColourDesired colour;
			bool transparent = false;
			xpm.PixelAt(x, y, colour, transparent);
			SetPixel(x, y, colour, transparent ? 0 : 255);
		}
	}
}

RGBAImage::~RGBAImage() {
}

int RGBAImage::CountBytes() const {
	return width * height * 4;
}

const unsigned char *RGBAImage::Pixels() const {
	return &pixelBytes[0];
}

void RGBAImage::SetPixel(int x, int y, ColourDesired colour, int alpha) {
	unsigned char *pixel = &pixelBytes[0] + (y*width+x) * 4;
	// RGBA
	pixel[0] = static_cast<unsigned char>(colour.GetRed());
	pixel[1] = static_cast<unsigned char>(colour.GetGreen());
	pixel[2] = static_cast<unsigned char>(colour.GetBlue());
	pixel[3] = static_cast<unsigned char>(alpha);
}

RGBAImageSet::RGBAImageSet() : height(-1), width(-1){
}

RGBAImageSet::~RGBAImageSet() {
	Clear();
}

/// Remove all images.
void RGBAImageSet::Clear() {
	for (ImageMap::iterator it=images.begin(); it != images.end(); ++it) {
		delete it->second;
		it->second = 0;
	}
	images.clear();
	height = -1;
	width = -1;
}

/// Add an image.
void RGBAImageSet::Add(int ident, RGBAImage *image) {
	ImageMap::iterator it=images.find(ident);
	if (it == images.end()) {
		images[ident] = image;
	} else {
		delete it->second;
		it->second = image;
	}
	height = -1;
	width = -1;
}

/// Get image by id.
RGBAImage *RGBAImageSet::Get(int ident) {
	ImageMap::iterator it = images.find(ident);
	if (it != images.end()) {
		return it->second;
	}
	return NULL;
}

/// Give the largest height of the set.
int RGBAImageSet::GetHeight() const {
	if (height < 0) {
		for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
			if (height < it->second->GetHeight()) {
				height = it->second->GetHeight();
			}
		}
	}
	return (height > 0) ? height : 0;
}

/// Give the largest width of the set.
int RGBAImageSet::GetWidth() const {
	if (width < 0) {
		for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
			if (width < it->second->GetWidth()) {
				width = it->second->GetWidth();
			}
		}
	}
	return (width > 0) ? width : 0;
}

Added src/XPM.h.





































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
/** @file XPM.h
 ** Define a class that holds data in the X Pixmap (XPM) format.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef XPM_H
#define XPM_H

#include <string>

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 * Hold a pixmap in XPM format.
 */
class XPM {
	int pid;		// Assigned by container
	int height;
	int width;
	int nColours;
	int ncpp;
	char *data;
	std::string *codeTransparent;
	std::string *codes;
	ColourDesired *colours;
	ColourDesired ColourDesiredFromCode(const std::string &ch) const;
	ColourDesired ColourFromCode(const std::string &ch) const;
	void FillRun(Surface *surface, const std::string &code, int startX, int y, int x);
	char **lines;
	typedef std::map<std::string, ColourDesired*> ColourCodeMap;
	ColourCodeMap colourCodeTable;
public:
	XPM(const char *textForm);
	XPM(const char *const *linesForm);
	~XPM();
	void Init(const char *textForm);
	void Init(const char *const *linesForm);
	void Clear();
	/// Decompose image into runs and use FillRectangle for each run
	void Draw(Surface *surface, PRectangle &rc);
	char **InLinesForm() { return lines; }
	void SetId(int pid_) { pid = pid_; }
	int GetId() const { return pid; }
	int GetHeight() const { return height; }
	int GetWidth() const { return width; }
	void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const;
	static const char **LinesFormFromTextForm(const char *textForm);
};

/**
 * A collection of pixmaps indexed by integer id.
 */
class XPMSet {
	XPM **set;	///< The stored XPMs.
	int len;	///< Current number of XPMs.
	int maximum;	///< Current maximum number of XPMs, increased by steps if reached.
	int height;	///< Memorize largest height of the set.
	int width;	///< Memorize largest width of the set.
public:
	XPMSet();
	~XPMSet();
	/// Remove all XPMs.
	void Clear();
	/// Add a XPM.
	void Add(int ident, const char *textForm);
	/// Get XPM by id.
	XPM *Get(int ident);
	/// Give the largest height of the set.
	int GetHeight();
	/// Give the largest width of the set.
	int GetWidth();
};

/**
 * An translucent image stoed as a sequence of RGBA bytes.
 */
class RGBAImage {
	// Private so RGBAImage objects can not be copied
	RGBAImage(const RGBAImage &);
	RGBAImage &operator=(const RGBAImage &);
	int height;
	int width;
	float scale;
	std::vector<unsigned char> pixelBytes;
public:
	RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_);
	RGBAImage(const XPM &xpm);
	virtual ~RGBAImage();
	int GetHeight() const { return height; }
	int GetWidth() const { return width; }
	float GetScale() const { return scale; }
	float GetScaledHeight() const { return height / scale; }
	float GetScaledWidth() const { return width / scale; }
	int CountBytes() const;
	const unsigned char *Pixels() const;
	void SetPixel(int x, int y, ColourDesired colour, int alpha=0xff); 
};

/**
 * A collection of RGBAImage pixmaps indexed by integer id.
 */
class RGBAImageSet {
	typedef std::map<int, RGBAImage*> ImageMap;
	ImageMap images;
	mutable int height;	///< Memorize largest height of the set.
	mutable int width;	///< Memorize largest width of the set.
public:
	RGBAImageSet();
	~RGBAImageSet();
	/// Remove all images.
	void Clear();
	/// Add an image.
	void Add(int ident, RGBAImage *image);
	/// Get image by id.
	RGBAImage *Get(int ident);
	/// Give the largest height of the set.
	int GetHeight() const;
	/// Give the largest width of the set.
	int GetWidth() const;
};

#ifdef SCI_NAMESPACE
}
#endif

#endif

Added test/MessageNumbers.py.































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# List many windows message numbers

msgs = {
"WM_ACTIVATE":6,
"WM_ACTIVATEAPP":28,
"WM_CAPTURECHANGED":533,
"WM_CHAR":258,
"WM_CLOSE":16,
"WM_CREATE":1,
"WM_COMMAND":273,
"WM_DESTROY":2,
"WM_ENTERSIZEMOVE":561,
"WM_ERASEBKGND":20,
"WM_EXITSIZEMOVE":562,
"WM_GETMINMAXINFO":36,
"WM_GETTEXT":13,
"WM_IME_SETCONTEXT":0x0281,
"WM_IME_NOTIFY":0x0282,
"WM_KEYDOWN":256,
"WM_KEYUP":257,
"WM_KILLFOCUS":8,
"WM_LBUTTONDOWN":513,
"WM_LBUTTONUP":514,
"WM_MBUTTONDOWN":519,
"WM_MBUTTONUP":520,
"WM_MBUTTONDBLCLK":521,
"WM_MOUSEACTIVATE":33,
"WM_MOUSEMOVE":512,
"WM_MOVE":3,
"WM_MOVING":534,
"WM_NCACTIVATE":134,
"WM_NCCALCSIZE":131,
"WM_NCCREATE":129,
"WM_NCDESTROY":130,
"WM_NCHITTEST":132,
"WM_NCLBUTTONDBLCLK":163,
"WM_NCLBUTTONDOWN":161,
"WM_NCLBUTTONUP":162,
"WM_NCMOUSEMOVE":160,
"WM_NCPAINT":133,
"WM_PAINT":15,
"WM_PARENTNOTIFY":528,
"WM_SETCURSOR":32,
"WM_SETFOCUS":7,
"WM_SETFONT":48,
"WM_SETTEXT":12,
"WM_SHOWWINDOW":24,
"WM_SIZE":5,
"WM_SIZING":532,
"WM_SYNCPAINT":136,
"WM_SYSCOMMAND":274,
"WM_SYSKEYDOWN":260,
"WM_TIMER":275,
"WM_USER":1024,
"WM_USER+1":1025,
"WM_WINDOWPOSCHANGED":71,
"WM_WINDOWPOSCHANGING":70,
}

sgsm={}
for k,v in msgs.items():
	sgsm[v] = k

Added test/README.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
The test directory contains some unit and performance tests for Scintilla.

The tests can only be run on Windows using Python 2.7 or 3.x. Running on another platform
would require writing a file similar to XiteWin.py for that platform. Python 2.7+ is required 
because the bytes string type and literals are available.

A test application is in xite.py and this can be run to experiment:
pythonw xite.py

To run the basic tests:
pythonw simpleTests.py

There are some lexing tests with simple input files in several languages in the examples 
subdirectory and their expected lexed states in *.styled where the start of each style 
is marked with {styleNumber}, for example:
{15}<%@{16}language=javas{15}%>{0}

To run the lexing tests:
pythonw lexTests.py

To check for performance regressions:
pythonw performanceTests.py
While each test run will be different and the timer has only limited granularity, some results
from a 2 GHz Athlon with a DEBUG build are:
 0.187 testAddLine
. 0.203 testAddLineMiddle
. 0.171 testHuge
. 0.203 testHugeInserts
. 0.312 testHugeReplace
.

Added test/XiteMenu.py.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# -*- coding: utf-8 -*-

from __future__ import unicode_literals

""" Define the menu structure used by the Pentacle applications """

MenuStructure = [
	["&File", [
		["&New", "<control>N"],
		["&Open...", "<control>O"],
		["&Save", "<control>S"],
		["Save &As...", "<control><shift>S"],
		["Test", ""],
		["Exercised", ""],
		["Uncalled", ""],
		["-", ""],
		["&Exit", ""]]],
	[ "&Edit", [
		["&Undo", "<control>Z"],
		["&Redo", "<control>Y"],
		["-", ""],
		["Cu&t", "<control>X"],
		["&Copy", "<control>C"],
		["&Paste", "<control>V"],
		["&Delete", "Del"],
		["Select &All", "<control>A"],
		]],
]

Added test/XiteWin.py.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
# -*- coding: utf-8 -*-

from __future__ import with_statement
from __future__ import unicode_literals

import os, sys, unittest

import ctypes
from ctypes import wintypes
from ctypes import c_int, c_ulong, c_char_p, c_wchar_p, c_ushort
user32=ctypes.windll.user32
gdi32=ctypes.windll.gdi32
kernel32=ctypes.windll.kernel32
from MessageNumbers import msgs, sgsm

import XiteMenu

scintillaDirectory = ".."
scintillaIncludeDirectory = os.path.join(scintillaDirectory, "include")
sys.path.append(scintillaIncludeDirectory)
import Face

scintillaBinDirectory = os.path.join(scintillaDirectory, "bin")
os.environ['PATH'] = os.environ['PATH']  + ";" + scintillaBinDirectory
#print(os.environ['PATH'])

WFUNC = ctypes.WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)

WS_CHILD = 0x40000000
WS_CLIPCHILDREN = 0x2000000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_VISIBLE = 0x10000000
WS_HSCROLL = 0x100000
WS_VSCROLL = 0x200000
WA_INACTIVE = 0
MF_POPUP = 16
MF_SEPARATOR = 0x800
IDYES = 6
OFN_HIDEREADONLY = 4
MB_OK = 0
MB_YESNOCANCEL = 3
MF_CHECKED = 8
MF_UNCHECKED = 0
SW_SHOW = 5
PM_REMOVE = 1

VK_SHIFT = 16
VK_CONTROL = 17
VK_MENU = 18

class OPENFILENAME(ctypes.Structure):
	_fields_ = (("lStructSize", c_int),
		("hwndOwner", c_int),
		("hInstance", c_int),
		("lpstrFilter", c_wchar_p),
		("lpstrCustomFilter", c_char_p),
		("nMaxCustFilter", c_int),
		("nFilterIndex", c_int),
		("lpstrFile", c_wchar_p),
		("nMaxFile", c_int),
		("lpstrFileTitle", c_wchar_p),
		("nMaxFileTitle", c_int),
		("lpstrInitialDir", c_wchar_p),
		("lpstrTitle", c_wchar_p),
		("flags", c_int),
		("nFileOffset", c_ushort),
		("nFileExtension", c_ushort),
		("lpstrDefExt", c_char_p),
		("lCustData", c_int),
		("lpfnHook", c_char_p),
		("lpTemplateName", c_char_p),
		("pvReserved", c_char_p),
		("dwReserved", c_int),
		("flagsEx", c_int))

	def __init__(self, win, title):
		ctypes.Structure.__init__(self)
		self.lStructSize = ctypes.sizeof(OPENFILENAME)
		self.nMaxFile = 1024
		self.hwndOwner = win
		self.lpstrTitle = title
		self.Flags = OFN_HIDEREADONLY

trace = False
#~ trace = True

def WindowSize(w):
	rc = ctypes.wintypes.RECT()
	user32.GetClientRect(w, ctypes.byref(rc))
	return rc.right - rc.left, rc.bottom - rc.top

def IsKeyDown(key):
	return (user32.GetKeyState(key) & 0x8000) != 0

def KeyTranslate(w):
	tr = { 9: "Tab", 0xD:"Enter", 0x1B: "Esc" }
	if w in tr:
		return tr[w]
	elif ord("A") <= w <= ord("Z"):
		return chr(w)
	elif 0x70 <= w <= 0x7b:
		return "F" + str(w-0x70+1)
	else:
		return "Unknown_" + hex(w)

class WNDCLASS(ctypes.Structure):
	_fields_= (\
		('style', c_int),
		('lpfnWndProc', WFUNC),
		('cls_extra', c_int),
		('wnd_extra', c_int),
		('hInst', c_int),
		('hIcon', c_int),
		('hCursor', c_int),
		('hbrBackground', c_int),
		('menu_name', c_wchar_p),
		('lpzClassName', c_wchar_p),
	)

class XTEXTRANGE(ctypes.Structure):
	_fields_= (\
		('cpMin', c_int),
		('cpMax', c_int),
		('lpstrText', c_char_p),
	)

class TEXTRANGE(ctypes.Structure):
	_fields_= (\
		('cpMin', c_int),
		('cpMax', c_int),
		('lpstrText', ctypes.POINTER(ctypes.c_char)),
	)

class FINDTEXT(ctypes.Structure):
	_fields_= (\
		('cpMin', c_int),
		('cpMax', c_int),
		('lpstrText', c_char_p),
		('cpMinText', c_int),
		('cpMaxText', c_int),
	)

hinst = ctypes.windll.kernel32.GetModuleHandleW(0)

def RegisterClass(name, func, background = 0):
	# register a window class for toplevel windows.
	wc = WNDCLASS()
	wc.style = 0
	wc.lpfnWndProc = func
	wc.cls_extra = 0
	wc.wnd_extra = 0
	wc.hInst = hinst
	wc.hIcon = 0
	wc.hCursor = 0
	wc.hbrBackground = background
	wc.menu_name = 0
	wc.lpzClassName = name
	user32.RegisterClassW(ctypes.byref(wc))

class SciCall:
	def __init__(self, fn, ptr, msg):
		self._fn = fn
		self._ptr = ptr
		self._msg = msg
	def __call__(self, w=0, l=0):
		return self._fn(self._ptr, self._msg, w, l)

class Scintilla:
	def __init__(self, face, hwndParent, hinstance):
		self.__dict__["face"] = face
		self.__dict__["used"] = set()
		self.__dict__["all"] = set()
		# The k member is for accessing constants as a dictionary
		self.__dict__["k"] = {}
		for f in face.features:
			self.all.add(f)
			if face.features[f]["FeatureType"] == "val":
				self.k[f] = int(self.face.features[f]["Value"], 0)
			elif face.features[f]["FeatureType"] == "evt":
				self.k["SCN_"+f] = int(self.face.features[f]["Value"], 0)
		# Get the function first as that also loads the DLL
		self.__dict__["_scifn"] = ctypes.windll.SciLexer.Scintilla_DirectFunction
		self.__dict__["_hwnd"] = user32.CreateWindowExW(0,
			"Scintilla", "Source",
			WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,
			0, 0, 100, 100, hwndParent, 0, hinstance, 0)
		self.__dict__["_sciptr"] = user32.SendMessageW(self._hwnd,
			int(self.face.features["GetDirectPointer"]["Value"], 0), 0,0)
		user32.ShowWindow(self._hwnd, SW_SHOW)
	def __getattr__(self, name):
		if name in self.face.features:
			self.used.add(name)
			feature = self.face.features[name]
			value = int(feature["Value"], 0)
			#~ print("Feature", name, feature)
			if feature["FeatureType"] == "val":
				self.__dict__[name] = value
				return value
			else:
				return SciCall(self._scifn, self._sciptr, value)
		elif ("Get" + name) in self.face.features:
			self.used.add("Get" + name)
			feature = self.face.features["Get" + name]
			value = int(feature["Value"], 0)
			if feature["FeatureType"] == "get" and \
				not name.startswith("Get") and \
				not feature["Param1Type"] and \
				not feature["Param2Type"] and \
				feature["ReturnType"] in ["bool", "int", "position"]:
				#~ print("property", feature)
				return self._scifn(self._sciptr, value, 0, 0)
		elif name.startswith("SCN_") and name in self.k:
			self.used.add(name)
			feature = self.face.features[name[4:]]
			value = int(feature["Value"], 0)
			#~ print("Feature", name, feature)
			if feature["FeatureType"] == "val":
				return value
		raise AttributeError(name)
	def __setattr__(self, name, val):
		if ("Set" + name) in self.face.features:
			self.used.add("Set" + name)
			feature = self.face.features["Set" + name]
			value = int(feature["Value"], 0)
			#~ print("setproperty", feature)
			if feature["FeatureType"] == "set" and not name.startswith("Set"):
				if feature["Param1Type"] in ["bool", "int", "position"]:
					return self._scifn(self._sciptr, value, val, 0)
				elif feature["Param2Type"] in ["string"]:
					return self._scifn(self._sciptr, value, 0, val)
				raise AttributeError(name)
		raise AttributeError(name)
	def getvalue(self, name):
		if name in self.face.features:
			feature = self.face.features[name]
			if feature["FeatureType"] != "evt":
				try:
					return int(feature["Value"], 0)
				except ValueError:
					return -1
		return -1


	def ByteRange(self, start, end):
		tr = TEXTRANGE()
		tr.cpMin = start
		tr.cpMax = end
		length = end - start
		tr.lpstrText = ctypes.create_string_buffer(length + 1)
		self.GetTextRange(0, ctypes.byref(tr))
		text = tr.lpstrText[:length]
		text += b"\0" * (length - len(text))
		return text
	def StyledTextRange(self, start, end):
		tr = TEXTRANGE()
		tr.cpMin = start
		tr.cpMax = end
		length = 2 * (end - start)
		tr.lpstrText = ctypes.create_string_buffer(length + 2)
		self.GetStyledText(0, ctypes.byref(tr))
		styledText = tr.lpstrText[:length]
		styledText += b"\0" * (length - len(styledText))
		return styledText
	def FindBytes(self, start, end, s, flags):
		ft = FINDTEXT()
		ft.cpMin = start
		ft.cpMax = end
		ft.lpstrText = s
		ft.cpMinText = 0
		ft.cpMaxText = 0
		pos = self.FindText(flags, ctypes.byref(ft))
		#~ print(start, end, ft.cpMinText, ft.cpMaxText)
		return pos

	def Contents(self):
		return self.ByteRange(0, self.Length)
	def SizeTo(self, width, height):
		user32.SetWindowPos(self._hwnd, 0, 0, 0, width, height, 0)
	def FocusOn(self):
		user32.SetFocus(self._hwnd)

class XiteWin():
	def __init__(self, test=""):
		self.face = Face.Face()
		self.face.ReadFromFile(os.path.join(scintillaIncludeDirectory, "Scintilla.iface"))

		self.titleDirty = True
		self.fullPath = ""
		self.test = test

		self.appName = "xite"

		self.cmds = {}
		self.windowName = "XiteWindow"
		self.wfunc = WFUNC(self.WndProc)
		RegisterClass(self.windowName, self.wfunc)
		user32.CreateWindowExW(0, self.windowName, self.appName, \
			WS_VISIBLE | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, \
			0, 0, 500, 700, 0, 0, hinst, 0)

		args = sys.argv[1:]
		self.SetMenus()
		if args:
			self.GrabFile(args[0])
			self.ed.FocusOn()
			self.ed.GotoPos(self.ed.Length)

		if self.test:
			print(self.test)
			for k in self.cmds:
				if self.cmds[k] == "Test":
					user32.PostMessageW(self.win, msgs["WM_COMMAND"], k, 0)

	def OnSize(self):
		width, height = WindowSize(self.win)
		self.ed.SizeTo(width, height)
		user32.InvalidateRect(self.win, 0, 0)

	def OnCreate(self, hwnd):
		self.win = hwnd
		self.ed = Scintilla(self.face, hwnd, hinst)
		self.ed.FocusOn()


	def Invalidate(self):
		user32.InvalidateRect(self.win, 0, 0)

	def WndProc(self, h, m, w, l):
		ms = sgsm.get(m, "XXX")
		if trace:
			print("%s %s %s %s" % (hex(h)[2:],ms,w,l))
		if ms == "WM_CLOSE":
			user32.PostQuitMessage(0)
		elif ms == "WM_CREATE":
			self.OnCreate(h)
			return 0
		elif ms == "WM_SIZE":
			# Work out size
			if w != 1:
				self.OnSize()
			return 0
		elif ms == "WM_COMMAND":
			cmdCode = w & 0xffff
			if cmdCode in self.cmds:
				self.Command(self.cmds[cmdCode])
			return 0
		elif ms == "WM_ACTIVATE":
			if w != WA_INACTIVE:
				self.ed.FocusOn()
			return 0
		else:
			return user32.DefWindowProcW(h, m, w, l)
		return 0

	def Command(self, name):
		name = name.replace(" ", "")
		method = "Cmd" + name
		cmd = None
		try:
			cmd = getattr(self, method)
		except AttributeError:
			return
		if cmd:
			cmd()

	def KeyDown(self, w, prefix = ""):
		keyName = prefix
		if IsKeyDown(VK_CONTROL):
			keyName += "<control>"
		if IsKeyDown(VK_SHIFT):
			keyName += "<shift>"
		keyName += KeyTranslate(w)
		if trace:
			print("Key:", keyName)
		if keyName in self.keys:
			method = "Cmd" + self.keys[keyName]
			getattr(self, method)()
			return True
		#~ print("UKey:", keyName)
		return False

	def Accelerator(self, msg):
		ms = sgsm.get(msg.message, "XXX")
		if ms == "WM_KEYDOWN":
			return self.KeyDown(msg.wParam)
		elif ms == "WM_SYSKEYDOWN":
			return self.KeyDown(msg.wParam, "<alt>")
		return False

	def AppLoop(self):
		msg = ctypes.wintypes.MSG()
		lpmsg = ctypes.byref(msg)
		while user32.GetMessageW(lpmsg, 0, 0, 0):
			if trace and msg.message != msgs["WM_TIMER"]:
				print('mm', hex(msg.hWnd)[2:],sgsm.get(msg.message, "XXX"))
			if not self.Accelerator(msg):
				user32.TranslateMessage(lpmsg)
				user32.DispatchMessageW(lpmsg)

	def DoEvents(self):
		msg = ctypes.wintypes.MSG()
		lpmsg = ctypes.byref(msg)
		cont = True
		while cont:
			cont = user32.PeekMessageW(lpmsg, 0, 0, 0, PM_REMOVE)
			if cont:
				if not self.Accelerator(msg):
					user32.TranslateMessage(lpmsg)
					user32.DispatchMessageW(lpmsg)

	def SetTitle(self, changePath):
		if changePath or self.titleDirty != self.ed.Modify:
			self.titleDirty = self.ed.Modify
			self.title = self.fullPath
			if self.titleDirty:
				self.title += " * "
			else:
				self.title += " - "
			self.title += self.appName
			if self.win:
				user32.SetWindowTextW(self.win, self.title)

	def Open(self):
		ofx = OPENFILENAME(self.win, "Open File")
		opath = "\0" * 1024
		ofx.lpstrFile = opath
		filters = ["Python (.py;.pyw)|*.py;*.pyw|All|*.*"]
		filterText = "\0".join([f.replace("|", "\0") for f in filters])+"\0\0"
		ofx.lpstrFilter = filterText
		if ctypes.windll.comdlg32.GetOpenFileNameW(ctypes.byref(ofx)):
			absPath = opath.replace("\0", "")
			self.GrabFile(absPath)
			self.ed.FocusOn()
			self.ed.LexerLanguage = "python"
			self.ed.Lexer = self.ed.SCLEX_PYTHON
			self.ed.SetKeyWords(0, b"class def else for from if import print return while")
			for style in [k for k in self.ed.k if k.startswith("SCE_P_")]:
				self.ed.StyleSetFont(self.ed.k[style], b"Verdana")
				if "COMMENT" in style:
					self.ed.StyleSetFore(self.ed.k[style], 127 * 256)
					self.ed.StyleSetFont(self.ed.k[style], b"Comic Sans MS")
				elif "OPERATOR" in style:
					self.ed.StyleSetBold(self.ed.k[style], 1)
					self.ed.StyleSetFore(self.ed.k[style], 127 * 256 * 256)
				elif "WORD" in style:
					self.ed.StyleSetItalic(self.ed.k[style], 255)
					self.ed.StyleSetFore(self.ed.k[style], 255 * 256 * 256)
				elif "TRIPLE" in style:
					self.ed.StyleSetFore(self.ed.k[style], 0xA0A0)
				elif "STRING" in style or "CHARACTER" in style:
					self.ed.StyleSetFore(self.ed.k[style], 0xA000A0)
				else:
					self.ed.StyleSetFore(self.ed.k[style], 0)

	def SaveAs(self):
		ofx = OPENFILENAME(self.win, "Save File")
		opath = "\0" * 1024
		ofx.lpstrFile = opath
		if ctypes.windll.comdlg32.GetSaveFileNameW(ctypes.byref(ofx)):
			self.fullPath = opath.replace("\0", "")
			self.Save()
			self.SetTitle(1)
			self.ed.FocusOn()

	def SetMenus(self):
		ui = XiteMenu.MenuStructure
		self.cmds = {}
		self.keys = {}

		cmdId = 0
		self.menuBar = user32.CreateMenu()
		for name, contents in ui:
			cmdId += 1
			menu = user32.CreateMenu()
			for item in contents:
				text, key = item
				cmdText = text.replace("&", "")
				cmdText = cmdText.replace("...", "")
				cmdText = cmdText.replace(" ", "")
				cmdId += 1
				if key:
					keyText = key.replace("<control>", "Ctrl+")
					keyText = keyText.replace("<shift>", "Shift+")
					text += "\t" + keyText
				if text == "-":
					user32.AppendMenuW(menu, MF_SEPARATOR, cmdId, text)
				else:
					user32.AppendMenuW(menu, 0, cmdId, text)
				self.cmds[cmdId] = cmdText
				self.keys[key] = cmdText
				#~ print(cmdId, item)
			user32.AppendMenuW(self.menuBar, MF_POPUP, menu, name)
		user32.SetMenu(self.win, self.menuBar)
		self.CheckMenuItem("Wrap", True)
		user32.ShowWindow(self.win, SW_SHOW)

	def CheckMenuItem(self, name, val):
		#~ print(name, val)
		if self.cmds:
			for k,v in self.cmds.items():
				if v == name:
					#~ print(name, k)
					user32.CheckMenuItem(user32.GetMenu(self.win), \
						k, [MF_UNCHECKED, MF_CHECKED][val])

	def Exit(self):
		sys.exit(0)

	def DisplayMessage(self, msg, ask):
		return IDYES == user32.MessageBoxW(self.win, \
			msg, self.appName, [MB_OK, MB_YESNOCANCEL][ask])

	def NewDocument(self):
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.ed.SetSavePoint()

	def SaveIfUnsure(self):
		if self.ed.Modify:
			msg = "Save changes to \"" + self.fullPath + "\"?"
			print(msg)
			decision = self.DisplayMessage(msg, True)
			if decision:
				self.CmdSave()
			return decision
		return True

	def New(self):
		if self.SaveIfUnsure():
			self.fullPath = ""
			self.overrideMode = None
			self.NewDocument()
			self.SetTitle(1)
		self.Invalidate()

	def CheckMenus(self):
		pass

	def MoveSelection(self, caret, anchor=-1):
		if anchor == -1:
			anchor = caret
		self.ed.SetSelectionStart(caret)
		self.ed.SetSelectionEnd(anchor)
		self.ed.ScrollCaret()
		self.Invalidate()

	def GrabFile(self, name):
		self.fullPath = name
		self.overrideMode = None
		self.NewDocument()
		fsr = open(name, "rb")
		data = fsr.read()
		fsr.close()
		self.ed.AddText(len(data), data)
		self.ed.EmptyUndoBuffer()
		self.MoveSelection(0)
		self.SetTitle(1)

	def Save(self):
		fos = open(self.fullPath, "wb")
		blockSize = 1024
		length = self.ed.Length
		i = 0
		while i < length:
			grabSize = length - i
			if grabSize > blockSize:
				grabSize = blockSize
			#~ print(i, grabSize, length)
			data = self.ed.ByteRange(i, i + grabSize)
			fos.write(data)
			i += grabSize
		fos.close()
		self.ed.SetSavePoint()
		self.SetTitle(0)

	# Command handlers are called by menu actions

	def CmdNew(self):
		self.New()

	def CmdOpen(self):
		self.Open()

	def CmdSave(self):
		if (self.fullPath == None) or (len(self.fullPath) == 0):
			self.SaveAs()
		else:
			self.Save()

	def CmdSaveAs(self):
		self.SaveAs()

	def CmdTest(self):
		runner = unittest.TextTestRunner()
		if self.test:
			tests = unittest.defaultTestLoader.loadTestsFromName(self.test)
		else:
			tests = unittest.defaultTestLoader.loadTestsFromName("simpleTests")
		results = runner.run(tests)
		#~ print(results)
		if self.test:
			user32.PostQuitMessage(0)

	def CmdExercised(self):
		print()
		unused = sorted(self.ed.all.difference(self.ed.used))
		print("Unused", len(unused))
		print()
		print("\n".join(unused))
		print()
		print("Used", len(self.ed.used))
		print()
		print("\n".join(sorted(self.ed.used)))

	def Uncalled(self):
		print("")
		unused = sorted(self.ed.all.difference(self.ed.used))
		uu = {}
		for u in unused:
			v = self.ed.getvalue(u)
			if v > 2000:
				uu[v] = u
		#~ for x in sorted(uu.keys())[150:]:
		return uu

	def CmdExit(self):
		self.Exit()

	def CmdUndo(self):
		self.ed.Undo()

	def CmdRedo(self):
		self.ed.Redo()

	def CmdCut(self):
		self.ed.Cut()

	def CmdCopy(self):
		self.ed.Copy()

	def CmdPaste(self):
		self.ed.Paste()

	def CmdDelete(self):
		self.ed.Clear()

xiteFrame = None

def main(test):
	global xiteFrame
	xiteFrame = XiteWin(test)
	xiteFrame.AppLoop()
	#~ xiteFrame.CmdExercised()
	return xiteFrame.Uncalled()

Added test/examples/x.asp.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
<%@language=javas%>
<% 
#include 
function x() {
}
%>
<%@language=vbscript%>
<% 
sub x 'comment 
%>
<head>
<body></body>

Added test/examples/x.asp.styled.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
{15}<%@{16}language=javas{15}%>{0}
{15}<%{56} 
#{61}include{56} 
{62}function{56} {61}x{65}(){56} {65}{{56}
{65}}{56}
{15}%>{0}
{15}<%@{16}language=vbscript{15}%>{0}
{15}<%{81} 
{84}sub{81} {86}x{81} {82}'comment {81}
{15}%>{0}
{1}<head>{0}
{1}<body></body>{0}

Added test/examples/x.cxx.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// A demonstration program
#include <stdio.h>
#if 0 /* */
#define DUMMY() \
	if (1);
#endif

#define M\

\
 
int main() {
	double x[] = {3.14159,6.02e23,1.6e-19,1.0+1};
	int y[] = {75,0113,0x4b};
	printf("hello world %d %g\n", y[0], x[0]);
}

Added test/examples/x.cxx.styled.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{2}// A demonstration program
{9}#include <stdio.h>
#if 0 {23}/* */{9}
{73}#define DUMMY() \
	if (1);
{9}#endif
{0}
{9}#define M\

{0}\
 
{5}int{0} {11}main{10}(){0} {10}{{0}
	{11}double{0} {11}x{10}[]{0} {10}={0} {10}{{4}3.14159{10},{4}6.02e23{10},{4}1.6e-19{10},{4}1.0{10}+{4}1{10}};{0}
	{5}int{0} {11}y{10}[]{0} {10}={0} {10}{{4}75{10},{4}0113{10},{4}0x4b{10}};{0}
	{11}printf{10}({6}"hello world %d %g\n"{10},{0} {11}y{10}[{4}0{10}],{0} {11}x{10}[{4}0{10}]);{0}
{10}}{0}

Added test/examples/x.d.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
$
// /++ +/ doccomments are not yet supported
/* */
/** */
/// drdr
/+ /+ +/ +/
//keyword test
keyword1
keyword2
keyword4
keyword5
keyword6
keyword7
//unicode identifier test
вапёasdÓΘΣαԷԸՑהכ拉麺とひシマイ단결을
//strings test
's
'
w's'w
"multiline
			string"w
e"zz"e
r"asd\"e
r"multiline
			string"c
r`asd\`e
`multiline
			string`d
x"023 abc"e
x"023
	abc"w
//numbers test
a[3..4]=3
2.stringof
2.0.stringof
2.
2.2e+2
2.2e-2
.2e+2
.2
2e+2
0x2e+2
0x2ep+10
,.2.stringof,

end
 	  	 

Added test/examples/x.d.styled.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
{14}${0}
{2}// /++ +/ doccomments are not yet supported
{1}/* */{0}
{3}/** */{0}
{15}/// drdr
{4}/+ /+ +/ +/{0}
{2}//keyword test
{6}keyword1{0}
{7}keyword2{0}
{9}keyword4{0}
{20}keyword5{0}
{21}keyword6{0}
{22}keyword7{0}
{2}//unicode identifier test
{14}вапёasdÓΘΣαԷԸՑהכ拉麺とひシマイ단결을{0}
{2}//strings test
{11}'s
'
{14}w{12}'s'{14}w{0}
{10}"multiline
			string"w{0}
{14}e{10}"zz"{14}e{0}
{19}r"asd\"{14}e{0}
{19}r"multiline
			string"c{0}
{14}r{18}`asd\`{14}e{0}
{18}`multiline
			string`d{0}
{19}x"023 abc"{14}e{0}
{19}x"023
	abc"w{0}
{2}//numbers test
{14}a{13}[{5}3{13}..{5}4{13}]={5}3{0}
{5}2.stringof{0}
{5}2.0{13}.{14}stringof{0}
{5}2.{0}
{5}2.2e+2{0}
{5}2.2e-2{0}
{5}.2e+2{0}
{5}.2{0}
{5}2e+2{0}
{5}0x2e{13}+{5}2{0}
{5}0x2ep+10{0}
{13},{5}.2{13}.{14}stringof{13},{0}

{14}end{0}
 	  	 

Added test/examples/x.html.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
<html xmlns="http://www.w3.org/1999/xhtml">
<script type="text/javascript">
var b = /abc/i.test('abc');
'x\
</t>'
</script>
<head>
    <meta name="Date.Modified" content="20010515" />
    <title>SinkWorld - Portability</title>
    <unknown>SinkWorld - Portability</unknown>
    <link rel="stylesheet" type="text/css" href="SW.css">
</head>

Added test/examples/x.html.styled.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
{1}<html{8} {3}xmlns{8}={6}"http://www.w3.org/1999/xhtml"{1}>{0}
{1}<script{8} {3}type{8}={6}"text/javascript"{1}>{40}
{46}var{41} {46}b{41} {50}={41} {52}/abc/i{46}.test{50}({49}'abc'{50});{41}
{49}'x\
</t>'{41}
{1}</script>{0}
{1}<head>{0}
    {1}<meta{8} {3}name{8}={6}"Date.Modified"{8} {3}content{8}={6}"20010515"{8} {11}/>{0}
    {1}<title>{0}SinkWorld - Portability{1}</title>{0}
    {2}<unknown>{0}SinkWorld - Portability{2}</unknown>{0}
    {1}<link{8} {3}rel{8}={6}"stylesheet"{8} {3}type{8}={6}"text/css"{8} {3}href{8}={6}"SW.css"{1}>{0}
{1}</head>{0}

Added test/examples/x.php.













>
>
>
>
>
>
1
2
3
4
5
6
<head> <!-- About to script -->
<?php
echo "<!-- -->\n";
/* ?> */
?>
<strong>for</strong><b>if</b>

Added test/examples/x.php.styled.













>
>
>
>
>
>
1
2
3
4
5
6
{1}<head>{0} {9}<!-- About to script -->{0}
{18}<?php{118}
echo {119}"<!-- -->\n"{127};{118}
{124}/* ?> */{118}
{18}?>{0}
{1}<strong>{0}for{1}</strong><b>{0}if{1}</b>{0}

Added test/examples/x.py.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
# Convert all punctuation characters except '_', '*', and '.' into spaces.
def depunctuate(s):
	'''A docstring'''
	"""Docstring 2"""
	d = ""
	for ch in s:
		if ch in 'abcde':
			d = d + ch
		else:
			d = d + " "
	return d

Added test/examples/x.py.styled.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
{1}# Convert all punctuation characters except '_', '*', and '.' into spaces.{0}
{5}def{0} {9}depunctuate{10}({11}s{10}):{0}
	{6}'''A docstring'''{0}
	{7}"""Docstring 2"""{0}
	{11}d{0} {10}={0} {3}""{0}
	{5}for{0} {11}ch{0} {5}in{0} {11}s{10}:{0}
		{5}if{0} {11}ch{0} {5}in{0} {4}'abcde'{10}:{0}
			{11}d{0} {10}={0} {11}d{0} {10}+{0} {11}ch{0}
		{5}else{10}:{0}
			{11}d{0} {10}={0} {11}d{0} {10}+{0} {3}" "{0}
	{5}return{0} {11}d{0}

Added test/examples/x.vb.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
' String"
Dim a As String = "hello, world"
Dim b As String = "hello    world"
Dim c As String = "Joe said ""Hello"" to me"
Dim d As String = "\\\\server\\share\\file.txt"
' Character
""C "c"C "cc"C
' Date
d = #5/31/1993# or # 01/01/0001 12:00:00AM #

Added test/examples/x.vb.styled.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
{1}' String"
{3}Dim{0} {7}a{0} {3}As{0} {3}String{0} {6}={0} {4}"hello, world"{0}
{3}Dim{0} {7}b{0} {3}As{0} {3}String{0} {6}={0} {4}"hello    world"{0}
{3}Dim{0} {7}c{0} {3}As{0} {3}String{0} {6}={0} {4}"Joe said ""Hello"" to me"{0}
{3}Dim{0} {7}d{0} {3}As{0} {3}String{0} {6}={0} {4}"\\\\server\\share\\file.txt"{0}
{1}' Character
{4}""C{0} {4}"c"C{0} {4}"cc"C{0}
{1}' Date
{7}d{0} {6}={0} {8}#5/31/1993#{0} {3}or{0} {8}# 01/01/0001 12:00:00AM #{0}

Added test/lexTests.py.



































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# -*- coding: utf-8 -*-

from __future__ import with_statement

import io
import os
import unittest

import XiteWin

keywordsHTML = [
b"b body content head href html link meta "
	b"name rel script strong title type xmlns",
b"function",
b"sub"
]

class TestLexers(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def AsStyled(self):
		text = self.ed.Contents()
		data = io.BytesIO()
		prevStyle = -1
		for o in range(self.ed.Length):
			styleNow = self.ed.GetStyleAt(o)
			if styleNow != prevStyle:
				styleBuf = "{%0d}" % styleNow
				data.write(styleBuf.encode('utf-8'))
				prevStyle = styleNow
			data.write(text[o:o+1])
		return data.getvalue()

	def LexExample(self, name, lexerName, keywords=None):
		if keywords is None:
			keywords = []
		self.ed.LexerLanguage = lexerName
		bits = self.ed.StyleBitsNeeded
		mask = 2 << bits - 1
		self.ed.StyleBits = bits
		for i in range(len(keywords)):
			self.ed.SetKeyWords(i, keywords[i])

		nameExample = os.path.join("examples", name)
		namePrevious = nameExample +".styled"
		nameNew = nameExample +".new"
		with open(nameExample, "rb") as f:
			prog = f.read()
		BOM = b"\xEF\xBB\xBF"
		if prog.startswith(BOM):
			prog = prog[len(BOM):]
		lenDocument = len(prog)
		self.ed.AddText(lenDocument, prog)
		self.ed.Colourise(0, lenDocument)
		self.assertEquals(self.ed.EndStyled, lenDocument)
		with open(namePrevious, "rb") as f:
			prevStyled = f.read()
		progStyled = self.AsStyled()
		if progStyled != prevStyled:
			with open(nameNew, "wb") as f:
				f.write(progStyled)
			print(progStyled)
			print(prevStyled)
			self.assertEquals(progStyled, prevStyled)
			# The whole file doesn't parse like it did before so don't try line by line
			# as that is likely to fail many times.
			return

		# Try partial lexes from the start of every line which should all be identical.
		for line in range(self.ed.LineCount):
			lineStart = self.ed.PositionFromLine(line)
			self.ed.StartStyling(lineStart, mask)
			self.assertEquals(self.ed.EndStyled, lineStart)
			self.ed.Colourise(lineStart, lenDocument)
			progStyled = self.AsStyled()
			if progStyled != prevStyled:
				with open(nameNew, "wb") as f:
					f.write(progStyled)
				self.assertEquals(progStyled, prevStyled)
				# Give up after one failure
				return

	def testCXX(self):
		self.LexExample("x.cxx", b"cpp", [b"int"])

	def testPython(self):
		self.LexExample("x.py", b"python",
			[b"class def else for if import in print return while"])

	def testHTML(self):
		self.LexExample("x.html", b"hypertext", keywordsHTML)

	def testASP(self):
		self.LexExample("x.asp", b"hypertext", keywordsHTML)

	def testPHP(self):
		self.LexExample("x.php", b"hypertext", keywordsHTML)

	def testVB(self):
		self.LexExample("x.vb", b"vb", [b"as dim or string"])

	def testD(self):
		self.LexExample("x.d", b"d",
			[b"keyword1", b"keyword2", b"", b"keyword4", b"keyword5",
			b"keyword6", b"keyword7"])

if __name__ == '__main__':
	XiteWin.main("lexTests")

Added test/performanceTests.py.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# -*- coding: utf-8 -*-

from __future__ import with_statement
from __future__ import unicode_literals

import os, string, time, unittest

import XiteWin

class TestPerformance(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testAddLine(self):
		data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
		start = time.time()
		for i in range(1000):
			self.ed.AddText(len(data), data)
			self.assertEquals(self.ed.LineCount, i + 2)
		end = time.time()
		duration = end - start
		print("%6.3f testAddLine" % duration)
		self.xite.DoEvents()
		self.assert_(self.ed.Length > 0)

	def testAddLineMiddle(self):
		data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
		start = time.time()
		for i in range(1000):
			self.ed.AddText(len(data), data)
			self.assertEquals(self.ed.LineCount, i + 2)
		end = time.time()
		duration = end - start
		print("%6.3f testAddLineMiddle" % duration)
		self.xite.DoEvents()
		self.assert_(self.ed.Length > 0)

	def testHuge(self):
		data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
		data = data * 100000
		start = time.time()
		self.ed.AddText(len(data), data)
		end = time.time()
		duration = end - start
		print("%6.3f testHuge" % duration)
		self.xite.DoEvents()
		self.assert_(self.ed.Length > 0)

	def testHugeInserts(self):
		data = (string.ascii_letters + string.digits + "\n").encode('utf-8')
		data = data * 100000
		insert = (string.digits + "\n").encode('utf-8')
		self.ed.AddText(len(data), data)
		start = time.time()
		for i in range(1000):
			self.ed.InsertText(0, insert)
		end = time.time()
		duration = end - start
		print("%6.3f testHugeInserts" % duration)
		self.xite.DoEvents()
		self.assert_(self.ed.Length > 0)

	def testHugeReplace(self):
		oneLine = (string.ascii_letters + string.digits + "\n").encode('utf-8')
		data = oneLine * 100000
		insert = (string.digits + "\n").encode('utf-8')
		self.ed.AddText(len(data), data)
		start = time.time()
		for i in range(1000):
			self.ed.TargetStart = i * len(insert)
			self.ed.TargetEnd = self.ed.TargetStart + len(oneLine)
			self.ed.ReplaceTarget(len(insert), insert)
		end = time.time()
		duration = end - start
		print("%6.3f testHugeReplace" % duration)
		self.xite.DoEvents()
		self.assert_(self.ed.Length > 0)

if __name__ == '__main__':
	XiteWin.main("performanceTests")

Added test/simpleTests.py.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
# -*- coding: utf-8 -*-

from __future__ import with_statement
from __future__ import unicode_literals

import codecs, ctypes, os, sys, unittest

import XiteWin

class TestSimple(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testLength(self):
		self.assertEquals(self.ed.Length, 0)

	def testAddText(self):
		self.ed.AddText(1, "x")
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(self.ed.GetCharAt(0), ord("x"))
		self.assertEquals(self.ed.GetStyleAt(0), 0)
		self.ed.ClearAll()
		self.assertEquals(self.ed.Length, 0)

	def testDeleteRange(self):
		self.ed.AddText(5, b"abcde")
		self.assertEquals(self.ed.Length, 5)
		self.ed.DeleteRange(1, 2)
		self.assertEquals(self.ed.Length, 3)
		self.assertEquals(self.ed.Contents(), b"ade")

	def testAddStyledText(self):
		self.assertEquals(self.ed.EndStyled, 0)
		self.ed.AddStyledText(2, b"x\002")
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(self.ed.GetCharAt(0), ord("x"))
		self.assertEquals(self.ed.GetStyleAt(0), 2)
		self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\002")
		self.ed.ClearDocumentStyle()
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(self.ed.GetCharAt(0), ord("x"))
		self.assertEquals(self.ed.GetStyleAt(0), 0)
		self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\0")

	def testStyling(self):
		self.assertEquals(self.ed.EndStyled, 0)
		self.ed.AddStyledText(4, b"x\002y\003")
		self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\002y\003")
		self.ed.StartStyling(0,0xf)
		self.ed.SetStyling(1, 5)
		self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\005y\003")
		# Set the mask so 0 bit changed but not 2 bit
		self.ed.StartStyling(0,0x1)
		self.ed.SetStyling(1, 0)
		self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\004y\003")

		self.ed.StartStyling(0,0xff)
		self.ed.SetStylingEx(2, b"\100\101")
		self.assertEquals(self.ed.StyledTextRange(0, 2), b"x\100y\101")

	def testPosition(self):
		self.assertEquals(self.ed.CurrentPos, 0)
		self.assertEquals(self.ed.Anchor, 0)
		self.ed.AddText(1, "x")
		# Caret has automatically moved
		self.assertEquals(self.ed.CurrentPos, 1)
		self.assertEquals(self.ed.Anchor, 1)
		self.ed.SelectAll()
		self.assertEquals(self.ed.CurrentPos, 0)
		self.assertEquals(self.ed.Anchor, 1)
		self.ed.Anchor = 0
		self.assertEquals(self.ed.Anchor, 0)
		# Check line positions
		self.assertEquals(self.ed.PositionFromLine(0), 0)
		self.assertEquals(self.ed.GetLineEndPosition(0), 1)
		self.assertEquals(self.ed.PositionFromLine(1), 1)

		self.ed.CurrentPos = 1
		self.assertEquals(self.ed.Anchor, 0)
		self.assertEquals(self.ed.CurrentPos, 1)

	def testSelection(self):
		self.assertEquals(self.ed.CurrentPos, 0)
		self.assertEquals(self.ed.Anchor, 0)
		self.assertEquals(self.ed.SelectionStart, 0)
		self.assertEquals(self.ed.SelectionEnd, 0)
		self.ed.AddText(1, "x")
		self.ed.SelectionStart = 0
		self.assertEquals(self.ed.CurrentPos, 1)
		self.assertEquals(self.ed.Anchor, 0)
		self.assertEquals(self.ed.SelectionStart, 0)
		self.assertEquals(self.ed.SelectionEnd, 1)
		self.ed.SelectionStart = 1
		self.assertEquals(self.ed.CurrentPos, 1)
		self.assertEquals(self.ed.Anchor, 1)
		self.assertEquals(self.ed.SelectionStart, 1)
		self.assertEquals(self.ed.SelectionEnd, 1)

		self.ed.SelectionEnd = 0
		self.assertEquals(self.ed.CurrentPos, 0)
		self.assertEquals(self.ed.Anchor, 0)

	def testSetSelection(self):
		self.ed.AddText(4, b"abcd")
		self.ed.SetSel(1, 3)
		self.assertEquals(self.ed.SelectionStart, 1)
		self.assertEquals(self.ed.SelectionEnd, 3)
		result = b"\0" * 5
		length = self.ed.GetSelText(0, result)
		self.assertEquals(length, 3)
		self.assertEquals(result[:length], b"bc\0")
		self.ed.ReplaceSel(0, b"1234")
		self.assertEquals(self.ed.Length, 6)
		self.assertEquals(self.ed.Contents(), b"a1234d")

	def testReadOnly(self):
		self.ed.AddText(1, b"x")
		self.assertEquals(self.ed.ReadOnly, 0)
		self.assertEquals(self.ed.Contents(), b"x")
		self.ed.ReadOnly = 1
		self.assertEquals(self.ed.ReadOnly, 1)
		self.ed.AddText(1, b"x")
		self.assertEquals(self.ed.Contents(), b"x")
		self.ed.ReadOnly = 0
		self.ed.AddText(1, b"x")
		self.assertEquals(self.ed.Contents(), b"xx")
		self.ed.Null()
		self.assertEquals(self.ed.Contents(), b"xx")

	def testAddLine(self):
		data = b"x" * 70 + b"\n"
		for i in range(5):
			self.ed.AddText(len(data), data)
			self.xite.DoEvents()
			self.assertEquals(self.ed.LineCount, i + 2)
		self.assert_(self.ed.Length > 0)

	def testInsertText(self):
		data = b"xy"
		self.ed.InsertText(0, data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(data, self.ed.ByteRange(0,2))

		self.ed.InsertText(1, data)
		# Should now be "xxyy"
		self.assertEquals(self.ed.Length, 4)
		self.assertEquals(b"xxyy", self.ed.ByteRange(0,4))

	def testInsertNul(self):
		data = b"\0"
		self.ed.AddText(1, data)
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(data, self.ed.ByteRange(0,1))

	def testUndoRedo(self):
		data = b"xy"
		self.assertEquals(self.ed.Modify, 0)
		self.assertEquals(self.ed.UndoCollection, 1)
		self.assertEquals(self.ed.CanRedo(), 0)
		self.assertEquals(self.ed.CanUndo(), 0)
		self.ed.InsertText(0, data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.ed.Modify, 1)
		self.assertEquals(self.ed.CanRedo(), 0)
		self.assertEquals(self.ed.CanUndo(), 1)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.ed.Modify, 0)
		self.assertEquals(self.ed.CanRedo(), 1)
		self.assertEquals(self.ed.CanUndo(), 0)
		self.ed.Redo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.ed.Modify, 1)
		self.assertEquals(data, self.ed.Contents())
		self.assertEquals(self.ed.CanRedo(), 0)
		self.assertEquals(self.ed.CanUndo(), 1)

	def testUndoSavePoint(self):
		data = b"xy"
		self.assertEquals(self.ed.Modify, 0)
		self.ed.InsertText(0, data)
		self.assertEquals(self.ed.Modify, 1)
		self.ed.SetSavePoint()
		self.assertEquals(self.ed.Modify, 0)
		self.ed.InsertText(0, data)
		self.assertEquals(self.ed.Modify, 1)

	def testUndoCollection(self):
		data = b"xy"
		self.assertEquals(self.ed.UndoCollection, 1)
		self.ed.UndoCollection = 0
		self.assertEquals(self.ed.UndoCollection, 0)
		self.ed.InsertText(0, data)
		self.assertEquals(self.ed.CanRedo(), 0)
		self.assertEquals(self.ed.CanUndo(), 0)
		self.ed.UndoCollection = 1

	def testGetColumn(self):
		self.ed.AddText(1, b"x")
		self.assertEquals(self.ed.GetColumn(0), 0)
		self.assertEquals(self.ed.GetColumn(1), 1)
		# Next line caused infinite loop in 1.71
		self.assertEquals(self.ed.GetColumn(2), 1)
		self.assertEquals(self.ed.GetColumn(3), 1)

	def testTabWidth(self):
		self.assertEquals(self.ed.TabWidth, 8)
		self.ed.AddText(3, b"x\tb")
		self.assertEquals(self.ed.GetColumn(0), 0)
		self.assertEquals(self.ed.GetColumn(1), 1)
		self.assertEquals(self.ed.GetColumn(2), 8)
		for col in range(10):
			if col == 0:
				self.assertEquals(self.ed.FindColumn(0, col), 0)
			elif col == 1:
				self.assertEquals(self.ed.FindColumn(0, col), 1)
			elif col == 8:
				self.assertEquals(self.ed.FindColumn(0, col), 2)
			elif col == 9:
				self.assertEquals(self.ed.FindColumn(0, col), 3)
			else:
				self.assertEquals(self.ed.FindColumn(0, col), 1)
		self.ed.TabWidth = 4
		self.assertEquals(self.ed.TabWidth, 4)
		self.assertEquals(self.ed.GetColumn(0), 0)
		self.assertEquals(self.ed.GetColumn(1), 1)
		self.assertEquals(self.ed.GetColumn(2), 4)

	def testIndent(self):
		self.assertEquals(self.ed.Indent, 0)
		self.assertEquals(self.ed.UseTabs, 1)
		self.ed.Indent = 8
		self.ed.UseTabs = 0
		self.assertEquals(self.ed.Indent, 8)
		self.assertEquals(self.ed.UseTabs, 0)
		self.ed.AddText(3, b"x\tb")
		self.assertEquals(self.ed.GetLineIndentation(0), 0)
		self.ed.InsertText(0, b" ")
		self.assertEquals(self.ed.GetLineIndentation(0), 1)
		self.assertEquals(self.ed.GetLineIndentPosition(0), 1)
		self.assertEquals(self.ed.Contents(), b" x\tb")
		self.ed.SetLineIndentation(0,2)
		self.assertEquals(self.ed.Contents(), b"  x\tb")
		self.assertEquals(self.ed.GetLineIndentPosition(0), 2)
		self.ed.UseTabs = 1
		self.ed.SetLineIndentation(0,8)
		self.assertEquals(self.ed.Contents(), b"\tx\tb")
		self.assertEquals(self.ed.GetLineIndentPosition(0), 1)

	def testGetCurLine(self):
		self.ed.AddText(1, b"x")
		data = b"\0" * 100
		caret = self.ed.GetCurLine(len(data), data)
		data = data.rstrip(b"\0")
		self.assertEquals(caret, 1)
		self.assertEquals(data, b"x")

	def testGetLine(self):
		self.ed.AddText(1, b"x")
		data = b"\0" * 100
		length = self.ed.GetLine(0, data)
		self.assertEquals(length, 1)
		data = data[:length]
		self.assertEquals(data, b"x")

	def testLineEnds(self):
		self.ed.AddText(3, b"x\ny")
		self.assertEquals(self.ed.GetLineEndPosition(0), 1)
		self.assertEquals(self.ed.GetLineEndPosition(1), 3)
		self.assertEquals(self.ed.LineLength(0), 2)
		self.assertEquals(self.ed.LineLength(1), 1)
		self.assertEquals(self.ed.EOLMode, self.ed.SC_EOL_CRLF)
		lineEnds = [b"\r\n", b"\r", b"\n"]
		for lineEndType in [self.ed.SC_EOL_CR, self.ed.SC_EOL_LF, self.ed.SC_EOL_CRLF]:
			self.ed.EOLMode = lineEndType
			self.assertEquals(self.ed.EOLMode, lineEndType)
			self.ed.ConvertEOLs(lineEndType)
			self.assertEquals(self.ed.Contents(), b"x" + lineEnds[lineEndType] + b"y")
			self.assertEquals(self.ed.LineLength(0), 1 + len(lineEnds[lineEndType]))

	# Several tests for unicode line ends U+2028 and U+2029
	
	def testUnicodeLineEnds(self):
		# Add two lines separated with U+2028 and ensure it is seen as two lines
		# Then remove U+2028 and should be just 1 lines
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		self.ed.AddText(5, b"x\xe2\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 2)
		self.assertEquals(self.ed.GetLineEndPosition(0), 1)
		self.assertEquals(self.ed.GetLineEndPosition(1), 5)
		self.assertEquals(self.ed.LineLength(0), 4)
		self.assertEquals(self.ed.LineLength(1), 1)
		self.ed.TargetStart = 1
		self.ed.TargetEnd = 4
		self.ed.ReplaceTarget(0, b"")
		self.assertEquals(self.ed.LineCount, 1)
		self.assertEquals(self.ed.LineLength(0), 2)
		self.assertEquals(self.ed.GetLineEndPosition(0), 2)

	def testUnicodeLineEndsWithCodePage0(self):
		# Try the Unicode line ends when not in Unicode mode -> should remain 1 line
		self.ed.SetCodePage(0)
		self.ed.AddText(5, b"x\xe2\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 1)
		self.ed.AddText(4, b"x\xc2\x85y")
		self.assertEquals(self.ed.LineCount, 1)

	def testUnicodeLineEndsSwitchToUnicodeAndBack(self):
		# Add the Unicode line ends when not in Unicode mode
		self.ed.SetCodePage(0)
		self.ed.AddText(5, b"x\xe2\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 1)
		# Into UTF-8 mode - should now be interpreting as two lines
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		self.assertEquals(self.ed.LineCount, 2)
		# Back to code page 0 and 1 line
		self.ed.SetCodePage(0)
		self.assertEquals(self.ed.LineCount, 1)

	def testUFragmentedEOLCompletion(self):
		# Add 2 starting bytes of UTF-8 line end then complete it
		self.ed.ClearAll()
		self.ed.AddText(4, b"x\xe2\x80y")
		self.assertEquals(self.ed.LineCount, 1)
		self.assertEquals(self.ed.GetLineEndPosition(0), 4)
		self.ed.SetSel(3,3)
		self.ed.AddText(1, b"\xa8")
		self.assertEquals(self.ed.Contents(), b"x\xe2\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 2)

		# Add 1 starting bytes of UTF-8 line end then complete it
		self.ed.ClearAll()
		self.ed.AddText(3, b"x\xe2y")
		self.assertEquals(self.ed.LineCount, 1)
		self.assertEquals(self.ed.GetLineEndPosition(0), 3)
		self.ed.SetSel(2,2)
		self.ed.AddText(2, b"\x80\xa8")
		self.assertEquals(self.ed.Contents(), b"x\xe2\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 2)

	def testUFragmentedEOLStart(self):
		# Add end of UTF-8 line end then insert start
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		self.assertEquals(self.ed.LineCount, 1)
		self.ed.AddText(4, b"x\x80\xa8y")
		self.assertEquals(self.ed.LineCount, 1)
		self.ed.SetSel(1,1)
		self.ed.AddText(1, b"\xe2")
		self.assertEquals(self.ed.LineCount, 2)

	def testUBreakApartEOL(self):
		# Add two lines separated by U+2029 then remove and add back each byte ensuring
		# only one line after each removal of any byte in line end and 2 lines after reinsertion
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		text = b"x\xe2\x80\xa9y";
		self.ed.AddText(5, text)
		self.assertEquals(self.ed.LineCount, 2)
		
		for i in range(len(text)):
			self.ed.TargetStart = i
			self.ed.TargetEnd = i + 1
			self.ed.ReplaceTarget(0, b"")
			if i in [0, 4]:
				# Removing text characters does not change number of lines
				self.assertEquals(self.ed.LineCount, 2)
			else:
				# Removing byte from line end, removes 1 line
				self.assertEquals(self.ed.LineCount, 1)
				
			self.ed.TargetEnd = i
			self.ed.ReplaceTarget(1, text[i:i+1])
			self.assertEquals(self.ed.LineCount, 2)

	def testURemoveEOLFragment(self):
		# Add UTF-8 line end then delete each byte causing line end to disappear
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		for i in range(3):
			self.ed.ClearAll()
			self.ed.AddText(5, b"x\xe2\x80\xa8y")
			self.assertEquals(self.ed.LineCount, 2)
			self.ed.TargetStart = i+1
			self.ed.TargetEnd = i+2
			self.ed.ReplaceTarget(0, b"")
			self.assertEquals(self.ed.LineCount, 1)
		
	# Several tests for unicode NEL line ends U+0085

	def testNELLineEnds(self):
		# Add two lines separated with U+0085 and ensure it is seen as two lines
		# Then remove U+0085 and should be just 1 lines
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		self.ed.AddText(4, b"x\xc2\x85y")
		self.assertEquals(self.ed.LineCount, 2)
		self.assertEquals(self.ed.GetLineEndPosition(0), 1)
		self.assertEquals(self.ed.GetLineEndPosition(1), 4)
		self.assertEquals(self.ed.LineLength(0), 3)
		self.assertEquals(self.ed.LineLength(1), 1)
		self.ed.TargetStart = 1
		self.ed.TargetEnd = 3
		self.ed.ReplaceTarget(0, b"")
		self.assertEquals(self.ed.LineCount, 1)
		self.assertEquals(self.ed.LineLength(0), 2)
		self.assertEquals(self.ed.GetLineEndPosition(0), 2)

	def testNELFragmentedEOLCompletion(self):
		# Add starting byte of UTF-8 NEL then complete it
		self.ed.AddText(3, b"x\xc2y")
		self.assertEquals(self.ed.LineCount, 1)
		self.assertEquals(self.ed.GetLineEndPosition(0), 3)
		self.ed.SetSel(2,2)
		self.ed.AddText(1, b"\x85")
		self.assertEquals(self.ed.Contents(), b"x\xc2\x85y")
		self.assertEquals(self.ed.LineCount, 2)

	def testNELFragmentedEOLStart(self):
		# Add end of UTF-8 NEL then insert start
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		self.assertEquals(self.ed.LineCount, 1)
		self.ed.AddText(4, b"x\x85y")
		self.assertEquals(self.ed.LineCount, 1)
		self.ed.SetSel(1,1)
		self.ed.AddText(1, b"\xc2")
		self.assertEquals(self.ed.LineCount, 2)

	def testNELBreakApartEOL(self):
		# Add two lines separated by U+0085 then remove and add back each byte ensuring
		# only one line after each removal of any byte in line end and 2 lines after reinsertion
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.ed.SetCodePage(65001)
		self.ed.SetLineEndTypesAllowed(1)
		text = b"x\xc2\x85y";
		self.ed.AddText(4, text)
		self.assertEquals(self.ed.LineCount, 2)
		
		for i in range(len(text)):
			self.ed.TargetStart = i
			self.ed.TargetEnd = i + 1
			self.ed.ReplaceTarget(0, b"")
			if i in [0, 3]:
				# Removing text characters does not change number of lines
				self.assertEquals(self.ed.LineCount, 2)
			else:
				# Removing byte from line end, removes 1 line
				self.assertEquals(self.ed.LineCount, 1)
				
			self.ed.TargetEnd = i
			self.ed.ReplaceTarget(1, text[i:i+1])
			self.assertEquals(self.ed.LineCount, 2)

	def testNELRemoveEOLFragment(self):
		# Add UTF-8 NEL then delete each byte causing line end to disappear
		self.ed.SetCodePage(65001)
		for i in range(2):
			self.ed.ClearAll()
			self.ed.AddText(4, b"x\xc2\x85y")
			self.assertEquals(self.ed.LineCount, 2)
			self.ed.TargetStart = i+1
			self.ed.TargetEnd = i+2
			self.ed.ReplaceTarget(0, b"")
			self.assertEquals(self.ed.LineCount, 1)
		
	def testGoto(self):
		self.ed.AddText(5, b"a\nb\nc")
		self.assertEquals(self.ed.CurrentPos, 5)
		self.ed.GotoLine(1)
		self.assertEquals(self.ed.CurrentPos, 2)
		self.ed.GotoPos(4)
		self.assertEquals(self.ed.CurrentPos, 4)

	def testCutCopyPaste(self):
		self.ed.AddText(5, b"a1b2c")
		self.ed.SetSel(1,3)
		self.ed.Cut()
		self.assertEquals(self.ed.CanPaste(), 1)
		self.ed.SetSel(0, 0)
		self.ed.Paste()
		self.assertEquals(self.ed.Contents(), b"1ba2c")
		self.ed.SetSel(4,5)
		self.ed.Copy()
		self.ed.SetSel(1,3)
		self.ed.Paste()
		self.assertEquals(self.ed.Contents(), b"1c2c")
		self.ed.SetSel(2,4)
		self.ed.Clear()
		self.assertEquals(self.ed.Contents(), b"1c")

	def testGetSet(self):
		self.ed.SetText(0, b"abc")
		self.assertEquals(self.ed.TextLength, 3)
		result = b"\0" * 5
		length = self.ed.GetText(4, result)
		result = result[:length]
		self.assertEquals(result, b"abc")

	def testAppend(self):
		self.ed.SetText(0, b"abc")
		self.assertEquals(self.ed.SelectionStart, 0)
		self.assertEquals(self.ed.SelectionEnd, 0)
		text = b"12"
		self.ed.AppendText(len(text), text)
		self.assertEquals(self.ed.SelectionStart, 0)
		self.assertEquals(self.ed.SelectionEnd, 0)
		self.assertEquals(self.ed.Contents(), b"abc12")

	def testTarget(self):
		self.ed.SetText(0, b"abcd")
		self.ed.TargetStart = 1
		self.ed.TargetEnd = 3
		self.assertEquals(self.ed.TargetStart, 1)
		self.assertEquals(self.ed.TargetEnd, 3)
		rep = b"321"
		self.ed.ReplaceTarget(len(rep), rep)
		self.assertEquals(self.ed.Contents(), b"a321d")
		self.ed.SearchFlags = self.ed.SCFIND_REGEXP
		self.assertEquals(self.ed.SearchFlags, self.ed.SCFIND_REGEXP)
		searchString = b"\([1-9]+\)"
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(1, pos)
		tagString = b"abcdefghijklmnop"
		lenTag = self.ed.GetTag(1, tagString)
		tagString = tagString[:lenTag]
		self.assertEquals(tagString, b"321")
		rep = b"\\1"
		self.ed.TargetStart = 0
		self.ed.TargetEnd = 0
		self.ed.ReplaceTargetRE(len(rep), rep)
		self.assertEquals(self.ed.Contents(), b"321a321d")
		self.ed.SetSel(4,5)
		self.ed.TargetFromSelection()
		self.assertEquals(self.ed.TargetStart, 4)
		self.assertEquals(self.ed.TargetEnd, 5)

	def testTargetEscape(self):
		# Checks that a literal \ can be in the replacement. Bug #2959876
		self.ed.SetText(0, b"abcd")
		self.ed.TargetStart = 1
		self.ed.TargetEnd = 3
		rep = b"\\\\n"
		self.ed.ReplaceTargetRE(len(rep), rep)
		self.assertEquals(self.ed.Contents(), b"a\\nd")

	def testPointsAndPositions(self):
		self.ed.AddText(1, b"x")
		# Start of text
		self.assertEquals(self.ed.PositionFromPoint(0,0), 0)
		# End of text
		self.assertEquals(self.ed.PositionFromPoint(0,100), 1)

	def testLinePositions(self):
		text = b"ab\ncd\nef"
		nl = b"\n"
		if sys.version_info[0] == 3:
			nl = ord(b"\n")
		self.ed.AddText(len(text), text)
		self.assertEquals(self.ed.LineFromPosition(-1), 0)
		line = 0
		for pos in range(len(text)+1):
			self.assertEquals(self.ed.LineFromPosition(pos), line)
			if pos < len(text) and text[pos] == nl:
				line += 1

	def testWordPositions(self):
		text = b"ab cd\tef"
		self.ed.AddText(len(text), text)
		self.assertEquals(self.ed.WordStartPosition(3, 0), 2)
		self.assertEquals(self.ed.WordStartPosition(4, 0), 3)
		self.assertEquals(self.ed.WordStartPosition(5, 0), 3)
		self.assertEquals(self.ed.WordStartPosition(6, 0), 5)

		self.assertEquals(self.ed.WordEndPosition(2, 0), 3)
		self.assertEquals(self.ed.WordEndPosition(3, 0), 5)
		self.assertEquals(self.ed.WordEndPosition(4, 0), 5)
		self.assertEquals(self.ed.WordEndPosition(5, 0), 6)
		self.assertEquals(self.ed.WordEndPosition(6, 0), 8)

MODI = 1
UNDO = 2
REDO = 4

class TestContainerUndo(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.data = b"xy"

	def UndoState(self):
		return (MODI if self.ed.Modify else 0) | \
			(UNDO if self.ed.CanUndo() else 0) | \
			(REDO if self.ed.CanRedo() else 0)

	def testContainerActNoCoalesce(self):
		self.ed.InsertText(0, self.data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 0)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
		self.ed.Redo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()

	def testContainerActCoalesce(self):
		self.ed.InsertText(0, self.data)
		self.ed.AddUndoAction(5, 1)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)
		self.ed.Redo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)

	def testContainerMultiStage(self):
		self.ed.InsertText(0, self.data)
		self.ed.AddUndoAction(5, 1)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)
		self.ed.Redo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)

	def testContainerMultiStageNoText(self):
		self.ed.AddUndoAction(5, 1)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()
		self.assertEquals(self.UndoState(), REDO)
		self.ed.Redo()
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()
		self.assertEquals(self.UndoState(), REDO)

	def testContainerActCoalesceEnd(self):
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.InsertText(0, self.data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)
		self.ed.Redo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)

	def testContainerBetweenInsertAndInsert(self):
		self.assertEquals(self.ed.Length, 0)
		self.ed.InsertText(0, self.data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.InsertText(2, self.data)
		self.assertEquals(self.ed.Length, 4)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		# Undoes both insertions and the containerAction in the middle
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)

	def testContainerNoCoalesceBetweenInsertAndInsert(self):
		self.assertEquals(self.ed.Length, 0)
		self.ed.InsertText(0, self.data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 0)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.InsertText(2, self.data)
		self.assertEquals(self.ed.Length, 4)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		# Undo last insertion
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
		# Undo container
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO | REDO)
		# Undo first insertion
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 0)
		self.assertEquals(self.UndoState(), REDO)

	def testContainerBetweenDeleteAndDelete(self):
		self.ed.InsertText(0, self.data)
		self.ed.EmptyUndoBuffer()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), 0)
		self.ed.SetSel(2,2)
		self.ed.DeleteBack()
		self.assertEquals(self.ed.Length, 1)
		self.ed.AddUndoAction(5, 1)
		self.ed.DeleteBack()
		self.assertEquals(self.ed.Length, 0)
		# Undoes both deletions and the containerAction in the middle
		self.ed.Undo()
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), REDO)

	def testContainerBetweenInsertAndDelete(self):
		self.assertEquals(self.ed.Length, 0)
		self.ed.InsertText(0, self.data)
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.AddUndoAction(5, 1)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.SetSel(0,1)
		self.ed.Cut()
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(self.UndoState(), MODI | UNDO)
		self.ed.Undo()	# Only undoes the deletion
		self.assertEquals(self.ed.Length, 2)
		self.assertEquals(self.UndoState(), MODI | UNDO | REDO)

class TestKeyCommands(unittest.TestCase):
	""" These commands are normally assigned to keys and take no arguments """

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def selRange(self):
		return self.ed.CurrentPos, self.ed.Anchor

	def testLineMove(self):
		self.ed.AddText(8, b"x1\ny2\nz3")
		self.ed.SetSel(0,0)
		self.ed.ChooseCaretX()
		self.ed.LineDown()
		self.ed.LineDown()
		self.assertEquals(self.selRange(), (6, 6))
		self.ed.LineUp()
		self.assertEquals(self.selRange(), (3, 3))
		self.ed.LineDownExtend()
		self.assertEquals(self.selRange(), (6, 3))
		self.ed.LineUpExtend()
		self.ed.LineUpExtend()
		self.assertEquals(self.selRange(), (0, 3))

	def testCharMove(self):
		self.ed.AddText(8, b"x1\ny2\nz3")
		self.ed.SetSel(0,0)
		self.ed.CharRight()
		self.ed.CharRight()
		self.assertEquals(self.selRange(), (2, 2))
		self.ed.CharLeft()
		self.assertEquals(self.selRange(), (1, 1))
		self.ed.CharRightExtend()
		self.assertEquals(self.selRange(), (2, 1))
		self.ed.CharLeftExtend()
		self.ed.CharLeftExtend()
		self.assertEquals(self.selRange(), (0, 1))

	def testWordMove(self):
		self.ed.AddText(10, b"a big boat")
		self.ed.SetSel(3,3)
		self.ed.WordRight()
		self.ed.WordRight()
		self.assertEquals(self.selRange(), (10, 10))
		self.ed.WordLeft()
		self.assertEquals(self.selRange(), (6, 6))
		self.ed.WordRightExtend()
		self.assertEquals(self.selRange(), (10, 6))
		self.ed.WordLeftExtend()
		self.ed.WordLeftExtend()
		self.assertEquals(self.selRange(), (2, 6))

	def testHomeEndMove(self):
		self.ed.AddText(10, b"a big boat")
		self.ed.SetSel(3,3)
		self.ed.Home()
		self.assertEquals(self.selRange(), (0, 0))
		self.ed.LineEnd()
		self.assertEquals(self.selRange(), (10, 10))
		self.ed.SetSel(3,3)
		self.ed.HomeExtend()
		self.assertEquals(self.selRange(), (0, 3))
		self.ed.LineEndExtend()
		self.assertEquals(self.selRange(), (10, 3))

	def testStartEndMove(self):
		self.ed.AddText(10, b"a\nbig\nboat")
		self.ed.SetSel(3,3)
		self.ed.DocumentStart()
		self.assertEquals(self.selRange(), (0, 0))
		self.ed.DocumentEnd()
		self.assertEquals(self.selRange(), (10, 10))
		self.ed.SetSel(3,3)
		self.ed.DocumentStartExtend()
		self.assertEquals(self.selRange(), (0, 3))
		self.ed.DocumentEndExtend()
		self.assertEquals(self.selRange(), (10, 3))


class TestMarkers(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.ed.AddText(5, b"x\ny\nz")

	def testMarker(self):
		handle = self.ed.MarkerAdd(1,1)
		self.assertEquals(self.ed.MarkerLineFromHandle(handle), 1)
		self.ed.MarkerDelete(1,1)
		self.assertEquals(self.ed.MarkerLineFromHandle(handle), -1)

	def testTwiceAddedDelete(self):
		handle = self.ed.MarkerAdd(1,1)
		self.assertEquals(self.ed.MarkerGet(1), 2)
		handle2 = self.ed.MarkerAdd(1,1)
		self.assertEquals(self.ed.MarkerGet(1), 2)
		self.ed.MarkerDelete(1,1)
		self.assertEquals(self.ed.MarkerGet(1), 2)
		self.ed.MarkerDelete(1,1)
		self.assertEquals(self.ed.MarkerGet(1), 0)

	def testMarkerDeleteAll(self):
		h1 = self.ed.MarkerAdd(0,1)
		h2 = self.ed.MarkerAdd(1,2)
		self.assertEquals(self.ed.MarkerLineFromHandle(h1), 0)
		self.assertEquals(self.ed.MarkerLineFromHandle(h2), 1)
		self.ed.MarkerDeleteAll(1)
		self.assertEquals(self.ed.MarkerLineFromHandle(h1), -1)
		self.assertEquals(self.ed.MarkerLineFromHandle(h2), 1)
		self.ed.MarkerDeleteAll(-1)
		self.assertEquals(self.ed.MarkerLineFromHandle(h1), -1)
		self.assertEquals(self.ed.MarkerLineFromHandle(h2), -1)

	def testMarkerDeleteHandle(self):
		handle = self.ed.MarkerAdd(0,1)
		self.assertEquals(self.ed.MarkerLineFromHandle(handle), 0)
		self.ed.MarkerDeleteHandle(handle)
		self.assertEquals(self.ed.MarkerLineFromHandle(handle), -1)

	def testMarkerBits(self):
		self.assertEquals(self.ed.MarkerGet(0), 0)
		self.ed.MarkerAdd(0,1)
		self.assertEquals(self.ed.MarkerGet(0), 2)
		self.ed.MarkerAdd(0,2)
		self.assertEquals(self.ed.MarkerGet(0), 6)

	def testMarkerAddSet(self):
		self.assertEquals(self.ed.MarkerGet(0), 0)
		self.ed.MarkerAddSet(0,5)
		self.assertEquals(self.ed.MarkerGet(0), 5)
		self.ed.MarkerDeleteAll(-1)

	def testMarkerNext(self):
		self.assertEquals(self.ed.MarkerNext(0, 2), -1)
		h1 = self.ed.MarkerAdd(0,1)
		h2 = self.ed.MarkerAdd(2,1)
		self.assertEquals(self.ed.MarkerNext(0, 2), 0)
		self.assertEquals(self.ed.MarkerNext(1, 2), 2)
		self.assertEquals(self.ed.MarkerNext(2, 2), 2)
		self.assertEquals(self.ed.MarkerPrevious(0, 2), 0)
		self.assertEquals(self.ed.MarkerPrevious(1, 2), 0)
		self.assertEquals(self.ed.MarkerPrevious(2, 2), 2)

	def testMarkerNegative(self):
		self.assertEquals(self.ed.MarkerNext(-1, 2), -1)

	def testLineState(self):
		self.assertEquals(self.ed.MaxLineState, 0)
		self.assertEquals(self.ed.GetLineState(0), 0)
		self.assertEquals(self.ed.GetLineState(1), 0)
		self.assertEquals(self.ed.GetLineState(2), 0)
		self.ed.SetLineState(1, 100)
		self.assertNotEquals(self.ed.MaxLineState, 0)
		self.assertEquals(self.ed.GetLineState(0), 0)
		self.assertEquals(self.ed.GetLineState(1), 100)
		self.assertEquals(self.ed.GetLineState(2), 0)

	def testSymbolRetrieval(self):
		self.ed.MarkerDefine(1,3)
		self.assertEquals(self.ed.MarkerSymbolDefined(1), 3)

class TestIndicators(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testSetIndicator(self):
		self.assertEquals(self.ed.IndicGetStyle(0), 1)
		self.assertEquals(self.ed.IndicGetFore(0), 0x007f00)
		self.ed.IndicSetStyle(0, 2)
		self.ed.IndicSetFore(0, 0xff0080)
		self.assertEquals(self.ed.IndicGetStyle(0), 2)
		self.assertEquals(self.ed.IndicGetFore(0), 0xff0080)

	def testIndicatorFill(self):
		self.ed.InsertText(0, b"abc")
		self.ed.IndicatorCurrent = 3
		self.ed.IndicatorFillRange(1,1)
		self.assertEquals(self.ed.IndicatorValueAt(3, 0), 0)
		self.assertEquals(self.ed.IndicatorValueAt(3, 1), 1)
		self.assertEquals(self.ed.IndicatorValueAt(3, 2), 0)
		self.assertEquals(self.ed.IndicatorStart(3, 0), 0)
		self.assertEquals(self.ed.IndicatorEnd(3, 0), 1)
		self.assertEquals(self.ed.IndicatorStart(3, 1), 1)
		self.assertEquals(self.ed.IndicatorEnd(3, 1), 2)
		self.assertEquals(self.ed.IndicatorStart(3, 2), 2)
		self.assertEquals(self.ed.IndicatorEnd(3, 2), 3)

	def testIndicatorAtEnd(self):
		self.ed.InsertText(0, b"ab")
		self.ed.IndicatorCurrent = 3
		self.ed.IndicatorFillRange(1,1)
		self.assertEquals(self.ed.IndicatorValueAt(3, 0), 0)
		self.assertEquals(self.ed.IndicatorValueAt(3, 1), 1)
		self.assertEquals(self.ed.IndicatorStart(3, 0), 0)
		self.assertEquals(self.ed.IndicatorEnd(3, 0), 1)
		self.assertEquals(self.ed.IndicatorStart(3, 1), 1)
		self.assertEquals(self.ed.IndicatorEnd(3, 1), 2)
		self.ed.DeleteRange(1, 1)
		# Now only one character left and does not have indicator so indicator 3 is null
		self.assertEquals(self.ed.IndicatorValueAt(3, 0), 0)
		# Since null, remaining calls return 0
		self.assertEquals(self.ed.IndicatorStart(3, 0), 0)
		self.assertEquals(self.ed.IndicatorEnd(3, 0), 0)
		self.assertEquals(self.ed.IndicatorStart(3, 1), 0)
		self.assertEquals(self.ed.IndicatorEnd(3, 1), 0)

class TestScrolling(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		# 150 should be enough lines
		self.ed.InsertText(0, b"a" * 150 + b"\n" * 150)

	def testTop(self):
		self.ed.GotoLine(0)
		self.assertEquals(self.ed.FirstVisibleLine, 0)

	def testLineScroll(self):
		self.ed.GotoLine(0)
		self.ed.LineScroll(0, 3)
		self.assertEquals(self.ed.FirstVisibleLine, 3)
		self.ed.LineScroll(0, -2)
		self.assertEquals(self.ed.FirstVisibleLine, 1)
		self.assertEquals(self.ed.XOffset, 0)
		self.ed.LineScroll(10, 0)
		self.assertGreater(self.ed.XOffset, 0)
		scroll_width = float(self.ed.XOffset) / 10
		self.ed.LineScroll(-2, 0)
		self.assertEquals(self.ed.XOffset, scroll_width * 8)

	def testVisibleLine(self):
		self.ed.FirstVisibleLine = 7
		self.assertEquals(self.ed.FirstVisibleLine, 7)

class TestSearch(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.ed.InsertText(0, b"a\tbig boat\t")

	def testFind(self):
		pos = self.ed.FindBytes(0, self.ed.Length, b"zzz", 0)
		self.assertEquals(pos, -1)
		pos = self.ed.FindBytes(0, self.ed.Length, b"big", 0)
		self.assertEquals(pos, 2)

	def testFindEmpty(self):
		pos = self.ed.FindBytes(0, self.ed.Length, b"", 0)
		self.assertEquals(pos, 0)

	def testCaseFind(self):
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"big", 0), 2)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bIg", 0), 2)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bIg",
			self.ed.SCFIND_MATCHCASE), -1)

	def testWordFind(self):
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi",
			self.ed.SCFIND_WHOLEWORD), -1)

	def testWordStartFind(self):
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi", 0), 2)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"bi",
			self.ed.SCFIND_WORDSTART), 2)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"ig", 0), 3)
		self.assertEquals(self.ed.FindBytes(0, self.ed.Length, b"ig",
			self.ed.SCFIND_WORDSTART), -1)

	def testREFind(self):
		flags = self.ed.SCFIND_REGEXP
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\<b.g\>", flags))
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
			flags | self.ed.SCFIND_MATCHCASE))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
		self.assertEquals(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
		self.assertEquals(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\([a]\).*\0", flags))

	def testPosixREFind(self):
		flags = self.ed.SCFIND_REGEXP | self.ed.SCFIND_POSIX
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b.g", 0))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b.g", flags))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\<b.g\>", flags))
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"b[A-Z]g",
			flags | self.ed.SCFIND_MATCHCASE))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]g", flags))
		self.assertEquals(6, self.ed.FindBytes(0, self.ed.Length, b"b[a-z]*t", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"^a", flags))
		self.assertEquals(10, self.ed.FindBytes(0, self.ed.Length, b"\t$", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"([a]).*\0", flags))

	def testPhilippeREFind(self):
		# Requires 1.,72
		flags = self.ed.SCFIND_REGEXP
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\w", flags))
		self.assertEquals(1, self.ed.FindBytes(0, self.ed.Length, b"\W", flags))
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"\d", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\D", flags))
		self.assertEquals(1, self.ed.FindBytes(0, self.ed.Length, b"\s", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\S", flags))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\x62", flags))

	def testRENonASCII(self):
		self.ed.InsertText(0, b"\xAD")
		flags = self.ed.SCFIND_REGEXP
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"\\x10", flags))
		self.assertEquals(2, self.ed.FindBytes(0, self.ed.Length, b"\\x09", flags))
		self.assertEquals(-1, self.ed.FindBytes(0, self.ed.Length, b"\\xAB", flags))
		self.assertEquals(0, self.ed.FindBytes(0, self.ed.Length, b"\\xAD", flags))

class TestProperties(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testSet(self):
		self.ed.SetProperty(b"test", b"12")
		self.assertEquals(self.ed.GetPropertyInt(b"test"), 12)
		result = b"\0" * 10
		length = self.ed.GetProperty(b"test", result)
		result = result[:length]
		self.assertEquals(result, b"12")
		self.ed.SetProperty(b"test.plus", b"[$(test)]")
		result = b"\0" * 10
		length = self.ed.GetPropertyExpanded(b"test.plus", result)
		result = result[:length]
		self.assertEquals(result, b"[12]")

class TestTextMargin(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.txt = b"abcd"
		self.ed.AddText(1, b"x")

	def testAscent(self):
		lineHeight = self.ed.TextHeight(0)
		self.ed.ExtraAscent
		self.assertEquals(self.ed.ExtraAscent, 0)
		self.assertEquals(self.ed.ExtraDescent, 0)
		self.ed.ExtraAscent = 1
		self.assertEquals(self.ed.ExtraAscent, 1)
		self.ed.ExtraDescent = 2
		self.assertEquals(self.ed.ExtraDescent, 2)
		# Allow line height to recalculate
		self.xite.DoEvents()
		lineHeightIncreased = self.ed.TextHeight(0)
		self.assertEquals(lineHeightIncreased, lineHeight + 2 + 1)

	def testTextMargin(self):
		self.ed.MarginSetText(0, self.txt)
		result = b"\0" * 10
		length = self.ed.MarginGetText(0, result)
		result = result[:length]
		self.assertEquals(result, self.txt)
		self.ed.MarginTextClearAll()

	def testTextMarginStyle(self):
		self.ed.MarginSetText(0, self.txt)
		self.ed.MarginSetStyle(0, 33)
		self.assertEquals(self.ed.MarginGetStyle(0), 33)
		self.ed.MarginTextClearAll()

	def testTextMarginStyles(self):
		styles = b"\001\002\003\004"
		self.ed.MarginSetText(0, self.txt)
		self.ed.MarginSetStyles(0, styles)
		result = b"\0" * 10
		length = self.ed.MarginGetStyles(0, result)
		result = result[:length]
		self.assertEquals(result, styles)
		self.ed.MarginTextClearAll()

	def testTextMarginStyleOffset(self):
		self.ed.MarginSetStyleOffset(300)
		self.assertEquals(self.ed.MarginGetStyleOffset(), 300)

class TestAnnotation(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		self.txt = b"abcd"
		self.ed.AddText(1, b"x")

	def testTextAnnotation(self):
		self.assertEquals(self.ed.AnnotationGetLines(), 0)
		self.ed.AnnotationSetText(0, self.txt)
		self.assertEquals(self.ed.AnnotationGetLines(), 1)
		result = b"\0" * 10
		length = self.ed.AnnotationGetText(0, result)
		self.assertEquals(length, 4)
		result = result[:length]
		self.assertEquals(result, self.txt)
		self.ed.AnnotationClearAll()

	def testTextAnnotationStyle(self):
		self.ed.AnnotationSetText(0, self.txt)
		self.ed.AnnotationSetStyle(0, 33)
		self.assertEquals(self.ed.AnnotationGetStyle(0), 33)
		self.ed.AnnotationClearAll()

	def testTextAnnotationStyles(self):
		styles = b"\001\002\003\004"
		self.ed.AnnotationSetText(0, self.txt)
		self.ed.AnnotationSetStyles(0, styles)
		result = b"\0" * 10
		length = self.ed.AnnotationGetStyles(0, result)
		result = result[:length]
		self.assertEquals(result, styles)
		self.ed.AnnotationClearAll()

	def testExtendedStyles(self):
		start0 = self.ed.AllocateExtendedStyles(0)
		self.assertEquals(start0, 256)
		start1 = self.ed.AllocateExtendedStyles(10)
		self.assertEquals(start1, 256)
		start2 = self.ed.AllocateExtendedStyles(20)
		self.assertEquals(start2, start1 + 10)
		# Reset by changing lexer
		self.ed.ReleaseAllExtendedStyles()
		start0 = self.ed.AllocateExtendedStyles(0)
		self.assertEquals(start0, 256)

	def testTextAnnotationStyleOffset(self):
		self.ed.AnnotationSetStyleOffset(300)
		self.assertEquals(self.ed.AnnotationGetStyleOffset(), 300)

	def testTextAnnotationVisible(self):
		self.assertEquals(self.ed.AnnotationGetVisible(), 0)
		self.ed.AnnotationSetVisible(2)
		self.assertEquals(self.ed.AnnotationGetVisible(), 2)
		self.ed.AnnotationSetVisible(0)

class TestMultiSelection(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		# 3 lines of 3 characters
		t = b"xxx\nxxx\nxxx"
		self.ed.AddText(len(t), t)

	def testSelectionCleared(self):
		self.ed.ClearSelections()
		self.assertEquals(self.ed.Selections, 1)
		self.assertEquals(self.ed.MainSelection, 0)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 0)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 0)

	def test1Selection(self):
		self.ed.SetSelection(1, 2)
		self.assertEquals(self.ed.Selections, 1)
		self.assertEquals(self.ed.MainSelection, 0)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
		self.assertEquals(self.ed.GetSelectionNStart(0), 1)
		self.assertEquals(self.ed.GetSelectionNEnd(0), 2)
		self.ed.SwapMainAnchorCaret()
		self.assertEquals(self.ed.Selections, 1)
		self.assertEquals(self.ed.MainSelection, 0)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)

	def test1SelectionReversed(self):
		self.ed.SetSelection(2, 1)
		self.assertEquals(self.ed.Selections, 1)
		self.assertEquals(self.ed.MainSelection, 0)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
		self.assertEquals(self.ed.GetSelectionNStart(0), 1)
		self.assertEquals(self.ed.GetSelectionNEnd(0), 2)

	def test1SelectionByStartEnd(self):
		self.ed.SetSelectionNStart(0, 2)
		self.ed.SetSelectionNEnd(0, 3)
		self.assertEquals(self.ed.Selections, 1)
		self.assertEquals(self.ed.MainSelection, 0)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
		self.assertEquals(self.ed.GetSelectionNStart(0), 2)
		self.assertEquals(self.ed.GetSelectionNEnd(0), 3)

	def test2Selections(self):
		self.ed.SetSelection(1, 2)
		self.ed.AddSelection(4, 5)
		self.assertEquals(self.ed.Selections, 2)
		self.assertEquals(self.ed.MainSelection, 1)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 2)
		self.assertEquals(self.ed.GetSelectionNCaret(1), 4)
		self.assertEquals(self.ed.GetSelectionNAnchor(1), 5)
		self.assertEquals(self.ed.GetSelectionNStart(0), 1)
		self.assertEquals(self.ed.GetSelectionNEnd(0), 2)
		self.ed.MainSelection = 0
		self.assertEquals(self.ed.MainSelection, 0)
		self.ed.RotateSelection()
		self.assertEquals(self.ed.MainSelection, 1)

	def testRectangularSelection(self):
		self.ed.RectangularSelectionAnchor = 1
		self.assertEquals(self.ed.RectangularSelectionAnchor, 1)
		self.ed.RectangularSelectionCaret = 10
		self.assertEquals(self.ed.RectangularSelectionCaret, 10)
		self.assertEquals(self.ed.Selections, 3)
		self.assertEquals(self.ed.MainSelection, 2)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
		self.assertEquals(self.ed.GetSelectionNAnchor(1), 5)
		self.assertEquals(self.ed.GetSelectionNCaret(1), 6)
		self.assertEquals(self.ed.GetSelectionNAnchor(2), 9)
		self.assertEquals(self.ed.GetSelectionNCaret(2), 10)

	def testVirtualSpace(self):
		self.ed.SetSelection(3, 7)
		self.ed.SetSelectionNCaretVirtualSpace(0, 3)
		self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 3)
		self.ed.SetSelectionNAnchorVirtualSpace(0, 2)
		self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 2)
		# Does not check that virtual space is valid by being at end of line
		self.ed.SetSelection(1, 1)
		self.ed.SetSelectionNCaretVirtualSpace(0, 3)
		self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 3)

	def testRectangularVirtualSpace(self):
		self.ed.VirtualSpaceOptions=1
		self.ed.RectangularSelectionAnchor = 3
		self.assertEquals(self.ed.RectangularSelectionAnchor, 3)
		self.ed.RectangularSelectionCaret = 7
		self.assertEquals(self.ed.RectangularSelectionCaret, 7)
		self.ed.RectangularSelectionAnchorVirtualSpace = 1
		self.assertEquals(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
		self.ed.RectangularSelectionCaretVirtualSpace = 10
		self.assertEquals(self.ed.RectangularSelectionCaretVirtualSpace, 10)
		self.assertEquals(self.ed.Selections, 2)
		self.assertEquals(self.ed.MainSelection, 1)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
		self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 1)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
		self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 10)

	def testRectangularVirtualSpaceOptionOff(self):
		# Same as previous test but virtual space option off so no virtual space in result
		self.ed.VirtualSpaceOptions=0
		self.ed.RectangularSelectionAnchor = 3
		self.assertEquals(self.ed.RectangularSelectionAnchor, 3)
		self.ed.RectangularSelectionCaret = 7
		self.assertEquals(self.ed.RectangularSelectionCaret, 7)
		self.ed.RectangularSelectionAnchorVirtualSpace = 1
		self.assertEquals(self.ed.RectangularSelectionAnchorVirtualSpace, 1)
		self.ed.RectangularSelectionCaretVirtualSpace = 10
		self.assertEquals(self.ed.RectangularSelectionCaretVirtualSpace, 10)
		self.assertEquals(self.ed.Selections, 2)
		self.assertEquals(self.ed.MainSelection, 1)
		self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
		self.assertEquals(self.ed.GetSelectionNAnchorVirtualSpace(0), 0)
		self.assertEquals(self.ed.GetSelectionNCaret(0), 3)
		self.assertEquals(self.ed.GetSelectionNCaretVirtualSpace(0), 0)

class TestCaseMapping(unittest.TestCase):
	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def tearDown(self):
		self.ed.SetCodePage(0)
		self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)

	def testEmpty(self):
		# Trying to upper case an empty string caused a crash at one stage
		t = b"x"
		self.ed.SetText(len(t), t)
		self.ed.UpperCase()
		self.assertEquals(self.ed.Contents(), b"x")

	def testASCII(self):
		t = b"x"
		self.ed.SetText(len(t), t)
		self.ed.SetSel(0,1)
		self.ed.UpperCase()
		self.assertEquals(self.ed.Contents(), b"X")

	def testLatin1(self):
		t = "å".encode("Latin-1")
		r = "Å".encode("Latin-1")
		self.ed.SetText(len(t), t)
		self.ed.SetSel(0,1)
		self.ed.UpperCase()
		self.assertEquals(self.ed.Contents(), r)

	def testRussian(self):
		self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
		t = "Б".encode("Windows-1251")
		r = "б".encode("Windows-1251")
		self.ed.SetText(len(t), t)
		self.ed.SetSel(0,1)
		self.ed.LowerCase()
		self.assertEquals(self.ed.Contents(), r)

	def testUTF(self):
		self.ed.SetCodePage(65001)
		t = "å".encode("UTF-8")
		r = "Å".encode("UTF-8")
		self.ed.SetText(len(t), t)
		self.ed.SetSel(0,2)
		self.ed.UpperCase()
		self.assertEquals(self.ed.Contents(), r)

	def testUTFDifferentLength(self):
		self.ed.SetCodePage(65001)
		t = "ı".encode("UTF-8")
		r = "I".encode("UTF-8")
		self.ed.SetText(len(t), t)
		self.assertEquals(self.ed.Length, 2)
		self.ed.SetSel(0,2)
		self.ed.UpperCase()
		self.assertEquals(self.ed.Length, 1)
		self.assertEquals(self.ed.Contents(), r)

class TestCaseInsensitiveSearch(unittest.TestCase):
	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def tearDown(self):
		self.ed.SetCodePage(0)
		self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_DEFAULT)

	def testEmpty(self):
		text = b" x X"
		searchString = b""
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(0, pos)

	def testASCII(self):
		text = b" x X"
		searchString = b"X"
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(1, pos)

	def testLatin1(self):
		text = "Frånd Åå".encode("Latin-1")
		searchString = "Å".encode("Latin-1")
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(2, pos)

	def testRussian(self):
		self.ed.StyleSetCharacterSet(self.ed.STYLE_DEFAULT, self.ed.SC_CHARSET_RUSSIAN)
		text = "=(Б tex б)".encode("Windows-1251")
		searchString = "б".encode("Windows-1251")
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(2, pos)

	def testUTF(self):
		self.ed.SetCodePage(65001)
		text = "Frånd Åå".encode("UTF-8")
		searchString = "Å".encode("UTF-8")
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(2, pos)

	def testUTFDifferentLength(self):
		# Searching for a two byte string "ı" finds a single byte "I"
		self.ed.SetCodePage(65001)
		text = "Fråndi Ååİ $".encode("UTF-8")
		firstPosition = len("Frånd".encode("UTF-8"))
		searchString = "İ".encode("UTF-8")
		self.assertEquals(len(searchString), 2)
		self.ed.SetText(len(text), text)
		self.ed.TargetStart = 0
		self.ed.TargetEnd = self.ed.Length-1
		self.ed.SearchFlags = 0
		pos = self.ed.SearchInTarget(len(searchString), searchString)
		self.assertEquals(firstPosition, pos)
		self.assertEquals(firstPosition+1, self.ed.TargetEnd)

class TestLexer(unittest.TestCase):
	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testLexerNumber(self):
		self.ed.Lexer = self.ed.SCLEX_CPP
		self.assertEquals(self.ed.GetLexer(), self.ed.SCLEX_CPP)

	def testLexerName(self):
		self.ed.LexerLanguage = b"cpp"
		self.assertEquals(self.ed.GetLexer(), self.ed.SCLEX_CPP)
		name = b"-" * 100
		length = self.ed.GetLexerLanguage(0, name)
		name = name[:length]
		self.assertEquals(name, b"cpp")

class TestAutoComplete(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()
		# 1 line of 3 characters
		t = b"xxx\n"
		self.ed.AddText(len(t), t)

	def testDefaults(self):
		self.assertEquals(self.ed.AutoCGetSeparator(), ord(' '))
		self.assertEquals(self.ed.AutoCGetMaxHeight(), 5)
		self.assertEquals(self.ed.AutoCGetMaxWidth(), 0)
		self.assertEquals(self.ed.AutoCGetTypeSeparator(), ord('?'))
		self.assertEquals(self.ed.AutoCGetIgnoreCase(), 0)
		self.assertEquals(self.ed.AutoCGetAutoHide(), 1)
		self.assertEquals(self.ed.AutoCGetDropRestOfWord(), 0)

	def testChangeDefaults(self):
		self.ed.AutoCSetSeparator(ord('-'))
		self.assertEquals(self.ed.AutoCGetSeparator(), ord('-'))
		self.ed.AutoCSetSeparator(ord(' '))

		self.ed.AutoCSetMaxHeight(100)
		self.assertEquals(self.ed.AutoCGetMaxHeight(), 100)
		self.ed.AutoCSetMaxHeight(5)

		self.ed.AutoCSetMaxWidth(100)
		self.assertEquals(self.ed.AutoCGetMaxWidth(), 100)
		self.ed.AutoCSetMaxWidth(0)

		self.ed.AutoCSetTypeSeparator(ord('@'))
		self.assertEquals(self.ed.AutoCGetTypeSeparator(), ord('@'))
		self.ed.AutoCSetTypeSeparator(ord('?'))

		self.ed.AutoCSetIgnoreCase(1)
		self.assertEquals(self.ed.AutoCGetIgnoreCase(), 1)
		self.ed.AutoCSetIgnoreCase(0)

		self.ed.AutoCSetAutoHide(0)
		self.assertEquals(self.ed.AutoCGetAutoHide(), 0)
		self.ed.AutoCSetAutoHide(1)

		self.ed.AutoCSetDropRestOfWord(1)
		self.assertEquals(self.ed.AutoCGetDropRestOfWord(), 1)
		self.ed.AutoCSetDropRestOfWord(0)

	def testAutoShow(self):
		self.assertEquals(self.ed.AutoCActive(), 0)
		self.ed.SetSel(0, 0)

		self.ed.AutoCShow(0, b"za defn ghi")
		self.assertEquals(self.ed.AutoCActive(), 1)
		#~ time.sleep(2)
		self.assertEquals(self.ed.AutoCPosStart(), 0)
		self.assertEquals(self.ed.AutoCGetCurrent(), 0)
		t = b"xxx"
		l = self.ed.AutoCGetCurrentText(5, t)
		#~ self.assertEquals(l, 3)
		self.assertEquals(t, b"za\0")
		self.ed.AutoCCancel()
		self.assertEquals(self.ed.AutoCActive(), 0)

	def testAutoShowComplete(self):
		self.assertEquals(self.ed.AutoCActive(), 0)
		self.ed.SetSel(0, 0)

		self.ed.AutoCShow(0, b"za defn ghi")
		self.ed.AutoCComplete()
		self.assertEquals(self.ed.Contents(), b"zaxxx\n")

		self.assertEquals(self.ed.AutoCActive(), 0)

	def testAutoShowSelect(self):
		self.assertEquals(self.ed.AutoCActive(), 0)
		self.ed.SetSel(0, 0)

		self.ed.AutoCShow(0, b"za defn ghi")
		self.ed.AutoCSelect(0, b"d")
		self.ed.AutoCComplete()
		self.assertEquals(self.ed.Contents(), b"defnxxx\n")

		self.assertEquals(self.ed.AutoCActive(), 0)

class TestDirectAccess(unittest.TestCase):

	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def testGapPosition(self):
		text = b"abcd"
		self.ed.SetText(len(text), text)
		self.assertEquals(self.ed.GapPosition, 4)
		self.ed.TargetStart = 1
		self.ed.TargetEnd = 1
		rep = b"-"
		self.ed.ReplaceTarget(len(rep), rep)
		self.assertEquals(self.ed.GapPosition, 2)

	def testCharacterPointerAndRangePointer(self):
		text = b"abcd"
		self.ed.SetText(len(text), text)
		characterPointer = self.ed.CharacterPointer
		rangePointer = self.ed.GetRangePointer(0,3)
		self.assertEquals(characterPointer, rangePointer)
		cpBuffer = ctypes.c_char_p(characterPointer)
		self.assertEquals(cpBuffer.value, text)
		# Gap will not be moved as already moved for CharacterPointer call
		rangePointer = self.ed.GetRangePointer(1,3)
		cpBuffer = ctypes.c_char_p(rangePointer)
		self.assertEquals(cpBuffer.value, text[1:])

class TestWordChars(unittest.TestCase):
	def setUp(self):
		self.xite = XiteWin.xiteFrame
		self.ed = self.xite.ed
		self.ed.ClearAll()
		self.ed.EmptyUndoBuffer()

	def tearDown(self):
		self.ed.SetCharsDefault()

	def _setChars(self, charClass, chars):
		""" Wrapper to call self.ed.Set*Chars with the right type
		@param charClass {str} the character class, "word", "space", etc.
		@param chars {iterable of int} characters to set
		"""
		if sys.version_info.major == 2:
			# Python 2, use latin-1 encoded str
			unichars = (unichr(x) for x in chars if x != 0)
			# can't use literal u"", that's a syntax error in Py3k
			# uncode() doesn't exist in Py3k, but we never run it there
			result = unicode("").join(unichars).encode("latin-1")
		else:
			# Python 3, use bytes()
			result = bytes(x for x in chars if x != 0)
		meth = getattr(self.ed, "Set%sChars" % (charClass.capitalize()))
		return meth(None, result)

	def assertCharSetsEqual(self, first, second, *args, **kwargs):
		""" Assert that the two character sets are equal.
		If either set are an iterable of numbers, convert them to chars
		first. """
		first_set = set()
		for c in first:
			first_set.add(chr(c) if isinstance(c, int) else c)
		second_set = set()
		for c in second:
			second_set.add(chr(c) if isinstance(c, int) else c)
		return self.assertEqual(first_set, second_set, *args, **kwargs)

	def testDefaultWordChars(self):
		# check that the default word chars are as expected
		import string
		dataLen = self.ed.GetWordChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWordChars(None, data)
		self.assertEquals(dataLen, len(data))
		expected = set(string.digits + string.ascii_letters + '_') | \
			set(chr(x) for x in range(0x80, 0x100))
		self.assertCharSetsEqual(data, expected)

	def testDefaultWhitespaceChars(self):
		# check that the default whitespace chars are as expected
		import string
		dataLen = self.ed.GetWhitespaceChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWhitespaceChars(None, data)
		self.assertEquals(dataLen, len(data))
		expected = (set(chr(x) for x in (range(0, 0x20))) | set(' ')) - \
			set(['\r', '\n'])
		self.assertCharSetsEqual(data, expected)

	def testDefaultPunctuationChars(self):
		# check that the default punctuation chars are as expected
		import string
		dataLen = self.ed.GetPunctuationChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetPunctuationChars(None, data)
		self.assertEquals(dataLen, len(data))
		expected = set(chr(x) for x in range(0x20, 0x80)) - \
			set(string.ascii_letters + string.digits + "\r\n_ ")
		self.assertCharSetsEqual(data, expected)

	def testCustomWordChars(self):
		# check that setting things to whitespace chars makes them not words
		self._setChars("whitespace", range(1, 0x100))
		dataLen = self.ed.GetWordChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWordChars(None, data)
		self.assertEquals(dataLen, len(data))
		expected = set()
		self.assertCharSetsEqual(data, expected)
		# and now set something to make sure that works too
		expected = set(range(1, 0x100, 2))
		self._setChars("word", expected)
		dataLen = self.ed.GetWordChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWordChars(None, data)
		self.assertEquals(dataLen, len(data))
		self.assertCharSetsEqual(data, expected)

	def testCustomWhitespaceChars(self):
		# check setting whitespace chars to non-default values
		self._setChars("word", range(1, 0x100))
		# we can't change chr(0) from being anything but whitespace
		expected = set([0])
		dataLen = self.ed.GetWhitespaceChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWhitespaceChars(None, data)
		self.assertEquals(dataLen, len(data))
		self.assertCharSetsEqual(data, expected)
		# now try to set it to something custom
		expected = set(range(1, 0x100, 2)) | set([0])
		self._setChars("whitespace", expected)
		dataLen = self.ed.GetWhitespaceChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetWhitespaceChars(None, data)
		self.assertEquals(dataLen, len(data))
		self.assertCharSetsEqual(data, expected)

	def testCustomPunctuationChars(self):
		# check setting punctuation chars to non-default values
		self._setChars("word", range(1, 0x100))
		expected = set()
		dataLen = self.ed.GetPunctuationChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetPunctuationChars(None, data)
		self.assertEquals(dataLen, len(data))
		self.assertEquals(set(data), expected)
		# now try to set it to something custom
		expected = set(range(1, 0x100, 1))
		self._setChars("punctuation", expected)
		dataLen = self.ed.GetPunctuationChars(None, None)
		data = b"\0" * dataLen
		self.ed.GetPunctuationChars(None, data)
		self.assertEquals(dataLen, len(data))
		self.assertCharSetsEqual(data, expected)

#~ import os
#~ for x in os.getenv("PATH").split(";"):
	#~ n = "scilexer.dll"
	#~ nf = x + "\\" + n
	#~ print os.access(nf, os.R_OK), nf
if __name__ == '__main__':
	uu = XiteWin.main("simpleTests")
	#~ for x in sorted(uu.keys()):
		#~ print(x, uu[x])
	#~ print()

Added test/unit/README.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
The test/unit directory contains unit tests for Scintilla data structures.

The tests can be run on Windows or Linux using g++ and GNU make.
The Google Test framework is used.
http://code.google.com/p/googletest/

Google test must be installed first.
On Linux, install the google test packages libgtest-dev and libgtest0.
On Windows download Google test and install it as a peer to the directory
containing scintilla. The makefile assumes it is in ../../../../gtest-1.5.0.

To run the tests:
make
./unitTest

Added test/unit/SciTE.properties.









>
>
>
>
1
2
3
4
if PLAT_WIN
	make.command=mingw32-make
command.go.*.cxx=./unitTest
command.go.needs.$(file.patterns.cplusplus)=$(make.command)

Added test/unit/makefile.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Build all the unit tests
# Should be run using mingw32-make on Windows

.SUFFIXES: .cxx

GTEST_DIR = ../../../../gtest-1.5.0

ifdef windir

DEL = del /q
# Find Google Test headers.
CPPFLAGS += -I$(GTEST_DIR)/include
GTEST_ALL =  gtest-all.o
LINKFLAGS = $(CPPFLAGS) $(CXXFLAGS)
EXE = unitTest.exe

else

DEL = rm -f
CPPFLAGS = $(shell gtest-config --cppflags)
CXXFLAGS = $(shell gtest-config --cxxflags)
LINKFLAGS = $(shell gtest-config --ldflags --libs)
EXE = unitTest

# For coverage testing with gcov
#CPPFLAGS += -fprofile-arcs -ftest-coverage
#LINKFLAGS += -fprofile-arcs -ftest-coverage

endif

#vpath %.cxx ../src ../lexlib ../lexers
vpath %.cxx ../../src


INCLUDEDIRS = -I ../../include -I ../../src -I../../lexlib


# Find headers of test code.
CPPFLAGS += $(INCLUDEDIRS)

CXXFLAGS += -g -Wall -Wextra -Wno-unused-function
#~ CXXFLAGS += -g -Wall

CASES:=$(addsuffix .o,$(basename $(notdir $(wildcard test*.cxx))))
TESTEDOBJS=ContractionState.o RunStyles.o CharClassify.o

TESTS=$(EXE)

GTEST_HEADERS=$(GTEST_DIR)/include/gtest/*.h $(GTEST_DIR)/include/gtest/internal/*.h

all: $(TESTS)

clean:
	$(DEL) $(TESTS) *.a *.o *.exe *.gcov *.gcda *.gcno

# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)

gtest-all.o: $(GTEST_SRCS_)
	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(GTEST_DIR) -c \
            $(GTEST_DIR)/src/gtest-all.cc

.cxx.o:
	$(CXX) $(CPPFLAGS) $(CXXFLAGS)  -c $<

$(EXE): $(CASES) $(TESTEDOBJS) unitTest.o $(GTEST_ALL)
	$(CXX) $(LINKFLAGS) $^ -o $@

Added test/unit/testCharClassify.cxx.





























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

#include <string.h>

#include "Platform.h"

#include "CharClassify.h"

#include <gtest/gtest.h>

// Test CharClassify.

class CharClassifyTest : public::testing::Test {
protected:
	virtual void SetUp() {
		pcc = new CharClassify();
		for (int ch = 0; ch < 256; ch++) {
			if (ch == '\r' || ch == '\n')
				charClass[ch] = CharClassify::ccNewLine;
			else if (ch < 0x20 || ch == ' ')
				charClass[ch] = CharClassify::ccSpace;
			else if (ch >= 0x80 || isalnum(ch) || ch == '_')
				charClass[ch] = CharClassify::ccWord;
			else
				charClass[ch] = CharClassify::ccPunctuation;
		}
	}

	virtual void TearDown() {
		delete pcc;
		pcc = 0;
	}

	CharClassify *pcc;
	CharClassify::cc charClass[256];

	static const char* GetClassName(CharClassify::cc charClass) {
		switch(charClass) {
			#define CASE(c) case CharClassify::c: return #c
			CASE(ccSpace);
			CASE(ccNewLine);
			CASE(ccWord);
			CASE(ccPunctuation);
			#undef CASE
			default:
				return "<unknown>";
		}
	}
};

TEST_F(CharClassifyTest, Defaults) {
	for (int i = 0; i < 256; i++) {
		EXPECT_EQ(charClass[i], pcc->GetClass(i))
			<< "Character " << i
			<< " should be class " << GetClassName(charClass[i])
			<< ", but got " << GetClassName(pcc->GetClass(i));
	}
}

TEST_F(CharClassifyTest, Custom) {
	unsigned char buf[2] = {0, 0};
	for (int i = 0; i < 256; i++) {
		CharClassify::cc thisClass = CharClassify::cc(i % 4);
		buf[0] = i;
		pcc->SetCharClasses(buf, thisClass);
		charClass[i] = thisClass;
	}
	for (int i = 0; i < 256; i++) {
		EXPECT_EQ(charClass[i], pcc->GetClass(i))
			<< "Character " << i
			<< " should be class " << GetClassName(charClass[i])
			<< ", but got " << GetClassName(pcc->GetClass(i));
	}
}

TEST_F(CharClassifyTest, CharsOfClass) {
	unsigned char buf[2] = {0, 0};
	for (int i = 1; i < 256; i++) {
		CharClassify::cc thisClass = CharClassify::cc(i % 4);
		buf[0] = i;
		pcc->SetCharClasses(buf, thisClass);
		charClass[i] = thisClass;
	}
	for (int classVal = 0; classVal < 4; ++classVal) {
		CharClassify::cc thisClass = CharClassify::cc(classVal % 4);
		int size = pcc->GetCharsOfClass(thisClass, NULL);
		unsigned char* buffer = reinterpret_cast<unsigned char*>(malloc(size + 1));
		ASSERT_TRUE(buffer);
		buffer[size] = '\0';
		pcc->GetCharsOfClass(thisClass, buffer);
		for (int i = 1; i < 256; i++) {
			if (charClass[i] == thisClass) {
				EXPECT_TRUE(memchr(reinterpret_cast<char*>(buffer), i, size))
					<< "Character " << i
					<< " should be class " << GetClassName(thisClass)
					<< ", but was not in GetCharsOfClass;"
					<< " it is reported to be "
					<< GetClassName(pcc->GetClass(i));
			} else {
				EXPECT_FALSE(memchr(reinterpret_cast<char*>(buffer), i, size))
					<< "Character " << i
					<< " should not be class " << GetClassName(thisClass)
					<< ", but was in GetCharsOfClass"
					<< " it is reported to be "
					<< GetClassName(pcc->GetClass(i));
			}
		}
		free(buffer);
	}
}

Added test/unit/testContractionState.cxx.





































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"

#include <gtest/gtest.h>

// Test ContractionState.

class ContractionStateTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		pcs = new ContractionState();
	}

	virtual void TearDown() {
		delete pcs;
		pcs = 0;
	}

	ContractionState *pcs;
};

TEST_F(ContractionStateTest, IsEmptyInitially) {
	EXPECT_EQ(1, pcs->LinesInDoc());
	EXPECT_EQ(1, pcs->LinesDisplayed());
	EXPECT_EQ(0, pcs->DisplayFromDoc(0));
	EXPECT_EQ(0, pcs->DocFromDisplay(0));
}

TEST_F(ContractionStateTest, OneLine) {
	pcs->InsertLine(0);
	EXPECT_EQ(2, pcs->LinesInDoc());
	EXPECT_EQ(2, pcs->LinesDisplayed());
	EXPECT_EQ(0, pcs->DisplayFromDoc(0));
	EXPECT_EQ(0, pcs->DocFromDisplay(0));
	EXPECT_EQ(1, pcs->DisplayFromDoc(1));
	EXPECT_EQ(1, pcs->DocFromDisplay(1));
}

TEST_F(ContractionStateTest, InsertionThenDeletions) {
	pcs->InsertLines(0,4);
	pcs->DeleteLine(1);
	
	EXPECT_EQ(4, pcs->LinesInDoc());
	EXPECT_EQ(4, pcs->LinesDisplayed());
	for (int l=0;l<4;l++) {
		EXPECT_EQ(l, pcs->DisplayFromDoc(l));
		EXPECT_EQ(l, pcs->DocFromDisplay(l));
	}
	
	pcs->DeleteLines(0,2);
	EXPECT_EQ(2, pcs->LinesInDoc());
	EXPECT_EQ(2, pcs->LinesDisplayed());
	for (int l=0;l<2;l++) {
		EXPECT_EQ(l, pcs->DisplayFromDoc(l));
		EXPECT_EQ(l, pcs->DocFromDisplay(l));
	}
}

TEST_F(ContractionStateTest, ShowHide) {
	pcs->InsertLines(0,4);
	EXPECT_EQ(true, pcs->GetVisible(0));
	EXPECT_EQ(true, pcs->GetVisible(1));
	EXPECT_EQ(true, pcs->GetVisible(2));
	EXPECT_EQ(5, pcs->LinesDisplayed());

	pcs->SetVisible(1, 1, false);
	EXPECT_EQ(true, pcs->GetVisible(0));
	EXPECT_EQ(0, pcs->GetVisible(1));
	EXPECT_EQ(true, pcs->GetVisible(2));
	EXPECT_EQ(4, pcs->LinesDisplayed());
	EXPECT_EQ(1, pcs->HiddenLines());

	pcs->SetVisible(1, 2, true);
	for (int l=0;l<4;l++) {
		EXPECT_EQ(true, pcs->GetVisible(0));
	}

	pcs->SetVisible(1, 1, false);
	EXPECT_EQ(0, pcs->GetVisible(1));
	pcs->ShowAll();
	for (int l=0;l<4;l++) {
		EXPECT_EQ(true, pcs->GetVisible(0));
	}
	EXPECT_EQ(0, pcs->HiddenLines());
}

TEST_F(ContractionStateTest, Hidden) {
	pcs->InsertLines(0,1);
	for (int l=0;l<2;l++) {
		EXPECT_EQ(true, pcs->GetVisible(0));
	}
	EXPECT_EQ(0, pcs->HiddenLines());

	pcs->SetVisible(1, 1, false);
	EXPECT_EQ(true, pcs->GetVisible(0));
	EXPECT_EQ(0, pcs->GetVisible(1));
	EXPECT_EQ(1, pcs->HiddenLines());

	pcs->SetVisible(1, 1, true);
	for (int l=0;l<2;l++) {
		EXPECT_EQ(true, pcs->GetVisible(0));
	}
	EXPECT_EQ(0, pcs->HiddenLines());
}

TEST_F(ContractionStateTest, Contracting) {
	pcs->InsertLines(0,4);
	for (int l=0;l<4;l++) {
		EXPECT_EQ(true, pcs->GetExpanded(l));
	}

	pcs->SetExpanded(2, false);
	EXPECT_EQ(true, pcs->GetExpanded(1));
	EXPECT_EQ(0, pcs->GetExpanded(2));
	EXPECT_EQ(true, pcs->GetExpanded(3));
	
	EXPECT_EQ(2, pcs->ContractedNext(0));
	EXPECT_EQ(2, pcs->ContractedNext(1));
	EXPECT_EQ(2, pcs->ContractedNext(2));
	EXPECT_EQ(-1, pcs->ContractedNext(3));

	pcs->SetExpanded(2, true);
	EXPECT_EQ(true, pcs->GetExpanded(1));
	EXPECT_EQ(true, pcs->GetExpanded(2));
	EXPECT_EQ(true, pcs->GetExpanded(3));
}

TEST_F(ContractionStateTest, ChangeHeight) {
	pcs->InsertLines(0,4);
	for (int l=0;l<4;l++) {
		EXPECT_EQ(1, pcs->GetHeight(l));
	}

	pcs->SetHeight(1, 2);
	EXPECT_EQ(1, pcs->GetHeight(0));
	EXPECT_EQ(2, pcs->GetHeight(1));
	EXPECT_EQ(1, pcs->GetHeight(2));
}

Added test/unit/testPartitioning.cxx.

































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"

#include <gtest/gtest.h>

const int growSize = 4;

const int lengthTestArray = 8;
static const int testArray[lengthTestArray] = {3, 4, 5, 6, 7, 8, 9, 10};

// Test SplitVectorWithRangeAdd.

class SplitVectorWithRangeAddTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		psvwra = new SplitVectorWithRangeAdd(growSize);
	}

	virtual void TearDown() {
		delete psvwra;
		psvwra = 0;
	}

	SplitVectorWithRangeAdd *psvwra;
};

TEST_F(SplitVectorWithRangeAddTest, IsEmptyInitially) {
	EXPECT_EQ(0, psvwra->Length());
}

TEST_F(SplitVectorWithRangeAddTest, IncrementExceptEnds) {
	psvwra->InsertFromArray(0, testArray, 0, lengthTestArray);
	psvwra->RangeAddDelta(1, lengthTestArray-1, 1);
	for (int i=0; i<psvwra->Length(); i++) {
		if ((i == 0) || (i == lengthTestArray-1))
			EXPECT_EQ(i+3, psvwra->ValueAt(i));
		else
			EXPECT_EQ(i+4, psvwra->ValueAt(i));
	}
}

// Test Partitioning.

class PartitioningTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		pp = new Partitioning(growSize);
	}

	virtual void TearDown() {
		delete pp;
		pp = 0;
	}

	Partitioning *pp;
};

TEST_F(PartitioningTest, IsEmptyInitially) {
	EXPECT_EQ(1, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(pp->Partitions()));
	EXPECT_EQ(0, pp->PartitionFromPosition(0));
}

TEST_F(PartitioningTest, SimpleInsert) {
	pp->InsertText(0, 1);
	EXPECT_EQ(1, pp->Partitions());
	EXPECT_EQ(1, pp->PositionFromPartition(pp->Partitions()));
}

TEST_F(PartitioningTest, TwoPartitions) {
	pp->InsertText(0, 2);
	pp->InsertPartition(1, 1);
	EXPECT_EQ(2, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(1, pp->PositionFromPartition(1));
	EXPECT_EQ(2, pp->PositionFromPartition(2));
}

TEST_F(PartitioningTest, MoveStart) {
	pp->InsertText(0, 3);
	pp->InsertPartition(1, 2);
	pp->SetPartitionStartPosition(1,1);
	EXPECT_EQ(2, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(1, pp->PositionFromPartition(1));
	EXPECT_EQ(3, pp->PositionFromPartition(2));
}

TEST_F(PartitioningTest, InsertAgain) {
	pp->InsertText(0, 3);
	pp->InsertPartition(1, 2);
	pp->InsertText(0,3);
	pp->InsertText(1,2);
	EXPECT_EQ(2, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(5, pp->PositionFromPartition(1));
	EXPECT_EQ(8, pp->PositionFromPartition(2));
}

TEST_F(PartitioningTest, InsertReversed) {
	pp->InsertText(0, 3);
	pp->InsertPartition(1, 2);
	pp->InsertText(1,2);
	pp->InsertText(0,3);
	EXPECT_EQ(2, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(5, pp->PositionFromPartition(1));
	EXPECT_EQ(8, pp->PositionFromPartition(2));
}

TEST_F(PartitioningTest, InverseSearch) {
	pp->InsertText(0, 3);
	pp->InsertPartition(1, 2);
	pp->SetPartitionStartPosition(1,1);

	EXPECT_EQ(2, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(1, pp->PositionFromPartition(1));
	EXPECT_EQ(3, pp->PositionFromPartition(2));

	EXPECT_EQ(0, pp->PartitionFromPosition(0));
	EXPECT_EQ(1, pp->PartitionFromPosition(1));
	EXPECT_EQ(1, pp->PartitionFromPosition(2));

	EXPECT_EQ(1, pp->PartitionFromPosition(3));
}

TEST_F(PartitioningTest, DeletePartition) {
	pp->InsertText(0, 2);
	pp->InsertPartition(1, 1);
	pp->RemovePartition(1);
	EXPECT_EQ(1, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(2, pp->PositionFromPartition(1));
}

TEST_F(PartitioningTest, DeleteAll) {
	pp->InsertText(0, 3);
	pp->InsertPartition(1, 2);
	pp->SetPartitionStartPosition(1,1);
	pp->DeleteAll();
	// Back to initial state
	EXPECT_EQ(1, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(pp->Partitions()));
}

TEST_F(PartitioningTest, TestBackwards) {
	pp->InsertText(0, 10);
	pp->InsertPartition(1, 3);
	pp->InsertPartition(2, 6);
	pp->InsertPartition(3, 9);
	pp->InsertText(2,4);
	pp->InsertText(1,2);
	pp->InsertText(0,3);
	EXPECT_EQ(4, pp->Partitions());
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(6, pp->PositionFromPartition(1));
	EXPECT_EQ(11, pp->PositionFromPartition(2));
	EXPECT_EQ(18, pp->PositionFromPartition(3));
	EXPECT_EQ(19, pp->PositionFromPartition(4));
}

TEST_F(PartitioningTest, TestMany) {
	// Provoke backstep call
	pp->InsertText(0, 42);
	for (int i=0; i<20; i++) {
		pp->InsertPartition(i+1, (i+1) * 2);
	}
	for (int i=20; i>0; i--) {
		pp->InsertText(i,2);
	}
	EXPECT_EQ(21, pp->Partitions());
	for (int i=1; i<20; i++) {
		EXPECT_EQ(i*4 - 2, pp->PositionFromPartition(i));
		EXPECT_EQ(i, pp->PartitionFromPosition(i*4 - 2));
	}
	pp->InsertText(19,2);
	EXPECT_EQ(3, pp->PartitionFromPosition(10));
	pp->InsertText(0,2);
	pp->InsertText(0,-2);
	pp->RemovePartition(1);
	EXPECT_EQ(0, pp->PositionFromPartition(0));
	EXPECT_EQ(6, pp->PositionFromPartition(1));
	EXPECT_EQ(10, pp->PositionFromPartition(2));
	pp->RemovePartition(10);
	EXPECT_EQ(46, pp->PositionFromPartition(10));
	EXPECT_EQ(10, pp->PartitionFromPosition(46));
	EXPECT_EQ(50, pp->PositionFromPartition(11));
	EXPECT_EQ(11, pp->PartitionFromPosition(50));
}

#if !PLAT_WIN
// Omit death tests on Windows where they trigger a system "unitTest.exe has stopped working" popup.
TEST_F(PartitioningTest, OutOfRangeDeathTest) {
	::testing::FLAGS_gtest_death_test_style = "threadsafe";
	pp->InsertText(0, 2);
	pp->InsertPartition(1, 1);
	EXPECT_EQ(2, pp->Partitions());
	ASSERT_DEATH(pp->PositionFromPartition(-1), "Assertion");
	ASSERT_DEATH(pp->PositionFromPartition(3), "Assertion");
}
#endif

Added test/unit/testRunStyles.cxx.





















































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
// Unit Tests for Scintilla internal data structures

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"

#include <gtest/gtest.h>

// Test RunStyles.

class RunStylesTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		prs = new RunStyles();
	}

	virtual void TearDown() {
		delete prs;
		prs = 0;
	}

	RunStyles *prs;
};

TEST_F(RunStylesTest, IsEmptyInitially) {
	EXPECT_EQ(0, prs->Length());
	EXPECT_EQ(1, prs->Runs());
}

TEST_F(RunStylesTest, SimpleInsert) {
	prs->InsertSpace(0, 1);
	EXPECT_EQ(1, prs->Length());
	EXPECT_EQ(1, prs->Runs());
	EXPECT_EQ(0, prs->ValueAt(0));
	EXPECT_EQ(1, prs->FindNextChange(0, prs->Length()));
	EXPECT_EQ(2, prs->FindNextChange(1, prs->Length()));
}

TEST_F(RunStylesTest, TwoRuns) {
	prs->InsertSpace(0, 2);
	EXPECT_EQ(2, prs->Length());
	EXPECT_EQ(1, prs->Runs());
	prs->SetValueAt(0, 2);
	EXPECT_EQ(2, prs->Runs());
	EXPECT_EQ(2, prs->ValueAt(0));
	EXPECT_EQ(0, prs->ValueAt(1));
	EXPECT_EQ(1, prs->FindNextChange(0, prs->Length()));
	EXPECT_EQ(2, prs->FindNextChange(1, prs->Length()));
	EXPECT_EQ(3, prs->FindNextChange(2, prs->Length()));
}

TEST_F(RunStylesTest, LongerRuns) {
	prs->InsertSpace(0, 5);
	prs->SetValueAt(0, 3);
	prs->SetValueAt(1, 3);
	EXPECT_EQ(3, prs->ValueAt(0));
	EXPECT_EQ(3, prs->ValueAt(1));
	EXPECT_EQ(0, prs->ValueAt(2));
	EXPECT_EQ(2, prs->Runs());

	EXPECT_EQ(0, prs->StartRun(0));
	EXPECT_EQ(2, prs->EndRun(0));

	EXPECT_EQ(0, prs->StartRun(1));
	EXPECT_EQ(2, prs->EndRun(1));

	EXPECT_EQ(2, prs->StartRun(2));
	EXPECT_EQ(5, prs->EndRun(2));

	EXPECT_EQ(2, prs->StartRun(3));
	EXPECT_EQ(5, prs->EndRun(3));

	EXPECT_EQ(2, prs->StartRun(4));
	EXPECT_EQ(5, prs->EndRun(4));

	// At end
	EXPECT_EQ(2, prs->StartRun(5));
	EXPECT_EQ(5, prs->EndRun(5));

	// After end is same as end
	EXPECT_EQ(2, prs->StartRun(6));
	EXPECT_EQ(5, prs->EndRun(6));

	EXPECT_EQ(2, prs->FindNextChange(0, prs->Length()));
	EXPECT_EQ(5, prs->FindNextChange(2, prs->Length()));
	EXPECT_EQ(6, prs->FindNextChange(5, prs->Length()));
}

TEST_F(RunStylesTest, FillRange) {
	prs->InsertSpace(0, 5);
	int startFill = 1;
	int lengthFill = 3;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(1, startFill);
	EXPECT_EQ(3, lengthFill);

	EXPECT_EQ(0, prs->ValueAt(0));
	EXPECT_EQ(99, prs->ValueAt(1));
	EXPECT_EQ(99, prs->ValueAt(2));
	EXPECT_EQ(99, prs->ValueAt(3));
	EXPECT_EQ(0, prs->ValueAt(4));

	EXPECT_EQ(0, prs->StartRun(0));
	EXPECT_EQ(1, prs->EndRun(0));

	EXPECT_EQ(1, prs->StartRun(1));
	EXPECT_EQ(4, prs->EndRun(1));
}

TEST_F(RunStylesTest, FillRangeAlreadyFilled) {
	prs->InsertSpace(0, 5);
	int startFill = 1;
	int lengthFill = 3;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(1, startFill);
	EXPECT_EQ(3, lengthFill);

	int startFill2 = 2;
	int lengthFill2 = 1;
	// Compiler warnings if 'false' used instead of '0' as expected value:
	EXPECT_EQ(0, prs->FillRange(startFill2, 99, lengthFill2));
	EXPECT_EQ(2, startFill2);
	EXPECT_EQ(1, lengthFill2);
	EXPECT_EQ(0, prs->ValueAt(0));
	EXPECT_EQ(99, prs->ValueAt(1));
	EXPECT_EQ(99, prs->ValueAt(2));
	EXPECT_EQ(99, prs->ValueAt(3));
	EXPECT_EQ(0, prs->ValueAt(4));
	EXPECT_EQ(3, prs->Runs());
}

TEST_F(RunStylesTest, FillRangeAlreadyPartFilled) {
	prs->InsertSpace(0, 5);
	int startFill = 1;
	int lengthFill = 2;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(1, startFill);
	EXPECT_EQ(2, lengthFill);

	int startFill2 = 2;
	int lengthFill2 = 2;
	EXPECT_EQ(true, prs->FillRange(startFill2, 99, lengthFill2));
	EXPECT_EQ(3, startFill2);
	EXPECT_EQ(1, lengthFill2);
	EXPECT_EQ(3, prs->Runs());
}

TEST_F(RunStylesTest, DeleteRange) {
	prs->InsertSpace(0, 5);
	prs->SetValueAt(0, 3);
	EXPECT_EQ(2, prs->Runs());
	prs->SetValueAt(1, 3);
	EXPECT_EQ(2, prs->Runs());
	prs->DeleteRange(1, 1);
	EXPECT_EQ(4, prs->Length());
	EXPECT_EQ(2, prs->Runs());
	EXPECT_EQ(3, prs->ValueAt(0));
	EXPECT_EQ(0, prs->ValueAt(1));

	EXPECT_EQ(0, prs->StartRun(0));
	EXPECT_EQ(1, prs->EndRun(0));

	EXPECT_EQ(1, prs->StartRun(1));
	EXPECT_EQ(4, prs->EndRun(1));

	EXPECT_EQ(1, prs->StartRun(2));
	EXPECT_EQ(4, prs->EndRun(2));
}

TEST_F(RunStylesTest, Find) {
	prs->InsertSpace(0, 5);
	int startFill = 1;
	int lengthFill = 3;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(1, startFill);
	EXPECT_EQ(3, lengthFill);

	EXPECT_EQ(0, prs->Find(0,0));
	EXPECT_EQ(1, prs->Find(99,0));
	EXPECT_EQ(-1, prs->Find(3,0));
	
	EXPECT_EQ(4, prs->Find(0,1));
	EXPECT_EQ(1, prs->Find(99,1));
	EXPECT_EQ(-1, prs->Find(3,1));
	
	EXPECT_EQ(4, prs->Find(0,2));
	EXPECT_EQ(2, prs->Find(99,2));
	EXPECT_EQ(-1, prs->Find(3,2));

	EXPECT_EQ(4, prs->Find(0,4));
	EXPECT_EQ(-1, prs->Find(99,4));
	EXPECT_EQ(-1, prs->Find(3,4));

	EXPECT_EQ(-1, prs->Find(0,5));
	EXPECT_EQ(-1, prs->Find(99,5));
	EXPECT_EQ(-1, prs->Find(3,5));

	EXPECT_EQ(-1, prs->Find(0,6));
	EXPECT_EQ(-1, prs->Find(99,6));
	EXPECT_EQ(-1, prs->Find(3,6));
}

TEST_F(RunStylesTest, AllSame) {
	EXPECT_EQ(true, prs->AllSame());
	prs->InsertSpace(0, 5);
	EXPECT_EQ(true, prs->AllSame());
	EXPECT_EQ(0, prs->AllSameAs(88));
	EXPECT_EQ(true, prs->AllSameAs(0));
	int startFill = 1;
	int lengthFill = 3;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(0, prs->AllSame());
	EXPECT_EQ(0, prs->AllSameAs(88));
	EXPECT_EQ(0, prs->AllSameAs(0));
	EXPECT_EQ(true, prs->FillRange(startFill, 0, lengthFill));
	EXPECT_EQ(true, prs->AllSame());
	EXPECT_EQ(0, prs->AllSameAs(88));
	EXPECT_EQ(true, prs->AllSameAs(0));
}

TEST_F(RunStylesTest, FindWithReversion) {
	prs->InsertSpace(0, 5);
	EXPECT_EQ(1, prs->Runs());

	int startFill = 1;
	int lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(1, startFill);
	EXPECT_EQ(1, lengthFill);
	EXPECT_EQ(3, prs->Runs());

	startFill = 2;
	lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(2, startFill);
	EXPECT_EQ(1, lengthFill);
	EXPECT_EQ(3, prs->Runs());

	startFill = 1;
	lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 0, lengthFill));
	EXPECT_EQ(3, prs->Runs());
	EXPECT_EQ(1, lengthFill);

	startFill = 2;
	lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 0, lengthFill));
	EXPECT_EQ(1, prs->Runs());
	EXPECT_EQ(1, lengthFill);

	EXPECT_EQ(-1, prs->Find(0,6));
}

TEST_F(RunStylesTest, FinalRunInversion) {
	EXPECT_EQ(1, prs->Runs());
	prs->InsertSpace(0, 1);
	EXPECT_EQ(1, prs->Runs());
	prs->SetValueAt(0, 1);
	EXPECT_EQ(1, prs->Runs());
	prs->InsertSpace(1, 1);
	EXPECT_EQ(1, prs->Runs());
	prs->SetValueAt(1, 1);
	EXPECT_EQ(1, prs->Runs());
	prs->SetValueAt(1, 0);
	EXPECT_EQ(2, prs->Runs());
	prs->SetValueAt(1, 1);
	EXPECT_EQ(1, prs->Runs());
}	

TEST_F(RunStylesTest, DeleteAll) {
	prs->InsertSpace(0, 5);
	prs->SetValueAt(0, 3);
	prs->SetValueAt(1, 3);
	prs->DeleteAll();
	EXPECT_EQ(0, prs->Length());
	EXPECT_EQ(0, prs->ValueAt(0));
	EXPECT_EQ(1, prs->Runs());
}

TEST_F(RunStylesTest, DeleteSecond) {
	prs->InsertSpace(0, 3);
	int startFill = 1;
	int lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(3, prs->Length());
	EXPECT_EQ(3, prs->Runs());
	prs->DeleteRange(1, 1);
	EXPECT_EQ(2, prs->Length());
	EXPECT_EQ(1, prs->Runs());
}

TEST_F(RunStylesTest, DeleteEndRun) {
	prs->InsertSpace(0, 2);
	int startFill = 1;
	int lengthFill = 1;
	EXPECT_EQ(true, prs->FillRange(startFill, 99, lengthFill));
	EXPECT_EQ(2, prs->Length());
	EXPECT_EQ(2, prs->Runs());
	EXPECT_EQ(0, prs->StartRun(0));
	EXPECT_EQ(1, prs->EndRun(0));
	EXPECT_EQ(1, prs->StartRun(1));
	EXPECT_EQ(2, prs->EndRun(1));
	prs->DeleteRange(1, 1);
	EXPECT_EQ(1, prs->Length());
	EXPECT_EQ(1, prs->Runs());
	EXPECT_EQ(0, prs->StartRun(0));
	EXPECT_EQ(1, prs->EndRun(0));
	EXPECT_EQ(0, prs->StartRun(1));
	EXPECT_EQ(1, prs->EndRun(1));
}

Added test/unit/testSparseState.cxx.









































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

#include <string>
#include <vector>
#include <algorithm>

#include "Platform.h"

#include "SparseState.h"

#include <gtest/gtest.h>

// Test SparseState.

class SparseStateTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		pss = new SparseState<int>();
	}

	virtual void TearDown() {
		delete pss;
		pss = 0;
	}

	SparseState<int> *pss;
};

TEST_F(SparseStateTest, IsEmptyInitially) {
	EXPECT_EQ(0u, pss->size());
	int val = pss->ValueAt(0);
	EXPECT_EQ(0, val);
}

TEST_F(SparseStateTest, SimpleSetAndGet) {
	pss->Set(0, 22);
	pss->Set(1, 23);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(22, pss->ValueAt(0));
	EXPECT_EQ(23, pss->ValueAt(1));
	EXPECT_EQ(23, pss->ValueAt(2));
}

TEST_F(SparseStateTest, RetrieveBetween) {
	pss->Set(0, 10);
	pss->Set(2, 12);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(10, pss->ValueAt(0));
	EXPECT_EQ(10, pss->ValueAt(1));
	EXPECT_EQ(12, pss->ValueAt(2));
}

TEST_F(SparseStateTest, RetrieveBefore) {
	pss->Set(2, 12);
	EXPECT_EQ(1u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(0, pss->ValueAt(0));
	EXPECT_EQ(0, pss->ValueAt(1));
	EXPECT_EQ(12, pss->ValueAt(2));
}

TEST_F(SparseStateTest, Delete) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Delete(2);
	EXPECT_EQ(1u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(30, pss->ValueAt(0));
	EXPECT_EQ(30, pss->ValueAt(1));
	EXPECT_EQ(30, pss->ValueAt(2));
}

TEST_F(SparseStateTest, DeleteBetweeen) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Delete(1);
	EXPECT_EQ(1u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(30, pss->ValueAt(0));
	EXPECT_EQ(30, pss->ValueAt(1));
	EXPECT_EQ(30, pss->ValueAt(2));
}

TEST_F(SparseStateTest, ReplaceLast) {
	pss->Set(0, 30);
	pss->Set(2, 31);
	pss->Set(2, 32);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(0, pss->ValueAt(-1));
	EXPECT_EQ(30, pss->ValueAt(0));
	EXPECT_EQ(30, pss->ValueAt(1));
	EXPECT_EQ(32, pss->ValueAt(2));
	EXPECT_EQ(32, pss->ValueAt(3));
}

TEST_F(SparseStateTest, OnlyChangeAppended) {
	pss->Set(0, 30);
	pss->Set(2, 31);
	pss->Set(3, 31);
	EXPECT_EQ(2u, pss->size());
}

TEST_F(SparseStateTest, MergeBetween) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);
	EXPECT_EQ(3u, pss->size());

	SparseState<int> ssAdditions(3);
	ssAdditions.Set(4, 34);
	EXPECT_EQ(1u, ssAdditions.size());
	bool mergeChanged = pss->Merge(ssAdditions,5);
	EXPECT_EQ(0, mergeChanged);

	ssAdditions.Set(4, 44);
	EXPECT_EQ(1u, ssAdditions.size());
	mergeChanged = pss->Merge(ssAdditions,5);
	EXPECT_EQ(true, mergeChanged);
	EXPECT_EQ(3u, pss->size());
	EXPECT_EQ(44, pss->ValueAt(4));
}

TEST_F(SparseStateTest, MergeAtExisting) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);
	EXPECT_EQ(3u, pss->size());

	SparseState<int> ssAdditions(4);
	ssAdditions.Set(4, 34);
	EXPECT_EQ(1u, ssAdditions.size());
	bool mergeChanged = pss->Merge(ssAdditions,5);
	EXPECT_EQ(0, mergeChanged);

	ssAdditions.Set(4, 44);
	EXPECT_EQ(1u, ssAdditions.size());
	mergeChanged = pss->Merge(ssAdditions,5);
	EXPECT_EQ(true, mergeChanged);
	EXPECT_EQ(3u, pss->size());
	EXPECT_EQ(44, pss->ValueAt(4));
}

TEST_F(SparseStateTest, MergeWhichRemoves) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);
	EXPECT_EQ(3u, pss->size());

	SparseState<int> ssAdditions(2);
	ssAdditions.Set(2, 22);
	EXPECT_EQ(1u, ssAdditions.size());
	EXPECT_EQ(22, ssAdditions.ValueAt(2));
	bool mergeChanged = pss->Merge(ssAdditions,5);
	EXPECT_EQ(true, mergeChanged);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(22, pss->ValueAt(2));
}

TEST_F(SparseStateTest, MergeIgnoreSome) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);

	SparseState<int> ssAdditions(2);
	ssAdditions.Set(2, 32);
	bool mergeChanged = pss->Merge(ssAdditions,3);

	EXPECT_EQ(0, mergeChanged);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(32, pss->ValueAt(2));
}

TEST_F(SparseStateTest, MergeIgnoreSomeStart) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);

	SparseState<int> ssAdditions(2);
	ssAdditions.Set(2, 32);
	bool mergeChanged = pss->Merge(ssAdditions,2);

	EXPECT_EQ(0, mergeChanged);
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ(32, pss->ValueAt(2));
}

TEST_F(SparseStateTest, MergeIgnoreRepeat) {
	pss->Set(0, 30);
	pss->Set(2, 32);
	pss->Set(4, 34);

	SparseState<int> ssAdditions(5);
	// Appending same value as at end of pss.
	ssAdditions.Set(5, 34);
	bool mergeChanged = pss->Merge(ssAdditions,6);

	EXPECT_EQ(0, mergeChanged);
	EXPECT_EQ(3u, pss->size());
	EXPECT_EQ(34, pss->ValueAt(4));
}

class SparseStateStringTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		pss = new SparseState<std::string>();
	}

	virtual void TearDown() {
		delete pss;
		pss = 0;
	}

	SparseState<std::string> *pss;
};

TEST_F(SparseStateStringTest, IsEmptyInitially) {
	EXPECT_EQ(0u, pss->size());
	std::string val = pss->ValueAt(0);
	EXPECT_EQ("", val);
}

TEST_F(SparseStateStringTest, SimpleSetAndGet) {
	EXPECT_EQ(0u, pss->size());
	pss->Set(0, "22");
	pss->Set(1, "23");
	EXPECT_EQ(2u, pss->size());
	EXPECT_EQ("", pss->ValueAt(-1));
	EXPECT_EQ("22", pss->ValueAt(0));
	EXPECT_EQ("23", pss->ValueAt(1));
	EXPECT_EQ("23", pss->ValueAt(2));
}

TEST_F(SparseStateStringTest, DeleteBetweeen) {
	pss->Set(0, "30");
	pss->Set(2, "32");
	pss->Delete(1);
	EXPECT_EQ(1u, pss->size());
	EXPECT_EQ("", pss->ValueAt(-1));
	EXPECT_EQ("30", pss->ValueAt(0));
	EXPECT_EQ("30", pss->ValueAt(1));
	EXPECT_EQ("30", pss->ValueAt(2));
}

Added test/unit/testSplitVector.cxx.

























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

#include <string.h>

#include "Platform.h"

#include "SplitVector.h"

#include <gtest/gtest.h>

// Test SplitVector.

class SplitVectorTest : public ::testing::Test {
protected:
	virtual void SetUp() {
		psv = new SplitVector<int>;
	}

	virtual void TearDown() {
		delete psv;
		psv = 0;
	}

	SplitVector<int> *psv;
};

const int lengthTestArray = 4;
static const int testArray[4] = {3, 4, 5, 6};

TEST_F(SplitVectorTest, IsEmptyInitially) {
	EXPECT_EQ(0, psv->Length());
}

TEST_F(SplitVectorTest, InsertOne) {
	psv->InsertValue(0, 10, 0);
	psv->Insert(5, 3);
	EXPECT_EQ(11, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i == 5) ? 3 : 0, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, Insertion) {
	psv->InsertValue(0, 10, 0);
	EXPECT_EQ(10, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ(0, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, EnsureLength) {
	psv->EnsureLength(4);
	EXPECT_EQ(4, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ(0, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, InsertFromArray) {
	psv->InsertFromArray(0, testArray, 0, lengthTestArray);
	EXPECT_EQ(lengthTestArray, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ(i+3, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, SetValue) {
	psv->InsertValue(0, 10, 0);
	psv->SetValueAt(5, 3);
	EXPECT_EQ(10, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i == 5) ? 3 : 0, psv->ValueAt(i));
	}
	// Move the gap
	psv->InsertValue(7, 1, 17);
	EXPECT_EQ(17, psv->ValueAt(7));
	EXPECT_EQ(0, psv->ValueAt(8));
	// Set after the gap
	psv->SetValueAt(8, 19);
	EXPECT_EQ(19, psv->ValueAt(8));
}

TEST_F(SplitVectorTest, Indexing) {
	psv->InsertValue(0, 10, 0);
	psv->SetValueAt(5, 3);
	EXPECT_EQ(10, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i == 5) ? 3 : 0, (*psv)[i]);
	}
}

TEST_F(SplitVectorTest, Fill) {
	psv->InsertValue(0, 10, 0);
	EXPECT_EQ(10, psv->Length());
	psv->InsertValue(7, 1, 1);
	EXPECT_EQ(11, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i == 7) ? 1 : 0, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, DeleteOne) {
	psv->InsertFromArray(0, testArray, 0, lengthTestArray);
	psv->Delete(2);
	EXPECT_EQ(lengthTestArray-1, psv->Length());
	EXPECT_EQ(3, (*psv)[0]);
	EXPECT_EQ(4, (*psv)[1]);
	EXPECT_EQ(6, (*psv)[2]);
}

TEST_F(SplitVectorTest, DeleteRange) {
	psv->InsertValue(0, 10, 0);
	EXPECT_EQ(10, psv->Length());
	psv->InsertValue(7, 1, 1);
	EXPECT_EQ(11, psv->Length());
	psv->DeleteRange(2, 3);
	EXPECT_EQ(8, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i == 4) ? 1 : 0, psv->ValueAt(i));
	}
}

TEST_F(SplitVectorTest, DeleteAll) {
	psv->InsertValue(0, 10, 0);
	psv->InsertValue(7, 1, 1);
	psv->DeleteRange(2, 3);
	psv->DeleteAll();
	EXPECT_EQ(0, psv->Length());
}

TEST_F(SplitVectorTest, GetRange) {
	psv->InsertValue(0, 10, 0);
	psv->InsertValue(7, 1, 1);
	int retrieveArray[11] = {0};
	psv->GetRange(retrieveArray, 0, 11);
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ((i==7) ? 1 : 0, retrieveArray[i]);
	}
}

TEST_F(SplitVectorTest, GetRangeOverGap) {
	psv->InsertFromArray(0, testArray, 0, lengthTestArray);
	EXPECT_EQ(lengthTestArray, psv->Length());
	int retrieveArray[lengthTestArray] = {0};
	psv->GetRange(retrieveArray, 0, lengthTestArray);
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ(i+3, retrieveArray[i]);
	}
}

TEST_F(SplitVectorTest, ReplaceUp) {
	// Replace each element by inserting and then deleting the displaced element
	// This should perform many moves
	const int testLength=105;
	psv->EnsureLength(testLength);
	for (int i=0; i<testLength; i++)
		psv->SetValueAt(i, i+2);
	EXPECT_EQ(testLength, psv->Length());
	for (int i=0; i<psv->Length(); i++) {
		psv->InsertValue(i, 1, i+9);
		psv->Delete(i+1);
	}
	for (int i=0; i<psv->Length(); i++)
		EXPECT_EQ(i+9, psv->ValueAt(i));
}

TEST_F(SplitVectorTest, ReplaceDown) {
	// From the end, replace each element by inserting and then deleting the displaced element
	// This should perform many moves
	const int testLength=24;
	psv->EnsureLength(testLength);
	for (int i=0; i<testLength; i++)
		psv->SetValueAt(i, i+12);
	EXPECT_EQ(testLength, psv->Length());
	for (int i=psv->Length()-1; i>=0; i--) {
		psv->InsertValue(i, 1, i+5);
		psv->Delete(i+1);
	}
	for (int i=0; i<psv->Length(); i++)
		EXPECT_EQ(i+5, psv->ValueAt(i));
}

TEST_F(SplitVectorTest, BufferPointer) {
	psv->InsertFromArray(0, testArray, 0, lengthTestArray);
	int *retrievePointer = psv->BufferPointer();
	for (int i=0; i<psv->Length(); i++) {
		EXPECT_EQ(i+3, retrievePointer[i]);
	}
}

TEST_F(SplitVectorTest, DeleteBackAndForth) {
	psv->InsertValue(0, 10, 87);
	for (int i=0; i<10; i+=2) {
		int len = 10 - i;
		EXPECT_EQ(len, psv->Length());
		for (int i=0; i<psv->Length(); i++) {
			EXPECT_EQ(87, psv->ValueAt(i));
		}
		psv->Delete(len-1);
		psv->Delete(0);
	}
}

TEST_F(SplitVectorTest, GrowSize) {
	psv->SetGrowSize(5);
	EXPECT_EQ(5, psv->GetGrowSize());
}

TEST_F(SplitVectorTest, OutsideBounds) {
	psv->InsertValue(0, 10, 87);
	EXPECT_EQ(0, psv->ValueAt(-1));
	EXPECT_EQ(0, psv->ValueAt(10));

	/* Could be a death test as this asserts:
	psv->SetValueAt(-1,98);
	psv->SetValueAt(10,99);
	EXPECT_EQ(0, psv->ValueAt(-1));
	EXPECT_EQ(0, psv->ValueAt(10));
	*/
}

Added test/unit/unitTest.cxx.





































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Unit Tests for Scintilla internal data structures

/*
    Currently tested:
        SplitVector
        Partitioning
        RunStyles
        ContractionState

    To do:
        Decoration
        DecorationList
        PerLine *
        CellBuffer *
        Range
        StyledText
        CaseFolder ...
        Document
        RESearch
        Selection
        UniConversion
        Style

        lexlib:
        Accessor
        LexAccessor
        CharacterSet
        OptionSet
        PropSetSimple
        StyleContext
        WordList
*/

#include <stdio.h>

#include "Platform.h"

#include <gtest/gtest.h>

// Needed for PLATFORM_ASSERT in code being tested

void Platform::Assert(const char *c, const char *file, int line) {
	fprintf(stderr, "Assertion [%s] failed at %s %d\n", c, file, line);
	abort();
}

int main(int argc, char **argv) {
	testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}

Added test/xite.py.













>
>
>
>
>
>
1
2
3
4
5
6
# -*- coding: utf-8 -*-

import XiteWin

if __name__ == "__main__":
	XiteWin.main("")

Added tgzsrc.









>
>
>
>
1
2
3
4
cd ..
rm -f scintilla.tgz
tar --create --exclude \*.o --exclude \*.obj --exclude \*.dll --exclude \*.exe --exclude \*.a scintilla/* \
	| gzip -c >scintilla.tgz

Added tk/DynLexer.cxx.





































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// Scintilla source code edit control
/** @file DynLexer.cxx
 ** Lexer for Spice, modified for dynamic loading as an example
 **/
// Copyright 2006 by Fabien Proriol
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>

#include <string>

#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"

#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "PropSetSimple.h"
#include "LexerBase.h"

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT /*nothing*/
#endif

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

/*
 * Interface
 */

static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler);

static const char * const spiceWordListDesc[] = {
    "Keywords",        // SPICE command
    "Keywords2",    // SPICE functions
    "Keywords3",    // SPICE params
    0
};

// Don't define LexerModule when dynamic loading external lexer
//LexerModule lmDynLexer(SCLEX_AUTOMATIC, ColouriseDocument, "dynlexer", NULL, spiceWordListDesc);

/*
 * Implementation
 */

static void ColouriseComment(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWhiteSpace(StyleContext& sc, bool& apostropheStartsAttribute);
static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute);

static inline bool IsDelimiterCharacter(int ch);
static inline bool IsNumberStartCharacter(int ch);
static inline bool IsNumberCharacter(int ch);
static inline bool IsSeparatorOrDelimiterCharacter(int ch);
static inline bool IsWordStartCharacter(int ch);
static inline bool IsWordCharacter(int ch);

static void ColouriseComment(StyleContext& sc, bool&) {
    sc.SetState(SCE_SPICE_COMMENTLINE);
    while (!sc.atLineEnd) {
        sc.Forward();
    }
}

static void ColouriseDelimiter(StyleContext& sc, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = sc.Match (')');
    sc.SetState(SCE_SPICE_DELIMITER);
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
}

static void ColouriseNumber(StyleContext& sc, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = true;
    std::string number;
    sc.SetState(SCE_SPICE_NUMBER);
    // Get all characters up to a delimiter or a separator, including points, but excluding
    // double points (ranges).
    while (!IsSeparatorOrDelimiterCharacter(sc.ch) || (sc.ch == '.' && sc.chNext != '.')) {
        number += static_cast<char>(sc.ch);
        sc.Forward();
    }
    // Special case: exponent with sign
    if ((sc.chPrev == 'e' || sc.chPrev == 'E') &&
            (sc.ch == '+' || sc.ch == '-')) {
        number += static_cast<char>(sc.ch);
        sc.Forward ();
        while (!IsSeparatorOrDelimiterCharacter(sc.ch)) {
            number += static_cast<char>(sc.ch);
            sc.Forward();
        }
    }
    sc.SetState(SCE_SPICE_DEFAULT);
}

static void ColouriseWhiteSpace(StyleContext& sc, bool& ) {
    sc.SetState(SCE_SPICE_DEFAULT);
    sc.ForwardSetState(SCE_SPICE_DEFAULT);
}

static void ColouriseWord(StyleContext& sc, WordList& keywords, WordList& keywords2, WordList& keywords3, bool& apostropheStartsAttribute) {
    apostropheStartsAttribute = true;
    sc.SetState(SCE_SPICE_IDENTIFIER);
    std::string word;
    while (!sc.atLineEnd && !IsSeparatorOrDelimiterCharacter(sc.ch)) {
        word += static_cast<char>(tolower(sc.ch));
        sc.Forward();
    }
    if (keywords.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    else if (keywords2.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD2);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    else if (keywords3.InList(word.c_str())) {
        sc.ChangeState(SCE_SPICE_KEYWORD3);
        if (word != "all") {
            apostropheStartsAttribute = false;
        }
    }
    sc.SetState(SCE_SPICE_DEFAULT);
}

//
// ColouriseDocument
//
static void ColouriseDocument(
    unsigned int startPos,
    int length,
    int initStyle,
    WordList *keywordlists[],
    Accessor &styler) {
    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    StyleContext sc(startPos, length, initStyle, styler);
    int lineCurrent = styler.GetLine(startPos);
    bool apostropheStartsAttribute = (styler.GetLineState(lineCurrent) & 1) != 0;
    while (sc.More()) {
        if (sc.atLineEnd) {
            // Go to the next line
            sc.Forward();
            lineCurrent++;
            // Remember the line state for future incremental lexing
            styler.SetLineState(lineCurrent, apostropheStartsAttribute);
            // Don't continue any styles on the next line
            sc.SetState(SCE_SPICE_DEFAULT);
        }
        // Comments
        if ((sc.Match('*') && sc.atLineStart) || sc.Match('*','~')) {
            ColouriseComment(sc, apostropheStartsAttribute);
        // Whitespace
        } else if (IsASpace(sc.ch)) {
            ColouriseWhiteSpace(sc, apostropheStartsAttribute);
        // Delimiters
        } else if (IsDelimiterCharacter(sc.ch)) {
            ColouriseDelimiter(sc, apostropheStartsAttribute);
        // Numbers
        } else if (IsADigit(sc.ch) || sc.ch == '#') {
            ColouriseNumber(sc, apostropheStartsAttribute);
        // Keywords or identifiers
        } else {
            ColouriseWord(sc, keywords, keywords2, keywords3, apostropheStartsAttribute);
        }
    }
    sc.Complete();
}

static inline bool IsDelimiterCharacter(int ch) {
    switch (ch) {
    case '&':
    case '\'':
    case '(':
    case ')':
    case '*':
    case '+':
    case ',':
    case '-':
    case '.':
    case '/':
    case ':':
    case ';':
    case '<':
    case '=':
    case '>':
    case '|':
        return true;
    default:
        return false;
    }
}

static inline bool IsNumberCharacter(int ch) {
    return IsNumberStartCharacter(ch) ||
           ch == '_' ||
           ch == '.' ||
           ch == '#' ||
           (ch >= 'a' && ch <= 'f') ||
           (ch >= 'A' && ch <= 'F');
}

static inline bool IsNumberStartCharacter(int ch) {
    return IsADigit(ch);
}

static inline bool IsSeparatorOrDelimiterCharacter(int ch) {
    return IsASpace(ch) || IsDelimiterCharacter(ch);
}

static inline bool IsWordCharacter(int ch) {
    return IsWordStartCharacter(ch) || IsADigit(ch);
}

static inline bool IsWordStartCharacter(int ch) {
    return (isascii(ch) && isalpha(ch)) || ch == '_';
}

class DynLexer : public LexerBase {
public:
        DynLexer() {
        }
        void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
                try {
                        Accessor astyler(pAccess, &props);
                        ColouriseDocument(startPos, length, initStyle, keyWordLists, astyler);
                        astyler.Flush();
                } catch (...) {
                        // Should not throw into caller as may be compiled with different compiler or options
                        pAccess->SetErrorStatus(SC_STATUS_FAILURE);
                }
        }
        void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) {
                try {
                        Accessor astyler(pAccess, &props);
                        // folding unsupported by this lexer
                        //FoldDoc(startPos, length, initStyle, keyWordLists, astyler);
                        astyler.Flush();
                } catch (...) {
                        // Should not throw into caller as may be compiled with different compiler or options
                        pAccess->SetErrorStatus(SC_STATUS_FAILURE);
                }
        }

        static ILexer *LexerFactoryDynLexer() {
                try {
                        return new DynLexer();
                } catch (...) {
                        // Should not throw into caller as may be compiled with different compiler or options
                        return 0;
                }
        }
};

/*
 * External Lexer "glue" functions
 */
extern "C" {

DLLEXPORT int GetLexerCount()
{
    // return number of lexers in this library
    return 1;
}

DLLEXPORT void GetLexerName(unsigned int Index, char *name, int buflength)
{
    *name = 0;
    if (Index == 0) {
        if (buflength > 9) {
            strcpy(name, "dynlexer");
        }
    }
}

DLLEXPORT LexerFactoryFunction GetLexerFactory(unsigned int index) {
    if (index == 0) {
        return DynLexer::LexerFactoryDynLexer;
    } else
        return NULL;
}

}

Added tk/Makefile.in.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# Makefile.in --
#
#	This file is a Makefile for Sample TEA Extension.  If it has the name
#	"Makefile.in" then it is a template for a Makefile;  to generate the
#	actual Makefile, run "./configure", which is a configuration script
#	generated by the "autoconf" program (constructs like "@foo@" will get
#	replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================

#SAMPLE_NEW_VAR	= @SAMPLE_NEW_VAR@

#========================================================================
# Nothing of the variables below this line should need to be changed.
# Please check the TARGETS section below to make sure the make targets
# are correct.
#========================================================================

#========================================================================
# The names of the source files is defined in the configure script.
# The object files are used for linking into the final library.
# This will be used when a dist target is added to the Makefile.
# It is not important to specify the directory, as long as it is the
# $(srcdir) or in the generic, win or unix subdirectory.
#========================================================================

LEXOBJS = $(addsuffix .$(OBJEXT),$(basename $(notdir $(wildcard $(srcdir)/../lexers/Lex*.cxx))))
SRCOBJS = $(addsuffix .$(OBJEXT),$(basename $(notdir $(wildcard $(srcdir)/../lexlib/*cxx $(srcdir)/../src/*.cxx))))
PKG_SOURCES	= @PKG_SOURCES@ 
PKG_OBJECTS	= $(SRCOBJS) @PKG_OBJECTS@ $(LEXOBJS) 

PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@

#========================================================================
# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
# this package that need to be installed, if any.
#========================================================================

PKG_TCL_SOURCES = @PKG_TCL_SOURCES@

#========================================================================
# This is a list of public header files to be installed, if any.
#========================================================================

PKG_HEADERS	= @PKG_HEADERS@

#========================================================================
# "PKG_LIB_FILE" refers to the library (dynamic or static as per
# configuration options) composed of the named objects.
#========================================================================

PKG_LIB_FILE	= @PKG_LIB_FILE@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@

lib_BINARIES	= $(PKG_LIB_FILE)
BINARIES	= $(lib_BINARIES) DynLexer${SHLIB_SUFFIX} iface.tcl

SHELL		= @SHELL@

srcdir		= @srcdir@
prefix		= @prefix@
exec_prefix	= @exec_prefix@

bindir		= @bindir@
libdir		= @libdir@
includedir	= @includedir@
datarootdir	= @datarootdir@
datadir		= @datadir@
mandir		= @mandir@

DESTDIR		=

PKG_DIR		= $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir	= $(datadir)/$(PKG_DIR)
pkglibdir	= $(libdir)/$(PKG_DIR)
pkgincludedir	= $(includedir)/$(PKG_DIR)

top_builddir	= .

INSTALL_OPTIONS =
INSTALL		= $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS}
INSTALL_DATA_DIR = ${INSTALL} -d -m 755
INSTALL_PROGRAM	= ${INSTALL} -m 555
INSTALL_DATA	= ${INSTALL} -m 444
INSTALL_SCRIPT	= ${INSTALL_PROGRAM}
INSTALL_LIBRARY	= ${INSTALL_PROGRAM}

PACKAGE_NAME	= @PACKAGE_NAME@
PACKAGE_VERSION	= @PACKAGE_VERSION@
PACKAGE_DATE    = $(shell date "+%Y-%m-%d (beta)")
CC		= @CC@
CXX		= @CXX@
CFLAGS_DEFAULT	= @CFLAGS_DEFAULT@
CFLAGS_WARNING	= @CFLAGS_WARNING@
EXEEXT		= @EXEEXT@
LDFLAGS_DEFAULT	= @LDFLAGS_DEFAULT@
MAKE_LIB	= @MAKE_LIB@
MAKE_SHARED_LIB	= @MAKE_SHARED_LIB@
MAKE_STATIC_LIB	= @MAKE_STATIC_LIB@
MAKE_STUB_LIB	= @MAKE_STUB_LIB@
OBJEXT		= @OBJEXT@
RANLIB		= @RANLIB@
RANLIB_STUB	= @RANLIB_STUB@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_SUFFIX	= @SHLIB_SUFFIX@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
STLIB_LD	= @STLIB_LD@
TCL_DEFS	= @TCL_DEFS@
TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SRC_DIR	= @TCL_SRC_DIR@
TK_BIN_DIR	= @TK_BIN_DIR@
TK_SRC_DIR	= @TK_SRC_DIR@

# Not used, but retained for reference of what libs Tcl required
TCL_LIBS	= @TCL_LIBS@

#========================================================================
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
# package without installing.  The other environment variables allow us
# to test against an uninstalled Tcl.  Add special env vars that you
# require for testing here (like TCLX_LIBRARY).
#========================================================================

#EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR)
EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH	= $(top_builddir)
TCLSH_ENV	= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
PKG_ENV		= @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
		  PATH="$(EXTRA_PATH):$(PATH)" \
		  TCLLIBPATH="$(TCLLIBPATH)"

TCLSH_PROG	= @TCLSH_PROG@
TCLSH		= $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG)

#WISH_ENV	= TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
#WISH_PROG	= @WISH_PROG@
#WISH		= $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)

SHARED_BUILD	= @SHARED_BUILD@

#INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@
INCLUDES	= @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@

PKG_CFLAGS	= @PKG_CFLAGS@

# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# that your library may use.  TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS		= $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
DEFS		= @DEFS@ $(PKG_CFLAGS)

# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
CLEANFILES	= @CLEANFILES@

CPPFLAGS	= @CPPFLAGS@
LIBS		= @PKG_LIBS@ @LIBS@
AR		= @AR@
CFLAGS		= -DPACKAGE_DATE="\"$(PACKAGE_DATE)\"" @CFLAGS@
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
COMPILEXX	= $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CXXFLAGS)

.SUFFIXES: .cxx .c .$(OBJEXT) .h .a

#========================================================================
# Start of user-definable TARGETS section
#========================================================================

#========================================================================
# TEA TARGETS.  Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target includes executable programs and
# platform-dependent libraries.  Modify these targets so that they install
# the various pieces of your package.  The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================

all: binaries libraries doc examples

#========================================================================
# The binaries target builds executable programs, Windows .dll's, unix
# shared/static libraries, and any other platform-dependent files.
# The list of targets to build for "binaries:" is specified at the top
# of the Makefile, in the "BINARIES" variable.
#========================================================================

binaries: $(BINARIES)

libraries:

examples: DynLexer${SHLIB_SUFFIX}

DynLexer${SHLIB_SUFFIX}: DynLexer.$(OBJEXT) LexerBase.$(OBJEXT) Accessor.$(OBJEXT) WordList.$(OBJEXT) PropSetSimple.$(OBJEXT)
	rm -rf $@
	os=`uname -o`; \
	if test "$$os" = "Cygwin"; then \
	    ${SHLIB_LD} -out:$@ $^; \
	else \
	    ${SHLIB_LD} -o $@ $^; \
	fi
	${RANLIB} $@

iface.tcl: Scintilla.iface
	echo "# constant values defined in Scintilla.iface to be used by TCL clients" > iface.tcl
	echo "namespace eval ScintillaTk {" >> iface.tcl
	grep ^val $^ | sed -e s/^val/set/ -e s/=/\ / >> iface.tcl
	echo "}" >> iface.tcl

#========================================================================
# Your doc target should differentiate from doc builds (by the developer)
# and doc installs (see install-doc), which just install the docs on the
# end user machine when building from source.
#========================================================================

doc:
	@echo "If you have documentation to create, place the commands to"
	@echo "build the docs in the 'doc:' target.  For example:"
	@echo "        xml2nroff sample.xml > sample.n"
	@echo "        xml2html sample.xml > sample.html"

install: all install-binaries install-libraries install-doc

install-binaries: binaries install-lib-binaries install-bin-binaries

#========================================================================
# This rule installs platform-independent files, such as header files.
# The list=...; for p in $$list handles the empty list case x-platform.
#========================================================================

install-libraries: libraries
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir)
	@echo "Installing header files in $(DESTDIR)$(includedir)"
	@list='$(PKG_HEADERS)'; for i in $$list; do \
	    echo "Installing $(srcdir)/$$i" ; \
	    $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
	done;

#========================================================================
# Install documentation.  Unix manpages should go in the $(mandir)
# directory.
#========================================================================

install-doc: doc
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann
	@echo "Installing documentation in $(DESTDIR)$(mandir)"
	@list='$(srcdir)/doc/*.n'; for i in $$list; do \
	    echo "Installing $$i"; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)/doc
	@list='$(srcdir)/doc/*.html'; for i in $$list; do \
	    echo "Installing $$i"; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir)/doc ; \
	done
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)/doc/demos
	@list='$(srcdir)/doc/demos/*.tcl'; for i in $$list; do \
	    echo "Installing $$i"; \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir)/doc/demos ; \
	done

test: binaries libraries
	$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)

shell: binaries libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)

VALGRINDARGS =	--tool=memcheck --num-callers=8 --leak-resolution=high \
		--leak-check=yes --show-reachable=yes -v

valgrind: binaries libraries
	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) \
		`@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)

valgrindshell: binaries libraries
	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)

depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".
#
# The $(PKG_OBJECTS) objects are created and linked into the final
# library.  In most cases these object files will correspond to the
# source files above.
#========================================================================

$(PKG_LIB_FILE): $(PKG_OBJECTS)
	-rm -f $(PKG_LIB_FILE)
	${MAKE_LIB}
	$(RANLIB) $(PKG_LIB_FILE)

$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
	-rm -f $(PKG_STUB_LIB_FILE)
	${MAKE_STUB_LIB}
	$(RANLIB_STUB) $(PKG_STUB_LIB_FILE)

#========================================================================
# We need to enumerate the list of .c to .o lines here.
#
# In the following lines, $(srcdir) refers to the toplevel directory
# containing your extension.  If your sources are in a subdirectory,
# you will have to modify the paths to reflect this:
#
# sample.$(OBJEXT): $(srcdir)/generic/sample.c
# 	$(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================

VPATH = $(srcdir):$(srcdir)/../src:$(srcdir)/../include:$(srcdir)/../lexlib:$(srcdir)/../lexers

.c.@OBJEXT@:
	$(COMPILE) -c `@CYGPATH@ $<` -o $@

.cxx.@OBJEXT@:
	$(COMPILEXX) -c `@CYGPATH@ $<` -o $@

#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
#========================================================================

#COMPRESS	= tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
COMPRESS	= tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
DIST_ROOT	= /tmp/dist
DIST_DIR	= $(DIST_ROOT)/$(PKG_DIR)

dist-clean:
	rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*

dist: dist-clean
	mkdir -p $(DIST_DIR)
	cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
		$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
		$(DIST_DIR)/
	chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
	chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in

	for i in $(srcdir)/*.[ch]; do \
	    if [ -f $$i ]; then \
		cp -p $$i $(DIST_DIR)/ ; \
	    fi; \
	done;

	mkdir $(DIST_DIR)/tclconfig
	cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
		$(DIST_DIR)/tclconfig/
	chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
	chmod +x $(DIST_DIR)/tclconfig/install-sh

	list='demos doc generic library mac tests unix win'; \
	for p in $$list; do \
	    if test -d $(srcdir)/$$p ; then \
		mkdir $(DIST_DIR)/$$p; \
		cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
	    fi; \
	done

	(cd $(DIST_ROOT); $(COMPRESS);)

#========================================================================
# End of user-definable section
#========================================================================

#========================================================================
# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
# variable in configure.in
#========================================================================

clean:
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.$(OBJEXT) core *.core
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c
	-rm -f $(CONFIG_CLEAN_FILES)
	-rm -f config.cache config.log config.status

#========================================================================
# Install binary object libraries.  On Windows this includes both .dll and
# .lib files.  Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
# In addition, this will generate the pkgIndex.tcl
# file in the install location (assuming it can find a usable tclsh shell)
#
# You should not have to modify this target.
#========================================================================

install-lib-binaries: binaries
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)
	@list='$(lib_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
	    $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \
	    stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
	    if test "x$$stub" = "xstub"; then \
		echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
	    else \
		echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
		$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
	    fi; \
	    ext=`echo $$p|sed -e "s/.*\.//"`; \
	    if test "x$$ext" = "xdll"; then \
		lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
		if test -f $$lib; then \
		    echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
	            $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
		fi; \
	    fi; \
	  fi; \
	done
	@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
	  if test -f $(srcdir)/$$p; then \
	    destp=`basename $$p`; \
	    echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
	    $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
	  fi; \
	done
	@if test "x$(SHARED_BUILD)" = "x1"; then \
	    echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
	    $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
	fi
	$(INSTALL_DATA) iface.tcl $(DESTDIR)$(pkglibdir); \

#========================================================================
# Install binary executables (e.g. .exe files and dependent .dll files)
# This is for files that must go in the bin directory (located next to
# wish and tclsh), like dependent .dll files on Windows.
#
# You should not have to modify this target, except to define bin_BINARIES
# above if necessary.
#========================================================================

install-bin-binaries: binaries
	@$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir)
	@list='$(bin_BINARIES)'; for p in $$list; do \
	  if test -f $$p; then \
	    echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
	    $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
	  fi; \
	done

Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status

uninstall-binaries:
	list='$(lib_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \
	done
	list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
	  p=`basename $$p`; \
	  rm -f $(DESTDIR)$(pkglibdir)/$$p; \
	done
	list='$(bin_BINARIES)'; for p in $$list; do \
	  rm -f $(DESTDIR)$(bindir)/$$p; \
	done

.PHONY: all binaries clean depend distclean doc install libraries test

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

Added tk/PlatTK.cxx.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
// Scintilla source code edit control
// PlatTK.cxx - implementation of platform facilities on Linux using Tk
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>

#include <vector>
#include <map>

#ifdef _WIN32
#include <windows.h>
#endif

#include <tk.h>

#ifdef SCI_LEXER
#ifndef _WIN32
/* we include tclInt.h to pick up the definition of TclpFindSymbol. This doesn't work
 * on Windows because the symbol isn't exported.
 */
extern "C" {
#include <tclInt.h>
}
#endif

// dynamic loader also requires interpreter
extern Tcl_Interp *scintilla_interp;
#endif

#include "Platform.h"

#include "Scintilla.h"
#include "ScintillaWidget.h"
#include "UniConversion.h"
#include "XPM.h"

#include "scintilla-ext.h"
using namespace TkSciExt;

/* Use fast way of getting char data on win32 to work around problems
   with gdk_string_extents. */
#define FAST_WAY

#define USE_LOCK 0
#define DISABLE_GDK_FONT


#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

enum encodingType { singleByte, UTF8, dbcs};

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif


#if USE_LOCK
static GMutex *fontMutex = NULL;

static void InitializeGLIBThreads() {
   if (!g_thread_supported()) {
      g_thread_init(NULL);
   }
}
#endif

static void FontMutexAllocate() {
#if USE_LOCK
   if (!fontMutex) {
      InitializeGLIBThreads();
      fontMutex = g_mutex_new();
   }
#endif
}

static void FontMutexFree() {
#if USE_LOCK
   if (fontMutex) {
      g_mutex_free(fontMutex);
      fontMutex = NULL;
   }
#endif
}

static void FontMutexLock() {
#if USE_LOCK
   g_mutex_lock(fontMutex);
#endif
}

static void FontMutexUnlock() {
#if USE_LOCK
   if (fontMutex) {
      g_mutex_unlock(fontMutex);
   }
#endif
}


// The following will encapsulate the platform-specific font
class FontHandle {
   int width[128];
   encodingType et;
public:
   Tk_Font tkfont;
   int characterSet;
   FontHandle(Tk_Font tkfont_) {
      et = singleByte;
      tkfont = tkfont_;
      characterSet = -1;
      ResetWidths(et);
   }
   ~FontHandle() {
      Tk_FreeFont(tkfont);
   }
   void ResetWidths(encodingType et_) {
      et = et_;
      for (int i=0; i<=127; i++) {
         width[i] = 0;
      }
   }
   int CharWidth(unsigned char ch, encodingType et_) {
      int w = 0;
      FontMutexLock();
      if ((ch <= 127) && (et == et_)) {
         w = width[ch];
      }
      FontMutexUnlock();
      return w;
   }
   void SetCharWidth(unsigned char ch, int w, encodingType et_) {
      if (ch <= 127) {
         FontMutexLock();
         if (et != et_) {
            ResetWidths(et_);
         }
         width[ch] = w;
         FontMutexUnlock();
      }
   }
};

// X has a 16 bit coordinate space, so stop drawing here to avoid wrapping
static const int maxCoordinate = 32000;

static FontHandle *PFont(Font &f) {
	return reinterpret_cast<FontHandle *>(f.GetID());
}


///////////////////////////////////////////////////////////
// CLASS: SurfaceImpl
///////////////////////////////////////////////////////////
class SurfaceImpl : public Surface {
   encodingType et;
   Tk_Window tkwin;
   Tcl_Interp *interp;
   ScintillaObject *sc_obj;
   Display *display;
   GC gc;
   GC copyGC;
   Pixmap pixmap;

   int x;
   int y;
   bool inited;
   bool mainWindow; // TRUE if this is the main(client) window
   int mainWidth;
   int mainHeight;

   int characterSet;
   void SetConverter(int characterSet_);
   void FreeGC();
public:
   SurfaceImpl();
   virtual ~SurfaceImpl();

	void Init(WindowID wid);
	void Init(SurfaceID sid, WindowID wid);
	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);

	void Release();
	bool Initialised();
	void PenColour(ColourDesired fore);
	int LogPixelsY();
	int DeviceHeightFont(int points);
	void MoveTo(int x_, int y_);
	void LineTo(int x_, int y_);
	void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back);
	void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back);
	void FillRectangle(PRectangle rc, ColourDesired back);
	void FillRectangle(PRectangle rc, Surface &surfacePattern);
	void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back);
	void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags);
	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back);
	void Copy(PRectangle rc, Point from, Surface &surfaceSource);

	void DrawTextBase(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
	XYPOSITION WidthText(Font &font_, const char *s, int len);
	XYPOSITION WidthChar(Font &font_, char ch);
	XYPOSITION Ascent(Font &font_);
	XYPOSITION Descent(Font &font_);
	XYPOSITION InternalLeading(Font &font_);
	XYPOSITION ExternalLeading(Font &font_);
	XYPOSITION Height(Font &font_);
	XYPOSITION AverageCharWidth(Font &font_);

	void SetClip(PRectangle rc);
	void FlushCachedState();

	void SetUnicodeMode(bool unicodeMode_);
	void SetDBCSMode(int codePage);
};
#ifdef SCI_NAMESPACE
}
#endif

const char *CharacterSetID(int characterSet) {
   switch (characterSet) {
   case SC_CHARSET_ANSI:
      return "";
   case SC_CHARSET_DEFAULT:
      return "ISO-8859-1";
   case SC_CHARSET_BALTIC:
      return "ISO-8859-13";
   case SC_CHARSET_CHINESEBIG5:
      return "BIG-5";
   case SC_CHARSET_EASTEUROPE:
      return "ISO-8859-2";
   case SC_CHARSET_GB2312:
      return "CP936";
   case SC_CHARSET_GREEK:
      return "ISO-8859-7";
   case SC_CHARSET_HANGUL:
      return "CP949";
   case SC_CHARSET_MAC:
      return "MACINTOSH";
   case SC_CHARSET_OEM:
      return "ASCII";
   case SC_CHARSET_RUSSIAN:
      return "KOI8-R";
   case SC_CHARSET_CYRILLIC:
      return "CP1251";
   case SC_CHARSET_SHIFTJIS:
      return "SHIFT-JIS";
   case SC_CHARSET_SYMBOL:
      return "";
   case SC_CHARSET_TURKISH:
      return "ISO-8859-9";
   case SC_CHARSET_JOHAB:
      return "CP1361";
   case SC_CHARSET_HEBREW:
      return "ISO-8859-8";
   case SC_CHARSET_ARABIC:
      return "ISO-8859-6";
   case SC_CHARSET_VIETNAMESE:
      return "";
   case SC_CHARSET_THAI:
      return "ISO-8859-11";
   case SC_CHARSET_8859_15:
      return "ISO-8859-15";
   default:
      return "";
   }
}

void SurfaceImpl::SetConverter(int characterSet_) {
//    if (characterSet != characterSet_) {
//       characterSet = characterSet_;
//       conv.Open("UTF-8", CharacterSetID(characterSet), false);
//    }
}

SurfaceImpl::SurfaceImpl() : et(singleByte),
                             sc_obj(0),
                             display(0),
                             gc(0), copyGC(0),
                             pixmap(0),
                             x(0), y(0), 
                             inited(false),
                             mainWindow(false),mainWidth(0),mainHeight(0),
                             characterSet(-1) {
}

SurfaceImpl::~SurfaceImpl() {
//printf("Surface DTOR(main=%d) -- THIS=%p\n",mainWindow,(void *)this);
   FreeGC();
   if (pixmap && display) {
      Tk_FreePixmap(display, pixmap);
   }
}

/*
 *----------------------------------------------------------------------
 * Release --
 *
 *    Handles releases resources used by this surface
 *
 * Results:
 *    None
 *
 * Side affects:
 *    Resources releases and flags are reset
 *
 *----------------------------------------------------------------------
 */
void SurfaceImpl::Release() {
#if 0
   et = singleByte;
//printf("---RELEASE(main=%d) %p\n",mainWindow,(void *)this);
//_print_trace(1);
   FreeGC();

   if (pixmap && display) {
      Tk_FreePixmap(display, pixmap);
      pixmap = 0;
   }
#endif
   characterSet = -1;
   x = 0;
   y = 0;
   inited = false;
}
void SurfaceImpl::FreeGC() {
   if (gc) {
//printf("FreeGC (%p) >>> %d\n",(void *)this,gc);
      Tk_FreeGC(display, gc);
      gc = 0;
   }
}

bool SurfaceImpl::Initialised() {
//printf("SurfaceImpl::Initialised THIS=%p  inited=%d  pixmap=%d\n",(void *)this,inited,(int)pixmap);
   return (inited && (pixmap != 0));
}
static Tk_Window _curr_tkwin = 0;

/*
 *----------------------------------------------------------------------
 * Init --
 *
 *    Called by Editor to get the drawing pixmap for one of the internal
 *    surfaces initialized.
 *
 * Results:
 *    None
 *
 * Side affects:
 *    Creates drawing pixmap with requested dimensions
 *
 *----------------------------------------------------------------------
 */
void SurfaceImpl::Init(WindowID wid) {
   PLATFORM_ASSERT(wid);
   sc_obj = reinterpret_cast<ScintillaObject *>(wid);
   mainWindow = sc_obj->main;
//printf("SurfaceImpl::Init(main=%d) THIS=%p  WID=%p\n",mainWindow,(void *)this,(void *)wid);
   if (!mainWindow) {
      Release();
   }
   tkwin = sc_obj->tkwin;
//TODO: figure how to avoid needed the next line!!!!
_curr_tkwin = tkwin;

   interp  = Tk_Interp(tkwin);
   display = Tk_Display(tkwin);

   if (mainWindow && Tk_WindowId(tkwin)) {
      int new_w = Tk_Width(tkwin);
      int new_h = Tk_Height(tkwin);
      if ((new_w != mainWidth) || (new_h != mainHeight)) {
         if (pixmap)
            Tk_FreePixmap(display, pixmap);
         pixmap = Tk_GetPixmap(display, Tk_WindowId(tkwin),
            new_w, new_h, Tk_Depth(tkwin));
         mainWidth  = new_w;
         mainHeight = new_h;
//printf("SurfaceImpl::Init THIS=%p  WID=%p  PIXMAP=%d  WIDTH=%d HEIGHT=%d\n",(void *)this,(void *)wid,(int)pixmap,Tk_Width(tkwin),Tk_Height(tkwin));
      }
   }
   inited = true;
}

void SurfaceImpl::Init(SurfaceID sid, WindowID wid) {
   // it's not clear why we need to support this API, but since we're
   // required to implement it, just call the simple version
   Init(wid);
}

/*
 *----------------------------------------------------------------------
 * InitPixMap --
 *
 *    Called by Editor to get the drawing pixmap for one of the internal
 *    surfaces initialized. The surface which is passed in corresponds
 *    to the main(client) window.
 *
 * Results:
 *    None
 *
 * Side affects:
 *    Creates drawing pixmap with requested dimensions
 *
 *----------------------------------------------------------------------
 */
void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID wid) {
   PLATFORM_ASSERT(surface_);
   sc_obj = reinterpret_cast<ScintillaObject *>(wid);
   Release();
   SurfaceImpl *surfImpl = static_cast<SurfaceImpl *>(surface_);
//printf("INIT PIXMAP(main=%d, wid=%p): THIS=%p SRC=%p width=%d height=%d\n",sc_obj->main,(void *)wid,(void *)this,(void *)surfImpl,width,height);

   if (height > 0 && width > 0) {
      if (pixmap)
         Tk_FreePixmap(Tk_Display(tkwin), pixmap);
      pixmap = Tk_GetPixmap( surfImpl->display, Tk_WindowId(surfImpl->tkwin),
         width, height, Tk_Depth(surfImpl->tkwin) );
//printf("---InitPixMap: THIS=%p SRC=%p width=%d height=%d  PIX=%d\n",(void *)this,(void *)surfImpl,width,height,(int)pixmap);
   }
#if 1
   tkwin   = sc_obj->tkwin;
   interp  = Tk_Interp(tkwin);
   display = Tk_Display(tkwin);
   inited  = true;
#else
   if ( ! Initialised() ) {
      Init(wid);
   }
#endif
}

/*
 *----------------------------------------------------------------------
 * PenColour --
 *
 *    Called prior to drawing operation to set a specified color
 *
 * Results:
 *    None
 *
 * Side affects:
 *    A GC is obtained (Tk is allowed to reuse) with the specified
 *    color defined for the foreground.
 *
 *----------------------------------------------------------------------
 */
void SurfaceImpl::PenColour(ColourDesired fore) {
   FreeGC();

   XGCValues gcvalues;
   XColor *xc;
   static char rgb[7];
   sprintf(rgb, "#%02x%02x%02x", fore.GetRed(), fore.GetGreen(), fore.GetBlue());
   xc = Tk_GetColor(interp, tkwin, rgb);
   if (xc) {
      gcvalues.foreground = xc->pixel;
      gc = Tk_GetGC(tkwin, GCForeground, &gcvalues);
//printf("PenColour ####### SET GC = %ld for THIS=%p RGB=%d,%d,%d\n",(long)gc,(void *)this,fore.GetRed(),fore.GetGreen(),fore.GetBlue());
      Tk_FreeColor(xc);
   }
}

int SurfaceImpl::LogPixelsY() {
   return 72;
}

int SurfaceImpl::DeviceHeightFont(int points) {
   int logPix = LogPixelsY();
   return (points * logPix + logPix / 2) / 72;
}

void SurfaceImpl::MoveTo(int x_, int y_) {
//printf("MOVETO: %d,%d\n",x_,y_);
   x = x_;
   y = y_;
}

void SurfaceImpl::LineTo(int x_, int y_) {
   if (gc) {
//printf("LINETO: %d,%d -> %d,%d\n",x_,y_,x,y);
      XDrawLine( display, pixmap, gc, x_, y_, x, y );
   }
   x = x_;
   y = y_;
}

void SurfaceImpl::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back) {
#if 0
printf("SurfaceImpl::Polygon  BG=%d,%d,%d  FG=%d,%d,%d\n",
   back.GetRed(),back.GetGreen(),back.GetBlue(), fore.GetRed(),fore.GetGreen(),fore.GetBlue());
#endif
   XPoint points[20];
   if (npts < static_cast<int>((sizeof(points) / sizeof(points[0])))) {
      int i;
      int _x = 0;
      int _y = 0;
      for (i = 0;i < npts;i++) {
         if (i==0) {
            _x = pts[i].x;
            _y = pts[i].y;
         }
         points[i].x = static_cast<short>(pts[i].x);
         points[i].y = static_cast<short>(pts[i].y);
      }
      // add the closing coordinate
      points[i].x = _x;
      points[i].y = _y;
      npts++;

      PenColour(back);
      XFillPolygon(display, pixmap, gc, points, npts, Convex, CoordModeOrigin);

      PenColour(fore);
      XDrawLines(display, pixmap, gc, points, npts, CoordModeOrigin);
   }
}

void SurfaceImpl::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) {
#if 0
printf("##################################\n");
printf("# SurfaceImpl::RectangleDraw\n");
printf("#  FORE=%d,%d,%d",  fore.GetRed(),fore.GetGreen(),fore.GetBlue());
printf("   BACK=%d,%d,%d\n",back.GetRed(),back.GetGreen(),back.GetBlue());
printf("##################################\n");
#endif
   int x = rc.left;
   int y = rc.top;
   int w = (rc.right - rc.left);
   int h = (rc.bottom - rc.top);
   PenColour(back);
   XDrawRectangle(display, pixmap, gc, x + 1, y + 1, w - 2, h - 2);

   PenColour(fore);

   // The subtraction of 1 off the width and height here shouldn't be needed but
   // otherwise a different rectangle is drawn than would be done if the fill
   // parameter == 1

   XDrawRectangle(display, pixmap, gc, x, y, w - 1, h -1);
}

void SurfaceImpl::FillRectangle(PRectangle rc, ColourDesired back) {
#if 0
if ((rc.right-rc.left)>1 && (rc.bottom-rc.top)>1)
   printf("\nFILL RECT1 RGB=%d,%d,%d THIS=%p|PIX=%d|GC=%ld|+%d+%dx%dx%d\n",
      back.GetRed(),back.GetGreen(),back.GetBlue(),
      (void *)this,(int)pixmap,(long)gc,
      rc.left,rc.top,(rc.right-rc.left),(rc.bottom-rc.top));
#endif
   PenColour(back);
   if (gc && (rc.left < maxCoordinate)) { // Protect against out of range
//////////////////////
//-------CHANGE TO : Tk_Fill3DRectangle --- use Tk_3DBorder
bool to_screen = false;

      if (to_screen) {
      XFillRectangle(display, Tk_WindowId(tkwin), gc,
         rc.left, rc.top,
         (rc.right - rc.left), (rc.bottom - rc.top));
      Tcl_DoOneEvent(2); //DRAW NOW!!!!

      } else {
      XFillRectangle(display, pixmap, gc,
         rc.left, rc.top,
         (rc.right - rc.left), (rc.bottom - rc.top));
      }
   }
}

void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
//printf("SurfaceImpl::FillRectangle 2  THIS=%p\n",(void *)this);
   SurfaceImpl &surfOther = static_cast<SurfaceImpl &>(surfacePattern);
   if (Initialised() && surfOther.Initialised()) {
      // Tile pattern over rectangle
      // Currently assumes 8x8 pattern
      int widthPat = 8;
      int heightPat = 8;
      for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
         int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
         for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
            int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;

            if (!gc) {
               XGCValues gcValues; // just use defaults
               gc = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
            }
            XCopyArea(display, surfOther.pixmap, pixmap, gc,
               0, 0,        /* src X/Y */
               widthx, heighty,
               xTile, yTile /* dest X/Y */
            );
         }
      }
   } else {
      // Something is wrong so try to show anyway
      // Shows up black because colour not allocated
      FillRectangle(rc, ColourDesired(0));
   }
}

void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) {
   if (((rc.right - rc.left) > 4) && ((rc.bottom - rc.top) > 4)) {
       // Approximate a round rect with some cut off corners
       Point pts[] = {
           Point(rc.left + 2,  rc.top),
           Point(rc.right - 2, rc.top),
           Point(rc.right,     rc.top + 2),
           Point(rc.right,     rc.bottom - 3),
           Point(rc.right - 3, rc.bottom),
           Point(rc.left + 3,  rc.bottom),
           Point(rc.left,      rc.bottom - 3),
           Point(rc.left,      rc.top + 2),
       };
       Polygon(pts, sizeof(pts) / sizeof(pts[0]), fore, back);
   } else {
       RectangleDraw(rc, fore, back);
   }
}

void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
      ColourDesired outline, int alphaOutline, int flags) {
#if 1
// TEMPORARY HACK - the assumption is this will be called to draw one of the
// indicators that would normally try to create a translucent interior
if (cornerSize == 0)
    FillRectangle(rc, fill);
else
    RoundedRectangle(rc, fill, fill);
return;
#endif
fprintf(stderr, "WARNING: The AlphaRectangle Surface function has not been implemented!!\n");
#if TK_CAN_DO_TRANSPARENCY
   if (gc && drawable && rc.Width() > 0) {
      int width = rc.Width();
      int height = rc.Height();
      // Ensure not distorted too much by corners when small
      cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
      // Make a 32 bit deep pixbuf with alpha
      GdkPixbuf *pixalpha = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);

      guint32 valEmpty = u32FromRGBA(0,0,0,0);
      guint32 valFill = u32FromRGBA(GetRValue(fill.AsLong()),
         GetGValue(fill.AsLong()), GetBValue(fill.AsLong()), alphaFill);
      guint32 valOutline = u32FromRGBA(GetRValue(outline.AsLong()),
         GetGValue(outline.AsLong()), GetBValue(outline.AsLong()), alphaOutline);
      guint32 *pixels = reinterpret_cast<guint32 *>(gdk_pixbuf_get_pixels(pixalpha));
      int stride = gdk_pixbuf_get_rowstride(pixalpha) / 4;
      for (int yr=0; yr<height; yr++) {
         for (int xr=0; xr<width; xr++) {
            if ((xr==0) || (xr==width-1) || (yr == 0) || (yr == height-1)) {
               pixels[yr*stride+xr] = valOutline;
            } else {
               pixels[yr*stride+xr] = valFill;
            }
         }
      }
      for (int c=0;c<cornerSize; c++) {
         for (int xr=0;xr<c+1; xr++) {
            AllFour(pixels, stride, width, height, xr, c-xr, valEmpty);
         }
      }
      for (int xr=1;xr<cornerSize; xr++) {
         AllFour(pixels, stride, width, height, xr, cornerSize-xr, valOutline);
      }

      // Draw with alpha
      gdk_draw_pixbuf(drawable, gc, pixalpha,
         0,0, rc.left,rc.top, width,height, GDK_RGB_DITHER_NORMAL, 0, 0);

      g_object_unref(pixalpha);
   }
#endif
}

void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
fprintf(stderr, "WARNING: The DrawRGBAImage Surface function has not been implemented!!\n");
#if TK_CAN_DO_TRANSPARENCY
   if (rc.Width() > width)
      rc.left += (rc.Width() - width) / 2;
   rc.right = rc.left + width;
   if (rc.Height() > height)
      rc.top += (rc.Height() - height) / 2;
   rc.bottom = rc.top + height;

   GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(pixelsImage,
                                                         GDK_COLORSPACE_RGB,
                                                         TRUE,
                                                         8,
                                                         width,
                                                         height,
                                                         width * 4,
                                                         NULL,
                                                         NULL);
   gdk_draw_pixbuf(drawable, gc, pixbuf,
      0,0, rc.left,rc.top, width,height, GDK_RGB_DITHER_NORMAL, 0, 0);
   g_object_unref(pixbuf);
#endif
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {

   static int full_circle = 64 * 360;
   PenColour(back);
   XFillArc(display, pixmap, gc,
      rc.left + 1, rc.top + 1,
      rc.right - rc.left - 2, rc.bottom - rc.top - 2,
      0, full_circle);

   // The subtraction of 1 here is similar to the case for RectangleDraw
   PenColour(fore);
   XDrawArc(display, pixmap, gc,
      rc.left, rc.top,
      rc.right - rc.left - 1, rc.bottom - rc.top - 1,
      0, full_circle);
}

/****************************************************************
// Func: Copy
// Desc: Called from Editor code to copy a region from a source
//       surface to the screen as a result of a paint action
*****************************************************************/
//int cnt = 0;
void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
   bool to_screen;
   GC _gc;

   SurfaceImpl &surfOther = static_cast<SurfaceImpl &>(surfaceSource);
   //printf("\nSurfaceImpl::Copy THIS=%p<%d> OTHER=%p<%d>\n",(void *)this,(int)pixmap,(void *)&surfOther,(int)surfOther.pixmap);
   if (!Initialised() || !surfOther.Initialised()) {
      return;
   }

   to_screen = (surfOther.pixmap == pixmap);

   if (to_screen) {
      if (!copyGC) {
         XGCValues gcValues;
         gcValues.graphics_exposures = True;
         copyGC = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
      }
      _gc = copyGC;
   } else {
      _gc = surfOther.gc;
   }

//   cnt++;
   if (to_screen)  {
	  TkSciExt::SetPixmap((ClientData)sc_obj->client, pixmap);
//printf(">>>>>XCopyArea %d FROM %02d %02d SCREEN +%02d+%02dx%dx%d \n",cnt, from.x, from.y,rc.left,rc.top,(rc.right-rc.left),(rc.bottom-rc.top));
      XCopyArea(display,surfOther.pixmap,Tk_WindowId(tkwin),_gc,rc.left, rc.top,rc.right - rc.left, rc.bottom - rc.top,rc.left, rc.top);
   } else {
//printf(">>>>>XCopyArea %d FROM %02d %02d BUFFER +%02d+%02dx%dx%d \n",cnt, from.x, from.y, rc.left,rc.top,(rc.right-rc.left),(rc.bottom-rc.top));
      XCopyArea(display,surfOther.pixmap, pixmap, _gc,from.x, from.y,rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top); 
   }
}

char *UTF8FromLatin1(const char *s, int &len) {
   char *utfForm = new char[len*2+1];
   size_t lenU = 0;
   for (int i=0;i<len;i++) {
      unsigned int uch = static_cast<unsigned char>(s[i]);
      if (uch < 0x80) {
         utfForm[lenU++] = uch;
      } else {
         utfForm[lenU++] = static_cast<char>(0xC0 | (uch >> 6));
         utfForm[lenU++] = static_cast<char>(0x80 | (uch & 0x3f));
      }
   }
   utfForm[lenU] = '\0';
   len = lenU;
   return utfForm;
}

void SurfaceImpl::DrawTextBase(
   PRectangle rc, Scintilla::Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore
) {
//printf("DRAW TEXT(%d): @%d,%d THIS=%p pixmap=%d GC=%ld  STR=%s\n",len,rc.left,ybase,(void *)this,(int)pixmap,(long)gc,s);

   PenColour(fore);
   if (pixmap && gc && PFont(font_)) {
      Tk_Font tkfont = PFont(font_)->tkfont;
#ifdef _WIN32
      gc->font = (unsigned long)tkfont;
#endif
      Tk_DrawChars(display, pixmap, gc, tkfont, s, len, rc.left, ybase);
   } else {
//printf("DRAW TEXT ############### SKIPPED  pixmap=%d  gc=%ld\n",(int)pixmap,(long)gc);
   }
}

void SurfaceImpl::DrawTextNoClip(PRectangle rc, Scintilla::Font &font_, XYPOSITION ybase, const char *s, int len,
                                 ColourDesired fore, ColourDesired back) {
   FillRectangle(rc, back);
   DrawTextBase(rc, font_, ybase, s, len, fore);
}

// On GTK+, exactly same as DrawTextNoClip
void SurfaceImpl::DrawTextClipped(PRectangle rc, Scintilla::Font &font_, XYPOSITION ybase, const char *s, int len,
                                  ColourDesired fore, ColourDesired back) {
   FillRectangle(rc, back);
   DrawTextBase(rc, font_, ybase, s, len, fore);
}

void SurfaceImpl::DrawTextTransparent(PRectangle rc, Scintilla::Font &font_, XYPOSITION ybase, const char *s, int len,
                                  ColourDesired fore) {
   // Avoid drawing spaces in transparent mode
   for (int i=0;i<len;i++) {
      if (s[i] != ' ') {
         DrawTextBase(rc, font_, ybase, s, len, fore);
         return;
      }
   }
}

void SurfaceImpl::MeasureWidths(Scintilla::Font &font_, const char *s, int len, XYPOSITION *positions) {
   if (font_.GetID()) {
      Tk_Font tkfont = PFont(font_)->tkfont;
      int totalWidth = 0;
      for (int i = 0; i < len; i++) {
         int width = Tk_TextWidth(tkfont, (s+i), 1);
         totalWidth += width;
         positions[i] = totalWidth;
      }
   } else {
      // No font so return an ascending range of values
      for (int i = 0; i < len; i++) {
         positions[i] = i + 1;
      }
   }
}

XYPOSITION SurfaceImpl::WidthText(Scintilla::Font &font_, const char *s, int len) {
	if (font_.GetID()) {
      return Tk_TextWidth(PFont(font_)->tkfont, s, len);
	} else {
		return 10;
	}
}

XYPOSITION SurfaceImpl::WidthChar(Scintilla::Font &font_, char ch) {
   return WidthText(font_, &ch, 1);
}

// Ascent and descent determined by Pango font metrics.

XYPOSITION SurfaceImpl::Ascent(Scintilla::Font &font_) {
   if (!(font_.GetID())) {
      return 1;
   }
   Tk_FontMetrics fm;
   Tk_GetFontMetrics(PFont(font_)->tkfont, &fm);
   return fm.ascent;
}

XYPOSITION SurfaceImpl::Descent(Scintilla::Font &font_) {
	if (!(font_.GetID()))
		return 1;
   Tk_FontMetrics fm;
   Tk_GetFontMetrics(PFont(font_)->tkfont, &fm);
   return fm.descent;
}

XYPOSITION SurfaceImpl::InternalLeading(Scintilla::Font &) {
   return 0;
}

XYPOSITION SurfaceImpl::ExternalLeading(Scintilla::Font &) {
   return 0;
}

XYPOSITION SurfaceImpl::Height(Scintilla::Font &font_) {
   return Ascent(font_) + Descent(font_);
}

XYPOSITION SurfaceImpl::AverageCharWidth(Scintilla::Font &font_) {
   return WidthChar(font_, 'n');
}

void SurfaceImpl::SetClip(PRectangle rc) {
//TODO: is this something that needs to be implemented??
}

void SurfaceImpl::FlushCachedState() {}

void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
   if (unicodeMode_)
      et = UTF8;
}

void SurfaceImpl::SetDBCSMode(int codePage) {
   if (codePage && (codePage != SC_CP_UTF8))
      et = dbcs;
}

// The editor code calls this static function to get a surface object
Surface *Surface::Allocate(int) {
   Surface *surf = new SurfaceImpl();
//printf("Surface::Allocate -- THIS=%p\n",(void *)surf);
   return surf;
}


#ifdef SCI_LEXER

/* we can't get TclpFindSymbol from the TCL library because it's not exported. The following is a copy of the code
 */
#ifdef _WIN32
/*
 *----------------------------------------------------------------------
 *
 * TclpFindSymbol --
 *
 *  Looks up a symbol, by name, through a handle associated with a
 *  previously loaded piece of code (shared library).
 *
 * Results:
 *  Returns a pointer to the function associated with 'symbol' if it is
 *  found. Otherwise returns NULL and may leave an error message in the
 *  interp's result.
 *
 *----------------------------------------------------------------------
 */

Tcl_PackageInitProc *
TclpFindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    CONST char *symbol)
{
    Tcl_PackageInitProc *proc = NULL;
    HINSTANCE handle = (HINSTANCE)loadHandle;

    /*
     * For each symbol, check for both Symbol and _Symbol, since Borland
     * generates C symbols with a leading '_' by default.
     */

    proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
    if (proc == NULL) {
    Tcl_DString ds;

    Tcl_DStringInit(&ds);
    Tcl_DStringAppend(&ds, "_", 1);
    symbol = Tcl_DStringAppend(&ds, symbol, -1);
    proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol);
    Tcl_DStringFree(&ds);
    }
    return proc;
}

#endif

class DynamicLibraryImpl : public DynamicLibrary {
protected:
    Tcl_LoadHandle handle;
    Tcl_FSUnloadFileProc *unloadProc;
public:
    DynamicLibraryImpl(const char *modulePath) {
        // convert modulePath to Tcl_Obj
        Tcl_Obj *pathPtr = Tcl_NewStringObj(modulePath, strlen(modulePath));
        Tcl_PackageInitProc *unused;
        Tcl_IncrRefCount(pathPtr);
        if (Tcl_FSLoadFile(scintilla_interp, pathPtr, "unused1", "unused2", &unused, &unused, &handle, &unloadProc) != TCL_OK) {
            fprintf(stderr,"File load of %s failed %s\n", modulePath, Tcl_GetStringResult(scintilla_interp));
            handle = NULL;
        }
        Tcl_DecrRefCount(pathPtr);
    }

    virtual ~DynamicLibraryImpl() {
    }

    // Use g_module_symbol to get a pointer to the relevant function.
    virtual Function FindFunction(const char *name) {
        if (handle != NULL) {
            void *ptr = (void*) TclpFindSymbol(scintilla_interp, handle, name);
            if (ptr) {
                return ptr;
            } else
                return NULL;
        } else
            return NULL;
    }

    virtual bool IsValid() {
        return handle != NULL;
    }
};

DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
   return static_cast<DynamicLibrary *>( new DynamicLibraryImpl(modulePath) );
}
#endif


ColourDesired Platform::Chrome() {
   return ColourDesired(0xe0, 0xe0, 0xe0);
}

ColourDesired Platform::ChromeHighlight() {
   return ColourDesired(0x00, 0x00, 0xff);
//   return ColourDesired(0xff, 0xff, 0xff);
}

const char *Platform::DefaultFont() {
   return "courier";
}

int Platform::DefaultFontSize() {
   return 12;
}

unsigned int Platform::DoubleClickTime() {
   return 500;    // Half a second
}

bool Platform::MouseButtonBounce() {
   return true;
}

void Platform::DebugDisplay(const char *s) {
   fprintf(stderr, "%s", s);
}

bool Platform::IsKeyDown(int) {
   // TODO: discover state of keys in GTK+/X
   return false;
}

long Platform::SendScintilla(
    WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
   return 0;//scintilla_send_message(SCINTILLA(w), msg, wParam, lParam);
}

long Platform::SendScintillaPointer(
    WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
   return 0;
//    return scintilla_send_message(SCINTILLA(w), msg, wParam,
//                                  reinterpret_cast<sptr_t>(lParam));
}

bool Platform::IsDBCSLeadByte(int codePage, char ch) {
   // Byte ranges found in Wikipedia articles with relevant search strings in each case
   unsigned char uch = static_cast<unsigned char>(ch);
   switch (codePage) {
      case 932:
         // Shift_jis
         return ((uch >= 0x81) && (uch <= 0x9F)) ||
            ((uch >= 0xE0) && (uch <= 0xFC));
            // Lead bytes F0 to FC may be a Microsoft addition. 
      case 936:
         // GBK
         return (uch >= 0x81) && (uch <= 0xFE);
      case 950:
         // Big5
         return (uch >= 0x81) && (uch <= 0xFE);
      // Korean EUC-KR may be code page 949.
   }
   return false;
}

int Platform::DBCSCharLength(int codePage, const char *s) {
   if (codePage == 932 || codePage == 936 || codePage == 950) {
      return IsDBCSLeadByte(codePage, s[0]) ? 2 : 1;
   } else {
      int bytes = mblen(s, MB_CUR_MAX);
      if (bytes >= 1)
         return bytes;
      else
         return 1;
   }
}

int Platform::DBCSCharMaxLength() {
   return MB_CUR_MAX;
   //return 2;
}

// These are utility functions not really tied to a platform

int Platform::Minimum(int a, int b) {
   if (a < b)
      return a;
   else
      return b;
}

int Platform::Maximum(int a, int b) {
   if (a > b)
      return a;
   else
      return b;
}

//#define TRACE

#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) {
   char buffer[2000];
   va_list pArguments;
   va_start(pArguments, format);
   vsprintf(buffer, format, pArguments);
   va_end(pArguments);
   Platform::DebugDisplay(buffer);
}
#else
void Platform::DebugPrintf(const char *, ...) {}

#endif

// Not supported for GTK+
static bool assertionPopUps = true;

bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
   bool ret = assertionPopUps;
   assertionPopUps = assertionPopUps_;
   return ret;
}

void Platform::Assert(const char *c, const char *file, int line) {
   char buffer[2000];
   sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
   strcat(buffer, "\r\n");
   Platform::DebugDisplay(buffer);
   abort();
}

int Platform::Clamp(int val, int minVal, int maxVal) {
   if (val > maxVal)
      val = maxVal;
   if (val < minVal)
      val = minVal;
   return val;
}

void Platform_Initialise() {
   FontMutexAllocate();
}

void Platform_Finalise() {
   FontMutexFree();
}


#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
//==========================================================================
// CLASS Menu implementations (that seem to be needed from based class
// to get symbols to resolve during library loading)
//
Menu::Menu() : mid(0) {}
void Menu::Destroy() {
}
void Menu::CreatePopUp() {
}
void Menu::Show(Point pt, Window &) {
}

//==========================================================================
// CLASS Font implementation (also seemingly required)
//
Font::Font() : fid(0) {}
Font::~Font() {}
void Font::Create(const FontParameters &fp) {
//fprintf(stderr,"Font::Create ((%p))--> %s / %f / %d / italic=%d\n",(void *)this,fp.faceName,fp.size,fp.weight,fp.italic);

//TODO: NEED THE tkwin REFERENCE FOR THIS!!
//TODO: FIGURE OUT HOW TO SPECIFY THE Tk_Font BASED FROM FontParameters
//NOTE: The FontParameters gets family/size from Platform::DefaultFont
//      and Platform::DefaultFontSize

   // check if the point size is encoded to represent a negative value, which
   // for Tk would mean it will use that value as the number of pixels.
   int ptsize = static_cast<int>(fp.size);
   if (ptsize > MAGIC_FONT_OFFSET)
       ptsize = (MAGIC_FONT_OFFSET - ptsize);

   //########################################################
   // Font format: <family name> ?pt size? ?bold? ?italic?
   //########################################################
#if (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION < 5)
   Tcl_Obj *objPtr = Tcl_NewObj();
   char dbuf[64];
   sprintf(dbuf," %d", ptsize);
   Tcl_AppendStringsToObj(objPtr,"{", fp.faceName, "}", dbuf, (char*)NULL);
#else
   Tcl_Obj *objPtr = Tcl_ObjPrintf("{%s} %d", fp.faceName, ptsize);
#endif

   if (fp.weight == SC_WEIGHT_BOLD) {
      Tcl_AppendStringsToObj(objPtr, " bold", (char *)NULL);
   }
   if (fp.italic) {
      Tcl_AppendStringsToObj(objPtr, " italic", (char *)NULL);
   }

   Tk_Font tkf = Tk_GetFont(Tk_Interp(_curr_tkwin),_curr_tkwin, Tcl_GetString(objPtr));
   fid = new FontHandle(tkf);
}
void Font::Release() {
   if (fid) {
      delete reinterpret_cast<FontHandle *>(fid);
   }
   fid = 0;
}

//==========================================================================
// CLASS Window implementation (also seemingly required)
//
Window::~Window() {}
void Window::Destroy() {}

PRectangle Window::GetMonitorRect(Point pt) {
   return PRectangle(0,0,0,0);
}

void Window::SetCursor(Cursor curs) {

   ScintillaObject *sc_obj = reinterpret_cast<ScintillaObject *>(wid);
   if (!sc_obj) return;

   if ( ! Tk_IsMapped(sc_obj->tkwin) ) return;

//printf("##################Window::SetCursor %d\n",curs);
   TkSciExt::MSG_SetCursor((ClientData)sc_obj->client, static_cast<int>(curs));
}
void Window::SetFont(Scintilla::Font &) {
}
void Window::Show(bool show) {
}
void Window::SetPosition(PRectangle rc) {
}
void Window::SetPositionRelative(PRectangle rc, Window relativeTo) {
}
PRectangle Window::GetPosition() {
   return PRectangle(0,0,0,0);
}
PRectangle Window::GetClientPosition() {
   return GetPosition();
}
void Window::InvalidateRectangle(PRectangle rc) {

    ScintillaObject *sc_obj = reinterpret_cast<ScintillaObject *>(wid);
    if (!sc_obj) {
       return;
    }
    if ( ! Tk_IsMapped(sc_obj->tkwin) ) {
//printf("Window::InvalidateRectangle NOT MAPPED YET for sc_obj=%p\n",(void *)sc_obj);
       return;
    }
//printf("Window::InvalidateRectangle((%p)) >> +%d+%dx%dx%d\n",(void *)this,rc.left,rc.top,(rc.right-rc.left),(rc.bottom-rc.top));
    // We use an Expose event to indicate to the Tk widget functionality
    // what region needs to be repainted
    XEvent e;
    e.xexpose.type    = Expose;
    e.xexpose.count   = -1;
    e.xexpose.display = Tk_Display(sc_obj->tkwin);
    e.xexpose.window  = Tk_WindowId(sc_obj->tkwin);
    // HACK ALERT(maybe) We manually force the expose region to include
    // any margins which are visible
    if (rc.left > 0) {
       rc.left = 0;
       rc.right++;
    }
    e.xexpose.x       = rc.left;
    e.xexpose.y       = rc.top;
    e.xexpose.width   = (rc.right - rc.left);
    e.xexpose.height  = (rc.bottom - rc.top);

    Tk_QueueWindowEvent(&e, TCL_QUEUE_TAIL);
}
void Window::InvalidateAll() {
printf("Window::InvalidateAll\n");
}

//==========================================================================
// CLASS ListBox implementation (also seemingly required)
// NOTE: even if calltips and code-completion aren't going to be used, the
// following class _IS_ required
//
class ListBoxX : public ListBox {
public:
   ListBoxX() {}
   virtual ~ListBoxX() {}
   void SetFont(Font &) {}
   void Create(Window &, int, Point, int, bool, int) {}
   void SetAverageCharWidth(int) {}
   void SetVisibleRows(int) {}
   int GetVisibleRows() const {return 0;}
   PRectangle GetDesiredRect() { return PRectangle(); }
   int CaretFromEdge() { return 0; }
   void Clear() {}
   void Append(char *s, int type = -1) {}
   int Length() { return 0; }
   void Select(int n) {}
   int GetSelection() { return 0; }
   int Find(const char *prefix) { return -1; }
   void GetValue(int n, char *value, int len) {}
   void RegisterImage(int type, const char *xpm_data) {}
   void RegisterRGBAImage(int, int, int, const unsigned char *) {}
   void ClearRegisteredImages() {}
   void SetDoubleClickAction(CallBackAction, void *) {}
   void SetList(const char* list, char separator, char typesep) {}
};
ListBox::ListBox() {}
ListBox::~ListBox() {}
ListBox *ListBox::Allocate() {
   return new ListBoxX();
}

//==========================================================================
// CLASS ElapsedTime implementation (also seemingly required)
ElapsedTime::ElapsedTime() {
}
#ifdef SCI_NAMESPACE
}
#endif

Added tk/README.

































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
What is ScintillaTk?

Scintilla is a free source code editing component for Win32 and GTK+
developped by Neil Hodgson.
For more information about Scintilla, see http://www.scintilla.org.


This packages provides the Scintilla widget as a Tk Toolkit widget.
This Tk widget extension is modeled after the Tk text widget for
common or similar operations.  There are also additional subcommands
unique to Scintilla's features.  See the ScintillaTk man page for more
details.  This extension was developed using Tcl/Tk 8.5.  It will not
currently build with 8.4, but it may be possible with a little bit of
work.  It also requires Tk to have xft support in order to work
correctly.

This is a freely available open source package.  You can do virtually
anything you like with it, such as modifying it, redistributing it,
and selling it either in whole or in part.  See the file
"license.terms" for complete information.

CONTENTS
========
The following is a short description of the files you will find in
the tk platform directory.

Makefile.in	  Makefile template.  The configure script uses this file to
		  produce the final Makefile.

README		  This file

aclocal.m4	  Generated file.  Do not edit.  Autoconf uses this as input
		  when generating the final configure script.  See "tcl.m4"
		  below.

configure	  Generated file.  Do not edit.  This must be regenerated
		  anytime configure.in or tclconfig/tcl.m4 changes.

configure.in	  Configure script template.  Autoconf uses this file as input
		  to produce the final configure script.

pkgIndex.tcl.in   Package index template.  The configure script will use
		  this file as input to create pkgIndex.tcl.

license.terms     The licensing terms.

PlatTK.cxx        Tk platform implementation source files.
ScintillaTK.cxx
sciwrappers.cxx
sciwrappers.h
scintilla-ext.cxx
scintilla-ext.h
scintilla-cmd.cxx
scintilla-cmd.h

doc/scintilla.n		Unix nroff man page

widget-test.tcl
widget-text-test.tcl

tclconfig/	This directory contains various template files that build
		the configure script.  They should not need modification.

	install-sh	Program used for copying binaries and script files
			to their install locations.

	tcl.m4		Collection of Tcl autoconf macros.  Included by
			aclocal.m4 to define SC_* macros.

Scintilla Changes
=================
As part of this platform implementation, the following Scintilla
source files have been modified:

include/
        ILexer.h          - Add virtual destructors.
        Platform.h        - Add Tk platform defines and definitions.
        ScintillaWidget.h - Add Tk platform defines and definitions.

src/
    Editor.cxx - Force number conversion via casts.
    XPM.h    - Support 1-4 character color indexes.
    XPM.cxx    This allows more colorful marker images.


UNIX BUILD
==========

Building under most UNIX systems is easy, just run the configure script
and then run make. For more information about the build process, see
the tcl/unix/README file in the Tcl src dist. The following minimal
example will install the extension in the /opt/scintillatk directory.

	$ cd scintilla/tk
	$ ./configure
	$ make
	$ make install


WINDOWS BUILD
=============

The recommended method to build extensions under windows is to use the
Msys + Mingw build process. This provides a Unix-style build while
generating native Windows binaries. Using the Msys + Mingw build tools
means that you can use the same configure script as per the Unix build
to create a Makefile. See the tcl/win/README file for the URL of
the Msys + Mingw download.


INSTALLATION
============

The installation of a TEA package is structure like so:

         $exec_prefix
          /       \
        lib       bin
         |         |
   PACKAGEx.y   (dependent .dll files on Windows)
         |
  pkgIndex.tcl (.so|.dll files)

The main .so|.dll library file gets installed in the versioned PACKAGE
directory, which is OK on all platforms because it will be directly
referenced with by 'load' in the pkgIndex.tcl file.  Dependent DLL files on
Windows must go in the bin directory (or other directory on the user's
PATH) in order for them to be found.

Added tk/ScintillaTK.cxx.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
// Scintilla source code edit control
// ScintillaTK.cxx - Tk specific subclass of ScintillaBase
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be
// distributed.
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#include <tk.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <vector>
#include <map>

#include "Platform.h"
#include "SplitVector.h"

#include "ILexer.h"
#include "Scintilla.h"
#include "ScintillaWidget.h"

#include "AutoComplete.h"
#include "Partitioning.h"
#include "CallTip.h"
#include "CellBuffer.h"
#include "CharClassify.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "Decoration.h"
#include "Document.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "ViewStyle.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"

#ifdef SCI_LEXER
#include "SciLexer.h"
#include "LexerModule.h"
#include "ExternalLexer.h"
#endif

#include "scintilla-ext.h"
using namespace TkSciExt;

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif



/////////////////////////////////////////////////////////////////////
// CLASS: ScintillaTK
//
/////////////////////////////////////////////////////////////////////
class ScintillaTK : public ScintillaBase {

   // Private so ScintillaTK objects can not be copied
   ScintillaTK(const ScintillaTK &);
   ScintillaTK &operator=(const ScintillaTK &);

public:
   ScintillaTK(_ScintillaObject *sci_);
   virtual ~ScintillaTK();

private:
   // Required virtuals (ScintillaBase)
   virtual void Initialise();
   virtual void Finalise();

   // Required virtuals (Editor)
   virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
   virtual void ClaimSelection();
   virtual void Copy();
   virtual void CopyToClipboard(const SelectionText &selectedText);
   virtual void Paste();
   virtual void SetVerticalScrollPos();
   virtual void SetHorizontalScrollPos();
   virtual bool ModifyScrollBars(int nMax, int nPage);
   virtual void NotifyChange();
   virtual void NotifyParent(SCNotification scn);
   virtual void SetTicking(bool on);
   virtual void SetMouseCapture(bool on);
   virtual bool HaveMouseCapture();
   virtual void CreateCallTipWindow(PRectangle rc) {}
   virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true) {}

public:  // Public for client code to call back to scintilla
   virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

   // public to allow static "timeout" function access
   void Tick();
private:
   void CopyToScreen(bool margin_only = false);
   void PaintRect(PRectangle r);
   void FullPaint();

   void StoreOnClipboard(SelectionText *clipText);
   virtual PRectangle GetClientRectangle();
   virtual void DisplayCursor(Cursor c); // overload
   virtual void ScrollText(int linesToMove);

   bool capturedMouse;
   ScintillaObject *sc_obj;
   Surface *surfaceWindow;
   int press_button; // used to indicate which button was pressed
   int press_x;      // records X location of the press
   int press_y;      // Y location
   bool		  painted_region_set;
   PRectangle PaintedRegion;
};

//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// declared in ScintillaWidget.h
#ifdef _WIN32
void _print_trace (bool on) {}
#else
#include <execinfo.h> //FOR DUMPING THE CALL STACK...
void _print_trace (bool on) {
if (!on)
return;
#define TLEVELS 20
   void *array[TLEVELS];
   size_t size, i;
   char **strings;
   size = backtrace (array, TLEVELS);
   strings = backtrace_symbols (array, size);
   printf ("Obtained %d stack frames.\n", (int)size);
   for (i = 0; i < size; i++) printf (">>> %s\n", strings[i]);
   free (strings);
}
#endif
static int _x_error_count = 0;
int _x_error_handler(Display *dsp, XErrorEvent *evt) {
#ifndef _WIN32
   char buf[1000];
   if (_x_error_count++ > 10) {
      printf("X ERROR LIMIT EXCEEDED ... Bailing!!\n");
      exit(99);
      return 0;
   }
   XGetErrorText( dsp, evt->error_code, buf, 1000);
   printf("XERROR: %s\n\tDisplay=%p type=%d resourceid=%ld serial=%ld\n\terror_code=%d request_code=%d minor_code=%d\n",
      buf,
      (void *)dsp, evt->type, evt->resourceid, evt->serial, 
      evt->error_code, evt->request_code, evt->minor_code);
   _print_trace(1);
#endif
   return 0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

void ScintillaTK::Initialise() {
   //TODO: what goes in here???
printf("ScintillaTK::Initialise\n");
// maybe need to set up blinking of caret?
}
void ScintillaTK::Finalise() {
//   SetTicking(false);
   ScintillaBase::Finalise();
printf("ScintillaTK::Finalise\n");
}

//=============================================================
//CONSTRUCTOR
//=============================================================
extern int _Xdebug;

ScintillaTK::ScintillaTK(ScintillaObject *sc_obj_) :
   capturedMouse(false),
   surfaceWindow(0)
{
//printf("ScintillaTK CTOR this=%p\n",(void *)this);
   sc_obj = sc_obj_;
   wMain = sc_obj; // base class relies on this being set!!
//printf("CTOR >>>>>>>> wMain=%p\n",(void *)sc_obj);
#if 0
   //NOTE: Don't use this when running within vish !!
   _Xdebug = 1; // <<< this is a global in the X11 code
   XSetErrorHandler(_x_error_handler);
#endif
}
ScintillaTK::~ScintillaTK() {
//printf("ScintillaTK DTOR this=%p\n",(void *)this);
   if (surfaceWindow) {
      surfaceWindow->Release();

      if (timer.ticking) {
         Tcl_DeleteTimerHandler(reinterpret_cast<Tcl_TimerToken>(timer.tickerID));
      }
      delete surfaceWindow;
   }
}


/****************************************************************
// Func: WndProc
// Desc: Handles message processing
*****************************************************************/
sptr_t ScintillaTK::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
//printf("ScintillaTK::WndProc iMessage=%d\n",iMessage);
   try {
      switch (iMessage) {

         case SCI_TKMSG_ANNOTATIONLENGTH: {
            Document *doc = reinterpret_cast<Document *>(ScintillaBase::WndProc(SCI_GETDOCPOINTER,0,0));

            return doc->AnnotationStyledText(wParam).length;
         }
         case SCI_TKMSG_ANNOTATIONINDENT: {

            int line = static_cast<int>(wParam);
            bool pixels = static_cast<int>(lParam);

            Document *doc = reinterpret_cast<Document *>(ScintillaBase::WndProc(SCI_GETDOCPOINTER,0,0));

            // the indent value represents the number of spaces(tabs are converted to
            // the required number of spaces) preceding the text
            int indent = doc->GetLineIndentation(line);

            if ( ScintillaBase::WndProc(SCI_ANNOTATIONGETVISIBLE, 0,0) == ANNOTATION_BOXED ) {
               indent++; // box style adds extra space
            }
            if (pixels) {
               // adjust for width of margin(s) and pad region leftside of text
               int marginwidth = TkSciExt::GetMarginWidth((ClientData)sc_obj->client);
               marginwidth += ScintillaBase::WndProc(SCI_GETMARGINLEFT, 0,0);

               // adjust for hz scroll
               int xoff = ScintillaBase::WndProc(SCI_GETXOFFSET, 0,0);

               // the returned value will represent the X pixel location
               // of where the annotation text's left edge is.
               // Note: "vs" is a protected variable in Editor base class
               return (indent * vs.spaceWidth) + marginwidth - xoff;
            }
            return indent;
         }
		 case SCI_TKMSG_RESIZE : {
            ChangeSize();
			break;
         }
         case SCI_TKMSG_PAINT: {
            PRectangle *rc = reinterpret_cast<PRectangle *>(wParam);
            PaintRect(*rc);
            break;
         }
         case SCI_TKMSG_DESTROY: {
            delete this;
            break;
         }
         case SCI_TKMSG_DUMPSTYLES: {
            if (wParam != 0) {
               int n = static_cast<int>(ScintillaBase::WndProc(SCI_GETLENGTH,0,0));
               int last = -1;
               for (int i=0;i < n;i++) {
                  int curr = static_cast<int>(ScintillaBase::WndProc(SCI_GETSTYLEAT, i,0));
                  if (curr != last) {
                     last = curr;
                     printf("{%d}", curr); // << current style id
                  }
                  printf("%c", static_cast<char>(ScintillaBase::WndProc(SCI_GETCHARAT,i,0)));
               }
               printf("\n");
            }
            break;
         }
#ifdef SCI_LEXER
         case SCI_LOADLEXERLIBRARY:
            // support for dynamically loading external lexers
            LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
            break;
#endif
         case SCI_SETFOCUS: {
            //### KEEP THIS CASE ENTRY _LAST_ ###
            SetTicking(wParam != 0);
            // no "break", let base message handling deal with the rest
         }
         default:
            return ScintillaBase::WndProc(iMessage, wParam, lParam);
      }
   } catch (std::bad_alloc&) {
      errorStatus = SC_STATUS_BADALLOC;
   } catch (...) {
      errorStatus = SC_STATUS_FAILURE;
   }
   return 0l;
}
/****************************************************************
// Func: DefWndProc
// Desc: Required by Editor base class. It's called if the base
//       class's WndProc function doesn't handle a message
*****************************************************************/
sptr_t ScintillaTK::DefWndProc(unsigned int, uptr_t, sptr_t) {
   return 0;
}

/****************************************************************
// Func: PaintRect
// Desc: 
*****************************************************************/
void ScintillaTK::PaintRect(PRectangle r) {

   try {
      paintState = painting; // see Editor.h
      rcPaint = r;
      PRectangle rcClient = GetClientRectangle();

//printf("PaintRect: +%02d+%02dx%03dx%03d\n",rcPaint.left,rcPaint.top,(rcPaint.right-rcPaint.left),(rcPaint.bottom-rcPaint.top));

      paintingAllText = rcPaint.Contains(rcClient);
      if ( ! surfaceWindow) {
         surfaceWindow = Surface::Allocate(SC_TECHNOLOGY_DEFAULT);
      }
//printf("PaintRect: SURFACE=%p\n",(void *)surfaceWindow);
      if (surfaceWindow) {
         sc_obj->main = true;
         surfaceWindow->Init(sc_obj);
         painted_region_set = true;
         PaintedRegion = rcPaint;
         Paint(surfaceWindow, rcPaint); // call base class's Paint
         painted_region_set = false;

//printf("PaintRect: DONE\n^^^^^^^^^^\n");
      }
      if (paintState == paintAbandoned) {
         // Painting area was insufficient to cover new styling or brace highlight positions
         FullPaint();
      }
      paintState = notPainting;

   } catch (...) {
      // don't know how we would get here, but ScintiallaGTK does it this way...
      errorStatus = SC_STATUS_FAILURE;
   }
}

/****************************************************************
// Func: ScrollText
// Desc: Called from Editor::ScrollTo
*****************************************************************/
void ScintillaTK::ScrollText(int linesToMove) {

   int diff = vs.lineHeight * -linesToMove;
//printf("ScrollText %d pixels\n",diff);
   ClientData d = (ClientData)sc_obj->client;
   TkSciExt::SetYScrollDelta(d, diff);

   TkSciExt::UpdateForScroll(d);
//    if ( !(sciwidgetPtr->flags & REDRAW_PENDING) ) {
// //printf("ScrollText -- QUEUING DISPLAY\n");
//       Tk_DoWhenIdle(SciWidgetDisplay, (ClientData)sciwidgetPtr);

//    } else {
// //printf("ScrollText -- SKIPPING REDRAW...\n");
//    }
//    sciwidgetPtr->flags |= REDRAW_PENDING|REDRAW_YSCROLL;

//printf("OVERLOADED ScrollText moving %d lines\n",diff);
//   Editor::ScrollText(linesToMove);
}

/****************************************************************
// Func: GetClientRectangle
// Desc: Returns the bounding rectangle encompassing the parent
//       window
*****************************************************************/
PRectangle ScintillaTK::GetClientRectangle() {
   Tk_Window tkwin = sc_obj->tkwin;
   int w = Tk_Width(tkwin);
   int h = Tk_Height(tkwin);
//TODO: factor in borders???
int bd=0;
   PRectangle rc(bd,bd, w-(bd*2), h-(bd*2));
   return rc;
}

void ScintillaTK::DisplayCursor(Cursor c) {
printf("ScintillaTK::DisplayCursor\n");
}

// Redraw all of text area. This paint will not be abandoned.
void ScintillaTK::FullPaint() {
	paintState = painting;
	rcPaint = GetClientRectangle();
	paintingAllText = true;
	if (surfaceWindow) {
		Paint(surfaceWindow, rcPaint);
	} 
}

void ScintillaTK::Copy() {

   if (!sel.Empty()) {
      SelectionText *clipText = new SelectionText();
      CopySelectionRange(clipText);
      StoreOnClipboard(clipText);
   }
}
void ScintillaTK::CopyToClipboard(const SelectionText &selectedText) {

   SelectionText *clipText = new SelectionText();
   clipText->Copy(selectedText);
   StoreOnClipboard(clipText);
}
void ScintillaTK::StoreOnClipboard(SelectionText *clipText) {
//TODO: what do we do??
//Tk_ClipboardClear + Tk_ClipboardAppend ??
}
void ScintillaTK::Paste() {
//TODO: what do we do??
}

void ScintillaTK::ClaimSelection() {
//    // X Windows has a 'primary selection' as well as the clipboard.
//    // Whenever the user selects some text, we become the primary selection
//    if (!sel.Empty() && IS_WIDGET_REALIZED(GTK_WIDGET(PWidget(wMain)))) {
//       primarySelection = true;
//       gtk_selection_owner_set(GTK_WIDGET(PWidget(wMain)),
//                               GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
//       primary.Free();
//    } else if (OwnPrimarySelection()) {
//       primarySelection = true;
//       if (primary.s == NULL)
//          gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
//    } else {
//       primarySelection = false;
//       primary.Free();
//    }
}

// *required* virtual
void ScintillaTK::SetVerticalScrollPos() {
   DwellEnd(true);
   // most of the scroll functionality is handled in the widget's "yview" command

   TkSciExt::MSG_SyncYScroll((ClientData)sc_obj->client);
}

// *required* virtual
void ScintillaTK::SetHorizontalScrollPos() {
   DwellEnd(true);
   // the actual scroll functionality is handled in the widget's "xview" command

   TkSciExt::MSG_SyncXScroll((ClientData)sc_obj->client);
}

// *required* virtual
bool ScintillaTK::ModifyScrollBars(int nMax, int nPage) {
   bool modified = true;
   // this gets called _BEFORE_ the client window has it's size info set, which
   // means GetClientRectangle won't provide anything useful to the Editor code.
   // We'll deal with getting the initial scrollbar data set by handling the first
   // <Map> event - see widget.cxx in the SciWidgetEventProc function

   // CAVEAT: To support "scrollwidthtracking" we need to sync the horizontal
   // scrollbar because this function is called after Scintilla updates the
   // widest line info.
   if (!Tk_IsMapped(sc_obj->tkwin)) {
	   // if the window isn't mapped don't waste time updating the scrollbars
	   // the map notify event will force a scrollbar update
	   return 0;
   }
   if (WndProc(SCI_GETHSCROLLBAR, 0,0) && WndProc(SCI_GETSCROLLWIDTHTRACKING, 0,0)) {
       TkSciExt::MSG_SyncXScroll((ClientData)sc_obj->client);
   }
   if (WndProc(SCI_GETVSCROLLBAR, 0,0)) {
       TkSciExt::MSG_SyncYScroll((ClientData)sc_obj->client);
   }
   return modified;
}

void ScintillaTK::NotifyChange() {
//something changed in the document...
//printf("NotifyChange\n");
}
#define _RGB_(r,g,b) r | (g << 8) | (b << 16)
#include <time.h>

void ScintillaTK::NotifyParent(SCNotification scn) {
//printf("ScintillaTK::NotifyParent scn=%d  SURFACE=%p\n", scn.nmhdr.code,(void *)surfaceWindow);

   switch (scn.nmhdr.code) {

       case SCN_MODIFIED: {
          int mt = scn.modificationType;
          if (mt & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) {
             ClientData d = (ClientData)sc_obj->client;
             if (scn.linesAdded) {
                // send lines added message
                int ln = WndProc(SCI_LINEFROMPOSITION, scn.position, 0);

                TkSciExt::MSG_LinesAdded(d, ln, scn.linesAdded);
             }
             TkSciExt::MSG_Modified(d); // send notification of document modification
          } 
          break;
       }
      case SCN_PAINTED: {
         // This is called at the end of the Paint function, _BUT_ this
         // only happens if part of the text area had to be painted.
         //
         CopyToScreen();
         break;
      }
      case SCN_UPDATEUI: {
         // Note that this is how SciTE does updates for the statusbar's
         // line and column indicator.

         TkSciExt::MSG_MoveUpdate((ClientData)sc_obj->client);
         break;
      }
   }
}

void ScintillaTK::CopyToScreen(bool margin_only) {
   PRectangle r;
   Point pt = Point(0,0);
   if (painted_region_set) { 
		r = PaintedRegion;
   } else { 
	    r = GetClientRectangle();
   }

   if (margin_only) {

      int marginwidth = TkSciExt::GetMarginWidth((ClientData)sc_obj->client);
      if (marginwidth <= 0) return;
      r.right = marginwidth;
   }
   // copy offscreen pixmap used by drawing operations
   // to the screen
   surfaceWindow->Copy(r, pt, *surfaceWindow);
}


//////////////////////////////////////////////////////
// BEGIN caret(aka "tick") management
//////////////////////////////////////////////////////
static void _TimeOut(ClientData cd) {

   ScintillaTK *sc = reinterpret_cast<ScintillaTK *>(cd);
   sc->Tick(); // call our overloaded function
}
void ScintillaTK::Tick() {

   // Mimic how Tk shows the insert caret(which is 1-pixel wide
   // for the first column and thicker for the others)
   int currpos = CurrentPosition();
   int col = WndProc(SCI_GETCOLUMN, currpos, 0);
   vs.caretWidth = (col == 0 ? 1 : 2);

   Editor::Tick();

   // schedule another timer...
   timer.tickerID = reinterpret_cast<TickerID>(
      Tcl_CreateTimerHandler(timer.tickSize, _TimeOut, (ClientData)this)
   );
}
// This is called from Editor
void ScintillaTK::SetTicking(bool on) {

   if (timer.ticking != on) {
      timer.ticking = on;
      if (timer.ticking) {
         timer.tickerID = reinterpret_cast<TickerID>(
            Tcl_CreateTimerHandler(timer.tickSize, _TimeOut, (ClientData)this)
         );
      } else {
         Tcl_DeleteTimerHandler(reinterpret_cast<Tcl_TimerToken>(timer.tickerID));
      }
   }
   timer.ticksToWait = caret.period;
}
//////////////////////////////////////////////////////

void ScintillaTK::SetMouseCapture(bool on) {

   if (mouseDownCaptures) {
      if (on) {
         Tk_Grab(sc_obj->interp, sc_obj->tkwin, 0/*is_global*/);
      } else {
         Tk_Ungrab(sc_obj->tkwin);
      }
   }
   capturedMouse = on;
}
bool ScintillaTK::HaveMouseCapture() {
   return capturedMouse;
}

//--- end of class ScintillaTK

//#############################################################################
//#
//# The following two functions, which are declared in ScintillaWidget.h, are
//# how Tk-based widgets create and communicate with the Scintilla editor
//#
//#############################################################################
ScintillaObject* scintilla_new(Tcl_Interp *interp, Tk_Window tkwin, ClientData cd) {

   ScintillaObject *sci_obj = new ScintillaObject;
   sci_obj->interp = interp;
   sci_obj->tkwin  = tkwin;
   sci_obj->client = cd;
   sci_obj->main = false;
   sci_obj->pscin  = new ScintillaTK(sci_obj);
   return sci_obj;
}

sptr_t scintilla_send_message(ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam) {

   ScintillaTK *psci = reinterpret_cast<ScintillaTK *>(sci->pscin);
   return psci->WndProc(iMessage, wParam, lParam);
}

Added tk/aclocal.m4.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
#
# Include the TEA standard macro set
#

builtin(include,tclconfig/tcl.m4)

#
# Add here whatever m4 macros you want to define for your package
#

Added tk/configure.

more than 10,000 changes

Added tk/configure.in.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
#!/bin/bash -norc
dnl	This file is an input file used by the GNU "autoconf" program to
dnl	generate the file "configure", which is run during Tcl installation
dnl	to configure the system for the local environment.

#-----------------------------------------------------------------------
# Sample configure.in for Tcl Extensions.  The only places you should
# need to modify this file are marked by the string __CHANGE__
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
# __CHANGE__
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided.  These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
# This will also define a special symbol for Windows (BUILD_sample in
# this case) so that we create the export library with the dll.
#-----------------------------------------------------------------------

AC_INIT([ScintillaTk], [0.26])

#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------

TEA_INIT([3.9])

AC_CONFIG_AUX_DIR(tclconfig)

#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------

TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG

#--------------------------------------------------------------------
# Load the tkConfig.sh file if necessary (Tk extension)
#--------------------------------------------------------------------

TEA_PATH_TKCONFIG
TEA_LOAD_TKCONFIG

#-----------------------------------------------------------------------
# Handle the --prefix=... option by defaulting to what Tcl gave.
# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
#-----------------------------------------------------------------------

TEA_PREFIX

#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC and a few others to create the basic setup
# necessary to compile executables.
#-----------------------------------------------------------------------

TEA_SETUP_COMPILER
AC_PROG_CXX
AC_PROG_CXXCPP


#-----------------------------------------------------------------------
# __CHANGE__
# Specify the C source files to compile in TEA_ADD_SOURCES,
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
# and PKG_TCL_SOURCES.
#-----------------------------------------------------------------------

TEA_ADD_SOURCES([PlatTK.cxx ScintillaTK.cxx sciwrappers.cxx scintilla-cmd.cxx scintilla-ext.cxx])
TEA_ADD_HEADERS([])
TEA_ADD_INCLUDES([-I\"${srcdir}/../include\" -I\"${srcdir}/../src\" -I\"${srcdir}/../lexlib\"])
TEA_ADD_LIBS([${TK_LIBS}])
SCI_CORE_VER=`cat ${srcdir}/../win32/ScintRes.rc | awk '/#define VERSION_SCINTILLA/ {printf("%s\n",$3);}'`
TEA_ADD_CFLAGS([-DSCI_NAMESPACE -DTK -DSCI_LEXER -DSCI_CORE_VERSION=\\\"${SCI_CORE_VER}\\\"])
TEA_ADD_STUB_SOURCES([])
TEA_ADD_TCL_SOURCES([scintillatk.tcl])

#--------------------------------------------------------------------
# __CHANGE__
#
# You can add more files to clean if your extension creates any extra
# files by extending CLEANFILES.
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#
# A few miscellaneous platform-specific items:
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------

#CLEANFILES="$CLEANFILES pkgIndex.tcl"
if test "${TEA_PLATFORM}" = "windows" ; then
    # Ensure no empty if clauses
    :
    #TEA_ADD_SOURCES([win/winFile.c])
    #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
else
    # Ensure no empty else clauses
    :
    #TEA_ADD_SOURCES([unix/unixFile.c])
    #TEA_ADD_LIBS([-lsuperfly])
fi

#--------------------------------------------------------------------
# __CHANGE__
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
#--------------------------------------------------------------------

TEA_PUBLIC_TCL_HEADERS
#TEA_PRIVATE_TCL_HEADERS

TEA_PUBLIC_TK_HEADERS
#TEA_PRIVATE_TK_HEADERS
#TEA_PATH_X

#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
# This auto-enables if Tcl was compiled threaded.
#--------------------------------------------------------------------

TEA_ENABLE_THREADS

#--------------------------------------------------------------------
# The statement below defines a collection of symbols related to
# building as a shared library instead of a static library.
#--------------------------------------------------------------------

TEA_ENABLE_SHARED

#--------------------------------------------------------------------
# This macro figures out what flags to use with the compiler/linker
# when building shared/static debug/optimized objects.  This information
# can be taken from the tclConfig.sh file, but this figures it all out.
#--------------------------------------------------------------------

TEA_CONFIG_CFLAGS

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols option.
#--------------------------------------------------------------------

TEA_ENABLE_SYMBOLS

#--------------------------------------------------------------------
# Everyone should be linking against the Tcl stub library.  If you
# can't for some reason, remove this definition.  If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library.  Add Tk too if necessary.
#--------------------------------------------------------------------

AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])

#--------------------------------------------------------------------
# This macro generates a line to use when building a library.  It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
# and TEA_LOAD_TCLCONFIG macros above.
#--------------------------------------------------------------------

TEA_MAKE_LIB

#--------------------------------------------------------------------
# Determine the name of the tclsh and/or wish executables in the
# Tcl and Tk build directories or the location they were installed
# into. These paths are used to support running test cases only,
# the Makefile should not be making use of these paths to generate
# a pkgIndex.tcl file or anything else at extension build time.
#--------------------------------------------------------------------

TEA_PROG_TCLSH
#TEA_PROG_WISH

#--------------------------------------------------------------------
# Finally, substitute all of the various values into the Makefile.
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in.  Include these here.
#--------------------------------------------------------------------

AC_OUTPUT([Makefile pkgIndex.tcl])

Added tk/doc/demos/ypedit.tcl.





















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# ypedit.tcl --
#    Shell procedures for Young Programmers Project:
#    It defines several utility commands:
#    ed       - edit a file
#    vw       - view the contents of a file
#
# From: http://wiki.tcl.tk/9600
#
# Modified to use ScintillaTk text widget
#             use ttk widgets

package require Tk
lappend auto_path [file normalize ../../../../build/usr/lib]
package require ScintillaTk

ttk::style theme use clam

# ypshell --
#    Namespace for the commands
#
namespace eval ::ypshell {

   namespace export ed vw

   variable editfile
   set editfile(count) 0
}

# ed --
#    Edit a file
#
# Arguments:
#    filename   Name of the file to edit
#
# Return value:
#    None
#
proc ::ypshell::ed { filename } {
   ::ypshell::EditFile 1 0 $filename
}

# vw --
#    View a file
#
# Arguments:
#    filename   Name of the file to view
#
# Return value:
#    None
#
proc ::ypshell::vw { filename } {
   ::ypshell::EditFile 0 0 $filename
}

# EditFile --
#    Edit or view a file (actual procedure)
#
# Arguments:
#    editable   Select edit mode (1=edit, 0=view)
#    newopen    Allow new/open menu items (1=yes, 0=no)
#    filename   Name of the file to edit/view
#
# Return value:
#    None
#
proc ::ypshell::EditFile { editable newopen filename } {
   variable editfile

   incr editfile(count)
   set  w .edit$editfile(count)
   toplevel $w
   wm withdraw .
   wm title $w "Edit/view: $filename"

   set  mb $w.menubar
   menu      $mb
   #pack       $mb -side top -fill x -pady 0
   $w configure -menu $mb
   #ttk::menubutton $mb.file   -text File   -menu $mb.file.menu    -underline 0
   #ttk::menubutton $mb.edit   -text Edit   -menu $mb.edit.menu    -underline 0
   #ttk::menubutton $mb.search -text Search -menu $mb.search.menu  -underline 0
   #ttk::menubutton $mb.help   -text Help   -menu $mb.help.menu    -underline 0

	menu       $mb.file   -tearoff false; $mb add cascade -label File -menu $mb.file
	menu       $mb.edit   -tearoff false; $mb add cascade -label Edit -menu $mb.edit
	menu       $mb.search -tearoff false; $mb add cascade -label Search -menu $mb.search
	menu       $mb.help   -tearoff false; $mb add cascade -label Help -menu $mb.help

   #pack       $mb.file $mb.edit $mb.search -side left
   #pack       $mb.help -side left ;# Platform-dependent!

   #
   # Set up the "File" menu
   #
   if { $newopen } {
      if { $editable } {
         $mb.file add command -label New -underline 0 \
            -command [list ::ypshell::NewFile]
      }
      $mb.file add command -label Open -underline 0 \
         -command [list ::ypshell::OpenFile]
      $mb.file add separator
   }

   if { $editable } {
      $mb.file add command -label Save -underline 0 \
         -command [list ::ypshell::SaveFile $w $filename 0]
      if { $newopen } {
         $mb.file add command -label "Save as ..." -underline 1 \
            -command [list ::ypshell::SaveFile $w $filename 1]
      }
      $mb.file add separator
   }
   $mb.file add command -label Exit -underline 1 \
      -command [list ::ypshell::ExitEdit $w $newopen $editable $filename]

   #
   # Set up the "Edit" menu
   #
   if { $editable } {
      $mb.edit add command -label "Undo" -underline 0 \
         -command [list ::ypshell::UndoChange]
      $mb.edit add command -label "Redo" -underline 0 \
         -command [list ::ypshell::RedoChange]
      $mb.edit add separator
   }
   $mb.edit add command -label "Mark line(s)" -underline 0 \
      -command [list ::ypshell::MarkLines]
   $mb.edit add command -label "Unmark line(s)" -underline 1 \
      -command [list ::ypshell::UnmarkLines]
   $mb.edit add separator
   $mb.edit add command -label "Copy" -underline 0 \
      -command [list ::ypshell::CopyBlock]
   if { $editable } {
      $mb.edit add command -label "Paste" -underline 0 \
         -command [list ::ypshell::PasteBlock]
      $mb.edit add separator
      $mb.edit add command -label "Delete" -underline 0 \
         -command [list ::ypshell::DeleteBlock]
   }

   #
   # Set up the "Search" menu
   #
   $mb.search add command -label "Find" -underline 0 \
      -command [list ::ypshell::FindText $w]
   if { $editable } {
      $mb.search add command -label "Replace" -underline 0 \
      -command [list ::ypshell::ChangeText]
   }

   #
   # Set up the "Help" menu
   #
   $mb.help add command -label "Overview" -underline 1 \
      -command [list ::ypshell::HelpOverview]
   $mb.help add command -label "About" -underline 0 \
      -command [list ::ypshell::AboutEdit]

   #
   # Create a thin separator
   #
   set ts $w.separator
   #frame $ts -height 2 -relief sunken -borderwidth 1
	ttk::separator $ts -orient horizontal
   pack  $ts -side top -fill x

   #
   # Create the toolbar
   #
   set fnt       "Courier, 10"
   set fnt       "systemfixed"
   set fixedfont "Courier"
   set tb  $w.toolbar
   ttk::frame $tb -height 10
   ttk::button $tb.goto   -text "Go to:" -command [list ::ypshell::GotoLine $w ""]
   ttk::entry  $tb.lineno -textvariable ::ypshell::editfile(lineno,$w) \
      -width 5 -font $fnt
   ttk::button $tb.top    -text "Top"    -command [list ::ypshell::GotoLine $w 1]
   ttk::button $tb.bottom -text "Bottom" -command [list ::ypshell::GotoLine $w end]
   ttk::label  $tb.empty1 -text " "
   ttk::label  $tb.empty2 -text " "

   set ::ypshell::editfile(lineno,$w) 1

   pack   $tb.goto $tb.lineno $tb.empty1 $tb.top $tb.bottom $tb.empty2 -side left

   ttk::button $tb.find   -text "Find:" -command [list ::ypshell::FindText $w]
   ttk::entry  $tb.string -textvariable ::ypshell::editfile(find,$w) \
      -font $fnt

   set ypshell::editfile(find,$w) ""

   pack   $tb.goto $tb.find $tb.string -side left

   pack   $tb -fill x -side top

   #
   # Create the text widget and the scroll bars
   #
   set tf $w.textframe
   set tw $tf.text
   ttk::frame $tf
   ttk::scrollbar $tf.scrollx -orient horiz -command "$tw xview"
   ttk::scrollbar $tf.scrolly               -command "$tw yview"
	if {0} {
   text      $tw         -yscrollcommand "$tf.scrolly set" \
                         -xscrollcommand "$tf.scrollx set" \
                         -font $fixedfont
	} else {
		set bg [ttk::style lookup client -background]
   scintilla $tw         -yscrollcommand "$tf.scrolly set" \
                         -xscrollcommand "$tf.scrollx set" \
                         -font $fixedfont \
	                     -marginbackground $bg
		$tw margin configure 0 -type lnums
		$tw margin configure 4 -type fold
		$tw margin show 0
		$tw margin show 4

		$w configure -background $bg
		$mb configure -background $bg
	}

   grid      $tw         $tf.scrolly
   grid      $tf.scrollx x
   grid      $tw         -sticky news
   grid      $tf.scrolly -sticky ns
   grid      $tf.scrollx -sticky ew

   grid columnconfigure $tf 0 -weight 1
   grid rowconfigure    $tf 0 -weight 1

	if {0} {
   $tw configure -wrap none
	}

   pack $tf -fill both -side top -expand 1

   set ypshell::editfile(textwidget,$w) $tw

   LoadFile $tw $filename
}

# LoadFile --
#    Load the file into the text widget
#
# Arguments:
#    textw      Text widget to use
#    filename   Name of the file to edit/view
#
# Return value:
#    None
#
proc ::ypshell::LoadFile { textw filename } {
   set infile [ open "$filename" "r" ]
	set ext [string range [file extension $filename] 1 end]
	if {$ext ne ""} {
		catch {$textw configure -language $ext}
	}
   while { ! [ eof $infile ] } {
      gets $infile line
      $textw insert end $line
      $textw insert end "\n"
   }

	$textw tag configure pink -background #ffdddd -italic 1
	$textw annotate set 14 ""
	$textw annotate set 14 "At this point, the scintilla code is loaded." pink
	$textw tag configure bright -bold 1 -background blue -foreground yellow
	$textw annotate set 16 "Dig those clams man!\nI like clam style because it's the only\nttk style that does not look boring!" bright
	$textw annotate show 2

   close $infile
}

# SaveFile --
#    Save the file (possibly under a different name)
#
# Arguments:
#    w          Main widget holding the text
#    filename   Name of the file to edit/view
#    newname    Ask for a new name or not
#
# Return value:
#    None
#
proc ::ypshell::SaveFile { w filename newname } {
   variable editfile

   set tw $editfile(textwidget,$w)

   # Select a new file name -- TODO

   set outfile [ open "$filename" "w" ]

   set lineno 1
   while { [$tw compare $lineno.0 < end] } {
      puts $outfile [$tw get "$lineno.0" "$lineno.0 lineend"]
      incr lineno
   }

   close $outfile
}

# GotoLine --
#    Go to a specified line number
#
# Arguments:
#    w          Main widget containing the text widget
#    pos        Position
#
# Return value:
#    None
#
proc ::ypshell::GotoLine { w pos } {
   variable editfile

   set tw $editfile(textwidget,$w)
   if { $pos == "" } {
      set pos $editfile(lineno,$w)
   }

   if { $pos == "end" } {
      $tw mark set current "end linestart"
   } else {
      $tw mark set current "$pos.0"
   }
   $tw mark set insert [$tw index current]
	$tw see [$tw index current]

   focus $tw
}

# FindText --
#    Find a text string
#
# Arguments:
#    w          Main widget containing the text widget
#
# Return value:
#    None
#
proc ::ypshell::FindText { w } {
   variable editfile

   set string $editfile(find,$w)
   set tw     $editfile(textwidget,$w)

   if { $string != "" } {
      set newpos [$editfile(textwidget,$w) search -forwards -exact -- $string "insert + 1 chars"]

      if { $newpos != "" } {
         $tw mark set current $newpos
         $tw mark set insert [$tw index current]
		  $tw see [$tw index current]
         focus $tw
      }
   }
}

# ExitEdit --
#    Exit and save the file (if wanted)
#
# Arguments:
#    w          Widget from which it is called
#    editable   Select edit mode (1=edit, 0=view)
#    newopen    Allow new/open menu items (1=yes, 0=no)
#    filename   Name of the file to edit/view
#
# Return value:
#    None
#
proc ::ypshell::ExitEdit { w editable newopen filename } {
   if { $editable } {
      if { !$newopen } {
         SaveFile $w $filename 0
      } else {
         # Ask whether to save or not
      }
   }

   destroy $w
}

#
# Simple test code
#
namespace import ::ypshell::ed
namespace import ::ypshell::vw

ed [file join [file dirname [info script]] ypedit.tcl]
vw [file join [file dirname [info script]] ypedit.tcl]
#$tw annotate set 210 "This is where margins are configured to show\ndifferent contents."

Added tk/doc/scintillatk.html.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
<HTML>
<BODY>
<PRE>
<!-- Manpage converted by man2html 3.0.1 -->
       scintilla - Scintilla text widget


</PRE>
<H2>SYNOPSIS</H2><PRE>
       <B>package</B> <B>require</B> <B>scintillatk</B> ?<B>0.25</B>?

       <B>scintilla</B> <I>pathName</I> ?<I>options</I>?


</PRE>
<H2>STANDARD OPTIONS</H2><PRE>
       <B>-autoseparators</B>       <B>-highlight</B>           <B>-moveupdatecommand</B>
       <B>-background</B>           <B>-highlightthickness</B>  <B>-relief</B>
       <B>-blink</B>                <B>-highlightbackground</B> <B>-showws</B>
       <B>-borderwidth</B>          <B>-language</B>            <B>-state</B>
       <B>-busycursor</B>           <B>-linesaddedcommand</B>   <B>-tabwidth</B>
       <B>-cursor</B>               <B>-marginbackground</B>    <B>-takefocus</B>
       <B>-foldstyle</B>            <B>-marginbg</B>            <B>-xscrollcommand</B>
       <B>-font</B>                 <B>-marginforeground</B>    <B>-yscrollcommand</B>
       <B>-foreground</B>           <B>-marginfg</B>            <B>-undo</B>
       <B>-height</B>               <B>-marginwidthcommand</B>  <B>-width</B>

       See the <B>options</B> manual entry for details on the standard options.


</PRE>
<H2>WIDGET-SPECIFIC OPTIONS</H2><PRE>
       Command-Line Name:<B>-autoseparators</B>
       Database Name:  <B>autoSeparators</B>
       Database Class: <B>AutoSeparators</B>

              Specifies  a  boolean that says whether separators are automati-
              cally inserted in the undo stack. Only meaningful when the <B>-undo</B>
              option is true.

       Command-Line Name:<B>-height</B>
       Database Name:  <B>height</B>
       Database Class: <B>Height</B>

              Specifies the desired height for the window, in units of charac-
              ters in the font given by the <B>-font</B> option.  Must  be  at  least
              one.

       Command-Line Name:<B>-state</B>
       Database Name:  <B>state</B>
       Database Class: <B>State</B>

              Specifies  one  of two states for the text:  <B>normal</B> or <B>disabled</B>.
              If the text is disabled then characters may not be  inserted  or
              deleted  and  no insertion cursor will be displayed, even if the
              input focus is in the widget.

       Command-Line Name:<B>-width</B>
       Database Name:  <B>width</B>
       Database Class: <B>Width</B>

              Specifies the desired width for the window in units  of  charac-
              See Scintilla documentation for style values.

       Command-Line Name:<B>-language</B>
       Database Name:  <B>language</B>
       Database Class: <B>Language</B>

              Specifies  which  programming  language  lexer to use for syntax
              highlighting.

       Command-Line Name:<B>-linesaddedcommand</B>
       Database Name:  <B>lindesAddedCommand</B>
       Database Class: <B>LinesAddedCommand</B>

              Callback command when new lines are inserted  in  the  document.
              This  function can be used to update margin indicators if neces-
              sary.

       Command-Line Name:<B>-marginbackground</B>
       Database Name:  <B>marginBackground</B>
       Database Class: <B>MarginBackground</B>

              The backgound color of the margin columns.

       Command-Line Name:<B>-marginforeground</B>
       Database Name:  <B>marginForeground</B>
       Database Class: <B>MarginForeground</B>

              The foregound (font) color of the margin columns.

       Command-Line Name:<B>-marginwidthcommand</B>
       Database Name:
       Database Class:

              Callback command used when margin width changes.

       Command-Line Name:<B>-moveupdatecommand</B>
       Database Name:  <B>moveUpdateCommand</B>
       Database Class: <B>MoveUpdateCommand</B>

              Callback command when margin changes.

       Command-Line Name:<B>-showws</B>
       Database Name:  <B>showws</B>
       Database Class: <B>ShowWs</B>

              Show the ws???

_________________________________________________________________


</PRE>
<H2>DESCRIPTION</H2><PRE>
       The <B>scintilla</B> command creates a new window (given by the <I>pathName</I>  arg)
       and  makes  it  into  a  Scintilla  text  widget.  Additional  options,
              <B>clearall</B>
                     removes annotation strings for all lines

              <B>get</B> <I>line</I>
                     Returns the annotation text for the specified line.

              <B>set</B> <I>line</I> <I>text</I> <I>?tagName</I> <I>text</I> <I>tagName</I> <I>...?</I>
                     Assigns  the specified text string to the specified line.
                     If no tagName option is specified,  the  annotation  text
                     will  use  the  default text styling. If a single tagName
                     option is used it will control the appearance for all  of
                     the  annotation  text. By using multiple text and tagName
                     options it's possible to have different  appearances  for
                     different subranges of the text.

              <B>show</B> <I>0|1|2</I>
                     Used to control the display of annotations where 0 - hid-
                     ing, 1 - showing or 2 -  showing  with  a  bounding  box.
                     Note, this affects all lines with annotations.

       <I>pathName</I> <B>bbox</B> <I>index</I>
              Returns  a  list  of four elements describing the screen area of
              the character given by index. The first two elements of the list
              give  the  x  and  y coordinates of the upper-left corner of the
              area occupied by the character, and the last two  elements  give
              the  width and height of the area. If the character is not visi-
              ble on the screen then the return value is an empty list.

       <I>pathName</I> <B>cget</B> <I>option</I>
              Returns the current value of the configuration option  given  by
              option.  Option may have any of the values accepted by the scin-
              tilla command.

       <I>pathName</I> <B>compare</B> <I>index1</I> <I>op</I> <I>index2</I>
              Compares the indices given by index1 and index2 according to the
              relational  operator given by op, and returns 1 if the relation-
              ship is satisfied and 0 if it is not. Op  must  be  one  of  the
              operators  &lt;,  &lt;=, =, &gt;, &gt;, or !. If op is == then 1 is returned
              if the two indices refer to the same character, if op is &lt;  then
              1  is  returned  if index1 refers to an earlier character in the
              text than index2, and so on.

       <I>pathName</I> <B>configure</B> <I>?option?</I> <I>?value</I> <I>option</I> <I>value</I> <I>...?</I>
              Query or modify the configuration options of the widget.  If  no
              option is specified, returns a list describing all of the avail-
              able options for pathName. If option is specified with no value,
              then  the command returns a list describing the one named option
              (this list will be identical to the corresponding sublist of the
              value  returned  if  no  option  is  specified).  If one or more
              option-value pairs are specified, then the command modifies  the
              given  widget option(s) to have the given value(s); in this case
              the command returns an empty string. Option may have any of  the

              <B>-displaylines</B>
                     count  all  display  lines  (i.e.  ignore lines which are
                     folded) from the line of the first index up to,  but  not
                     including the display line of the second index. Therefore
                     if they are both on the same display line, zero  will  be
                     returned.  By  definition  displaylines  are  visible and
                     therefore this only counts  portions  of  actual  visible
                     lines.

              <B>-lines</B> count  all  lines (irrespective of folding) from the line
                     of the first index up to, but not including the  line  of
                     the  second index. Therefore if they are both on the same
                     line, zero will be returned. Lines  are  counted  whether
                     they are currently visible (non-folded) or not.

       <I>pathName</I> <B>delete</B> <I>index1</I> <I>?index2?</I>
              Delete  a  range of characters from the text. If both index1 and
              index2 are specified, then delete all  the  characters  starting
              with  the  one  given  by index1 and stopping just before index2
              (i.e. the character at index2 is not deleted). If index2 doesn't
              specify a position later in the text than index1 then no charac-
              ters are deleted. If index2  isn't  specified  then  the  single
              character  at  index1  is deleted. It is not allowable to delete
              characters in a way that would leave the text without a  newline
              as the last character. The command returns an empty string.

       <I>pathName</I> <B>dump</B> <I>?switches?</I> <I>index1</I> <I>?index2?</I><B>_</B>
              Return  the  contents  of the text widget from index1 up to, but
              not including index2, including the text and  information  about
              marks,  tags,  and embedded windows. If index2 is not specified,
              then it defaults to one character past index1.  The  information
              is  returned  in  the following format:: key1 value1 index1 key2
              value2 index2 ...  The  possible  key  values  are  indicatoron,
              indicatoroff,  text,  mark,  styleon,  styleoff,  tagon, tagoff,
              image, and window. The  corresponding  value  is  the  indicator
              type,  text,  mark  name, style number, tag name, image name, or
              window name. The index information is the index of the start  of
              the  indicator  transition,  style  transition,  text, mark, tag
              transition, image or window. The image and  window  options  are
              not  supported  and will return nothing. One or more of the fol-
              lowing switches (or abbreviations thereof) may be  specified  to
              control the dump:

              <B>-all</B>   Return  information about all elements: indicator, style,
                     text, marks,  tags,  images  and  windows.  This  is  the
                     default.

              <B>-command</B> <I>command</I>
                     Instead of returning the information as the result of the
                     dump operation, invoke the command on each element of the
                     text widget within the range. The command has three argu-

              <B>-style</B> Include  information  about style transitions in the dump
                     results. Style information is  returned  as  styleon  and
                     styleoff elements that indicate the begin and end of each
                     range of each style, respectively.

              <B>-tag</B>   Include information about tag  transitions  in  the  dump
                     results.  Tag information is returned as tagon and tagoff
                     elements that indicate the begin and end of each range of
                     each tag, respectively.

              <B>-text</B>  Include  information  about text in the dump results. The
                     value is the text up to the next element or  the  end  of
                     range  indicated  by index2. A text element does not span
                     newlines. A multi-line block of  text  that  contains  no
                     marks or tag transitions will still be dumped as a set of
                     text segments that each end with a newline.  The  newline
                     is part of the value.

              <B>-window</B>
                     Include  information  about  embedded windows in the dump
                     results. This option is unsupported in Scintilla.

       <I>pathName</I> <B>edit</B> <I>option</I> <I>?arg</I> <I>arg</I> <I>...?</I>
              This command controls the undo mechanism and the modified  flag.
              The exact behavior of the command depends on the option argument
              that follows the edit argument. The following forms of the  com-
              mand are currently supported:

              <I>pathName</I> <B>edit</B> <B>canredo</B>
                     Returns true if the redo stack is not empty.

              <I>pathName</I> <B>edit</B> <B>canundo</B>
                     Returns true if the undo stack is not empty.

              <I>pathName</I> <B>edit</B> <B>Imodified</B> <I>?boolean?</I>
                     If boolean is not specified, returns the modified flag of
                     the widget. The insert, delete, edit undo and  edit  redo
                     commands  or the user can set or clear the modified flag.
                     If boolean is specified, sets the modified  flag  of  the
                     widget to boolean.

              <I>pathName</I> <B>edit</B> <B>redo</B>
                     When  the -undo option is true, reapplies the last undone
                     edits provided no other edits were done since then.  Gen-
                     erates  an error when the redo stack is empty. Does noth-
                     ing when the -undo option is false.

              <I>pathName</I> <B>edit</B> <B>reset</B>
                     Clears the undo and redo stacks.

              <I>pathName</I> <B>edit</B> <B>separator</B>
                     Inserts a separator (boundary) on the  undo  stack.  Does

              document. The following commands are supported:

              <B>foldall</B>
                     folds all lines within the document

              <B>foldbelow</B> <I>line</I>
                     folds all lines which are after(below) line number line

              <B>foldparent</B> <I>line</I>
                     returns  the line containing the immediate fold parent of
                     line

              <B>foldroot</B> <I>line</I>
                     returns the line containing topmost fold  parent  of  the
                     specified line . This is at the top of the fold hierarchy
                     containing line .

              <B>isfolded</B> <I>line</I>
                     return 1 if line contained in a folded parent, and  0  if
                     it isn't

              <B>show</B> <I>line</I>
                     fully expand the containing fold hierarchy such that line
                     is visible

              <B>toggle</B> <I>line</I>
                     toggle the fold state of line (ie  if  collapsed,  expand
                     it; if expanded, collapse it)

              <B>topunfolded</B> <I>line</I>
                     return the line of the highest fold parent for line which
                     is currently expanded

              <B>unfoldall</B>
                     unfold all lines

              <B>unfoldbelow</B> <I>line</I>
                     unfold all lines which are after(below) line number line

       <I>pathName</I> <B>index</B> <I>index</I> <I>?-textonly?</I>
              Returns  the  position  corresponding  to  index  in  the   form
              line.char  where line is the line number and char is the charac-
              ter number. See the documentation for the Tk Text widget  for  a
              description of the formats used to specify indices. NOTE: Speci-
              fying an X/Y location that corresponds to a line  of  annotation
              text  will  return  the index for the end of the line associated
              with the annotation. If the -textonly option is  used,  then  an
              empty  string is returned if the X/Y location is over an annota-
              tion.

       <I>pathName</I> <B>insert</B> <I>index</I> <I>chars</I>
              Inserts all of the chars argument just before the  character  at
              alias name defined for the margin. The following  forms  of  the
              command are currently supported:

              <I>pathName</I> <B>margin</B> <B>bbox</B> <I>marginID</I> <I>line</I>
                     Returns  a  list  of  four elements describing the screen
                     area of the margin identified by marginID,  at  the  line
                     specified  by  line.  The  first two elements of the list
                     give the x and y coordinates of the upper-left corner  of
                     the area occupied by the character, and the last two ele-
                     ments give the width and height of the area. If the char-
                     acter  is not visible on the screen then the return value
                     is an empty list.

              <I>pathName</I> <B>margin</B> <B>cget</B> <I>marginID</I> <I>option</I>
                     This command returns the  current  value  of  the  option
                     named   option   associated  with  the  margin  given  by
                     marginID. Option may have any of the values  accepted  by
                     the pathName margin configure widget command.

              <I>pathName</I>  <B>margin</B>  <B>configure</B>  <I>marginID</I>  <I>?option?</I>  <I>?value?</I> <I>?option</I>
              <I>value</I> <I>...?</I>
                     This  command is similar to the pathName configure widget
                     command except that it modifies options  associated  with
                     the margin given by marginID instead of modifying options
                     for the overall text widget. If no option  is  specified,
                     the  command  returns a list describing all of the avail-
                     able options for marginID. If option is specified with no
                     value, then the command returns a list describing the one
                     named option (this list will be identical to  the  corre-
                     sponding  sublist  of  the value returned if no option is
                     specified). If one or more option-value pairs are  speci-
                     fied,  then  the  command modifies the given option(s) to
                     have the given value(s) in marginID;  in  this  case  the
                     command returns an empty string.

              <I>pathName</I> <B>margin</B> <B>count</B>
                     Returns the number of margins

              <I>pathName</I> <B>margin</B> <B>dump</B> <I>marginID</I> <I>?option?</I> <I>Index1</I> <I>?Index2?</I>
                     Return the contents of the text widget from index1 up to,
                     but not including index2, including the text and informa-
                     tion  about  marks, tags, and embedded windows. If index2
                     is not specified, then it defaults to one character  past
                     index1. The information is returned in the following for-
                     mat:: key1 value1 index1 key2 value2 index2 ...  The pos-
                     sible  key  values  are  indicatoron, indicatoroff, text,
                     mark, styleon, styleoff, tagon, and  tagoff.  The  corre-
                     sponding  value  is  the indicator type, text, mark name,
                     style number, or tag name. The index information  is  the
                     index  within  the  margin  of the start of the indicator
                     transition, style transition, text, mark, tag transition,
                     image  or  window.  One or more of the following switches
                     Include information about indicator  transitions  in  the
                     dump  results. Indicator information is returned as indi-
                     catoron and indicatoroff elements that indicate the begin
                     and end of each range of each indicator, respectively.

              <B>-mark</B>  Include information about marks in the dump results.

              <B>-style</B> Include  information  about style transitions in the dump
                     results. Style information is  returned  as  styleon  and
                     styleoff elements that indicate the begin and end of each
                     range of each style, respectively.

              <B>-tag</B>   Include information about tag  transitions  in  the  dump
                     results.  Tag information is returned as tagon and tagoff
                     elements that indicate the begin and end of each range of
                     each tag, respectively.

              <B>-text</B>  Include  information  about text in the dump results. The
                     value is the text up to the next element or  the  end  of
                     range  indicated  by index2. A text element does not span
                     newlines. A multi-line block of  text  that  contains  no
                     marks or tag transitions will still be dumped as a set of
                     text segments that each end with a newline.  The  newline
                     is part of the value.

              <I>pathName</I>  <B>margin</B> <B>fillnumbers</B> <I>marginID</I> <I>start</I> <I>count</I> <I>?tagName</I> <I>{line</I>
              <I>...}?</I>
                     This  would be used to manually managing filling a margin
                     with line numbers. This is really  only  used  for  cases
                     when  control  over the appearance of the line numbers is
                     needed. The fillnumbers command would  be  called  within
                     the  -linesaddedcommand  callback  function  in  a margin
                     whose type was set to  "lnums_alt".  Setting  the  margin
                     type  to  "lnums" would result in the Scintilla core code
                     handling filling of the line numbers.  The  start  option
                     identifies  where  the  line  numbering should begin. The
                     count option controls how many lines will be  numbers.  A
                     value  of &lt;= 0 will number all lines from start until the
                     end of the document. To apply custom styling  to  one  or
                     more  line  numbers,  first configure a tag named tagName
                     and then identify the list of line numbers as  the  argu-
                     ment  following  tagName.  For  example, to fill the line
                     numbers from 1 to 10  where  only  the  odd  numbers  are
                     styled  in  red,  first create a tag (ex: $sci tag config
                     red -margin -fg red) and then execute $sci  margin  fill-
                     numbers 1 10 red {1 3 5 7 9}.

              <I>pathName</I> <B>margin</B> <B>hide</B> <I>marginID</I>
                     Hides the margin specified by marginID. The margin's con-
                     figuration information is maintained while hidden.

              <I>pathName</I> <B>margin</B> <B>index</B> <I>@X,Y</I>
                     identifies  which  lines to add or remove the marker for.
                     When removing, if the lines list is empty, then the spec-
                     ified  marker would be removed from all lines. Also, when
                     removing, if the markerName is set to "*", then all mark-
                     ers present for the specified lines would be removed.

              <I>pathName</I> <B>margin</B> <B>marker</B> <I>marginID</I> <I>list</I> <I>markerName</I> <I>?line?</I>
                     This  command  returns a list of the lines containing the
                     specified marker. If markerName is specified as  "*"  the
                     line  argument is required. When this done, the all mark-
                     ers present on the specified line will be returned.

              <I>pathName</I> <B>margin</B> <B>names</B>
                     Returns information about each of the margins. Each  mar-
                     gin  is identified by a three element list containing the
                     following: 1) the ID value of the margin  (where  "0"  is
                     the  leftmost  margin), 2) the type of the margin, and 3)
                     the alias name, or an empty string  if  one  hasn't  been
                     defined.

              <I>pathName</I> <B>margin</B> <B>show</B> <I>marginID</I>
                     Shows  the margin specified by marginID. For margins that
                     have not yet had a width set (ie their  width  is  zero),
                     the  show  operation will report an error unless the mar-
                     gin's type is set for linenumbers  or  the  special  fold
                     margin.  For those margins, the widget will automatically
                     determine the appropriate width to use in order to  allow
                     the margin to be made visible.

              <I>pathName</I> <B>margin</B> <B>tag</B> <I>{line</I> <I>...}</I> <I>?tagName</I> <I>-clear?</I>
                     This  command  will  either  add or remove a tag that was
                     previously configured for use in  the  margin  area  (see
                     here  for  more details). The margin tag will affect only
                     text-based margins (ie not those  holding  symbols).  The
                     tag  named  tagName  will  be  added to the list of lines
                     unless the -clear option is specified, in which case  the
                     tag  will  be  removed.  When  removing  a tag, it can be
                     removed from all lines by specifying an  empty  list  for
                     the  lines. To remove all margin tags from all lines, the
                     tagName option should not be specified  (ie  $sci  margin
                     tag {} -clear).

              <I>pathName</I> <B>margin</B> <B>text</B> <I>marginID</I> <I>command</I> <I>arglist</I>
                     This command is used to manipulate the margin text within
                     the margin specified by marginID. The margin specified by
                     marginID  must  be  of  type text or rtext. The operation
                     performed is controlled by the  command  argument,  which
                     would  either be one of "clear", "get", or "set". If com-
                     mand is "clear", and there is no arglist, then the margin
                     text for all lines in the document is removed. If arglist
                     is provided, it is a list of one or more lines to  clear.
                     If  the command argument is "get", the arglist must spec-

       <I>pathName</I> <B>mark</B> <I>option</I> <I>?arg</I> <I>arg</I> <I>...?</I>
              This  command is used to manipulate marks. The exact behavior of
              the command depends on the option argument that follows the mark
              argument.  The following forms of the command are currently sup-
              ported:

              <I>pathName</I> <B>mark</B> <B>exists</B> <I>markName</I>
                     If markName exists, the command will return 1;  otherwise
                     0 is returned.

              <I>pathName</I> <B>mark</B> <B>gravity</B> <I>markName</I> <I>?direction?</I>
                     If  direction  is not specified, returns left or right to
                     indicate which of its  adjacent  characters  markName  is
                     attached  to.  If direction is specified, it must be left
                     or right; the gravity of markName is  set  to  the  given
                     value.

              <I>pathName</I> <B>mark</B> <B>names</B>
                     Returns  a  list  whose elements are the names of all the
                     marks that are currently set.

              <I>pathName</I> <B>mark</B> <B>next</B> <I>index</I>
                     Returns the name of the next mark at or after  index.  If
                     index is specified in numerical form, then the search for
                     the next mark begins at that index. If index is the  name
                     of a mark, then the search for the next mark begins imme-
                     diately after that mark. This can still return a mark  at
                     the same position if there are multiple marks at the same
                     index. These semantics mean that the mark next  operation
                     can  be used to step through all the marks in a text wid-
                     get. An empty string is returned if there  are  no  marks
                     after index.

              <I>pathName</I> <B>mark</B> <B>previous</B> <I>index</I>
                     Returns the name of the mark at or before index. If index
                     is specified in numerical form, then the search  for  the
                     previous  mark begins with the character just before that
                     index. If index is the name of a mark,  then  the  search
                     for  the  next  mark begins immediately before that mark.
                     This can still return a mark  at  the  same  position  if
                     there  are multiple marks at the same index. These seman-
                     tics mean that the mark previous operation can be used to
                     step  through  all  the  marks in a text widget. An empty
                     string is returned if there are no marks before index.

              <I>pathName</I> <B>mark</B> <B>set</B> <I>markName</I> <I>index</I>
                     Sets the mark named markName to a  position  just  before
                     the character at index. If markName already exists, it is
                     moved from its old position; if it does not exist, a  new
                     mark is created. This command returns an empty string.

              <I>pathName</I>  <B>marker</B>  <B>configure</B>  <I>markerName</I>  <I>?option?</I>  <I>?value</I> <I>option</I>
              <I>value</I> <I>...?</I>
                     This  command is similar to the pathName configure widget
                     command except that it modifies options  associated  with
                     the marker given by markName instead of modifying options
                     for the overall widget. If no option  is  specified,  the
                     command  returns  a  list describing all of the available
                     options for markerName. If option is  specified  with  no
                     value, then the command returns a list describing the one
                     named option (this list will be identical to  the  corre-
                     sponding  sublist  of  the value returned if no option is
                     specified). If one or more option-value pairs are  speci-
                     fied,  then  the  command modifies the given option(s) to
                     have the given value(s) in markerName; in this  case  the
                     command returns an empty string.

              <I>pathName</I> <B>marker</B> <B>delete</B> <I>markerName</I> <I>?markerName</I> <I>...?</I>
                     Deletes the named markers

              <I>pathName</I> <B>marker</B> <B>exists</B> <I>markerName</I> <I>line</I>
                     Checks  if  the marker specified by markerName exists for
                     line. Returns 1 if it does, 0 otherwise.

              <I>pathName</I> <B>marker</B> <B>names</B>
                     Returns a sorted list of all  currently  defined  markers
                     (created by using the marker configure command).

              <I>pathName</I> <B>marker</B> <B>types</B>
                     Returns the list of type names which can be used with the
                     -type option to the configure command.

       <I>pathName</I> <B>search</B> <I>?switches?</I> <I>pattern</I> <I>index</I> <I>?stopIndex?</I>
              Searches the text in pathName starting at index for a  range  of
              characters  that matches pattern. If a match is found, the index
              of the first character in the match is returned as result;  oth-
              erwise an empty string is returned. One or more of the following
              switches (or abbreviations thereof) may be specified to  control
              the search:

              <B>-forwards</B>
                     The search will proceed forward through the text, finding
                     the first matching range starting at or after  the  posi-
                     tion given by index. This is the default.

              <B>-backwards</B>
                     The  search will proceed backward through the text, find-
                     ing the matching range closest to index whose first char-
                     acter is before index (it is not allowed to be at index).
                     Note that, for a variety of reasons,  backwards  searches
                     can  be substantially slower than forwards searches (par-
                     ticularly when using -regexp), so it is recommended  that
                     performance-critical code use forward searches.

              <B>-nolinestop</B>
                     This allows . and [^ sequences to match the newline char-
                     acter  0 which they will otherwise not do (see the regexp
                     command for details). This option is only  meaningful  if
                     -regexp is also given, and an error will be thrown other-
                     wise. For example, to match the entire text, use pathName
                     search -nolinestop -regexp ".*" 1.0.

              <B>-nocase</B>
                     Ignore case differences between the pattern and the text.

              <B>-count</B> <I>varName</I>
                     The argument following -count gives the name of  a  vari-
                     able;  if a match is found, the number of index positions
                     between beginning and end of the matching range  will  be
                     stored  in  the variable. If there are no embedded images
                     or windows in the matching range (and there are no elided
                     characters if -elide is not given), this is equivalent to
                     the number of characters matched.  In  either  case,  the
                     range matchIdx to matchIdx + $count chars will return the
                     entire matched text.

              <B>-all</B>   Find all matches in the given range and return a list  of
                     the  indices  of  the first character of each match. If a
                     -count varName switch is given, then varName is also  set
                     to  a  list  containing  one  element for each successful
                     match. Note that, even for exact searches,  the  elements
                     of  this  list  may  be  different, if there are embedded
                     images, windows or hidden text. Searches with -all behave
                     very  similarly  to  the Tcl command regexp -all, in that
                     overlapping matches are not normally returned. For  exam-
                     ple, applying an -all search of the pattern 1992Z against
                     ZooZooZoo will just match once.

              <B>-overlap</B>
                     When performing -all searches, the  normal  behaviour  is
                     that  matches  which  overlap an already-found match will
                     not be returned. This switch changes  that  behaviour  so
                     that  all  matches  which are not totally enclosed within
                     another match are  returned.  For  example,  applying  an
                     -overlap  search  of  the pattern 2304Z against ZooZooZoo
                     will now match twice. An error will  be  thrown  if  this
                     switch is used without -all.

              <B>-strictlimits</B>
                     When  performing any search, the normal behaviour is that
                     the start and stop limits are checked with respect to the
                     start  of the matching text. With the -strictlimits flag,
                     the entire matching range must lie inside the  start  and
                     stop limits specified for the match to be valid.

       searches, no match at or after stopIndex will be considered; for  back-
       ward searches, no match earlier in the text than stopIndex will be con-
       sidered. If stopIndex is omitted, the entire  text  will  be  searched:
       when  the beginning or end of the text is reached, the search continues
       at the other end until the  starting  location  is  reached  again;  if
       stopIndex is specified, no wrap-around will occur. This means that, for
       example, if the search is -forwards but stopIndex  is  earlier  in  the
       text  than startIndex, nothing will ever be found. See the Tk Text wid-
       get man page for more information.

       <I>pathName</I> <B>scisearch</B> <I>?switches?</I> <I>pattern</I> <I>index</I> <I>?stopIndex?</I>
              Scintilla Search searches the text in pathName starting at index
              for  a  range  of characters that matches pattern. If a match is
              found, the index of the first character in the match is returned
              as result; otherwise an empty string is returned. One or more of
              the following switches (or abbreviations thereof) may be  speci-
              fied to control the search:

              <B>-forwards</B>
                     The search will proceed forward through the text, finding
                     the first matching range starting at or after  the  posi-
                     tion given by index. This is the default.

              <B>-backwards</B>
                     The  search will proceed backward through the text, find-
                     ing the matching range closest to index whose first char-
                     acter is before index (it is not allowed to be at index).

              <B>-count</B> <I>varName</I>
                     The argument following -count gives the name of  a  vari-
                     able;  if a match is found, the number of index positions
                     between beginning and end of the matching range  will  be
                     stored in the variable.

              <B>-exact</B> Use  exact matching: the characters in the matching range
                     must be identical  to  those  in  pattern.  This  is  the
                     default.

              <B>-nocase</B>
                     Ignore case differences between the pattern and the text.

              <B>-regexp</B>
                     Treat pattern as  a  regular  expression.  In  a  regular
                     expression, special characters interpreted are:

                     Matches any character.

                      <B>\(</B>     This  marks  the  start of a region for tagging a
                             match.

                      <B>\)</B>     This marks the end of a tagged region.

                      <B>\x</B>     This allows you to use a character x  that  would
                             otherwise have a special meaning. For example, \[
                             would be interpreted as [ and not as the start of
                             a character set.

                      <B>[...]</B>  This  indicates a set of characters, for example,
                             [abc] means any of the characters a, b or c.  You
                             can  also  use  ranges, for example [a-z] for any
                             lower case character.

                      <B>[^...]</B> The complement of the characters in the set.  For
                             example,  [^A-Za-z] means any character except an
                             alphabetic character.

                      <B>^</B>      This matches the start of  a  line  (unless  used
                             inside a set, see above).

                      <B>$</B>      This matches the end of a line.

                      <B>*</B>      This  matches  0 or more times. For example, Sa*m
                             matches Sm, Sam, Saam, Saaam and so on.

                      <B>+</B>      This matches 1 or more times. For  example,  Sa+m
                             matches Sam, Saam, Saaam and so on.
              Regular expressions will only match ranges within a single line,
              never matching over multiple lines.

              <B>-word</B>  A match only occurs if the characters  before  and  after
                     are not word characters.

              <B>--</B>     This switch has no effect except to terminate the list of
                     switches: the next argument will be  treated  as  pattern
                     even if it starts with -.
       The  matching  range  must be within a single line of text. For regular
       expression matching one can use the various  newline-matching  features
       such  as  $  to  match the end of a line, ^ to match the beginning of a
       line. If stopIndex is specified, the search stops at  that  index:  for
       forward  searches,  no  match at or after stopIndex will be considered;
       for backward searches, no match earlier in the text than stopIndex will
       be  considered.  If  stopIndex  is  omitted,  the  entire  text will be
       searched.

       <I>pathName</I> <B>see</B> <I>index</I> <I>?-center?</I>
              Adjusts the view in the window so that the  character  given  by
              index  is  completely  visible. If index is already visible then
              the command does nothing. If index is a short  distance  out  of
              view,  the  command  adjusts  the view just enough to make index
              visible at the edge of the window. If index is far out of  view,
              then the command centers index in the window. The -center option
              can be used to force index to be centered in the window.

       <I>pathName</I> <B>tag</B> <I>?option?</I> <I>?arg</I> <I>arg</I> <I>...?</I>

              <I>pathName</I> <B>tag</B> <B>add</B> <I>tagName</I> <I>index1</I> <I>?index2?</I>
                     Associate  the  tag  tagName  (one  will be created if it
                     doesn't already exist) with all of the characters  start-
                     ing  with index1 and ending just before index2 (the char-
                     acter at index2 is not tagged). If index2 is omitted then
                     the single character at index1 is tagged. If there are no
                     characters in the specified range (e.g.  index1  is  past
                     the  end  of  the file or index2 is less than or equal to
                     index1) then the command has  no  effect.  EXCEPTION:  If
                     tagName  is  the  predefined  selection tag (i.e. "sel"),
                     then specifying index2 to be less than index1  will  have
                     the  effect  of  positioning  the  insertion point at the
                     start of the selection.

              <I>pathName</I> <B>tag</B> <B>bind</B> <I>tagName</I> <I>?sequence?</I> <I>?script?</I>
                     This command associates script with the tag given by tag-
                     Name.  Whenever  the  event  sequence  given  by sequence
                     occurs for a character that has been tagged with tagName,
                     the  script will be invoked. This widget command is simi-
                     lar to the bind command except that it operates on  char-
                     acters in a text rather than entire widgets. See the bind
                     manual entry  for  complete  details  on  the  syntax  of
                     sequence and the substitutions performed on script before
                     invoking it. If all arguments are specified  then  a  new
                     binding  is  created,  replacing any existing binding for
                     the same sequence and tagName (if the first character  of
                     script  is  +  then  script  augments an existing binding
                     rather than replacing it). In this case the return  value
                     is an empty string. If script is omitted then the command
                     returns the script associated with tagName  and  sequence
                     (an  error  occurs  if there is no such binding). If both
                     script and sequence are omitted then the command  returns
                     a  list of all the sequences for which bindings have been
                     defined for tagName. The only events for  which  bindings
                     may  be specified are those related to the mouse and key-
                     board (such as Enter,  Leave,  ButtonPress,  Motion,  and
                     KeyPress)  or  virtual  events. Event bindings for a text
                     widget use the current mark. An Enter event triggers  for
                     a  tag  when the tag first becomes present on the current
                     character, and a Leave event triggers for a tag  when  it
                     ceases  to be present on the current character. Enter and
                     Leave events can happen either because the  current  mark
                     moved  or because the character at that position changed.
                     Note that these events are different than Enter and Leave
                     events   for  windows.  Mouse  and  keyboard  events  are
                     directed to the current character. If a virtual event  is
                     used  in  a binding, that binding can trigger only if the
                     virtual event is defined by an  underlying  mouse-related
                     or keyboard-related event.

              <I>pathName</I> <B>tag</B> <B>cget</B> <I>tagName</I> <I>option</I>
                     named  option  (this list will be identical to the corre-
                     sponding sublist of the value returned if  no  option  is
                     specified).  If one or more option-value pairs are speci-
                     fied, then the command modifies the  given  option(s)  to
                     have the given value(s) in tagName; in this case the com-
                     mand returns an empty string. Note, the  special  -margin
                     option,  if  used, must immediately follow tagName. It is
                     used to create and configure tags used within the  margin
                     area. See "configure options" for more details

              <I>pathName</I> <B>tag</B> <B>delete</B> <I>tagName</I> <I>?tagName</I> <I>...?</I>
                     Deletes all tag information for each of the tagName argu-
                     ments. The command removes the tags from  all  characters
                     in  the file and also deletes any other information asso-
                     ciated with the tags, such as bindings and display infor-
                     mation. The command returns an empty string.

              <I>pathName</I> <B>tag</B> <B>lower</B> <I>tagName</I>
                     This  has  NOT  BEEN  IMPLEMENTED  because Scintilla core
                     functionality regarding "markers" (which is how the Scin-
                     tillaTk  tag functionality has been implemented) does not
                     support drawing priority for markers that overlap.

              <I>pathName</I> <B>tag</B> <B>names</B> <I>?index?</I>
                     Returns a list whose elements are the names  of  all  the
                     tags  that  are active at the character position given by
                     index. If index is omitted, then the  return  value  will
                     describe all of the tags that exist for the widget.

              <I>pathName</I> <B>tag</B> <B>nextrange</B> <I>tagName</I> <I>index1</I> <I>?index2?</I>
                     This  command searches the text for a range of characters
                     tagged with tagName where  the  first  character  of  the
                     range  is  no earlier than the character at index1 and no
                     later than the character  just  before  index2  (a  range
                     starting at index2 will not be considered). The command's
                     return value is a list containing two elements, which are
                     the  index  of  the  first character of the range and the
                     index of the character just after the  last  one  in  the
                     range.  If  no  matching  range  is found then the return
                     value is an empty string. If index2 is not given then  it
                     defaults to the end of the text.

              <I>pathName</I> <B>tag</B> <B>prevrange</B> <I>tagName</I> <I>index1</I> <I>?index2?</I>
                     This  command searches the text for a range of characters
                     tagged with tagName where  the  first  character  of  the
                     range  is  before  the character at index1 and no earlier
                     than the character at index2 (a range starting at  index2
                     will be considered). The command's return value is a list
                     containing two elements, which are the index of the first
                     character  of  the  range  and the index of the character
                     just after the last one in  the  range.  If  no  matching
                     range  is found then the return value is an empty string.
                     The first element of each pair contains the index of  the
                     first  character  of the range, and the second element of
                     the pair contains the index of the character  just  after
                     the  last  one  in  the range. If there are no characters
                     tagged with tag then an empty string is returned.

              <I>pathName</I> <B>tag</B> <B>remove</B> <I>tagName</I> <I>index1</I> <I>?index2</I> <I>index1</I> <I>index2</I> <I>...?</I>
                     Remove the tag tagName from all of the characters  start-
                     ing  at index1 and ending just before index2 (the charac-
                     ter at index2 is not affected). A single command may con-
                     tain  any  number  of  index1-index2  pairs.  If the last
                     index2 is omitted then the tag is removed from the single
                     character  at  index1.  If there are no characters in the
                     specified range (e.g. index1 is past the end of the  file
                     or  index2 is less than or equal to index1) then the com-
                     mand has no effect. This command returns an empty string.
       <B>Tag</B> <B>Types</B>

       +----------------------------------------------------------------------------------+
       |<B>Type</B>          <B>ID</B>   <B>Description</B>                                                    |
       |plain          0    Underlined with a single, straight line.                      |
       |squiggle       1    A squiggly underline, 3 pixels in height                      |
       |tt             2    A line of small "T" shapes                                    |
       |diagonal       3    Diagonal hatching                                             |
       |strike         4    A solid "strike through" line draw at the vertical mid-point  |
       |hidden         5    No visual effect                                              |
       |box            6    A rectangular box around the text                             |
       |roundbox       7    A  rectangle  with  rounded  corners  around the text, using  |
       |                    translucent drawing for the interior (NOT SUPPORTED YET)      |
       |squarebox      8    A rectangle around the text, using translucent  drawing  for  |
       |                    the interior (NOT SUPPORTED YET)                              |
       |dash           9    A dashed underline                                            |
       |dots          10    A dotted underline                                            |
       |squigglelow   11    Similar to squiggle but only 2 pixels in height               |
       |dotbox        12    A  dotted rectangle around the text, using translucent draw-  |
       |                    ing for the interior (NOT SUPPORTED YET)                      |
       +----------------------------------------------------------------------------------+

       For the above types, use the -foreground configuration option  for  the
       tag to control the color. For types that use a filled interior, use the
       -background option to set the interior color. The following  lists  the
       supported  configuration options, though not all are supported for each
       type of tag (exceptions are noted):

       <B>-background|-bg</B> <I>color</I>
              Color specifies the color used for tags that have a filled inte-
              rior.

       <B>-bold</B> <I>boolean</I> (ONLY FOR MARGIN TAGS)
              Specifies if margins showing text will use a bold font

       <B>-foreground|-fg</B> <I>color</I>
              current version of the widget. The fields of the list are:  ver-
              sion  :  identifies  the Tcl package version date : the date the
              package was created core_rls: this identifies the release of the
              Scintilla core widget



</PRE>
<H2>KNOWN BUGS</H2><PRE>
       Patterns including newline (0 may not work correctly in all cases. This
       limitation is due to how Scintilla stores document  text;  the  end  of
       line  characters are stripped from the document making the search chal-
       lenging.

       The pathName search -regexp sub-command attempts to  perform  sophisti-
       cated  regexp  matching  across multiple lines in an efficient fashion.
       Under certain conditions the  search  result  might  differ  from  that
       obtained by applying the same regexp to the entire text from the widget
       in one go.

       Whenever one possible match is fully enclosed in  another,  the  search
       command  will attempt to ensure only the larger match is returned. When
       performing backwards regexp searches it is possible that Tcl  will  not
       always achieve this.





Tk                                   0.25                         scintilla(n)
</PRE>
<HR>
<ADDRESS>
Man(1) output converted with
<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a>
</ADDRESS>
</BODY>
</HTML>

Added tk/doc/scintillatk.n.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
'\"
.\"
.\" .DE
.\"	End of indented unfilled display.
.\"
.\" .SO ?manpage?
.\"	Start of list of standard options for a Tk widget. The manpage
.\"	argument defines where to look up the standard options; if
.\"	omitted, defaults to "options". The options follow on successive
.\"	lines, in three columns separated by tabs.
.\"
.\" .SE
.\"	End of list of standard options for a Tk widget.
.\"
.\" .OP cmdName dbName dbClass
.\"	Start of description of a specific option.  cmdName gives the
.\"	option's name as specified in the class command, dbName gives
.\"	the option's name in the option database, and dbClass gives
.\"	the option's class in the option database.
.\"
.\" .UL arg1 arg2
.\"	Print arg1 underlined, then print arg2 normally.
.\"
.\" .QW arg1 ?arg2?
.\"	Print arg1 in quotes, then arg2 normally (for trailing punctuation).
.\"
.\" .PQ arg1 ?arg2?
.\"	Print an open parenthesis, arg1 in quotes, then arg2 normally
.\"	(for trailing punctuation) and then a closing parenthesis.
.\"
.\"	# Set up traps and other miscellaneous stuff for Tcl/Tk man pages.
.if t .wh -1.3i ^B
.nr ^l \n(.l
.ad b
.\"	# Start an argument description
.de AP
.ie !"\\$4"" .TP \\$4
.el \{\
.   ie !"\\$2"" .TP \\n()Cu
.   el          .TP 15
.\}
.ta \\n()Au \\n()Bu
.ie !"\\$3"" \{\
\&\\$1 \\fI\\$2\\fP (\\$3)
.\".b
.\}
.el \{\
.br
.ie !"\\$2"" \{\
\&\\$1	\\fI\\$2\\fP
.\}
.el \{\
\&\\fI\\$1\\fP
.\}
.\}
..
.\"	# define tabbing values for .AP
.de AS
.nr )A 10n
.if !"\\$1"" .nr )A \\w'\\$1'u+3n
.nr )B \\n()Au+15n
.\"
.if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n
.nr )C \\n()Bu+\\w'(in/out)'u+2n
..
.AS Tcl_Interp Tcl_CreateInterp in/out
.\"	# BS - start boxed text
.\"	# ^y = starting y location
.\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
.\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
.\"	Draw four-sided box normally, but don't draw top of
.\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# VS - start vertical sidebar
.\"	# ^Y = starting y location
.\"	# ^v = 1 (for troff;  for nroff this doesn't matter)
.de VS
.if !"\\$2"" .br
.mk ^Y
.ie n 'mc \s12\(br\s0
.el .nr ^v 1u
..
.\"	# VE - end of vertical sidebar
.de VE
.ie n 'mc
.el \{\
.ev 2
.nf
.ti 0
.mk ^t
\h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n'
.sp -1
.fi
.ev
.\}
.nr ^v 0
..
.\"	# Special macro to handle page bottom:  finish off current
.\"	# box/sidebar if in box/sidebar mode, then invoked standard
.\"	# page bottom macro.
.de ^B
.ev 2
'ti 0
'nf
.mk ^t
.if \\n(^b \{\
.\"	Draw three-sided box if this is the box's first page,
.\"	draw two sides but no top otherwise.
.ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c
.\}
.if \\n(^v \{\
.nr ^x \\n(^tu+1v-\\n(^Yu
\kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c
.\}
.bp
'fi
.ev
.if \\n(^b \{\
.mk ^y
.nr ^b 2
.\}
.if \\n(^v \{\
.mk ^Y
.\}
..
.\"	# DS - begin display
.de DS
.RS
.nf
.sp
..
.\"	# DE - end display
.de DE
.fi
.RE
.sp
..
.\"	# SO - start of list of standard options
.de SO
'ie '\\$1'' .ds So \\fBoptions\\fR
'el .ds So \\fB\\$1\\fR
.SH "STANDARD OPTIONS"
.LP
.nf
.ta 5.5c 11c
.ft B
..
.\"	# SE - end of list of standard options
.de SE
.fi
.ft R
.LP
See the \\*(So manual entry for details on the standard options.
..
.\"	# OP - start of full description for a single option
.de OP
.LP
.nf
.ta 4c
Command-Line Name:	\\fB\\$1\\fR
Database Name:	\\fB\\$2\\fR
Database Class:	\\fB\\$3\\fR
.fi
.IP
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
.\"	# UL - underline word
.de UL
\\$1\l'|0\(ul'\\$2
..
.\"	# QW - apply quotation marks to word
.de QW
.ie '\\*(lq'"' ``\\$1''\\$2
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\$2
..
.\"	# PQ - apply parens and quotation marks to word
.de PQ
.ie '\\*(lq'"' (``\\$1''\\$2)\\$3
.\"" fix emacs highlighting
.el (\\*(lq\\$1\\*(rq\\$2)\\$3
..
.\"	# QR - quoted range
.de QR
.ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3
.\"" fix emacs highlighting
.el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3
..
.\"	# MT - "empty" string
.de MT
.QW ""
..
.TH scintilla n 0.25 Tk "ScintillaTK Text Widget"
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
scintilla \- Scintilla text widget
.SH SYNOPSIS
\fBpackage require scintillatk\fR ?\fB0.25\fR?
.sp
\fBscintilla\fR \fIpathName \fR?\fIoptions\fR?
.SO
\-autoseparators	\-highlight	\-moveupdatecommand
\-background	\-highlightthickness	\-relief
\-blink	\-highlightbackground	\-showws
\-borderwidth	\-language	\-state
\-busycursor	\-linesaddedcommand	\-tabwidth
\-cursor	\-marginbackground	\-takefocus
\-foldstyle	\-marginbg	\-xscrollcommand
\-font	\-marginforeground	\-yscrollcommand
\-foreground	\-marginfg	\-undo
\-height	\-marginwidthcommand	\-width
.SE
.SH "WIDGET-SPECIFIC OPTIONS"
.OP \-autoseparators autoSeparators AutoSeparators
Specifies a boolean that says whether separators are automatically
inserted in the undo stack. Only meaningful when the \fB\-undo\fR
option is true.
.OP \-height height Height
Specifies the desired height for the window, in units of characters
in the font given by the \fB\-font\fR option.
Must be at least one.
.OP \-state state State
Specifies one of two states for the text:  \fBnormal\fR or \fBdisabled\fR.
If the text is disabled then characters may not be inserted or deleted
and no insertion cursor will be displayed, even if the input focus is
in the widget.
.OP \-width width Width
Specifies the desired width for the window in units of characters
in the font given by the \fB\-font\fR option.
If the font does not have a uniform width then the width of the character
.QW 0
is used in translating from character units to screen units.
.OP \-busycursor cursor Cursor
Cursor to display when text widget is computationally busy.
.OP \-foldstyle foldstyle FoldStyle
See Scintilla documentation for style values.
.OP \-language language Language
Specifies which programming language lexer to use for syntax highlighting.
.OP \-linesaddedcommand lindesAddedCommand LinesAddedCommand
Callback command when new lines are inserted in the document.  This function can be used to update margin indicators if necessary.
.OP \-marginbackground marginBackground MarginBackground
The backgound color of the margin columns.
.OP \-marginforeground marginForeground MarginForeground
The foregound (font) color of the margin columns.
.OP \-marginwidthcommand 
Callback command used when margin width changes.
.OP \-moveupdatecommand moveUpdateCommand MoveUpdateCommand
Callback command when margin changes.
.OP \-showws showws ShowWs
Show the ws???

.BE
.SH DESCRIPTION
.PP
The \fBscintilla\fR command creates a new window (given by the \fIpathName\fR arg) and makes it into a Scintilla text widget. Additional options, described above, may be specified on the command line or in the option database to configure aspects of the text such as its default background color and relief.  The \fBtext\fR command returns the path name of the new window.
.PP
.SH "WIDGET COMMAND"
.PP
.TP
\fIpathName \fBannotate \fIoption ?arg arg ...?\fR
Text annotations are separate strings that can be assigned to the lines within the document. The annotation is displayed without any line numbers and appears in extra space which is created by the widget for its display. There are various options available:
.RS
.TP
\fBclearall\fR
removes annotation strings for all lines
.TP
\fBget \fIline\fR
Returns the annotation text for the specified line.
.TP
\fBset \fIline text ?tagName text tagName ...?\fR
Assigns the specified text string to the specified line. If no tagName option is specified, the annotation text will use the default text styling. If a single tagName option is used it will control the appearance for all of the annotation text. By using multiple text and tagName options it's possible to have different appearances for different subranges of the text.
.TP
\fBshow \fI0|1|2\fR
Used to control the display of annotations where 0 - hiding, 1 - showing or 2 - showing with a bounding box. Note, this affects all lines with annotations.
.RE
.TP
\fIpathName \fBbbox \fIindex\fR
Returns a list of four elements describing the screen area of the character given by index. The first two elements of the list give the x and y coordinates of the upper\-left corner of the area occupied by the character, and the last two elements give the width and height of the area. If the character is not visible on the screen then the return value is an empty list.
.TP
\fIpathName \fBcget \fIoption\fR
Returns the current value of the configuration option given by option. Option may have any of the values accepted by the scintilla command.
.TP
\fIpathName \fBcompare \fIindex1 op index2\fR
Compares the indices given by index1 and index2 according to the relational operator given by op, and returns 1 if the relationship is satisfied and 0 if it is not. Op must be one of the operators <, <=, =, >, >, or !. If op is == then 1 is returned if the two indices refer to the same character, if op is < then 1 is returned if index1 refers to an earlier character in the text than index2, and so on.
.TP
\fIpathName \fBconfigure \fI?option? ?value option value ...?\fR
Query or modify the configuration options of the widget. If no option is specified, returns a list describing all of the available options for pathName. If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option\-value pairs are specified, then the command modifies the given widget option(s) to have the given value(s); in this case the command returns an empty string. Option may have any of the values accepted by the scintilla command.
.TP
\fIpathName \fBcount \fI?options? index1 index2\fR
Counts the number of relevant things between the two indices. If index1 is after index2, the result will be a negative number (and this holds for each of the possible options). The actual items which are counted depend on the options given. The result is a list of integers, one for the result of each counting option given. Valid counting options are \-chars, \-displaylines and \-lines. The default value, if no option is specified, is \-chars. The count options are interpreted as follows:
.RS
.IP \fB\-chars\fR
count all characters, whether elided or not. Do not count embedded windows or images.
.IP \fB\-displaylines\fR
count all display lines (i.e. ignore lines which are folded) from the line of the first index up to, but not including the display line of the second index. Therefore if they are both on the same display line, zero will be returned. By definition displaylines are visible and therefore this only counts portions of actual visible lines.
.IP \fB\-lines\fR
count all lines (irrespective of folding) from the line of the first index up to, but not including the line of the second index. Therefore if they are both on the same line, zero will be returned. Lines are counted whether they are currently visible (non\-folded) or not.
.RE
.TP
\fIpathName \fBdelete \fIindex1 ?index2?\fR
Delete a range of characters from the text. If both index1 and index2 are specified, then delete all the characters starting with the one given by index1 and stopping just before index2 (i.e. the character at index2 is not deleted). If index2 doesn't specify a position later in the text than index1 then no characters are deleted. If index2 isn't specified then the single character at index1 is deleted. It is not allowable to delete characters in a way that would leave the text without a newline as the last character. The command returns an empty string.
.TP
\fIpathName \fBdump \fI?switches? index1 ?index2?_\fR
Return the contents of the text widget from index1 up to, but not including index2, including the text and information about marks, tags, and embedded windows. If index2 is not specified, then it defaults to one character past index1. The information is returned in the following format::
key1 value1 index1 key2 value2 index2 ...
The possible key values are indicatoron, indicatoroff, text, mark, styleon, styleoff, tagon, tagoff, image, and window. The corresponding value is the indicator type, text, mark name, style number, tag name, image name, or window name. The index information is the index of the start of the indicator transition, style transition, text, mark, tag transition, image or window. The image and window options are not supported and will return nothing. One or more of the following switches (or abbreviations thereof) may be specified to control the dump:
.RS
.IP \fB\-all\fR
Return information about all elements: indicator, style, text, marks, tags, images and windows. This is the default.
.TP
\fB\-command \fIcommand\fR
Instead of returning the information as the result of the dump operation, invoke the command on each element of the text widget within the range. The command has three arguments appended to it before it is evaluated: the key, value, and index.
.TP
\fB\-image\fR
Include information about images in the dump results. This option is unsupported in Scintilla.
.TP
\fB\-indicator\fR
Include information about indicator transitions in the dump results. Indicator information is returned as indicatoron and indicatoroff elements that indicate the begin and end of each range of each indicator, respectively.
.TP
\fB\-mark\fR
Include information about marks in the dump results.
.TP
\fB\-style\fR
Include information about style transitions in the dump results. Style information is returned as styleon and styleoff elements that indicate the begin and end of each range of each style, respectively.
.TP
\fB\-tag\fR
Include information about tag transitions in the dump results. Tag information is returned as tagon and tagoff elements that indicate the begin and end of each range of each tag, respectively.
.TP
\fB\-text\fR
Include information about text in the dump results. The value is the text up to the next element or the end of range indicated by index2. A text element does not span newlines. A multi\-line block of text that contains no marks or tag transitions will still be dumped as a set of text segments that each end with a newline. The newline is part of the value.
.TP
\fB\-window\fR
Include information about embedded windows in the dump results. This option is unsupported in Scintilla.
.RE
.TP
\fIpathName \fBedit \fIoption ?arg arg ...?\fR
This command controls the undo mechanism and the modified flag. The exact behavior of the command depends on the option argument that follows the edit argument. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBedit canredo\fR
Returns true if the redo stack is not empty.
.TP
\fIpathName \fBedit canundo\fR
Returns true if the undo stack is not empty.
.TP
\fIpathName \fBedit Imodified \fI?boolean?\fR
If boolean is not specified, returns the modified flag of the widget. The insert, delete, edit undo and edit redo commands or the user can set or clear the modified flag. If boolean is specified, sets the modified flag of the widget to boolean.
.TP
\fIpathName \fBedit redo\fR
When the \-undo option is true, reapplies the last undone edits provided no other edits were done since then. Generates an error when the redo stack is empty. Does nothing when the \-undo option is false.
.TP
\fIpathName \fBedit reset\fR
Clears the undo and redo stacks.
.TP
\fIpathName \fBedit separator\fR
Inserts a separator (boundary) on the undo stack. Does nothing when the \-undo option is false.
.TP
\fIpathName \fBedit undo\fR
Undoes the last edit action when the \-undo option is true. An edit action is defined as all the insert and delete commands that are recorded on the undo stack in between two separators. Generates an error when the undo stack is empty. Does nothing when the \-undo option is false.
.RE
.TP
\fIpathName \fBfold \fIcommand ?line?\fR
The fold command provides various capabilities related to Scintilla's folding functionality. Some operations are simple queries while others will impact the fold structure within the document. The following commands are supported:
.RS
.TP
\fBfoldall\fR
folds all lines within the document
.TP
\fBfoldbelow \fIline\fR
folds all lines which are after(below) line number line
.TP
\fBfoldparent \fIline\fR
returns the line containing the immediate fold parent of line
.TP
\fBfoldroot \fIline\fR
returns the line containing topmost fold parent of the specified line . This is at the top of the fold hierarchy containing line .
.TP
\fBisfolded \fIline\fR
return 1 if line contained in a folded parent, and 0 if it isn't
.TP
\fBshow \fIline\fR
fully expand the containing fold hierarchy such that line is visible
.TP
\fBtoggle \fIline\fR
toggle the fold state of line (ie if collapsed, expand it; if expanded, collapse it)
.TP
\fBtopunfolded \fIline\fR
return the line of the highest fold parent for line which is currently expanded
.TP
\fBunfoldall\fR
unfold all lines
.TP
\fBunfoldbelow \fIline\fR
unfold all lines which are after(below) line number line
.RE
.TP
\fIpathName \fBindex \fIindex ?\-textonly?\fR
Returns the position corresponding to index in the form line.char where line is the line number and char is the character number. See the documentation for the Tk Text widget for a description of the formats used to specify indices. NOTE: Specifying an X/Y location that corresponds to a line of annotation text will return the index for the end of the line associated with the annotation. If the \-textonly option is used, then an empty string is returned if the X/Y location is over an annotation.
.TP
\fIpathName \fBinsert \fIindex chars\fR
Inserts all of the chars argument just before the character at index. If index refers to the end of the text (the character after the last newline) then the new text is inserted just before the last newline instead.
.RE
.TP
\fIpathName \fBmargin \fIoption ?arg arg ...?\fR
This command is used to manage the widget's various margins (aka columns). The exact behavior of the command depends on the option argument that follows the margin argument. In most of the subcommands below, there is an argument which identifies the margin. It is labeled "marginID" in the following descriptions. The format of this argument can be any of the following: 1) the numeric index of the margin, where "0" is the leftmost margin, and "4" is rightmost, 2) the name of the margin, which will match the margin's type (eg "text", "symbol", etc), or 3) the alias name defined for the margin. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBmargin bbox \fImarginID line\fR
Returns a list of four elements describing the screen area of the margin identified by marginID, at the line specified by line. The first two elements of the list give the x and y coordinates of the upper\-left corner of the area occupied by the character, and the last two elements give the width and height of the area. If the character is not visible on the screen then the return value is an empty list.
.TP
\fIpathName \fBmargin cget \fImarginID option\fR
This command returns the current value of the option named option associated with the margin given by marginID. Option may have any of the values accepted by the pathName margin configure widget command.
.TP
\fIpathName \fBmargin configure \fImarginID ?option? ?value? ?option value ...?\fR
This command is similar to the pathName configure widget command except that it modifies options associated with the margin given by marginID instead of modifying options for the overall text widget. If no option is specified, the command returns a list describing all of the available options for marginID. If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option\-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in marginID; in this case the command returns an empty string.
.TP
\fIpathName \fBmargin count\fR
Returns the number of margins
.TP
\fIpathName \fBmargin dump \fImarginID ?option? Index1 ?Index2?\fR
Return the contents of the text widget from index1 up to, but not including index2, including the text and information about marks, tags, and embedded windows. If index2 is not specified, then it defaults to one character past index1. The information is returned in the following format::
key1 value1 index1 key2 value2 index2 ...
The possible key values are indicatoron, indicatoroff, text, mark, styleon, styleoff, tagon, and tagoff. The corresponding value is the indicator type, text, mark name, style number, or tag name. The index information is the index within the margin of the start of the indicator transition, style transition, text, mark, tag transition, image or window. One or more of the following switches (or abbreviations thereof) may be specified to control the dump:
.TP
\fB\-all\fR
Return information about all elements: indicator, style, text, marks, and tags. This is the default.
.TP
\fB\-command \fIcommand\fR
Instead of returning the information as the result of the dump operation, invoke the command on each element of the text widget within the range. The command has three arguments appended to it before it is evaluated: the key, value, and index.
.TP
\fB\-indicator\fR
Include information about indicator transitions in the dump results. Indicator information is returned as indicatoron and indicatoroff elements that indicate the begin and end of each range of each indicator, respectively.
.TP
\fB\-mark\fR
Include information about marks in the dump results.
.TP
\fB\-style\fR
Include information about style transitions in the dump results. Style information is returned as styleon and styleoff elements that indicate the begin and end of each range of each style, respectively.
.TP
\fB\-tag\fR
Include information about tag transitions in the dump results. Tag information is returned as tagon and tagoff elements that indicate the begin and end of each range of each tag, respectively.
.TP
\fB\-text\fR
Include information about text in the dump results. The value is the text up to the next element or the end of range indicated by index2. A text element does not span newlines. A multi\-line block of text that contains no marks or tag transitions will still be dumped as a set of text segments that each end with a newline. The newline is part of the value.
.TP
\fIpathName \fBmargin fillnumbers \fImarginID start count ?tagName {line ...}?\fR
This would be used to manually managing filling a margin with line numbers. This is really only used for cases when control over the appearance of the line numbers is needed. The fillnumbers command would be called within the \-linesaddedcommand callback function in a margin whose type was set to "lnums_alt". Setting the margin type to "lnums" would result in the Scintilla core code handling filling of the line numbers. The start option identifies where the line numbering should begin. The count option controls how many lines will be numbers. A value of <= 0 will number all lines from start until the end of the document. To apply custom styling to one or more line numbers, first configure a tag named tagName and then identify the list of line numbers as the argument following tagName. For example, to fill the line numbers from 1 to 10 where only the odd numbers are styled in red, first create a tag (ex: $sci tag config red \-margin \-fg red) and then execute $sci margin fillnumbers 1 10 red {1 3 5 7 9}.
.TP
\fIpathName \fBmargin hide \fImarginID\fR
Hides the margin specified by marginID. The margin's configuration information is maintained while hidden.
.TP
\fIpathName \fBmargin index \fI@X,Y\fR
Returns a list of three elements to identify the margin at the location indicated by the X and Y window location (where "@0,0" corresponds to the upperleft corner of the window). If a margin exists at the location, then the three values returned are: 1) the margin id, 2) the line number, and 3) the margin's alias (or an empty string if it an alias hasn't been defined). If the X/Y location isn't over a margin then an empty string is returned.
.TP
\fIpathName \fBmargin marker \fImarginID command markerName lines\fR
This command is used to add or remove the marker named markerName to the margin specified by marginID. The operation performed is controlled by the command argument, which would either be "add" or "clear". The lines option identifies which lines to add or remove the marker for. When removing, if the lines list is empty, then the specified marker would be removed from all lines. Also, when removing, if the markerName is set to "*", then all markers present for the specified lines would be removed.
.TP
\fIpathName \fBmargin marker \fImarginID list markerName ?line?\fR
This command returns a list of the lines containing the specified marker. If markerName is specified as "*" the line argument is required. When this done, the all markers present on the specified line will be returned.
.TP
\fIpathName \fBmargin names\fR
Returns information about each of the margins. Each margin is identified by a three element list containing the following: 1) the ID value of the margin (where "0" is the leftmost margin), 2) the type of the margin, and 3) the alias name, or an empty string if one hasn't been defined.
.TP
\fIpathName \fBmargin show \fImarginID\fR
Shows the margin specified by marginID. For margins that have not yet had a width set (ie their width is zero), the show operation will report an error unless the margin's type is set for linenumbers or the special fold margin. For those margins, the widget will automatically determine the appropriate width to use in order to allow the margin to be made visible.
.TP
\fIpathName \fBmargin tag \fI{line ...} ?tagName \-clear?\fR
This command will either add or remove a tag that was previously configured for use in the margin area (see here for more details). The margin tag will affect only text\-based margins (ie not those holding symbols). The tag named tagName will be added to the list of lines unless the \-clear option is specified, in which case the tag will be removed. When removing a tag, it can be removed from all lines by specifying an empty list for the lines. To remove all margin tags from all lines, the tagName option should not be specified (ie $sci margin tag {} \-clear).
.TP
\fIpathName \fBmargin text \fImarginID command arglist\fR
This command is used to manipulate the margin text within the margin specified by marginID. The margin specified by marginID must be of type text or rtext. The operation performed is controlled by the command argument, which would either be one of "clear", "get", or "set". If command is "clear", and there is no arglist, then the margin text for all lines in the document is removed. If arglist is provided, it is a list of one or more lines to clear. If the command argument is "get", the arglist must specify the line number of the margin text to return. If the command argument is "set", the arglist consists of a string value to set in the margin followed by one or more line numbers that should be modified.
.TP
\fIpathName \fBmargin visible \fImarginID\fR
Returns if the margin specified by marginID is currently being shown. This is different from checking if the margin's configuration value for the \-width option is zero, because when a margin is hidden its width value is retained so that it can be shown with the intended width.
.TP
\fIpathName \fBmargin width\fR
Return the total width in pixels of the visible margins.
.RE
.TP
\fIpathName \fBmark \fIoption ?arg arg ...?\fR
This command is used to manipulate marks. The exact behavior of the command depends on the option argument that follows the mark argument. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBmark exists \fImarkName\fR
If markName exists, the command will return 1; otherwise 0 is returned.
.TP
\fIpathName \fBmark gravity \fImarkName ?direction?\fR
If direction is not specified, returns left or right to indicate which of its adjacent characters markName is attached to. If direction is specified, it must be left or right; the gravity of markName is set to the given value.
.TP
\fIpathName \fBmark names\fR
Returns a list whose elements are the names of all the marks that are currently set.
.TP
\fIpathName \fBmark next \fIindex\fR
Returns the name of the next mark at or after index. If index is specified in numerical form, then the search for the next mark begins at that index. If index is the name of a mark, then the search for the next mark begins immediately after that mark. This can still return a mark at the same position if there are multiple marks at the same index. These semantics mean that the mark next operation can be used to step through all the marks in a text widget. An empty string is returned if there are no marks after index.
.TP
\fIpathName \fBmark previous \fIindex\fR
Returns the name of the mark at or before index. If index is specified in numerical form, then the search for the previous mark begins with the character just before that index. If index is the name of a mark, then the search for the next mark begins immediately before that mark. This can still return a mark at the same position if there are multiple marks at the same index. These semantics mean that the mark previous operation can be used to step through all the marks in a text widget. An empty string is returned if there are no marks before index.
.TP
\fIpathName \fBmark set \fImarkName index\fR
Sets the mark named markName to a position just before the character at index. If markName already exists, it is moved from its old position; if it does not exist, a new mark is created. This command returns an empty string.
.TP
\fIpathName \fBmark unset \fImarkName ?markName ...?\fR
Remove the mark corresponding to each of the markName arguments. The removed marks will not be usable in indices and will not be returned by future calls to pathName mark names. This command returns an empty string.
.RE
.TP
\fIpathName \fBmarker \fI?option? ?arg arg ...?\fR
Markers are used to apply visual attributes to locations within one or more margins at specific line locations. The types of markers include simple shapes, like circles or arrows, as well as arbitrary images. For text\-based margins, the foreground and background colors can be specified. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBmarker configure \fImarkerName ?option? ?value option value ...?\fR
This command is similar to the pathName configure widget command except that it modifies options associated with the marker given by markName instead of modifying options for the overall widget. If no option is specified, the command returns a list describing all of the available options for markerName. If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option\-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in markerName; in this case the command returns an empty string.
.TP
\fIpathName \fBmarker delete \fImarkerName ?markerName ...?\fR
Deletes the named markers
.TP
\fIpathName \fBmarker exists \fImarkerName line\fR
Checks if the marker specified by markerName exists for line. Returns 1 if it does, 0 otherwise.
.TP
\fIpathName \fBmarker names\fR
Returns a sorted list of all currently defined markers (created by using the marker configure command).
.TP
\fIpathName \fBmarker types\fR
Returns the list of type names which can be used with the \-type option to the configure command.
.RE
.TP
\fIpathName \fBsearch \fI?switches? pattern index ?stopIndex?\fR
Searches the text in pathName starting at index for a range of characters that matches pattern. If a match is found, the index of the first character in the match is returned as result; otherwise an empty string is returned. One or more of the following switches (or abbreviations thereof) may be specified to control the search:
.RS
.TP
\fB\-forwards\fR
The search will proceed forward through the text, finding the first matching range starting at or after the position given by index. This is the default.
.TP
\fB\-backwards\fR
The search will proceed backward through the text, finding the matching range closest to index whose first character is before index (it is not allowed to be at index). Note that, for a variety of reasons, backwards searches can be substantially slower than forwards searches (particularly when using \-regexp), so it is recommended that performance\-critical code use forward searches.
.TP
\fB\-exact\fR
Use exact matching: the characters in the matching range must be identical to those in pattern. This is the default.
.TP
\fB\-regexp\fR
Treat pattern as a regular expression and match it against the text using the rules for regular expressions (see the regexp command for details). The default matching automatically passes both the \-lineanchor and \-linestop options to the regexp engine (unless \-nolinestop is used), so that ^$ match beginning and end of line, and ., [^ sequences will never match the newline character \n.
.TP
\fB\-nolinestop\fR
This allows . and [^ sequences to match the newline character \n, which they will otherwise not do (see the regexp command for details). This option is only meaningful if \-regexp is also given, and an error will be thrown otherwise. For example, to match the entire text, use pathName search \-nolinestop \-regexp ".*" 1.0.
.TP
\fB\-nocase\fR
Ignore case differences between the pattern and the text.
.TP
\fB\-count \fIvarName\fR
The argument following \-count gives the name of a variable; if a match is found, the number of index positions between beginning and end of the matching range will be stored in the variable. If there are no embedded images or windows in the matching range (and there are no elided characters if \-elide is not given), this is equivalent to the number of characters matched. In either case, the range matchIdx to matchIdx + $count chars will return the entire matched text.
.TP
\fB\-all\fR
Find all matches in the given range and return a list of the indices of the first character of each match. If a \-count varName switch is given, then varName is also set to a list containing one element for each successful match. Note that, even for exact searches, the elements of this list may be different, if there are embedded images, windows or hidden text. Searches with \-all behave very similarly to the Tcl command regexp \-all, in that overlapping matches are not normally returned. For example, applying an \-all search of the pattern \w+ against hello there will just match twice, once for each word, and matching Z[a\-z]+Z against ZooZooZoo will just match once.
.TP
\fB\-overlap\fR
When performing \-all searches, the normal behaviour is that matches which overlap an already\-found match will not be returned. This switch changes that behaviour so that all matches which are not totally enclosed within another match are returned. For example, applying an \-overlap search of the pattern \w+ against hello there will just match twice (i.e. no different to just \-all), but matching Z[a\-z]+Z against ZooZooZoo will now match twice. An error will be thrown if this switch is used without \-all.
.TP
\fB\-strictlimits\fR
When performing any search, the normal behaviour is that the start and stop limits are checked with respect to the start of the matching text. With the \-strictlimits flag, the entire matching range must lie inside the start and stop limits specified for the match to be valid.
.TP
\fB\-elide \fIcurrently not supported\fR
Find elided (hidden) text as well. By default only displayed text is searched.
.TP
\fB\-\-\fR
This switch has no effect except to terminate the list of switches: the next argument will be treated as pattern even if it starts with \-.
.RE
.PP
The matching range may be within a single line of text, or run across multiple lines (if parts of the pattern can match a new\-line). For regular expression matching one can use the various newline\-matching features such as $ to match the end of a line, ^ to match the beginning of a line, and to control whether . is allowed to match a new\-line. If stopIndex is specified, the search stops at that index: for forward searches, no match at or after stopIndex will be considered; for backward searches, no match earlier in the text than stopIndex will be considered. If stopIndex is omitted, the entire text will be searched: when the beginning or end of the text is reached, the search continues at the other end until the starting location is reached again; if stopIndex is specified, no wrap\-around will occur. This means that, for example, if the search is \-forwards but stopIndex is earlier in the text than startIndex, nothing will ever be found. See the Tk Text widget man page for more information.
.RE
.TP
\fIpathName \fBscisearch \fI?switches? pattern index ?stopIndex?\fR
Scintilla Search searches the text in pathName starting at index for a range of characters that matches pattern. If a match is found, the index of the first character in the match is returned as result; otherwise an empty string is returned. One or more of the following switches (or abbreviations thereof) may be specified to control the search:
.RS
.TP
\fB\-forwards\fR
The search will proceed forward through the text, finding the first matching range starting at or after the position given by index. This is the default.
.TP
\fB\-backwards\fR
The search will proceed backward through the text, finding the matching range closest to index whose first character is before index (it is not allowed to be at index).
.TP
\fB\-count \fIvarName\fR
The argument following \-count gives the name of a variable; if a match is found, the number of index positions between beginning and end of the matching range will be stored in the variable.
.TP
\fB\-exact\fR
Use exact matching: the characters in the matching range must be identical to those in pattern. This is the default.
.TP
\fB\-nocase\fR
Ignore case differences between the pattern and the text.
.TP
\fB\-regexp\fR
Treat pattern as a regular expression. In a regular expression, special characters interpreted are:
.RS
.TP 
\fB.\fR
Matches any character.
.TP 
\fB\\(\fR 
This marks the start of a region for tagging a match.
.TP 
\fB\\)\fR
This marks the end of a tagged region.
.TP
\fB\\n\fR 
Where n is 1 through 9 refers to the first through ninth tagged region when replacing. For example, if the search string was Fred\\([1-9]\\)XXX and the replace string was Sam\1YYY, when applied to Fred2XXX this would generate Sam2YYY. \0 refers to all of the matching text.
.TP
\fB\\<\fR
This matches the start of a word using Scintilla's definitions of words.
.TP
\fB\\>\fR
This matches the end of a word using Scintilla's definition of words.
.TP
\fB\\x\fR
This allows you to use a character x that would otherwise have a special meaning. For example, \\[ would be interpreted as [ and not as the start of a character set.
.TP
\fB[...]\fR
This indicates a set of characters, for example, [abc] means any of the characters a, b or c. You can also use ranges, for example [a\-z] for any lower case character.
.TP
\fB[^...]\fR
The complement of the characters in the set. For example, [^A\-Za\-z] means any character except an alphabetic character.
.TP
\fB^\fR
This matches the start of a line (unless used inside a set, see above).
.TP
\fB$\fR
This matches the end of a line.
.TP
\fB*\fR
This matches 0 or more times. For example, Sa*m matches Sm, Sam, Saam, Saaam and so on.
.TP
\fB+\fR
This matches 1 or more times. For example, Sa+m matches Sam, Saam, Saaam and so on.
.RE
Regular expressions will only match ranges within a single line, never matching over multiple lines.
.TP
\fB\-word\fR
A match only occurs if the characters before and after are not word characters.
.TP
\fB--\fR
This switch has no effect except to terminate the list of switches: the next argument will be treated as pattern even if it starts with \-.
.RE
The matching range must be within a single line of text. For regular expression matching one can use the various newline\-matching features such as $ to match the end of a line, ^ to match the beginning of a line. If stopIndex is specified, the search stops at that index: for forward searches, no match at or after stopIndex will be considered; for backward searches, no match earlier in the text than stopIndex will be considered. If stopIndex is omitted, the entire text will be searched.
.TP
\fIpathName \fBsee \fIindex ?\-center?\fR
Adjusts the view in the window so that the character given by index is completely visible. If index is already visible then the command does nothing. If index is a short distance out of view, the command adjusts the view just enough to make index visible at the edge of the window. If index is far out of view, then the command centers index in the window. The \-center option can be used to force index to be centered in the window.
.TP
\fIpathName \fBtag \fI?option? ?arg arg ...?\fR
A tag is a textual string that is associated with some of the characters in the widget. Tags may contain arbitrary characters, but it is probably best to avoid using the characters   (space), +, or \-: these characters have special meaning in indices, so tags containing them cannot be used as indices. There may be any number of tags associated with characters in a text. Each tag may refer to a single character, a range of characters, or several ranges of characters. An individual character may have any number of tags associated with it. The order that overlapping tags are displayed is controlled by the logical identifier associated with each of the tag types below(higher ID numbers are drawn last). See the table below for descriptions of the supported types. The following forms of the command are currently supported:
.RS
.TP
\fIpathName \fBtag add \fItagName index1 ?index2?\fR
Associate the tag tagName (one will be created if it doesn't already exist) with all of the characters starting with index1 and ending just before index2 (the character at index2 is not tagged). If index2 is omitted then the single character at index1 is tagged. If there are no characters in the specified range (e.g. index1 is past the end of the file or index2 is less than or equal to index1) then the command has no effect. EXCEPTION: If tagName is the predefined selection tag (i.e. "sel"), then specifying index2 to be less than index1 will have the effect of positioning the insertion point at the start of the selection.
.TP
\fIpathName \fBtag bind \fItagName ?sequence? ?script?\fR
This command associates script with the tag given by tagName. Whenever the event sequence given by sequence occurs for a character that has been tagged with tagName, the script will be invoked. This widget command is similar to the bind command except that it operates on characters in a text rather than entire widgets. See the bind manual entry for complete details on the syntax of sequence and the substitutions performed on script before invoking it. If all arguments are specified then a new binding is created, replacing any existing binding for the same sequence and tagName (if the first character of script is + then script augments an existing binding rather than replacing it). In this case the return value is an empty string. If script is omitted then the command returns the script associated with tagName and sequence (an error occurs if there is no such binding). If both script and sequence are omitted then the command returns a list of all the sequences for which bindings have been defined for tagName. The only events for which bindings may be specified are those related to the mouse and keyboard (such as Enter, Leave, ButtonPress, Motion, and KeyPress) or virtual events. Event bindings for a text widget use the current mark. An Enter event triggers for a tag when the tag first becomes present on the current character, and a Leave event triggers for a tag when it ceases to be present on the current character. Enter and Leave events can happen either because the current mark moved or because the character at that position changed. Note that these events are different than Enter and Leave events for windows. Mouse and keyboard events are directed to the current character. If a virtual event is used in a binding, that binding can trigger only if the virtual event is defined by an underlying mouse\-related or keyboard\-related event.
.TP
\fIpathName \fBtag cget \fItagName option\fR
This command returns the current value of the option named option associated with the tag given by tagName. Option may have any of the values accepted by the pathName tag configure widget command.
.TP
\fIpathName \fBtag configure \fItagName ?\-margin? ?option? ?value? ?option value ...?\fR
This command is similar to the pathName configure widget command except that it modifies options associated with the tag given by tagName instead of modifying options for the overall text widget. If no option is specified, the command returns a list describing all of the available options for tagName. If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option\-value pairs are specified, then the command modifies the given option(s) to have the given value(s) in tagName; in this case the command returns an empty string. Note, the special \-margin option, if used, must immediately follow tagName. It is used to create and configure tags used within the margin area. See "configure options" for more details
.TP
\fIpathName \fBtag delete \fItagName ?tagName ...?\fR
Deletes all tag information for each of the tagName arguments. The command removes the tags from all characters in the file and also deletes any other information associated with the tags, such as bindings and display information. The command returns an empty string.
.TP
\fIpathName \fBtag lower \fItagName\fR
This has NOT BEEN IMPLEMENTED because Scintilla core functionality regarding "markers" (which is how the ScintillaTk tag functionality has been implemented) does not support drawing priority for markers that overlap.
.TP
\fIpathName \fBtag names \fI?index?\fR
Returns a list whose elements are the names of all the tags that are active at the character position given by index. If index is omitted, then the return value will describe all of the tags that exist for the widget.
.TP
\fIpathName \fBtag nextrange \fItagName index1 ?index2?\fR
This command searches the text for a range of characters tagged with tagName where the first character of the range is no earlier than the character at index1 and no later than the character just before index2 (a range starting at index2 will not be considered). The command's return value is a list containing two elements, which are the index of the first character of the range and the index of the character just after the last one in the range. If no matching range is found then the return value is an empty string. If index2 is not given then it defaults to the end of the text.
.TP
\fIpathName \fBtag prevrange \fItagName index1 ?index2?\fR
This command searches the text for a range of characters tagged with tagName where the first character of the range is before the character at index1 and no earlier than the character at index2 (a range starting at index2 will be considered). The command's return value is a list containing two elements, which are the index of the first character of the range and the index of the character just after the last one in the range. If no matching range is found then the return value is an empty string. If index2 is not given then it defaults to the beginning of the text.
.TP
\fIpathName \fBtag raise \fItagName\fR
This has NOT BEEN IMPLEMENTED because Scintilla core functionality regarding "markers" (which is how the ScintillaTk tag functionality has been implemented) does not support drawing priority for markers that overlap.
.TP
\fIpathName \fBtag ranges \fItagName\fR
Returns a list describing all of the ranges of text that have been tagged with tagName. The first two elements of the list describe the first tagged range in the text, the next two elements describe the second range, and so on. The first element of each pair contains the index of the first character of the range, and the second element of the pair contains the index of the character just after the last one in the range. If there are no characters tagged with tag then an empty string is returned.
.TP
\fIpathName \fBtag remove \fItagName index1 ?index2 index1 index2 ...?\fR
Remove the tag tagName from all of the characters starting at index1 and ending just before index2 (the character at index2 is not affected). A single command may contain any number of index1\-index2 pairs. If the last index2 is omitted then the tag is removed from the single character at index1. If there are no characters in the specified range (e.g. index1 is past the end of the file or index2 is less than or equal to index1) then the command has no effect. This command returns an empty string.
.RE
\fBTag Types\fR
.TS
box;
lfB lfB lfB
l np1 ap9.
Type	ID	Description
plain	0	Underlined with a single, straight line.
squiggle	1	A squiggly underline, 3 pixels in height
tt	2	A line of small "T" shapes
diagonal	3	Diagonal hatching
strike	4	A solid "strike through" line draw at the vertical mid\-point
hidden	5	No visual effect
box	6	A rectangular box around the text
roundbox	7	T{
A rectangle with rounded corners around the text, 
using translucent drawing for the interior 
(NOT SUPPORTED YET)
T}
squarebox	8	T{
A rectangle around the text, using translucent 
drawing for the interior 
(NOT SUPPORTED YET)
T}
dash	9	A dashed underline
dots	10	A dotted underline
squigglelow	11	Similar to squiggle but only 2 pixels in height
dotbox	12	T{
A dotted rectangle around the text, using translucent 
drawing for the interior 
(NOT SUPPORTED YET)
T}
.TE
.PP
.PP
For the above types, use the \-foreground configuration option for the tag to control the color. For types that use a filled interior, use the \-background option to set the interior color. The following lists the supported configuration options, though not all are supported for each type of tag (exceptions are noted):
.TP
\fB\-background|\-bg \fIcolor\fR
Color specifies the color used for tags that have a filled interior.
.TP
\fB\-bold \fIboolean \fR(ONLY FOR MARGIN TAGS)
Specifies if margins showing text will use a bold font
.TP
\fB\-foreground|\-fg \fIcolor\fR
Color specifies the color used for tags, and for tags will filled interiors color is for the outline.
.TP
\fB\-indicatortype \fItype \fR(NOT FOR MARGIN TAGS)
The type value matches the names in the above table
.TP
\fB\-italic \fIboolean \fR(ONLY FOR MARGIN TAGS)
Specifies if margins showing text will use an italicized font
There is a special tag used to control the appearance (foreground and background colors only) of the widget's selection. The name of this tag is sel, and it cannot be deleted.
.TP
\fIpathName \fBversion\fR
Returns a 3\-element list containing information identifying the current version of the widget. The fields of the list are:\fR
version : identifies the Tcl package version
date : the date the package was created
core_rls: this identifies the release of the Scintilla core widget
.PP
.SH "KNOWN BUGS"
Patterns including newline (\n) may not work correctly in all cases. This limitation is due to how Scintilla stores document text; the end of line characters are stripped from the document making the search challenging.
.PP
The pathName search \-regexp sub\-command attempts to perform sophisticated regexp matching across multiple lines in an efficient fashion. Under certain conditions the search result might differ from that obtained by applying the same regexp to the entire text from the widget in one go.
.PP
Whenever one possible match is fully enclosed in another, the search command will attempt to ensure only the larger match is returned. When performing backwards regexp searches it is possible that Tcl will not always achieve this.
.RE
.RE


'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Added tk/doc/scintillatk.txt.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
scintilla(n)                ScintillaTK Text Widget               scintilla(n)



______________________________________________________________________________

NNAAMMEE
       scintilla - Scintilla text widget

SSYYNNOOPPSSIISS
       ppaacckkaaggee rreeqquuiirree sscciinnttiillllaattkk ?00..2255?

       sscciinnttiillllaa _p_a_t_h_N_a_m_e ?_o_p_t_i_o_n_s?

SSTTAANNDDAARRDD OOPPTTIIOONNSS
       --aauuttoosseeppaarraattoorrss       --hhiigghhlliigghhtt           --mmoovveeuuppddaatteeccoommmmaanndd
       --bbaacckkggrroouunndd           --hhiigghhlliigghhtttthhiicckknneessss  --rreelliieeff
       --bblliinnkk                --hhiigghhlliigghhttbbaacckkggrroouunndd --sshhoowwwwss
       --bboorrddeerrwwiiddtthh          --llaanngguuaaggee            --ssttaattee
       --bbuussyyccuurrssoorr           --lliinneessaaddddeeddccoommmmaanndd   --ttaabbwwiiddtthh
       --ccuurrssoorr               --mmaarrggiinnbbaacckkggrroouunndd    --ttaakkeeffooccuuss
       --ffoollddssttyyllee            --mmaarrggiinnbbgg            --xxssccrroollllccoommmmaanndd
       --ffoonntt                 --mmaarrggiinnffoorreeggrroouunndd    --yyssccrroollllccoommmmaanndd
       --ffoorreeggrroouunndd           --mmaarrggiinnffgg            --uunnddoo
       --hheeiigghhtt               --mmaarrggiinnwwiiddtthhccoommmmaanndd  --wwiiddtthh

       See the ooppttiioonnss manual entry for details on the standard options.

WWIIDDGGEETT--SSPPEECCIIFFIICC OOPPTTIIOONNSS
       Command-Line Name:--aauuttoosseeppaarraattoorrss
       Database Name:  aauuttooSSeeppaarraattoorrss
       Database Class: AAuuttooSSeeppaarraattoorrss

              Specifies  a  boolean that says whether separators are automati-
              cally inserted in the undo stack. Only meaningful when the --uunnddoo
              option is true.

       Command-Line Name:--hheeiigghhtt
       Database Name:  hheeiigghhtt
       Database Class: HHeeiigghhtt

              Specifies the desired height for the window, in units of charac-
              ters in the font given by the --ffoonntt option.  Must  be  at  least
              one.

       Command-Line Name:--ssttaattee
       Database Name:  ssttaattee
       Database Class: SSttaattee

              Specifies  one  of two states for the text:  nnoorrmmaall or ddiissaabblleedd.
              If the text is disabled then characters may not be  inserted  or
              deleted  and  no insertion cursor will be displayed, even if the
              input focus is in the widget.

       Command-Line Name:--wwiiddtthh
       Database Name:  wwiiddtthh
       Database Class: WWiiddtthh

              Specifies the desired width for the window in units  of  charac-
              ters  in  the  font given by the --ffoonntt option.  If the font does
              not have a uniform width then the width of the character "0"  is
              used in translating from character units to screen units.

       Command-Line Name:--bbuussyyccuurrssoorr
       Database Name:  ccuurrssoorr
       Database Class: CCuurrssoorr

              Cursor to display when text widget is computationally busy.

       Command-Line Name:--ffoollddssttyyllee
       Database Name:  ffoollddssttyyllee
       Database Class: FFoollddSSttyyllee

              See Scintilla documentation for style values.

       Command-Line Name:--llaanngguuaaggee
       Database Name:  llaanngguuaaggee
       Database Class: LLaanngguuaaggee

              Specifies  which  programming  language  lexer to use for syntax
              highlighting.

       Command-Line Name:--lliinneessaaddddeeddccoommmmaanndd
       Database Name:  lliinnddeessAAddddeeddCCoommmmaanndd
       Database Class: LLiinneessAAddddeeddCCoommmmaanndd

              Callback command when new lines are inserted  in  the  document.
              This  function can be used to update margin indicators if neces-
              sary.

       Command-Line Name:--mmaarrggiinnbbaacckkggrroouunndd
       Database Name:  mmaarrggiinnBBaacckkggrroouunndd
       Database Class: MMaarrggiinnBBaacckkggrroouunndd

              The backgound color of the margin columns.

       Command-Line Name:--mmaarrggiinnffoorreeggrroouunndd
       Database Name:  mmaarrggiinnFFoorreeggrroouunndd
       Database Class: MMaarrggiinnFFoorreeggrroouunndd

              The foregound (font) color of the margin columns.

       Command-Line Name:--mmaarrggiinnwwiiddtthhccoommmmaanndd
       Database Name:
       Database Class:

              Callback command used when margin width changes.

       Command-Line Name:--mmoovveeuuppddaatteeccoommmmaanndd
       Database Name:  mmoovveeUUppddaatteeCCoommmmaanndd
       Database Class: MMoovveeUUppddaatteeCCoommmmaanndd

              Callback command when margin changes.

       Command-Line Name:--sshhoowwwwss
       Database Name:  sshhoowwwwss
       Database Class: SShhoowwWWss

              Show the ws???

_________________________________________________________________

DDEESSCCRRIIPPTTIIOONN
       The sscciinnttiillllaa command creates a new window (given by the _p_a_t_h_N_a_m_e  arg)
       and  makes  it  into  a  Scintilla  text  widget.  Additional  options,
       described above, may be specified on the command line or in the  option
       database  to  configure  aspects  of the text such as its default back-
       ground color and relief.  The tteexxtt command returns the path name of the
       new window.


WWIIDDGGEETT CCOOMMMMAANNDD
       _p_a_t_h_N_a_m_e aannnnoottaattee _o_p_t_i_o_n _?_a_r_g _a_r_g _._._._?
              Text  annotations  are  separate strings that can be assigned to
              the lines within  the  document.  The  annotation  is  displayed
              without  any  line  numbers  and appears in extra space which is
              created by the widget for its display. There are various options
              available:

              cclleeaarraallll
                     removes annotation strings for all lines

              ggeett _l_i_n_e
                     Returns the annotation text for the specified line.

              sseett _l_i_n_e _t_e_x_t _?_t_a_g_N_a_m_e _t_e_x_t _t_a_g_N_a_m_e _._._._?
                     Assigns  the specified text string to the specified line.
                     If no tagName option is specified,  the  annotation  text
                     will  use  the  default text styling. If a single tagName
                     option is used it will control the appearance for all  of
                     the  annotation  text. By using multiple text and tagName
                     options it's possible to have different  appearances  for
                     different subranges of the text.

              sshhooww _0_|_1_|_2
                     Used to control the display of annotations where 0 - hid-
                     ing, 1 - showing or 2 -  showing  with  a  bounding  box.
                     Note, this affects all lines with annotations.

       _p_a_t_h_N_a_m_e bbbbooxx _i_n_d_e_x
              Returns  a  list  of four elements describing the screen area of
              the character given by index. The first two elements of the list
              give  the  x  and  y coordinates of the upper-left corner of the
              area occupied by the character, and the last two  elements  give
              the  width and height of the area. If the character is not visi-
              ble on the screen then the return value is an empty list.

       _p_a_t_h_N_a_m_e ccggeett _o_p_t_i_o_n
              Returns the current value of the configuration option  given  by
              option.  Option may have any of the values accepted by the scin-
              tilla command.

       _p_a_t_h_N_a_m_e ccoommppaarree _i_n_d_e_x_1 _o_p _i_n_d_e_x_2
              Compares the indices given by index1 and index2 according to the
              relational  operator given by op, and returns 1 if the relation-
              ship is satisfied and 0 if it is not. Op  must  be  one  of  the
              operators  <,  <=, =, >, >, or !. If op is == then 1 is returned
              if the two indices refer to the same character, if op is <  then
              1  is  returned  if index1 refers to an earlier character in the
              text than index2, and so on.

       _p_a_t_h_N_a_m_e ccoonnffiigguurree _?_o_p_t_i_o_n_? _?_v_a_l_u_e _o_p_t_i_o_n _v_a_l_u_e _._._._?
              Query or modify the configuration options of the widget.  If  no
              option is specified, returns a list describing all of the avail-
              able options for pathName. If option is specified with no value,
              then  the command returns a list describing the one named option
              (this list will be identical to the corresponding sublist of the
              value  returned  if  no  option  is  specified).  If one or more
              option-value pairs are specified, then the command modifies  the
              given  widget option(s) to have the given value(s); in this case
              the command returns an empty string. Option may have any of  the
              values accepted by the scintilla command.

       _p_a_t_h_N_a_m_e ccoouunntt _?_o_p_t_i_o_n_s_? _i_n_d_e_x_1 _i_n_d_e_x_2
              Counts the number of relevant things between the two indices. If
              index1 is after index2, the result will  be  a  negative  number
              (and  this  holds  for each of the possible options). The actual
              items which are counted depend on the options given. The  result
              is  a  list  of  integers,  one  for the result of each counting
              option given. Valid counting options are  -chars,  -displaylines
              and  -lines.  The  default  value, if no option is specified, is
              -chars. The count options are interpreted as follows:

              --cchhaarrss count all characters, whether elided or not. Do not count
                     embedded windows or images.

              --ddiissppllaayylliinneess
                     count  all  display  lines  (i.e.  ignore lines which are
                     folded) from the line of the first index up to,  but  not
                     including the display line of the second index. Therefore
                     if they are both on the same display line, zero  will  be
                     returned.  By  definition  displaylines  are  visible and
                     therefore this only counts  portions  of  actual  visible
                     lines.

              --lliinneess count  all  lines (irrespective of folding) from the line
                     of the first index up to, but not including the  line  of
                     the  second index. Therefore if they are both on the same
                     line, zero will be returned. Lines  are  counted  whether
                     they are currently visible (non-folded) or not.

       _p_a_t_h_N_a_m_e ddeelleettee _i_n_d_e_x_1 _?_i_n_d_e_x_2_?
              Delete  a  range of characters from the text. If both index1 and
              index2 are specified, then delete all  the  characters  starting
              with  the  one  given  by index1 and stopping just before index2
              (i.e. the character at index2 is not deleted). If index2 doesn't
              specify a position later in the text than index1 then no charac-
              ters are deleted. If index2  isn't  specified  then  the  single
              character  at  index1  is deleted. It is not allowable to delete
              characters in a way that would leave the text without a  newline
              as the last character. The command returns an empty string.

       _p_a_t_h_N_a_m_e dduummpp _?_s_w_i_t_c_h_e_s_? _i_n_d_e_x_1 _?_i_n_d_e_x_2_?__
              Return  the  contents  of the text widget from index1 up to, but
              not including index2, including the text and  information  about
              marks,  tags,  and embedded windows. If index2 is not specified,
              then it defaults to one character past index1.  The  information
              is  returned  in  the following format:: key1 value1 index1 key2
              value2 index2 ...  The  possible  key  values  are  indicatoron,
              indicatoroff,  text,  mark,  styleon,  styleoff,  tagon, tagoff,
              image, and window. The  corresponding  value  is  the  indicator
              type,  text,  mark  name, style number, tag name, image name, or
              window name. The index information is the index of the start  of
              the  indicator  transition,  style  transition,  text, mark, tag
              transition, image or window. The image and  window  options  are
              not  supported  and will return nothing. One or more of the fol-
              lowing switches (or abbreviations thereof) may be  specified  to
              control the dump:

              --aallll   Return  information about all elements: indicator, style,
                     text, marks,  tags,  images  and  windows.  This  is  the
                     default.

              --ccoommmmaanndd _c_o_m_m_a_n_d
                     Instead of returning the information as the result of the
                     dump operation, invoke the command on each element of the
                     text widget within the range. The command has three argu-
                     ments appended to it before it  is  evaluated:  the  key,
                     value, and index.

              --iimmaaggee Include  information  about  images  in the dump results.
                     This option is unsupported in Scintilla.

              --iinnddiiccaattoorr
                     Include information about indicator  transitions  in  the
                     dump  results. Indicator information is returned as indi-
                     catoron and indicatoroff elements that indicate the begin
                     and end of each range of each indicator, respectively.

              --mmaarrkk  Include information about marks in the dump results.

              --ssttyyllee Include  information  about style transitions in the dump
                     results. Style information is  returned  as  styleon  and
                     styleoff elements that indicate the begin and end of each
                     range of each style, respectively.

              --ttaagg   Include information about tag  transitions  in  the  dump
                     results.  Tag information is returned as tagon and tagoff
                     elements that indicate the begin and end of each range of
                     each tag, respectively.

              --tteexxtt  Include  information  about text in the dump results. The
                     value is the text up to the next element or  the  end  of
                     range  indicated  by index2. A text element does not span
                     newlines. A multi-line block of  text  that  contains  no
                     marks or tag transitions will still be dumped as a set of
                     text segments that each end with a newline.  The  newline
                     is part of the value.

              --wwiinnddooww
                     Include  information  about  embedded windows in the dump
                     results. This option is unsupported in Scintilla.

       _p_a_t_h_N_a_m_e eeddiitt _o_p_t_i_o_n _?_a_r_g _a_r_g _._._._?
              This command controls the undo mechanism and the modified  flag.
              The exact behavior of the command depends on the option argument
              that follows the edit argument. The following forms of the  com-
              mand are currently supported:

              _p_a_t_h_N_a_m_e eeddiitt ccaannrreeddoo
                     Returns true if the redo stack is not empty.

              _p_a_t_h_N_a_m_e eeddiitt ccaannuunnddoo
                     Returns true if the undo stack is not empty.

              _p_a_t_h_N_a_m_e eeddiitt IImmooddiiffiieedd _?_b_o_o_l_e_a_n_?
                     If boolean is not specified, returns the modified flag of
                     the widget. The insert, delete, edit undo and  edit  redo
                     commands  or the user can set or clear the modified flag.
                     If boolean is specified, sets the modified  flag  of  the
                     widget to boolean.

              _p_a_t_h_N_a_m_e eeddiitt rreeddoo
                     When  the -undo option is true, reapplies the last undone
                     edits provided no other edits were done since then.  Gen-
                     erates  an error when the redo stack is empty. Does noth-
                     ing when the -undo option is false.

              _p_a_t_h_N_a_m_e eeddiitt rreesseett
                     Clears the undo and redo stacks.

              _p_a_t_h_N_a_m_e eeddiitt sseeppaarraattoorr
                     Inserts a separator (boundary) on the  undo  stack.  Does
                     nothing when the -undo option is false.

              _p_a_t_h_N_a_m_e eeddiitt uunnddoo
                     Undoes  the  last  edit  action  when the -undo option is
                     true. An edit action is defined as  all  the  insert  and
                     delete  commands  that  are recorded on the undo stack in
                     between two separators. Generates an error when the  undo
                     stack  is  empty.  Does  nothing when the -undo option is
                     false.

       _p_a_t_h_N_a_m_e ffoolldd _c_o_m_m_a_n_d _?_l_i_n_e_?
              The fold command provides various capabilities related to  Scin-
              tilla's   folding  functionality.  Some  operations  are  simple
              queries while others will impact the fold structure  within  the
              document. The following commands are supported:

              ffoollddaallll
                     folds all lines within the document

              ffoollddbbeellooww _l_i_n_e
                     folds all lines which are after(below) line number line

              ffoollddppaarreenntt _l_i_n_e
                     returns  the line containing the immediate fold parent of
                     line

              ffoollddrroooott _l_i_n_e
                     returns the line containing topmost fold  parent  of  the
                     specified line . This is at the top of the fold hierarchy
                     containing line .

              iissffoollddeedd _l_i_n_e
                     return 1 if line contained in a folded parent, and  0  if
                     it isn't

              sshhooww _l_i_n_e
                     fully expand the containing fold hierarchy such that line
                     is visible

              ttooggggllee _l_i_n_e
                     toggle the fold state of line (ie  if  collapsed,  expand
                     it; if expanded, collapse it)

              ttooppuunnffoollddeedd _l_i_n_e
                     return the line of the highest fold parent for line which
                     is currently expanded

              uunnffoollddaallll
                     unfold all lines

              uunnffoollddbbeellooww _l_i_n_e
                     unfold all lines which are after(below) line number line

       _p_a_t_h_N_a_m_e iinnddeexx _i_n_d_e_x _?_-_t_e_x_t_o_n_l_y_?
              Returns  the  position  corresponding  to  index  in  the   form
              line.char  where line is the line number and char is the charac-
              ter number. See the documentation for the Tk Text widget  for  a
              description of the formats used to specify indices. NOTE: Speci-
              fying an X/Y location that corresponds to a line  of  annotation
              text  will  return  the index for the end of the line associated
              with the annotation. If the -textonly option is  used,  then  an
              empty  string is returned if the X/Y location is over an annota-
              tion.

       _p_a_t_h_N_a_m_e iinnsseerrtt _i_n_d_e_x _c_h_a_r_s
              Inserts all of the chars argument just before the  character  at
              index.  If  index  refers  to the end of the text (the character
              after the last newline) then  the  new  text  is  inserted  just
              before the last newline instead.

       _p_a_t_h_N_a_m_e mmaarrggiinn _o_p_t_i_o_n _?_a_r_g _a_r_g _._._._?
              This command is used to manage the widget's various margins (aka
              columns). The exact behavior  of  the  command  depends  on  the
              option argument that follows the margin argument. In most of the
              subcommands below, there is an  argument  which  identifies  the
              margin.  It is labeled "marginID" in the following descriptions.
              The format of this argument can be any of the following: 1)  the
              numeric  index  of the margin, where "0" is the leftmost margin,
              and "4" is rightmost, 2) the name  of  the  margin,  which  will
              match  the  margin's  type (eg "text", "symbol", etc), or 3) the
              alias name defined for the margin. The following  forms  of  the
              command are currently supported:

              _p_a_t_h_N_a_m_e mmaarrggiinn bbbbooxx _m_a_r_g_i_n_I_D _l_i_n_e
                     Returns  a  list  of  four elements describing the screen
                     area of the margin identified by marginID,  at  the  line
                     specified  by  line.  The  first two elements of the list
                     give the x and y coordinates of the upper-left corner  of
                     the area occupied by the character, and the last two ele-
                     ments give the width and height of the area. If the char-
                     acter  is not visible on the screen then the return value
                     is an empty list.

              _p_a_t_h_N_a_m_e mmaarrggiinn ccggeett _m_a_r_g_i_n_I_D _o_p_t_i_o_n
                     This command returns the  current  value  of  the  option
                     named   option   associated  with  the  margin  given  by
                     marginID. Option may have any of the values  accepted  by
                     the pathName margin configure widget command.

              _p_a_t_h_N_a_m_e  mmaarrggiinn  ccoonnffiigguurree  _m_a_r_g_i_n_I_D  _?_o_p_t_i_o_n_?  _?_v_a_l_u_e_? _?_o_p_t_i_o_n
              _v_a_l_u_e _._._._?
                     This  command is similar to the pathName configure widget
                     command except that it modifies options  associated  with
                     the margin given by marginID instead of modifying options
                     for the overall text widget. If no option  is  specified,
                     the  command  returns a list describing all of the avail-
                     able options for marginID. If option is specified with no
                     value, then the command returns a list describing the one
                     named option (this list will be identical to  the  corre-
                     sponding  sublist  of  the value returned if no option is
                     specified). If one or more option-value pairs are  speci-
                     fied,  then  the  command modifies the given option(s) to
                     have the given value(s) in marginID;  in  this  case  the
                     command returns an empty string.

              _p_a_t_h_N_a_m_e mmaarrggiinn ccoouunntt
                     Returns the number of margins

              _p_a_t_h_N_a_m_e mmaarrggiinn dduummpp _m_a_r_g_i_n_I_D _?_o_p_t_i_o_n_? _I_n_d_e_x_1 _?_I_n_d_e_x_2_?
                     Return the contents of the text widget from index1 up to,
                     but not including index2, including the text and informa-
                     tion  about  marks, tags, and embedded windows. If index2
                     is not specified, then it defaults to one character  past
                     index1. The information is returned in the following for-
                     mat:: key1 value1 index1 key2 value2 index2 ...  The pos-
                     sible  key  values  are  indicatoron, indicatoroff, text,
                     mark, styleon, styleoff, tagon, and  tagoff.  The  corre-
                     sponding  value  is  the indicator type, text, mark name,
                     style number, or tag name. The index information  is  the
                     index  within  the  margin  of the start of the indicator
                     transition, style transition, text, mark, tag transition,
                     image  or  window.  One or more of the following switches
                     (or abbreviations thereof) may be  specified  to  control
                     the dump:

              --aallll   Return  information about all elements: indicator, style,
                     text, marks, and tags. This is the default.

              --ccoommmmaanndd _c_o_m_m_a_n_d
                     Instead of returning the information as the result of the
                     dump operation, invoke the command on each element of the
                     text widget within the range. The command has three argu-
                     ments  appended  to  it  before it is evaluated: the key,
                     value, and index.

              --iinnddiiccaattoorr
                     Include information about indicator  transitions  in  the
                     dump  results. Indicator information is returned as indi-
                     catoron and indicatoroff elements that indicate the begin
                     and end of each range of each indicator, respectively.

              --mmaarrkk  Include information about marks in the dump results.

              --ssttyyllee Include  information  about style transitions in the dump
                     results. Style information is  returned  as  styleon  and
                     styleoff elements that indicate the begin and end of each
                     range of each style, respectively.

              --ttaagg   Include information about tag  transitions  in  the  dump
                     results.  Tag information is returned as tagon and tagoff
                     elements that indicate the begin and end of each range of
                     each tag, respectively.

              --tteexxtt  Include  information  about text in the dump results. The
                     value is the text up to the next element or  the  end  of
                     range  indicated  by index2. A text element does not span
                     newlines. A multi-line block of  text  that  contains  no
                     marks or tag transitions will still be dumped as a set of
                     text segments that each end with a newline.  The  newline
                     is part of the value.

              _p_a_t_h_N_a_m_e  mmaarrggiinn ffiillllnnuummbbeerrss _m_a_r_g_i_n_I_D _s_t_a_r_t _c_o_u_n_t _?_t_a_g_N_a_m_e _{_l_i_n_e
              _._._._}_?
                     This  would be used to manually managing filling a margin
                     with line numbers. This is really  only  used  for  cases
                     when  control  over the appearance of the line numbers is
                     needed. The fillnumbers command would  be  called  within
                     the  -linesaddedcommand  callback  function  in  a margin
                     whose type was set to  "lnums_alt".  Setting  the  margin
                     type  to  "lnums" would result in the Scintilla core code
                     handling filling of the line numbers.  The  start  option
                     identifies  where  the  line  numbering should begin. The
                     count option controls how many lines will be  numbers.  A
                     value  of <= 0 will number all lines from start until the
                     end of the document. To apply custom styling  to  one  or
                     more  line  numbers,  first configure a tag named tagName
                     and then identify the list of line numbers as  the  argu-
                     ment  following  tagName.  For  example, to fill the line
                     numbers from 1 to 10  where  only  the  odd  numbers  are
                     styled  in  red,  first create a tag (ex: $sci tag config
                     red -margin -fg red) and then execute $sci  margin  fill-
                     numbers 1 10 red {1 3 5 7 9}.

              _p_a_t_h_N_a_m_e mmaarrggiinn hhiiddee _m_a_r_g_i_n_I_D
                     Hides the margin specified by marginID. The margin's con-
                     figuration information is maintained while hidden.

              _p_a_t_h_N_a_m_e mmaarrggiinn iinnddeexx _@_X_,_Y
                     Returns a list of three elements to identify  the  margin
                     at  the location indicated by the X and Y window location
                     (where "@0,0" corresponds to the upperleft corner of  the
                     window).  If  a  margin  exists at the location, then the
                     three values returned are: 1) the margin id, 2) the  line
                     number,  and 3) the margin's alias (or an empty string if
                     it an alias hasn't been defined).  If  the  X/Y  location
                     isn't over a margin then an empty string is returned.

              _p_a_t_h_N_a_m_e mmaarrggiinn mmaarrkkeerr _m_a_r_g_i_n_I_D _c_o_m_m_a_n_d _m_a_r_k_e_r_N_a_m_e _l_i_n_e_s
                     This  command  is  used to add or remove the marker named
                     markerName to the margin specified by marginID. The oper-
                     ation  performed  is  controlled by the command argument,
                     which would either be "add" or "clear". The lines  option
                     identifies  which  lines to add or remove the marker for.
                     When removing, if the lines list is empty, then the spec-
                     ified  marker would be removed from all lines. Also, when
                     removing, if the markerName is set to "*", then all mark-
                     ers present for the specified lines would be removed.

              _p_a_t_h_N_a_m_e mmaarrggiinn mmaarrkkeerr _m_a_r_g_i_n_I_D _l_i_s_t _m_a_r_k_e_r_N_a_m_e _?_l_i_n_e_?
                     This  command  returns a list of the lines containing the
                     specified marker. If markerName is specified as  "*"  the
                     line  argument is required. When this done, the all mark-
                     ers present on the specified line will be returned.

              _p_a_t_h_N_a_m_e mmaarrggiinn nnaammeess
                     Returns information about each of the margins. Each  mar-
                     gin  is identified by a three element list containing the
                     following: 1) the ID value of the margin  (where  "0"  is
                     the  leftmost  margin), 2) the type of the margin, and 3)
                     the alias name, or an empty string  if  one  hasn't  been
                     defined.

              _p_a_t_h_N_a_m_e mmaarrggiinn sshhooww _m_a_r_g_i_n_I_D
                     Shows  the margin specified by marginID. For margins that
                     have not yet had a width set (ie their  width  is  zero),
                     the  show  operation will report an error unless the mar-
                     gin's type is set for linenumbers  or  the  special  fold
                     margin.  For those margins, the widget will automatically
                     determine the appropriate width to use in order to  allow
                     the margin to be made visible.

              _p_a_t_h_N_a_m_e mmaarrggiinn ttaagg _{_l_i_n_e _._._._} _?_t_a_g_N_a_m_e _-_c_l_e_a_r_?
                     This  command  will  either  add or remove a tag that was
                     previously configured for use in  the  margin  area  (see
                     here  for  more details). The margin tag will affect only
                     text-based margins (ie not those  holding  symbols).  The
                     tag  named  tagName  will  be  added to the list of lines
                     unless the -clear option is specified, in which case  the
                     tag  will  be  removed.  When  removing  a tag, it can be
                     removed from all lines by specifying an  empty  list  for
                     the  lines. To remove all margin tags from all lines, the
                     tagName option should not be specified  (ie  $sci  margin
                     tag {} -clear).

              _p_a_t_h_N_a_m_e mmaarrggiinn tteexxtt _m_a_r_g_i_n_I_D _c_o_m_m_a_n_d _a_r_g_l_i_s_t
                     This command is used to manipulate the margin text within
                     the margin specified by marginID. The margin specified by
                     marginID  must  be  of  type text or rtext. The operation
                     performed is controlled by the  command  argument,  which
                     would  either be one of "clear", "get", or "set". If com-
                     mand is "clear", and there is no arglist, then the margin
                     text for all lines in the document is removed. If arglist
                     is provided, it is a list of one or more lines to  clear.
                     If  the command argument is "get", the arglist must spec-
                     ify the line number of the margin text to return. If  the
                     command  argument  is  "set",  the  arglist consists of a
                     string value to set in the margin followed by one or more
                     line numbers that should be modified.

              _p_a_t_h_N_a_m_e mmaarrggiinn vviissiibbllee _m_a_r_g_i_n_I_D
                     Returns  if the margin specified by marginID is currently
                     being shown. This is different from checking if the  mar-
                     gin's  configuration value for the -width option is zero,
                     because when a  margin  is  hidden  its  width  value  is
                     retained so that it can be shown with the intended width.

              _p_a_t_h_N_a_m_e mmaarrggiinn wwiiddtthh
                     Return the total width in pixels of the visible  margins.

       _p_a_t_h_N_a_m_e mmaarrkk _o_p_t_i_o_n _?_a_r_g _a_r_g _._._._?
              This  command is used to manipulate marks. The exact behavior of
              the command depends on the option argument that follows the mark
              argument.  The following forms of the command are currently sup-
              ported:

              _p_a_t_h_N_a_m_e mmaarrkk eexxiissttss _m_a_r_k_N_a_m_e
                     If markName exists, the command will return 1;  otherwise
                     0 is returned.

              _p_a_t_h_N_a_m_e mmaarrkk ggrraavviittyy _m_a_r_k_N_a_m_e _?_d_i_r_e_c_t_i_o_n_?
                     If  direction  is not specified, returns left or right to
                     indicate which of its  adjacent  characters  markName  is
                     attached  to.  If direction is specified, it must be left
                     or right; the gravity of markName is  set  to  the  given
                     value.

              _p_a_t_h_N_a_m_e mmaarrkk nnaammeess
                     Returns  a  list  whose elements are the names of all the
                     marks that are currently set.

              _p_a_t_h_N_a_m_e mmaarrkk nneexxtt _i_n_d_e_x
                     Returns the name of the next mark at or after  index.  If
                     index is specified in numerical form, then the search for
                     the next mark begins at that index. If index is the  name
                     of a mark, then the search for the next mark begins imme-
                     diately after that mark. This can still return a mark  at
                     the same position if there are multiple marks at the same
                     index. These semantics mean that the mark next  operation
                     can  be used to step through all the marks in a text wid-
                     get. An empty string is returned if there  are  no  marks
                     after index.

              _p_a_t_h_N_a_m_e mmaarrkk pprreevviioouuss _i_n_d_e_x
                     Returns the name of the mark at or before index. If index
                     is specified in numerical form, then the search  for  the
                     previous  mark begins with the character just before that
                     index. If index is the name of a mark,  then  the  search
                     for  the  next  mark begins immediately before that mark.
                     This can still return a mark  at  the  same  position  if
                     there  are multiple marks at the same index. These seman-
                     tics mean that the mark previous operation can be used to
                     step  through  all  the  marks in a text widget. An empty
                     string is returned if there are no marks before index.

              _p_a_t_h_N_a_m_e mmaarrkk sseett _m_a_r_k_N_a_m_e _i_n_d_e_x
                     Sets the mark named markName to a  position  just  before
                     the character at index. If markName already exists, it is
                     moved from its old position; if it does not exist, a  new
                     mark is created. This command returns an empty string.

              _p_a_t_h_N_a_m_e mmaarrkk uunnsseett _m_a_r_k_N_a_m_e _?_m_a_r_k_N_a_m_e _._._._?
                     Remove  the  mark  corresponding  to each of the markName
                     arguments. The  removed  marks  will  not  be  usable  in
                     indices and will not be returned by future calls to path-
                     Name mark names. This command returns an empty string.

       _p_a_t_h_N_a_m_e mmaarrkkeerr _?_o_p_t_i_o_n_? _?_a_r_g _a_r_g _._._._?
              Markers are used to apply visual attributes to locations  within
              one  or  more  margins  at specific line locations. The types of
              markers include simple shapes, like circles or arrows,  as  well
              as  arbitrary images. For text-based margins, the foreground and
              background colors can be specified. The following forms  of  the
              command are currently supported:

              _p_a_t_h_N_a_m_e  mmaarrkkeerr  ccoonnffiigguurree  _m_a_r_k_e_r_N_a_m_e  _?_o_p_t_i_o_n_?  _?_v_a_l_u_e _o_p_t_i_o_n
              _v_a_l_u_e _._._._?
                     This  command is similar to the pathName configure widget
                     command except that it modifies options  associated  with
                     the marker given by markName instead of modifying options
                     for the overall widget. If no option  is  specified,  the
                     command  returns  a  list describing all of the available
                     options for markerName. If option is  specified  with  no
                     value, then the command returns a list describing the one
                     named option (this list will be identical to  the  corre-
                     sponding  sublist  of  the value returned if no option is
                     specified). If one or more option-value pairs are  speci-
                     fied,  then  the  command modifies the given option(s) to
                     have the given value(s) in markerName; in this  case  the
                     command returns an empty string.

              _p_a_t_h_N_a_m_e mmaarrkkeerr ddeelleettee _m_a_r_k_e_r_N_a_m_e _?_m_a_r_k_e_r_N_a_m_e _._._._?
                     Deletes the named markers

              _p_a_t_h_N_a_m_e mmaarrkkeerr eexxiissttss _m_a_r_k_e_r_N_a_m_e _l_i_n_e
                     Checks  if  the marker specified by markerName exists for
                     line. Returns 1 if it does, 0 otherwise.

              _p_a_t_h_N_a_m_e mmaarrkkeerr nnaammeess
                     Returns a sorted list of all  currently  defined  markers
                     (created by using the marker configure command).

              _p_a_t_h_N_a_m_e mmaarrkkeerr ttyyppeess
                     Returns the list of type names which can be used with the
                     -type option to the configure command.

       _p_a_t_h_N_a_m_e sseeaarrcchh _?_s_w_i_t_c_h_e_s_? _p_a_t_t_e_r_n _i_n_d_e_x _?_s_t_o_p_I_n_d_e_x_?
              Searches the text in pathName starting at index for a  range  of
              characters  that matches pattern. If a match is found, the index
              of the first character in the match is returned as result;  oth-
              erwise an empty string is returned. One or more of the following
              switches (or abbreviations thereof) may be specified to  control
              the search:

              --ffoorrwwaarrddss
                     The search will proceed forward through the text, finding
                     the first matching range starting at or after  the  posi-
                     tion given by index. This is the default.

              --bbaacckkwwaarrddss
                     The  search will proceed backward through the text, find-
                     ing the matching range closest to index whose first char-
                     acter is before index (it is not allowed to be at index).
                     Note that, for a variety of reasons,  backwards  searches
                     can  be substantially slower than forwards searches (par-
                     ticularly when using -regexp), so it is recommended  that
                     performance-critical code use forward searches.

              --eexxaacctt Use  exact matching: the characters in the matching range
                     must be identical  to  those  in  pattern.  This  is  the
                     default.

              --rreeggeexxpp
                     Treat  pattern  as  a  regular  expression  and  match it
                     against the text using the rules for regular  expressions
                     (see  the regexp command for details). The default match-
                     ing  automatically  passes  both  the   -lineanchor   and
                     -linestop   options   to   the   regexp   engine  (unless
                     -nolinestop is used), so that ^$ match beginning and  end
                     of line, and ., [^ sequences will never match the newline
                     character 0

              --nnoolliinneessttoopp
                     This allows . and [^ sequences to match the newline char-
                     acter  0 which they will otherwise not do (see the regexp
                     command for details). This option is only  meaningful  if
                     -regexp is also given, and an error will be thrown other-
                     wise. For example, to match the entire text, use pathName
                     search -nolinestop -regexp ".*" 1.0.

              --nnooccaassee
                     Ignore case differences between the pattern and the text.

              --ccoouunntt _v_a_r_N_a_m_e
                     The argument following -count gives the name of  a  vari-
                     able;  if a match is found, the number of index positions
                     between beginning and end of the matching range  will  be
                     stored  in  the variable. If there are no embedded images
                     or windows in the matching range (and there are no elided
                     characters if -elide is not given), this is equivalent to
                     the number of characters matched.  In  either  case,  the
                     range matchIdx to matchIdx + $count chars will return the
                     entire matched text.

              --aallll   Find all matches in the given range and return a list  of
                     the  indices  of  the first character of each match. If a
                     -count varName switch is given, then varName is also  set
                     to  a  list  containing  one  element for each successful
                     match. Note that, even for exact searches,  the  elements
                     of  this  list  may  be  different, if there are embedded
                     images, windows or hidden text. Searches with -all behave
                     very  similarly  to  the Tcl command regexp -all, in that
                     overlapping matches are not normally returned. For  exam-
                     ple, applying an -all search of the pattern 1992Z against
                     ZooZooZoo will just match once.

              --oovveerrllaapp
                     When performing -all searches, the  normal  behaviour  is
                     that  matches  which  overlap an already-found match will
                     not be returned. This switch changes  that  behaviour  so
                     that  all  matches  which are not totally enclosed within
                     another match are  returned.  For  example,  applying  an
                     -overlap  search  of  the pattern 2304Z against ZooZooZoo
                     will now match twice. An error will  be  thrown  if  this
                     switch is used without -all.

              --ssttrriiccttlliimmiittss
                     When  performing any search, the normal behaviour is that
                     the start and stop limits are checked with respect to the
                     start  of the matching text. With the -strictlimits flag,
                     the entire matching range must lie inside the  start  and
                     stop limits specified for the match to be valid.

              --eelliiddee _c_u_r_r_e_n_t_l_y _n_o_t _s_u_p_p_o_r_t_e_d
                     Find  elided  (hidden) text as well. By default only dis-
                     played text is searched.

              ----     This switch has no effect except to terminate the list of
                     switches:  the  next  argument will be treated as pattern
                     even if it starts with -.

       The matching range may be within a single line of text, or  run  across
       multiple lines (if parts of the pattern can match a new-line). For reg-
       ular expression matching one can use the various newline-matching  fea-
       tures such as $ to match the end of a line, ^ to match the beginning of
       a line, and to control whether . is allowed to  match  a  new-line.  If
       stopIndex  is  specified,  the  search stops at that index: for forward
       searches, no match at or after stopIndex will be considered; for  back-
       ward searches, no match earlier in the text than stopIndex will be con-
       sidered. If stopIndex is omitted, the entire  text  will  be  searched:
       when  the beginning or end of the text is reached, the search continues
       at the other end until the  starting  location  is  reached  again;  if
       stopIndex is specified, no wrap-around will occur. This means that, for
       example, if the search is -forwards but stopIndex  is  earlier  in  the
       text  than startIndex, nothing will ever be found. See the Tk Text wid-
       get man page for more information.

       _p_a_t_h_N_a_m_e sscciisseeaarrcchh _?_s_w_i_t_c_h_e_s_? _p_a_t_t_e_r_n _i_n_d_e_x _?_s_t_o_p_I_n_d_e_x_?
              Scintilla Search searches the text in pathName starting at index
              for  a  range  of characters that matches pattern. If a match is
              found, the index of the first character in the match is returned
              as result; otherwise an empty string is returned. One or more of
              the following switches (or abbreviations thereof) may be  speci-
              fied to control the search:

              --ffoorrwwaarrddss
                     The search will proceed forward through the text, finding
                     the first matching range starting at or after  the  posi-
                     tion given by index. This is the default.

              --bbaacckkwwaarrddss
                     The  search will proceed backward through the text, find-
                     ing the matching range closest to index whose first char-
                     acter is before index (it is not allowed to be at index).

              --ccoouunntt _v_a_r_N_a_m_e
                     The argument following -count gives the name of  a  vari-
                     able;  if a match is found, the number of index positions
                     between beginning and end of the matching range  will  be
                     stored in the variable.

              --eexxaacctt Use  exact matching: the characters in the matching range
                     must be identical  to  those  in  pattern.  This  is  the
                     default.

              --nnooccaassee
                     Ignore case differences between the pattern and the text.

              --rreeggeexxpp
                     Treat pattern as  a  regular  expression.  In  a  regular
                     expression, special characters interpreted are:

                     Matches any character.

                      \\((     This  marks  the  start of a region for tagging a
                             match.

                      \\))     This marks the end of a tagged region.

                      \\nn     Where n is  1  through  9  refers  to  the  first
                             through  ninth  tagged region when replacing. For
                             example,    if    the    search    string     was
                             Fred\([1-9]\)XXX   and  the  replace  string  was
                             Sam1YYY, when applied to Fred2XXX this would gen-
                             erate  Sam2YYY.     refers to all of the matching
                             text.

                      \\<<     This matches the start  of  a  word  using  Scin-
                             tilla's definitions of words.

                      \\>>     This  matches the end of a word using Scintilla's
                             definition of words.

                      \\xx     This allows you to use a character x  that  would
                             otherwise have a special meaning. For example, \[
                             would be interpreted as [ and not as the start of
                             a character set.

                      [[......]]  This  indicates a set of characters, for example,
                             [abc] means any of the characters a, b or c.  You
                             can  also  use  ranges, for example [a-z] for any
                             lower case character.

                      [[^^......]] The complement of the characters in the set.  For
                             example,  [^A-Za-z] means any character except an
                             alphabetic character.

                      ^^      This matches the start of  a  line  (unless  used
                             inside a set, see above).

                      $$      This matches the end of a line.

                      **      This  matches  0 or more times. For example, Sa*m
                             matches Sm, Sam, Saam, Saaam and so on.

                      ++      This matches 1 or more times. For  example,  Sa+m
                             matches Sam, Saam, Saaam and so on.
              Regular expressions will only match ranges within a single line,
              never matching over multiple lines.

              --wwoorrdd  A match only occurs if the characters  before  and  after
                     are not word characters.

              ----     This switch has no effect except to terminate the list of
                     switches: the next argument will be  treated  as  pattern
                     even if it starts with -.
       The  matching  range  must be within a single line of text. For regular
       expression matching one can use the various  newline-matching  features
       such  as  $  to  match the end of a line, ^ to match the beginning of a
       line. If stopIndex is specified, the search stops at  that  index:  for
       forward  searches,  no  match at or after stopIndex will be considered;
       for backward searches, no match earlier in the text than stopIndex will
       be  considered.  If  stopIndex  is  omitted,  the  entire  text will be
       searched.

       _p_a_t_h_N_a_m_e sseeee _i_n_d_e_x _?_-_c_e_n_t_e_r_?
              Adjusts the view in the window so that the  character  given  by
              index  is  completely  visible. If index is already visible then
              the command does nothing. If index is a short  distance  out  of
              view,  the  command  adjusts  the view just enough to make index
              visible at the edge of the window. If index is far out of  view,
              then the command centers index in the window. The -center option
              can be used to force index to be centered in the window.

       _p_a_t_h_N_a_m_e ttaagg _?_o_p_t_i_o_n_? _?_a_r_g _a_r_g _._._._?
              A tag is a textual string that is associated with  some  of  the
              characters in the widget. Tags may contain arbitrary characters,
              but it is probably best to avoid using the characters   (space),
              +,  or  -:  these characters have special meaning in indices, so
              tags containing them cannot be used as indices. There may be any
              number  of  tags  associated with characters in a text. Each tag
              may refer to a single character, a range of characters, or  sev-
              eral  ranges of characters. An individual character may have any
              number of tags associated with it. The  order  that  overlapping
              tags are displayed is controlled by the logical identifier asso-
              ciated with each of the tag types below(higher  ID  numbers  are
              drawn  last).  See  the table below for descriptions of the sup-
              ported types. The following forms of the command  are  currently
              supported:

              _p_a_t_h_N_a_m_e ttaagg aadddd _t_a_g_N_a_m_e _i_n_d_e_x_1 _?_i_n_d_e_x_2_?
                     Associate  the  tag  tagName  (one  will be created if it
                     doesn't already exist) with all of the characters  start-
                     ing  with index1 and ending just before index2 (the char-
                     acter at index2 is not tagged). If index2 is omitted then
                     the single character at index1 is tagged. If there are no
                     characters in the specified range (e.g.  index1  is  past
                     the  end  of  the file or index2 is less than or equal to
                     index1) then the command has  no  effect.  EXCEPTION:  If
                     tagName  is  the  predefined  selection tag (i.e. "sel"),
                     then specifying index2 to be less than index1  will  have
                     the  effect  of  positioning  the  insertion point at the
                     start of the selection.

              _p_a_t_h_N_a_m_e ttaagg bbiinndd _t_a_g_N_a_m_e _?_s_e_q_u_e_n_c_e_? _?_s_c_r_i_p_t_?
                     This command associates script with the tag given by tag-
                     Name.  Whenever  the  event  sequence  given  by sequence
                     occurs for a character that has been tagged with tagName,
                     the  script will be invoked. This widget command is simi-
                     lar to the bind command except that it operates on  char-
                     acters in a text rather than entire widgets. See the bind
                     manual entry  for  complete  details  on  the  syntax  of
                     sequence and the substitutions performed on script before
                     invoking it. If all arguments are specified  then  a  new
                     binding  is  created,  replacing any existing binding for
                     the same sequence and tagName (if the first character  of
                     script  is  +  then  script  augments an existing binding
                     rather than replacing it). In this case the return  value
                     is an empty string. If script is omitted then the command
                     returns the script associated with tagName  and  sequence
                     (an  error  occurs  if there is no such binding). If both
                     script and sequence are omitted then the command  returns
                     a  list of all the sequences for which bindings have been
                     defined for tagName. The only events for  which  bindings
                     may  be specified are those related to the mouse and key-
                     board (such as Enter,  Leave,  ButtonPress,  Motion,  and
                     KeyPress)  or  virtual  events. Event bindings for a text
                     widget use the current mark. An Enter event triggers  for
                     a  tag  when the tag first becomes present on the current
                     character, and a Leave event triggers for a tag  when  it
                     ceases  to be present on the current character. Enter and
                     Leave events can happen either because the  current  mark
                     moved  or because the character at that position changed.
                     Note that these events are different than Enter and Leave
                     events   for  windows.  Mouse  and  keyboard  events  are
                     directed to the current character. If a virtual event  is
                     used  in  a binding, that binding can trigger only if the
                     virtual event is defined by an  underlying  mouse-related
                     or keyboard-related event.

              _p_a_t_h_N_a_m_e ttaagg ccggeett _t_a_g_N_a_m_e _o_p_t_i_o_n
                     This  command  returns  the  current  value of the option
                     named option associated with the tag  given  by  tagName.
                     Option  may  have any of the values accepted by the path-
                     Name tag configure widget command.

              _p_a_t_h_N_a_m_e  ttaagg  ccoonnffiigguurree  _t_a_g_N_a_m_e  _?_-_m_a_r_g_i_n_?  _?_o_p_t_i_o_n_?   _?_v_a_l_u_e_?
              _?_o_p_t_i_o_n _v_a_l_u_e _._._._?
                     This command is similar to the pathName configure  widget
                     command  except  that it modifies options associated with
                     the tag given by tagName instead of modifying options for
                     the  overall  text widget. If no option is specified, the
                     command returns a list describing all  of  the  available
                     options  for  tagName.  If  option  is  specified with no
                     value, then the command returns a list describing the one
                     named  option  (this list will be identical to the corre-
                     sponding sublist of the value returned if  no  option  is
                     specified).  If one or more option-value pairs are speci-
                     fied, then the command modifies the  given  option(s)  to
                     have the given value(s) in tagName; in this case the com-
                     mand returns an empty string. Note, the  special  -margin
                     option,  if  used, must immediately follow tagName. It is
                     used to create and configure tags used within the  margin
                     area. See "configure options" for more details

              _p_a_t_h_N_a_m_e ttaagg ddeelleettee _t_a_g_N_a_m_e _?_t_a_g_N_a_m_e _._._._?
                     Deletes all tag information for each of the tagName argu-
                     ments. The command removes the tags from  all  characters
                     in  the file and also deletes any other information asso-
                     ciated with the tags, such as bindings and display infor-
                     mation. The command returns an empty string.

              _p_a_t_h_N_a_m_e ttaagg lloowweerr _t_a_g_N_a_m_e
                     This  has  NOT  BEEN  IMPLEMENTED  because Scintilla core
                     functionality regarding "markers" (which is how the Scin-
                     tillaTk  tag functionality has been implemented) does not
                     support drawing priority for markers that overlap.

              _p_a_t_h_N_a_m_e ttaagg nnaammeess _?_i_n_d_e_x_?
                     Returns a list whose elements are the names  of  all  the
                     tags  that  are active at the character position given by
                     index. If index is omitted, then the  return  value  will
                     describe all of the tags that exist for the widget.

              _p_a_t_h_N_a_m_e ttaagg nneexxttrraannggee _t_a_g_N_a_m_e _i_n_d_e_x_1 _?_i_n_d_e_x_2_?
                     This  command searches the text for a range of characters
                     tagged with tagName where  the  first  character  of  the
                     range  is  no earlier than the character at index1 and no
                     later than the character  just  before  index2  (a  range
                     starting at index2 will not be considered). The command's
                     return value is a list containing two elements, which are
                     the  index  of  the  first character of the range and the
                     index of the character just after the  last  one  in  the
                     range.  If  no  matching  range  is found then the return
                     value is an empty string. If index2 is not given then  it
                     defaults to the end of the text.

              _p_a_t_h_N_a_m_e ttaagg pprreevvrraannggee _t_a_g_N_a_m_e _i_n_d_e_x_1 _?_i_n_d_e_x_2_?
                     This  command searches the text for a range of characters
                     tagged with tagName where  the  first  character  of  the
                     range  is  before  the character at index1 and no earlier
                     than the character at index2 (a range starting at  index2
                     will be considered). The command's return value is a list
                     containing two elements, which are the index of the first
                     character  of  the  range  and the index of the character
                     just after the last one in  the  range.  If  no  matching
                     range  is found then the return value is an empty string.
                     If index2 is not given then it defaults to the  beginning
                     of the text.

              _p_a_t_h_N_a_m_e ttaagg rraaiissee _t_a_g_N_a_m_e
                     This  has  NOT  BEEN  IMPLEMENTED  because Scintilla core
                     functionality regarding "markers" (which is how the Scin-
                     tillaTk  tag functionality has been implemented) does not
                     support drawing priority for markers that overlap.

              _p_a_t_h_N_a_m_e ttaagg rraannggeess _t_a_g_N_a_m_e
                     Returns a list describing all of the ranges of text  that
                     have  been tagged with tagName. The first two elements of
                     the list describe the first tagged range in the text, the
                     next  two  elements describe the second range, and so on.
                     The first element of each pair contains the index of  the
                     first  character  of the range, and the second element of
                     the pair contains the index of the character  just  after
                     the  last  one  in  the range. If there are no characters
                     tagged with tag then an empty string is returned.

              _p_a_t_h_N_a_m_e ttaagg rreemmoovvee _t_a_g_N_a_m_e _i_n_d_e_x_1 _?_i_n_d_e_x_2 _i_n_d_e_x_1 _i_n_d_e_x_2 _._._._?
                     Remove the tag tagName from all of the characters  start-
                     ing  at index1 and ending just before index2 (the charac-
                     ter at index2 is not affected). A single command may con-
                     tain  any  number  of  index1-index2  pairs.  If the last
                     index2 is omitted then the tag is removed from the single
                     character  at  index1.  If there are no characters in the
                     specified range (e.g. index1 is past the end of the  file
                     or  index2 is less than or equal to index1) then the com-
                     mand has no effect. This command returns an empty string.
       TTaagg TTyyppeess

       +----------------------------------------------------------------------------------+
       |TTyyppee          IIDD   DDeessccrriippttiioonn                                                    |
       |plain          0    Underlined with a single, straight line.                      |
       |squiggle       1    A squiggly underline, 3 pixels in height                      |
       |tt             2    A line of small "T" shapes                                    |
       |diagonal       3    Diagonal hatching                                             |
       |strike         4    A solid "strike through" line draw at the vertical mid-point  |
       |hidden         5    No visual effect                                              |
       |box            6    A rectangular box around the text                             |
       |roundbox       7    A  rectangle  with  rounded  corners  around the text, using  |
       |                    translucent drawing for the interior (NOT SUPPORTED YET)      |
       |squarebox      8    A rectangle around the text, using translucent  drawing  for  |
       |                    the interior (NOT SUPPORTED YET)                              |
       |dash           9    A dashed underline                                            |
       |dots          10    A dotted underline                                            |
       |squigglelow   11    Similar to squiggle but only 2 pixels in height               |
       |dotbox        12    A  dotted rectangle around the text, using translucent draw-  |
       |                    ing for the interior (NOT SUPPORTED YET)                      |
       +----------------------------------------------------------------------------------+

       For the above types, use the -foreground configuration option  for  the
       tag to control the color. For types that use a filled interior, use the
       -background option to set the interior color. The following  lists  the
       supported  configuration options, though not all are supported for each
       type of tag (exceptions are noted):

       --bbaacckkggrroouunndd||--bbgg _c_o_l_o_r
              Color specifies the color used for tags that have a filled inte-
              rior.

       --bboolldd _b_o_o_l_e_a_n (ONLY FOR MARGIN TAGS)
              Specifies if margins showing text will use a bold font

       --ffoorreeggrroouunndd||--ffgg _c_o_l_o_r
              Color  specifies  the  color  used  for  tags, and for tags will
              filled interiors color is for the outline.

       --iinnddiiccaattoorrttyyppee _t_y_p_e (NOT FOR MARGIN TAGS)
              The type value matches the names in the above table

       --iittaalliicc _b_o_o_l_e_a_n (ONLY FOR MARGIN TAGS)
              Specifies if margins showing text will use  an  italicized  font
              There  is  a  special  tag used to control the appearance (fore-
              ground and background colors only) of  the  widget's  selection.
              The name of this tag is sel, and it cannot be deleted.

       _p_a_t_h_N_a_m_e vveerrssiioonn
              Returns  a 3-element list containing information identifying the
              current version of the widget. The fields of the list are:  ver-
              sion  :  identifies  the Tcl package version date : the date the
              package was created core_rls: this identifies the release of the
              Scintilla core widget


KKNNOOWWNN BBUUGGSS
       Patterns including newline (0 may not work correctly in all cases. This
       limitation is due to how Scintilla stores document  text;  the  end  of
       line  characters are stripped from the document making the search chal-
       lenging.

       The pathName search -regexp sub-command attempts to  perform  sophisti-
       cated  regexp  matching  across multiple lines in an efficient fashion.
       Under certain conditions the  search  result  might  differ  from  that
       obtained by applying the same regexp to the entire text from the widget
       in one go.

       Whenever one possible match is fully enclosed in  another,  the  search
       command  will attempt to ensure only the larger match is returned. When
       performing backwards regexp searches it is possible that Tcl  will  not
       always achieve this.





Tk                                   0.25                         scintilla(n)

Added tk/license.terms.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
Copyright (c) 2013 Mentor Graphics Corporation

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.

   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   * The name of the author may not be used to endorse or promote
     products derived from this software without specific prior
     written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

-----

Portions of the code here came from Tcl 8.5 under the following license terms:

This software is copyrighted by the Regents of the University of
California, Sun Microsystems, Inc., and other parties.  The following
terms apply to all files associated with the software unless explicitly
disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (b) (3) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.

Added tk/makefile.













































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# Make file for Scintilla on Linux or compatible OS
# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
# The License.txt file describes the conditions under which this software may be distributed.
# This makefile assumes GCC 4.3 is used and changes will be needed to use other compilers.
# GNU make does not like \r\n line endings so should be saved to CVS in binary form.
# Builds for GTK+ 2 and no longer supports GTK+ 1.
# Also works with ming32-make on Windows.

# Environment variable WINDIR always defined on Win32

# NOTES:
# 1) To enable a debug build  : define PROFILE -OR- DEBUG
# 2) To enable a 32-bit build : define BIT32

ifdef PROFILE
DEBUG=1
endif

ifdef WINDIR
OBJSUFFIX = .obj
SHLIBSUFFIX = .dll
else
OBJSUFFIX = .o
SHLIBSUFFIX = .so
endif

.SUFFIXES: .cxx .c $(OBJSUFFIX) .h .a

#########################################################
# Tools/commands
#########################################################
ifdef WINDIR
CC = cl
CCOMP = cl
LINK = link
ifndef PRODDIR
PROD = //prod/prod
else
PROD = $(PRODDIR)
endif
else
CC = g++
CCOMP = gcc
PROD = /u/prod
FPIC = -fPIC
MMFLAG = -MM
LINK = g++
endif
AR = ar
COPY = cp
RANLIB = touch
DEL = rm -f
COMPLIB=../bin/scintilla.a
MKDIR = mkdir

vpath %.h ../src ../include ../lexlib
vpath %.cxx ../src ../lexlib ../lexers

#########################################################
# Variables
#
# NOTE: use 8.5 to match Modelsim mainline
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The current TCL version used by Modelsim can be found
# by searching for "TCLN" in src/misc/platform.mk
#
#########################################################
TCLVER=tcl8513-20130313
ifdef DEBUG
TCLDIR=$(PROD)/tcltk/$(TCLVER)/debug
else
TCLDIR=$(PROD)/tcltk/$(TCLVER)/opt
endif

# Retrieve the Scintilla core version (stored in the version.txt file)
SCI_CORE_VER = $(shell cat ../version.txt)
PACKAGE_VERSION = "\"0.25\""
PACKAGE_DATE = \"$(shell date "+%Y-%m-%d (beta)")\"

ifdef WINDIR
#--------------
#-- WINDOWS
#--------------
ifdef DEBUG
DBGLIB=g
endif

ifdef BIT32
TCLSH=$(shell /usr/bin/cygpath -m $(TCLDIR)/win32/usr/bin/tclsh85$(DBGLIB).exe)
TCL85INCLUDE=$(shell /usr/bin/cygpath -m $(TCLDIR)/win32/usr/include)
TCL85LIBLOC=$(shell /usr/bin/cygpath -m $(TCLDIR)/win32/usr/lib)
else
TCLSH=$(shell /usr/bin/cygpath -m $(TCLDIR)/win64/usr/bin/tclsh85$(DBGLIB).exe)
TCL85INCLUDE=$(shell /usr/bin/cygpath -m $(TCLDIR)/win64/usr/include)
TCL85LIBLOC=$(shell /usr/bin/cygpath -m $(TCLDIR)/win64/usr/lib)
endif

else
#--------------
#-- LINUX
#--------------
TCLSH=$(TCLDIR)/linux/usr/bin/tclsh8.5

TCL85INCLUDE=$(TCLDIR)/linux_x86_64/usr/include
endif

# Name of the primary shared library
SHAREDLIB    := libscintilla$(SHLIBSUFFIX)
SHAREDDBGLIB := libscintilla$(DBGLIB)$(SHLIBSUFFIX)


INCLUDEDIRS=-I $(TCL85INCLUDE)  -I ../include -I ../src -I ../lexlib

ifdef WINDIR
CXXBASEFLAGS := -Od /EHsc
else
# Using -Wno-write-strings to avoid warnings about calls like this:
#   warning: deprecated conversion from string constant to 'char*'
#
# These occur from code like this:
#   Tcl_SetResult(interp, "some message text", TCL_STATIC)
CXXBASEFLAGS := $(FPIC) -Wno-write-strings -Wall -Wno-missing-braces -Wno-char-subscripts -Wno-long-long -pedantic
endif
CXXBASEFLAGS += -DTK -DSCI_LEXER $(INCLUDEDIRS) -DSCI_CORE_VERSION=\"$(SCI_CORE_VER)\"

ifdef NOTHREADS
THREADFLAGS=-DG_THREADS_IMPL_NONE
else
THREADFLAGS=
endif

ifdef DEBUG
ifdef WINDIR
LINKFLAGS=/DEBUG
else
LINKFLAGS=-g
endif
endif

# Package support definitions
PKGNAME := ScintillaTk
PKGDIR  := $(PKGNAME)
PKGINDEX:=$(PKGDIR)/pkgIndex.tcl

WIDGETTCL:=scintillatk.tcl
ifdef DEBUG
PKGOBJS:=$(WIDGETTCL) $(SHAREDDBGLIB)
else
PKGOBJS:=$(WIDGETTCL) $(SHAREDLIB)
endif

ifdef WINDIR
ifdef DEBUG
#include the debug file
PKGOBJS += libscintilla$(DBGLIB).pdb
endif
endif


ifdef WINDIR
LINKOBJS:= widget.obj ScintillaTK.obj ../bin/scintilla.a tcl85$(DBGLIB).lib tk85$(DBGLIB).lib
LINKCMD = $(LINK) $(LINKFLAGS) /DLL /OUT:libscintilla$(DBGLIB).dll /LIBPATH:$(TCL85LIBLOC) $(LINKOBJS)
else
LINKCMD = $(LINK) $(LINKFLAGS) -shared -Wl,-soname,libscintilla.so -o libscintilla.so widget.o ScintillaTK.o ../bin/scintilla.a
endif

ifdef WINDIR
#--------------
#--- WINDOWS
#--------------
CXXFLAGS := -DWIN32 -D_WIN32 -D__CYGWIN__ -D__MWERKS__ $(CXXBASEFLAGS) $(THREADFLAGS)
ifdef DEBUG
CXXFLAGS := $(CXXFLAGS) -Z7 -DDEBUG
endif
else
#--------------
#-- LINUX
#--------------
ifdef DEBUG
CXXFLAGS=-DDEBUG -g $(CXXBASEFLAGS) $(THREADFLAGS)
else
CXXFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS) $(THREADFLAGS)
endif
endif

ifdef BIT32
CXXFLAGS += -m32
LINKFLAGS += -m32
endif

CXXFLAGS += -DPACKAGE_VERSION=$(PACKAGE_VERSION) -DPACKAGE_DATE="$(PACKAGE_DATE)"
CFLAGS:=$(CXXFLAGS)

OPTIONS=-DSCI_NAMESPACE

.cxx$(OBJSUFFIX):
	$(CC) $(OPTIONS) $(CXXFLAGS) -c $<
.c$(OBJSUFFIX):
	$(CCOMP) $(OPTIONS) $(CFLAGS) -w -c $<

LEXOBJS:=$(addsuffix $(OBJSUFFIX),$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))

SRCOBJS:=$(addsuffix $(OBJSUFFIX),$(basename $(notdir $(wildcard ../lexlib/*cxx ../src/*.cxx *cxx))))


##################################################
# Build Targets
##################################################
all: $(COMPLIB) $(SHAREDLIB) $(PKGINDEX)

clean:
	$(DEL) -r *.o *.obj $(COMPLIB) libscintilla* $(PKGDIR) ../bin/*

localclean:
	$(DEL) -r $(PKGDIR) ScintillaTK$(OBJSUFFIX) PlatTK$(OBJSUFFIX) widget*$(OBJSUFFIX) sciwrappers$(OBJSUFFIX) libscintilla*

deps:
	$(CC) $(MMFLAG) $(CXXFLAGS) *.h *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep '[a-zA-Z]' >deps.mak

ifdef WINDIR
ifndef BIT32
# win64 doesn't like ar output, use lib instead
$(COMPLIB): $(SRCOBJS) \
	$(LEXOBJS)
	lib /OUT:$@ $^
else
$(COMPLIB): $(SRCOBJS) \
	$(LEXOBJS)
	$(AR) rc $@ $^
	$(RANLIB) $@
endif
else
$(COMPLIB): $(SRCOBJS) \
	$(LEXOBJS)
	$(AR) rc $@ $^
	$(RANLIB) $@
endif

$(SHAREDLIB): $(COMPLIB)
	$(LINKCMD)

# target to get a Tcl package created, which is what client code would load

# support for auto-versioning the package
WIDGET_SRC := widget.cxx

# NOTE: we want to use an explicit package name with the "load" command to prevent
# Tcl from deriving the "init" C function name based on the name of the library
$(PKGINDEX): widget$(OBJSUFFIX) $(PKGOBJS)
	$(DEL) -r $(PKGDIR)
	$(MKDIR) $(PKGDIR)
	$(COPY) $(PKGOBJS) $(PKGDIR)
	@echo "*** Creating pkgIndex.tcl file using VERSION $(PACKAGE_VERSION)"
	@echo "package ifneeded $(PKGNAME) $(PACKAGE_VERSION) \"\\"              >>$(PKGINDEX)
	@echo "   load [file join \$$dir $(SHAREDDBGLIB)] $(PKGNAME);\\"    >>$(PKGINDEX)
	@echo "   source [file join \$$dir $(WIDGETTCL)]\""       >>$(PKGINDEX)


ifndef WINDIR
# Automatically generate header dependencies with "make deps"
include deps.mak
endif

Added tk/man/mann.



>
1
../doc

Added tk/pkgIndex.tcl.in.



















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
# Tcl package index file - handcrafted

# NOTE: keep version string in sync with the line
#       containing Tcl_PkgProvide in widget.cxx

package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ "\
   load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@;\
   source [file join $dir iface.tcl];\
   source [file join $dir scintillatk.tcl]"

Added tk/scintilla-cmd.cxx.

more than 10,000 changes

Added tk/scintilla-cmd.h.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
//
// scintilla-cmd.h --
//
// Declarations shared among the files that implement the Tk-flavor
// of the Scintilla editor widget.
//
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#ifndef _SCINTILLA_CMD
#define _SCINTILLA_CMD 

#include <string.h>

// NOTE: Because the Scintilla code is C++, we need for this Tcl widget
//       to use a C++ compiler
#include "Scintilla.h"
#include <SciLexer.h>
#include "ScintillaWidget.h"
#include <bitset>

#include "Platform.h" // for access to PRectangle
using namespace Scintilla;

// create a namespace for ourselves
namespace TkSci {

//----------------------------------------------------------------
// We do _NOT_ want the following within the TkSci namespace.

// next one needs C access because it's called as an idle task
extern "C" void SciWidgetDisplay (ClientData clientData);

#ifdef _WIN32
extern "C" __declspec(dllexport) int Scintillatk_Init(Tcl_Interp *interp);
#endif
//----------------------------------------------------------------



// define mapping macros to go between Tk's 1-based line number
// and Scintilla's 0-based line numbers
#define LINE2TK(ln)  ((ln < 0) ? ln : (ln + 1))
#define LINE2SCI(ln) ((ln < 0) ? ln : (ln - 1))

// Flag bit definitions.
//
#define REDRAW_PENDING 0x1
#define GOT_FOCUS      0x2
#define REDRAW_YSCROLL 0x4
#define REDRAW_XSCROLL 0x8
#define REDRAW_EXPOSE  0x10
#define INIT_CFG_DONE  0x20
#define BUSY_MODE      0x40
#define BUTTON_DOWN    0x80
#define DESTROYED      0x100
#define RESIZE         0x120

// data structure describing a change in the
// number of lines within the widget
typedef struct {
   int line;  // the line location of the add/delete
   int added; // >0 to indicate an addition, <0 indicates a deletion
} SciWidgetLinesAdded;

// forward decl
class MarginMgr;
class TagMgr;
class MarkerMgr;
class MarkMgr;


// data structure for widget
typedef struct {
   ScintillaObject *editor;
   Tcl_Interp      *interp;
   Tcl_Command      widgetCmd;
   Tk_Window        tkwin;
   Display         *display;
   GC               copyGC;
   Pixmap           mainPixmap;
   int				width;
   int              height;
   Tk_OptionTable   optionTable;
   Tk_BindingTable  bindingTable;

   /* widget-specific options */
   Tk_Font     tkfont;
   Tk_Cursor   cursor;
   Tk_Cursor   busycursor;
   Tk_3DBorder background;
   XColor     *foreground;
   XColor     *highlight;
   XColor     *highlightBg;
   XColor     *marginBg;
   XColor     *marginFg;
   int         relief;
   int         highlightWidth;
   int         borderWidth;
	int        reqWidth;
	int        reqHeight;
   char       *showws;
   char       *takefocus;
   int         tabwidth;
   int         state;
   bool        readonly;
   char       *language;
   int         langType;
   int         foldstyle;
   char        undo;
   char        autoseps; // only provided to be compatible w/ Tk Text widget
   char        inUndoAction;    // keeps track of undo collection state when "edit separator" used
   char       *blinkcaret;

   /* callback commands */
   char       *linesAddedCmd;
   char       *marginWidthCmd;
   char       *moveUpdateCmd;
   char       *yScrollCmd;
   char       *xScrollCmd;

   /* other stuff */
   int        padX;
   int        padY;
   int        yscrollDelta;
   int        flags;
   MarginMgr *marginMgr;
   MarkerMgr *markerMgr;
   MarkMgr   *markMgr;
   TagMgr    *tagMgr;
   SciWidgetLinesAdded *added_data;
   int       styleBits; // number of bits in styleId devoted to style, remainder of 8 bits are indicator bits

   /* data used for expose repaints */
   int expose_x;
   int expose_y;
   int expose_w;
   int expose_h;
} SciWidget;


// provide a callback mechanism for code on the Scintilla side
#define SCIW_SYNC_XSCROLL      100
#define SCIW_SYNC_YSCROLL      101
#define SCIW_MOVE_UPDATE       102
#define SCIW_LINESADDED_UPDATE 103
#define SCIW_MODIFIED          104

extern void MessageFromScintilla(ClientData clientData, int msg_id, uptr_t data);
extern void MessageFromScintilla(ClientData clientData, int msg_id);


////////////////////////////////////////////////////////////////////
// Margin management
//
enum MarginType {
   NONE, LINE_NUMS, LINE_NUMS_ALT, TEXT, RTEXT, SYMBOL, FOLD
};
static const char *MarginTypeNames[] = {
   "none", "lnums", "lnums_alt", "text", "rtext", "symbol", "fold"
};
#define IS_LINE_NUMS(t) (t == LINE_NUMS || t == LINE_NUMS_ALT)
#define IS_TEXT_TYPE(t) (IS_LINE_NUMS(t) || t == TEXT || t == RTEXT)

// data structure to hold configuration options used by each margin
typedef struct {
   char     *alias;     //(STRING) an alternate name(ie alias) for identifying the margin
   char     *clickcmd;  //(STRING) command to callback for clicks (null = clicks disabled)
   int       type;      //(STRING_TABLE) index of margin type in MarginTypeNames
   int       width;     //(INT)    margin's width(in pixels) - value of "0" will hide the margin
   Tk_Cursor cursor;    //(CURSOR) margin's cursor
} MarginOptions;

//-------------------------------------
// CLASS MarginData
//-------------------------------------
class MarginData {
public:
   MarginData(MarginMgr *, int, int);
   ~MarginData();

   // these can't be changed by client going thru the 
   // options interface, so we keep them as class data
   //
   int col_id;   // Scintilla uses columns 0 - 4
   int viswidth; // holds width when margin is visible

   // other info
   MarginMgr     *mgr;
   MarginOptions *mopts;
   Tk_OptionTable optionTable;

   // functions
   int Configure(int, Tcl_Obj *CONST[]);

   // accessor calls for options data
   const char *GetAlias()    { return mopts->alias; }
   const char *GetClickCmd() { return mopts->clickcmd; }
   const char *GetTypeStr()  { return MarginTypeNames[mopts->type]; }
   MarginType  GetType()     { return static_cast<MarginType>(mopts->type); }
   Tk_Cursor   GetCursor()   { return mopts->cursor; }
   const char *GetCursorStr();
   int  GetWidth()           { return mopts->width; }
   int  GetVisibleWidth()    { return viswidth; }
   void SetWidth(int w)      { mopts->width = w; viswidth = w;}
};


//-------------------------------------
// CLASS MarginMgr
//-------------------------------------
class MarginMgr {
public:
   MarginMgr(SciWidget *);
   ~MarginMgr();

   // these support the command interface to the widget
   int  CmdBbox    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdCget    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdConfig  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdDump    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdFillNums(int objc, Tcl_Obj *CONST objv[]);
   int  CmdIndex   (int objc, Tcl_Obj *CONST objv[]);
   int  CmdMarker  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdShow    (int objc, Tcl_Obj *CONST objv[], bool);
   int  CmdTag     (int objc, Tcl_Obj *CONST objv[]);
   int  CmdText    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdVisible (int objc, Tcl_Obj *CONST objv[]);
   int  InstanceCmd(int objc, Tcl_Obj *CONST objv[]);

   void Click(XButtonEvent be);
   void DumpText(Tcl_DString *dstr, int line1, int idx1, int line2, int idx2, const char* command);
   int  Get(Tcl_Obj *, int *);
   int  GetLineNWidth(int ndigits = 0);
   void RemoveMarker(int id);
   void RemoveMarker(int marginID, int id);
   void RemoveAllMarkers(int marginID);
   bool SetCursor(int x, int y);
   void UpdateMargin(int);
   int  ValidateTypeChange(int);
   int  Width();
   void ZoomPre();
   void ZoomPost();

private:
   //--- VARIABLES
   static const int MAXM = 5; // largest margin id

   MarginData    *margins[MAXM];
   SciWidget     *sciwidgetPtr; // note: required var name for use by SSM macro

public:
   // give easy access to MarginData
   Tcl_Interp    *interp;
   Display       *display;
   Tk_Window      tkwin;

private:
   // linenumber and fold columns are special. make it easy to find them
   int currLnum;
   int currFold;

   int preZoomWidth; // holds char width prior to a zoom

   //--- FUNCTIONS
   int  _atX(int x);
   void _click(int, int, int, int, int, bool, bool, bool);
   bool _hasMarker(int, int);
   int  _get(Tcl_Obj *, int *);
   void _reportError(const char *);
   void _reportError(Tcl_Obj *);
   int  _show(int id, bool show);
   int  _validAlias(const char *);
   int  _validId(int);
   int  _validName(const char *, int *);
   int  _validType(const char *, MarginType *);
};


////////////////////////////////////////////////////////////////////
// Tag management

typedef enum {
    TT_TEXT  = 1,
    TT_MARG  = 2,
    TT_INDIC = 4
} TagType;

// tags can be associated with an indicator style (they match those
// defined by Scintilla, but aren't hardwired to their constant values)
typedef enum {
    indicNONE,
    indicPlain,       // solid 1-pixel underline
    indicSquiggle,    // squiggly 3-pixel high underline
    indicTt,          // small "T" shapes drawn under text
    indicDiag,        // diaganol hatching
    indicStrike,      // strike-through drawn at midpoint of text
    indicHidden,      // an indicator that has no visual attributes
    indicBox,         // rectangle drawn around text using solid 1-pixel line
    indicRoundBox,    // rectange w/ rounded corners drawn around text - uses transparent interior
    indicSquareBox,   // same as above but with square corners
    indicDash,        // dashed underline
    indicDots,        // dotted underline
    indicSquiggleLow, // same as indicSquiggle but only using 2 pixels
    indicDotBox       // dotted rectangle around text - uses transparent interior
} IndicTypeID;


// data structure to hold configuration options used by each tag
typedef struct {
    const char    *name;       // symbolic name of the tag
    int            style_id;   // Scintilla style id
    int            indic_id;   // Scintilla id used for indicators
    XColor        *fgColor;    // foreground color of text
    XColor        *bgColor;    // background color of text
    int            bold;       // boolean to indicate if text is bold
    int            italic   ;  // boolean to indicate if text is italicized
    int            underline;  // boolean to indicate if text is underlined
    int            tagType;    // mask intended to identify the owning area (text or margin)
    IndicTypeID    indicType;  // indicator type (if any)
    Tk_OptionTable optionTable;// table to hold config options

    const char *Name()      { return name; }
    int Bold()              { return bold; }
    int Italic()            { return italic; }
    int Underline()         { return underline; }
    XColor *BG()            { return bgColor; }
    XColor *FG()            { return fgColor; }
    int StyleID()           { return style_id; }
    int IndicID()           { return indic_id; }
    int Type()              { return tagType; }
    IndicTypeID IndicType() { return indicType; }
} TagData;

//-------------------------------------
// CLASS TagMgr
//-------------------------------------
class TagMgr {
public:
   TagMgr(SciWidget *);
   ~TagMgr();

   // these support the command interface to the widget
   int  CmdAdd     (int objc, Tcl_Obj *CONST objv[]);
   int  CmdBind    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdCget    (int objc, Tcl_Obj *CONST objv[]);
   int  CmdConfig  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdDelete  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdNames   (int objc, Tcl_Obj *CONST objv[]);
   int  CmdNPRange (int objc, Tcl_Obj *CONST objv[], bool next);
   int  CmdRanges  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdRemove  (int objc, Tcl_Obj *CONST objv[]);
   int  InstanceCmd(int objc, Tcl_Obj *CONST objv[]);

   void      HandleBindEvent(XEvent *eventPtr);
   void      BindEvent(XEvent *eventPtr, int nTags, TagData **tagArrayPtr);
   void      DumpText(int mask, Tcl_DString *dstr, int pos1, int pos2, const char *command);
   void      DumpMargin(int mask, Tcl_DString *dstr, int line1, int pos1, int line2, int pos2, const char *command);
   TagData  *FindTag(const char *tagname);
   TagData  *FindTag(int style_id);
   void      FireSelectionVirtual();
   TagData  *GetMarginTag() { return marginTag; }
   TagData  *GetSelectTag() { return selTag; }
   void      PickCurrent(XEvent *);
   void      SaveRestore(bool save);
   void      UpdateMarginColor(bool bg, bool fg);
   TagData  *ValidateForMargin(const char *tagname);
   bool IsIndicator(TagData *tagPtr) {
       return (tagPtr->IndicType() != indicNONE);
   }
   // return list of all margin tags
   Tcl_Obj *GetMarginTags(Tcl_Interp *interp);

private:
   int       _configIndicator(TagData *, int mask = -1);
   TagData  *_createTag(int ttMask, const char *tagname, int *newTag = NULL);
   void      _deleteTag(const char *tagname);
   void      _deleteTag(TagData *tagPtr, bool force = false);
   TagData **_getTagsAtPos(int pos, int *num);
   bool      _isTagAtPos(TagData *tagPtr, int pos, const char *tagName = NULL);
   int       _nextStyleID(int *, int ttMask);
   int       _nextIndicID(int *);
   void      _setIndicStyle(TagData *, int);

   // for testing purposes
   void _dump  (TagData *tagPtr = NULL);
   void _dumpIt(TagData *tagPtr);

   const char *TAG_SEL;
   bool IS_SEL(const char *tagname) {
      return (strcmp(tagname, TAG_SEL) == 0);
   }
   const char *TAG_MARGIN;
   bool IS_MARGIN(const char *tagname) {
      return (strcmp(tagname, TAG_MARGIN) == 0);
   }

   SciWidget     *sciwidgetPtr;
   Tcl_Interp    *interp;
   Tk_Window      tkwin;

   Tcl_HashTable tagTable;
   TagData      *selTag;      // special built-in tag for selection
   TagData      *marginTag;   // special built-in tag for the margins
   int           freeIndic;   // bit mask of available indicators (max 32)
   std::bitset<255>  freeTextStyles;
   std::bitset<255>  freeMarginStyles;
   int           numTags;     // total number of defined tags

   // info used for event bindings associated with tags
   XEvent pickEvent;           /* The event used to determine "current" character */
   int numCurTags;             /* Number of tags associated with character at
                                * current mark. */
   TagData **curTagArrayPtr;   /* Pointer to array of tags for current mark,
                                * or NULL if none. */
};


////////////////////////////////////////////////////////////////////
// Marker management

// data structure for marker configuration options
typedef struct {
   XColor *bgColor; //(COLOR) bgd color of marker
   XColor *fgColor; //(COLOR) fgd color
   char   *imgName; //(STRING) name of Tk image - only used w/ -image option
   int     type;    //(STRING_TABLE) index of marker type in MarkerTypeNames
   char   *xpmData; //(STRING) char array containing XPM data - only used w/ -xpm option
} MarkerOptions;

//-------------------------------------
// CLASS MarkerData
//-------------------------------------
class MarkerData {
public:
   MarkerData(MarkerMgr *);
   ~MarkerData();

   // these can't be changed by client going thru the 
   // options interface, so we keep them as class data
   //
   char *name;    // name to identify the marker
   int id;        // logical ID identifying bit-mask position
   int handle;    // Scintilla handle created when this marker is assigned
   int typeID;    // Scintilla constant (eg SC_MARK_xxx)
   int margin;    // ID of margin holding this marker
   int cloned_n;  // the count of how many cloned copies there are

   MarkerData *cloned_from; // is cloned, this will be the marker it was cloned from

   // other info
   MarkerMgr     *mgr;
   MarkerOptions *mopts;
   Tk_OptionTable optionTable;

   void UpdateType();
   void Copy(MarkerData *src);
   int CloneCount() { return cloned_n; }
   bool IsClone() { return (cloned_from != NULL); }
   bool MatchName(const char *src_name);
};

//-------------------------------------
// CLASS MarkerMgr
//-------------------------------------
typedef enum {
    cloneCopy,  // 0
    cloneDelete // 1
} CloneOpId;

class MarkerMgr {
public:
   MarkerMgr(SciWidget *);
   ~MarkerMgr();

   // these support the command interface to the widget
   int  CmdConfig  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdDelete  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdExists  (int objc, Tcl_Obj *CONST objv[]);
   int  CmdNames   (int objc, Tcl_Obj *CONST objv[], bool include_clones = false);
   int  InstanceCmd(int objc, Tcl_Obj *CONST objv[]);

   int         AddMarker(int marginID, MarkerData *mPtr, int line);
   MarkerData *FindMarker(const char *);
   MarkerData *FindMarker(int marker_id);
   MarkerData *FindMarker(int marginID, const char *, bool ok_to_clone = true);
   int         GetMaxId();

private:
   MarkerData *_cloneOp(CloneOpId, MarkerData *);
   MarkerData *_cloneMarker(const char *, MarkerData *);
   MarkerData *_createMarker(const char *, int *);
   void        _deleteMarker(MarkerData *);
   void        _deleteMarkerImpl(MarkerData *);
   int         _getNextId();
   int         _validateImage(MarkerData *, bool check_xpm);

   // for testing purposes
   void _dump  (MarkerData *mPtr = NULL);
   void _dumpIt(MarkerData *mPtr);

   Tcl_HashTable  markerTable;
   int            ids;

public:
   // for easy access by MarkerData
   SciWidget     *sciwidgetPtr;
   Tcl_Interp    *interp;
   Tk_Window      tkwin;
};


////////////////////////////////////////////////////////////////////
// Mark management (this is the same as Tk Text widget "marks")

typedef struct {
    const char *name;
    int         pos;
    bool        gravityLeft; // TRUE = left, FALSE = right
} MarkData;

//-------------------------------------
// CLASS MarkMgr
//-------------------------------------
class MarkMgr {
public:
    MarkMgr(SciWidget *);
    ~MarkMgr();

    // these support the command interface to the widget
    int  CmdGravity (int objc, Tcl_Obj *CONST objv[]); 
    int  CmdSet     (int objc, Tcl_Obj *CONST objv[]); 
    int  InstanceCmd(int objc, Tcl_Obj *CONST objv[]);

    MarkData *AddMark(const char *name, int pos);
    MarkData *FindMark(const char *, int *offset = NULL);
    int       GetCurrentPos() { return currentMark->pos; }
    // dump marks in selected margin from line1 to line2
    void      Dump(Tcl_DString *dstr, int margin_id, int line1, int line2, const char *command);

private:
    MarkData *_createMark(const char *name, int *newMark = NULL);
    void      _deleteMark(MarkData *);

    // for testing purposes
    void _dump(MarkData *mPtr = NULL);

    SciWidget     *sciwidgetPtr;
    MarkData      *insertMark;  // special built-in mark
    MarkData      *currentMark; // special built-in mark
    Tcl_HashTable  markTable;
    Tcl_Interp    *interp;
    Tk_Window      tkwin;
};

} // end of "using namespace TkSci"
#endif

Added tk/scintilla-ext.cxx.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
// scintilla-ext.cxx - This file provides access to the widget services required by
//                  code outside(aka "EXTernal") of the widget implementation
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#include "scintilla-ext.h"
#include "scintilla-cmd.h"

using namespace TkSci;

namespace TkSciExt {

//==================================================
// Return the current width of the visible margins
//==================================================
int GetMarginWidth(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;
   return sciw->marginMgr->Width();
}

//==================================================
// Store the main pixmap that we get from the
// platform code
//==================================================
void SetPixmap(ClientData d, Pixmap p) {

   SciWidget *sciw = (SciWidget *)d;
   sciw->mainPixmap = p;
}

//==================================================
// Add the specified Y delta to the current value
// being maintained in the widget
//==================================================
void SetYScrollDelta(ClientData d, int delta) {

   SciWidget *sciw = (SciWidget *)d;
   sciw->yscrollDelta += delta;
}

//==================================================
// Schedule an update to redraw following a
// scroll change initiated by the user
//==================================================
void UpdateForScroll(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;

   if ( !(sciw->flags & REDRAW_PENDING) ) {
//printf("ScrollText -- QUEUING DISPLAY\n");
     Tk_DoWhenIdle(SciWidgetDisplay, d);

   } else {
//printf("ScrollText -- SKIPPING REDRAW...\n");
   }
   sciw->flags |= REDRAW_PENDING|REDRAW_YSCROLL;
}

//==================================================
// Callback from Scintilla that lines were added.
// Note, if the "added" value is <0 it means that
// lines were removed instead of added.
//==================================================
void MSG_LinesAdded(ClientData d, int line, int added) {

   SciWidget *sciw = (SciWidget *)d;

   sciw->added_data->line  = LINE2TK(line);
   sciw->added_data->added = added;

   MessageFromScintilla(sciw, SCIW_LINESADDED_UPDATE);
}

//==================================================
// Callback from Scintilla to change mouse cursor
//==================================================
void MSG_SetCursor(ClientData d, int cursor_id) {

   SciWidget *sciw = (SciWidget *)d;

   //TODO: this needs a better way to indicate what
   //cursor is being request
   MessageFromScintilla(sciw, static_cast<int>(cursor_id));
}

//==================================================
// Callback from Scintilla that we use to notify
// client so it can respond to a change
// to the current document contents.
//==================================================
void MSG_Modified(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;

   MessageFromScintilla(sciw, SCIW_MODIFIED);
}

//==================================================
// Callback from Scintilla that we use to notify
// client so it can respond to a possible change
// to the current document position.
//==================================================
void MSG_MoveUpdate(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;

   MessageFromScintilla(sciw, SCIW_MOVE_UPDATE);
}

//==================================================
// Sync the widget's scroll position data based on
// a programmatic change from Scintilla
//==================================================
void MSG_SyncXScroll(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;
   MessageFromScintilla(sciw, SCIW_SYNC_XSCROLL);
}
void MSG_SyncYScroll(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;
   MessageFromScintilla(sciw, SCIW_SYNC_YSCROLL);
}

}//--- end of TkSciExt namespace

Added tk/scintilla-ext.h.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Scintilla source code edit control
// scintilla-ext.cxx - This file provides access to the widget services required by
//                     code outside(aka "EXTernal") of the widget implementation
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#ifndef _SCINTILLA_EXT
#define _SCINTILLA_EXT

#include <tcl.h>
#include <tk.h>
#include "Scintilla.h"

// the following constant is used to allow the widget code to preserve
// point sizes set by Tk which use a negative value(to indicate pixels)
#define MAGIC_FONT_OFFSET 1000

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// create out namespace
namespace TkSciExt {

int  GetMarginWidth (ClientData d);
void SetPixmap      (ClientData d, Pixmap p);
void SetYScrollDelta(ClientData d, int delta);
void UpdateForScroll(ClientData d);

void MSG_SetCursor  (ClientData d, int cursor_id);
void MSG_LinesAdded (ClientData d, int line, int added);
void MSG_Modified (ClientData d);
void MSG_MoveUpdate (ClientData d);
void MSG_SyncXScroll(ClientData d);
void MSG_SyncYScroll(ClientData d);

}//--- end of TkSciExt namespace
#endif

Added tk/scintillatk.tcl.





















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# ScintillaTK class bindings

option add *Scintilla.textbackground white

# We won't assume clients want a default selection action when a multi-click
# event occurs in the margin area - we'll leave that up to the client
bind Scintilla <Double-1> {
    if {[%W margin index @%x,%y] == ""} {
        set tk::Priv(selectMode) word
        tk::TextSelectTo %W %x %y
        catch {%W mark set insert sel.first}
    }
}
bind Scintilla <Triple-1> {
    if {[%W margin index @%x,%y] == ""} {
        set tk::Priv(selectMode) line
        tk::TextSelectTo %W %x %y
        catch {%W mark set insert sel.first}
    }
}

# Mimic some of the button bindings from Tk Text widget
set btns {
    1
    B1-Motion
    B1-Enter
    B1-Leave
    ButtonRelease-1
}
foreach e $btns {
    bind Scintilla <$e> [bind Text <$e>]
}

#OVERLOAD: we have to overload this one because of the -state value check where
# the Tk code looks for "== normal". Since our Scintilla widget implementation
# allows a state value of "readonly" and we still want to be able to receive
# focus upon a click, we change the check to "!= disabled".
proc ::tk::TextButton1 {w x y} {
    variable ::tk::Priv

    set Priv(selectMode) char
    set Priv(mouseMoved) 0
    set Priv(pressX) $x
    set anchorname [tk::TextAnchor $w]
    $w mark set insert [TextClosestGap $w $x $y]
    $w mark set $anchorname insert
    # Set the anchor mark's gravity depending on the click position
    # relative to the gap
    set bbox [$w bbox [$w index $anchorname]]
    if {$x > [lindex $bbox 0]} {
        $w mark gravity $anchorname right
    } else {
        $w mark gravity $anchorname left
    }
    # Allow focus in any case on Windows, because that will let the
    # selection be displayed even for state disabled text widgets.
    if {$::tcl_platform(platform) eq "windows" \
            || [$w cget -state] ne "disabled"} {
        focus $w
    }
}


# Note: this is an overload of the function called by the Text class
# binding for B1-Leave. We're using the pre-8.5 implementation because
# beginning in 8.5 the scrolling was pixel-based, which isn't supported
# in Scintilla.
proc ::tk::TextAutoScan {w} {
    variable ::tk::Priv
    if {![winfo exists $w]} return
    if {$Priv(y) >= [winfo height $w]} {
        $w yview scroll 2 units
    } elseif {$Priv(y) < 0} {
        $w yview scroll -2 units
    } elseif {$Priv(x) >= [winfo width $w]} {
        $w xview scroll 2 units
    } elseif {$Priv(x) < 0} {
        $w xview scroll -2 units
    } else {
        return
    }
    TextSelectTo $w $Priv(x) $Priv(y)
    set Priv(afterId) [after 50 [list tk::TextAutoScan $w]]
}

#OVERLOAD: see below
proc ::tk::TextKeySelect {w new} {

    set anchorname [tk::TextAnchor $w]
    if {[$w tag nextrange sel 1.0 end] eq ""} {
        set insert_ix [$w index insert]
        if {[$w compare $new < insert]} {
            $w tag add sel $new insert
        } else {
            $w tag add sel insert $new
        }
        #----------------------------------------------------------------------
        # This differs from the code in text.tcl because of a fundamental
        # difference between Scintilla selection behavior and Tk Text.
        # The latter allows independent positioning of the insert location
        # relative to the selection; whereas Scintilla requires it to be
        # one of the extents of the selection region. So the problem we face,
        # which is the reason for this overload, is the above call to add
        # the selection: "tag add sel insert $new" will actually cause a change
        # in the location of the insertion point with Scintilla. Since the
        # intent of the next command is to move the anchor to where the insert
        # point was at the start of this function, we get that location first
        # and then reuse it via "$insert_ix"
        #----------------------------------------------------------------------
        $w mark set $anchorname $insert_ix
    } else {
        if {[$w compare $new < $anchorname]} {
            set first $new
            set last $anchorname
        } else {
            set first $anchorname
            set last $new
        }
        $w tag remove sel 1.0 $first
        $w tag add sel $first $last
        $w tag remove sel $last end
    }
    $w mark set insert $new
    $w see insert
    update idletasks
}




# define the class key bindings
bind Scintilla <Left>         { %W mark set insert "charleft" }
bind Scintilla <Right>        { %W mark set insert "charright" }
bind Scintilla <Up>           { %W mark set insert "lineup" }
bind Scintilla <Down>         { %W mark set insert "linedown" }
bind Scintilla <Home>         { %W mark set insert "linehome" }
bind Scintilla <End>          { %W mark set insert "lineend" }
bind Scintilla <Control-Home> { %W mark set insert "top" }
bind Scintilla <Control-End>  { %W mark set insert "bottom" }

# Mimic some of the key bindings from Tk Text widget
set keys {
    Shift-Left
    Shift-Right
    Shift-Up
    Shift-Down
    Shift-Home
    Shift-End
}    
foreach e $keys {
    bind Scintilla <$e> [bind Text <$e>]
}


bind Scintilla <Next> {
   %W yview scroll 1 pages
}
bind Scintilla <Prior> {
   %W yview scroll -1 pages
}

bind Scintilla <Return> {
   ::tk::ScintillaInsert %W \n
}

bind Scintilla <Delete> {
    if {[%W tag nextrange sel 1.0 end] ne ""} {
       %W delete sel.first sel.last
    } else {
       %W delete insert
       %W see insert
    }
}

bind Scintilla <BackSpace> {
    if {[%W tag nextrange sel 1.0 end] ne ""} {
       %W delete sel.first sel.last
    } elseif {[%W compare insert != 1.0]} {
       %W delete insert-1c
       %W see insert
    }
}

bind Scintilla <Control-KP_Add>      {%W zoomin}
bind Scintilla <Control-KP_Subtract> {%W zoomout}
if { [tk windowingsystem] eq "win32" } {
bind Scintilla <Control-Key-plus>    {%W zoomin}
bind Scintilla <Control-Key-minus>   {%W zoomout}
}

# This next group of bindings mimics what is used for the Tk Text widget.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for <Escape>.
bind Scintilla <Alt-KeyPress>     {# nothing }
bind Scintilla <Meta-KeyPress>    {# nothing}
bind Scintilla <Control-KeyPress> {# nothing}
bind Scintilla <Escape>           {# nothing}
bind Scintilla <KP_Enter>         {# nothing}

bind Scintilla <KeyPress> {
   ::tk::ScintillaInsert %W %A
}

# MOUSE WHEEL
bind Scintilla <Button-4> {
   %W yview scroll -5 units
}
bind Scintilla <Button-5> {
   %W yview scroll 5 units
}
if { [tk windowingsystem] eq "win32" } {
   # NOTE: match Tk 8.4 behavior, since 8.5 uses pixel-level scrolling
   bind Scintilla <MouseWheel> {
      %W yview scroll [expr {- (%D / 120) * 4}] units
   }
}

#############################################################################
# define the functions tied to the bindings
proc ::tk::ScintillaInsert {w s} {
   # prevent insert if state is disabled or readonly
   if {$s eq "" || [$w cget -state] ne "normal"} {
      return
   }
#puts "INSERT $w --> (($s))"
    if {[$w tag nextrange sel 1.0 end] ne ""} {
       $w delete sel.first sel.last
    }
   $w insert insert $s
   $w see insert
}

Added tk/sciwrappers.cxx.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
// Scintilla source code edit control
// sciwrappers.cxx - Wrapper functions around Scintilla msg api.
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#include <string.h>

#include "sciwrappers.h"

#define _UNUSED_ 0

// macro to simplify calling scintilla message API
#define SSM(sci, m, w, l) scintilla_send_message(sci, m, w, l)

// macro to convert an XColor value for scintilla
#define _XRGB_(c) (c->red & 0xff) | (c->green & 0xff)<<8 | (c->blue & 0xff)<<16


sptr_t sci_cmd(ScintillaObject *sci, int msg, uptr_t wparam, sptr_t lparam)
{
   return SSM(sci, msg, wparam, lparam);
}


//#############################################################################
// ACTIONs
//#############################################################################

//=============================================================================
// sci_add_text
//
// Add new text at the specified document position
//-----------------------------------------------------------------------------
void sci_add_text(ScintillaObject *sci, int pos, const char *s)
{
    // check if the add is being done at the insertion point, and if it
    // is then we want the add to cause the insertion point to be moved
    // to the end of the added text.
    int currpos = sci_get_current_pos(sci);
    //fprintf(stderr,"add: currpos %d pos %d\n", currpos, pos);

    // inserting text clears the current selection, remember what the selection was
    int sel_beg = sci_cmd(sci, SCI_GETSELECTIONSTART, _UNUSED_, _UNUSED_);
    int sel_end = sci_cmd(sci, SCI_GETSELECTIONEND,   _UNUSED_, _UNUSED_);
    if (pos == currpos) {
        SSM(sci, SCI_ADDTEXT, strlen(s), (sptr_t)s); // moves insert pt after the add
    } else {
        SSM(sci, SCI_INSERTTEXT, pos, (sptr_t)s);
    }
    if (sel_beg != sel_end) {
        // restore selection if one existed before insert
        int len = strlen(s);
        if (pos < sel_beg) {
            // text inserted before selection
            // adjust selection offsets so they remain on same text
            sel_beg += len;
            sel_end += len;
        } else if ((pos >= sel_beg) && (pos <= sel_end)) {
            // text inserted within selection
            // "grow" selection by the added text
            sel_end += len;
        }
        sci_cmd(sci, SCI_SETSELECTIONSTART, sel_beg, _UNUSED_);
        sci_cmd(sci, SCI_SETSELECTIONEND,   sel_end, _UNUSED_);
    }
 }

//=============================================================================
// sci_delete_text
//
// Deletes text between two positions
//-----------------------------------------------------------------------------
void sci_delete_text(ScintillaObject *sci, int pos1, int pos2)
{
   if (pos1 == pos2) return;
   if (pos1 > pos2) {
      int tmp = pos2;
      pos2 = pos1;
      pos1 = tmp;
   }
   SSM(sci, SCI_SETTARGETSTART, pos1, 0);
   SSM(sci, SCI_SETTARGETEND,   pos2, 0);
   SSM(sci, SCI_REPLACETARGET, 0, (sptr_t)"");
}

//=============================================================================
// sci_enable_margin_click
//
// Set a margin to receive (or disable) click notifications
//-----------------------------------------------------------------------------
void sci_enable_margin_click(ScintillaObject *sci, int m, bool enable)
{
   SSM(sci, SCI_SETMARGINSENSITIVEN, m, (sptr_t)enable);
}

//=============================================================================
// sci_goto_pos
//
// Change current position and scroll(if needed) to see it
//-----------------------------------------------------------------------------
void sci_goto_pos(ScintillaObject *sci, int pos)
{
    int sel_beg = sci_cmd(sci, SCI_GETSELECTIONSTART, _UNUSED_, _UNUSED_);
    int sel_end = sci_cmd(sci, SCI_GETSELECTIONEND,   _UNUSED_, _UNUSED_);
    int end = sci_get_length(sci);

    if (pos && pos == end) pos--;

    //fprintf(stderr,"sci_goto_pos %d\n", pos);
    SSM(sci, SCI_GOTOPOS, pos, 0); // this will clear the selection!!!

    if (sel_beg != sel_end) {
        // restore selection
        SSM(sci, SCI_SETSELECTIONSTART, sel_beg, _UNUSED_);
        SSM(sci, SCI_SETSELECTIONEND,   sel_end, _UNUSED_);
    }
}

//=============================================================================
// sci_has_selection
//
// Return whether any text is selected
//-----------------------------------------------------------------------------
bool sci_has_selection(ScintillaObject *sci)
{
    int pos1 = SSM(sci, SCI_GETSELECTIONSTART, 0, 0);
    int pos2 = SSM(sci, SCI_GETSELECTIONEND, 0, 0);
    return (pos1 != pos2);
}

//=============================================================================
// sci_redo
//-----------------------------------------------------------------------------
void sci_redo(ScintillaObject *sci)
{
   SSM(sci, SCI_REDO, 0, 0);
}

//=============================================================================
// sci_reset_undo_history
//
// Clears the undo/redo history buffers
//-----------------------------------------------------------------------------
void sci_reset_undo_history(ScintillaObject *sci)
{
   SSM(sci, SCI_EMPTYUNDOBUFFER, 0, 0);
}

//=============================================================================
// sci_select
//
// Selects a range of text. If additive is TRUE then a "alternate"
// selection is created (preserving the "main" selection)
//-----------------------------------------------------------------------------
void sci_select(ScintillaObject *sci, int pos1, int pos2, bool additive)
{
   int end = sci_get_length(sci);
   if ((pos2 == end) && (pos2 > 0)) {
      int lastChar =  SSM(sci, SCI_GETCHARAT, pos2-1, 0);
      // don't include final end of line at end of document
      if (lastChar == '\n')
         --pos2;
   }
   if (additive) {
      // Need special handling to do additive tagging for the selection
      // tag since Scintilla will by default remove an existing selection
      // before setting a new one.
      SSM(sci, SCI_ADDSELECTION, pos1, pos2);
   } else {
      SSM(sci, SCI_SETANCHOR,     pos1, 0);
      SSM(sci, SCI_SETCURRENTPOS, pos2, 0);
   }
}


//=============================================================================
// sci_show_ws
//
// Control display of whitespace indicators
//-----------------------------------------------------------------------------
void sci_show_ws(ScintillaObject *sci, bool show)
{
   if (show)
      SSM(sci, SCI_SETVIEWWS, SCWS_VISIBLEALWAYS, 0);
   else
      SSM(sci, SCI_SETVIEWWS, SCWS_INVISIBLE, 0);
}

//=============================================================================
// sci_toggle_fold
//
// Toggle the fold level for the specfied line
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
void sci_toggle_fold(ScintillaObject *sci, int line)
{
   SSM(sci, SCI_TOGGLEFOLD, line, 0);
}

//=============================================================================
// sci_undo
//-----------------------------------------------------------------------------
void sci_undo(ScintillaObject *sci)
{
   SSM(sci, SCI_UNDO, 0, 0);
}

//=============================================================================
// sci_zoom_in/sci_zoom_out
//
// Causes the document font size to be increased/decreased by a set amount
//-----------------------------------------------------------------------------
void sci_zoom_in(ScintillaObject *sci)
{
   SSM(sci, SCI_ZOOMIN, 0, 0);
}
void sci_zoom_out(ScintillaObject *sci)
{
   SSM(sci, SCI_ZOOMOUT, 0, 0);
}

//#############################################################################
// GETs
//#############################################################################

//=============================================================================
// sci_get_column
//
// Return the column position from a document position
//-----------------------------------------------------------------------------
int sci_get_column(ScintillaObject *sci, int pos)
{
   int end = sci_get_length(sci);
   if (end && pos == end) pos--;
   return SSM(sci, SCI_GETCOLUMN, pos, 0);
}

//=============================================================================
// sci_get_current_pos
//
// Returns the current document position(ie where insertion point is)
//-----------------------------------------------------------------------------
int sci_get_current_pos(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETCURRENTPOS, 0, 0);
}

//=============================================================================
// sci_get_foldlevel
//
// Return the fold level for the specified line number
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
int sci_get_foldlevel(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_GETFOLDLEVEL, line, 0);
}

//=============================================================================
// sci_get_is_modified
//
// Return if the document is currently modified(1) or not(0)
//-----------------------------------------------------------------------------
int sci_get_is_modified(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETMODIFY, 0, 0);
}

//=============================================================================
// sci_get_length
//
// Return the number of characters in the document
//-----------------------------------------------------------------------------
int sci_get_length(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETLENGTH, 0, 0);
}

//=============================================================================
// sci_get_line
//
// Return line number for a document position
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
int sci_get_line(ScintillaObject *sci, int pos)
{
   return SSM(sci, SCI_LINEFROMPOSITION, pos, 0);
}

//=============================================================================
// sci_get_line_count
//
// Return the number of lines in the document
//-----------------------------------------------------------------------------
int sci_get_line_count(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETLINECOUNT, 0, 0);
}

//=============================================================================
// sci_get_line_length
//
// Return length(in characters) of a line
//-----------------------------------------------------------------------------
int sci_get_line_length(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_LINELENGTH, line, 0);
}

//=============================================================================
// sci_get_line_markers
//
// Return mask indicating which markers exist on the specified line
//-----------------------------------------------------------------------------
int sci_get_line_markers(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_MARKERGET, line, 0);
}

//=============================================================================
// sci_get_lineend_pos
//
// Return the document position for a line
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
int sci_get_lineend_pos(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_GETLINEENDPOSITION, line, 0);
}

//=============================================================================
// sci_get_margin_mask
//
// Return the margin mask for a specific margin
//-----------------------------------------------------------------------------
int sci_get_margin_mask(ScintillaObject *sci, int m)
{
   return SSM(sci, SCI_GETMARGINMASKN, m, 0);
}

//=============================================================================
// sci_get_margin_width
//
// Get the width(in pixels) of the specified margin
//-----------------------------------------------------------------------------
int sci_get_margin_width(ScintillaObject *sci, int m)
{
   return SSM(sci, SCI_GETMARGINWIDTHN, m, 0);
}

//=============================================================================
// sci_get_pos
//
// Return document position for specified line number
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
int sci_get_pos(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_POSITIONFROMLINE, line, 0);
}

//=============================================================================
// sci_get_pos_from_xy
//
// Return document position for specified X/Y screen position
// If "close" is true, then will only match if X/Y is actually determined
// to be "close enough" to a character.
//-----------------------------------------------------------------------------
int sci_get_pos_from_xy(ScintillaObject *sci, int x, int y, bool close)
{
    if (close)
        return SSM(sci, SCI_POSITIONFROMPOINTCLOSE, x, y);

    return SSM(sci, SCI_POSITIONFROMPOINT, x, y);
}

//=============================================================================
// sci_get_text_height
//
// Return the height(in pixels) of the specified line
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
int sci_get_text_height(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_TEXTHEIGHT, line, 0);
}

//=============================================================================
// sci_get_text_width
//
// Return the text width, using current default style, of an arbitrary string
//-----------------------------------------------------------------------------
int sci_get_text_width(ScintillaObject *sci, const char *str)
{
   return (int)SSM(sci, SCI_TEXTWIDTH, STYLE_DEFAULT, (sptr_t)str);
}

//=============================================================================
// sci_get_x_from_pos
//
// Return the screen X location corresponding to a document position
//-----------------------------------------------------------------------------
int sci_get_x_from_pos(ScintillaObject *sci, int pos)
{
    return SSM(sci, SCI_POINTXFROMPOSITION, 0/*unused*/, pos);
}

//=============================================================================
// sci_get_y_from_pos
//
// Return the screen Y location corresponding to a document position
//-----------------------------------------------------------------------------
int sci_get_y_from_pos(ScintillaObject *sci, int pos)
{
    return SSM(sci, SCI_POINTYFROMPOSITION, 0/*unused*/, pos);
}

//=============================================================================
// sci_get_zoom
//
// Return the current zoom level
//-----------------------------------------------------------------------------
int sci_get_zoom(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETZOOM, 0, 0);
}

//#############################################################################
// SETs
//#############################################################################

//=============================================================================
// sci_set_focus
//-----------------------------------------------------------------------------
void sci_set_focus(ScintillaObject *sci, bool turn_on)
{
   SSM(sci, SCI_SETFOCUS, turn_on, 0);
}

//=============================================================================
// sci_set_fold_flags
//
// The "flags" arg represents a bit-mask of various folding options
//-----------------------------------------------------------------------------
void sci_set_fold_flags(ScintillaObject *sci, int flags)
{
   SSM(sci, SCI_SETFOLDFLAGS, flags, 0);
}

//=============================================================================
// sci_set_font
//
// Propagate a font change to all known styles
//-----------------------------------------------------------------------------
void sci_set_font(ScintillaObject *sci, const char *family, int ptsize, bool bold, bool italic)
{
   for (int i=0; i < STYLE_MAX; i++) {
      SSM(sci, SCI_STYLESETFONT,   i, (sptr_t)family);
      SSM(sci, SCI_STYLESETSIZE,   i, ptsize);
      SSM(sci, SCI_STYLESETBOLD,   i, bold);
      SSM(sci, SCI_STYLESETITALIC, i, italic);
   }
}

//=============================================================================
// sci_set_margin_mask
//
// Set the mask of which markers a margin is allowed to display
//-----------------------------------------------------------------------------
void sci_set_margin_mask(ScintillaObject *sci, int m, int mask)
{
   SSM(sci, SCI_SETMARGINMASKN, m, mask);
}

//=============================================================================
// sci_set_margin_width
//
// Set the width(in pixels) of the specified margin. A value of zero
// will hide the margin.
//-----------------------------------------------------------------------------
void sci_set_margin_width(ScintillaObject *sci, int m, int width)
{
   SSM(sci, SCI_SETMARGINWIDTHN, m, width);
}

//=============================================================================
// sci_set_margin_type
//
// Set the type of a margin
//-----------------------------------------------------------------------------
void sci_set_margin_type(ScintillaObject *sci, int m, int type)
{
   SSM(sci, SCI_SETMARGINTYPEN, m, type);
}

//=============================================================================
// sci_set_padding
//
// Define how many pixels of padding exist between the left and right
// edges of the text (the default Scintilla uses is 1).
//-----------------------------------------------------------------------------
void sci_set_padding(ScintillaObject *sci, int left, int right)
{
   if (right < 0)
      right = left;
   SSM(sci, SCI_SETMARGINLEFT,  0/*unused*/, left);
   SSM(sci, SCI_SETMARGINRIGHT, 0/*unused*/, right);
}

//=============================================================================
// sci_set_readonly
//-----------------------------------------------------------------------------
void sci_set_readonly(ScintillaObject *sci, bool ro)
{
   SSM(sci, SCI_SETREADONLY, ro, 0);
}

//=============================================================================
// sci_set_style_bg
//
// Sets the background color for the specified style
//-----------------------------------------------------------------------------
void sci_set_style_bg(ScintillaObject *sci, int id, XColor *c)
{
   SSM(sci, SCI_STYLESETBACK, id, (c ? _XRGB_(c) : 0));
}

//=============================================================================
// sci_set_style_fg
//
// Sets the foreground color for the specified style
//-----------------------------------------------------------------------------
void sci_set_style_fg(ScintillaObject *sci, int id, XColor *c)
{
   SSM(sci, SCI_STYLESETFORE, id, (c ? _XRGB_(c) : 0));
}

//=============================================================================
// sci_set_tab_width
//-----------------------------------------------------------------------------
void sci_set_tab_width(ScintillaObject *sci, int width)
{
   SSM(sci, SCI_SETTABWIDTH, width, 0);
}

Added tk/sciwrappers.h.

















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Provide wrapper APIs for calling the scintilla
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

#ifndef SCIWRAPPERS_H
#define SCIWRAPPERS_H

#include "Scintilla.h"
#include "ScintillaWidget.h"

#ifdef __cplusplus
extern "C" {
#endif

// Short-hand command API
sptr_t sci_cmd(ScintillaObject *sci, int msg, uptr_t wparam = 0, sptr_t lparam = 0);
   

// ACTIONs
void sci_add_text           (ScintillaObject *sci, int pos, const char *s);
void sci_delete_text        (ScintillaObject *sci, int pos1, int pos2);
void sci_enable_margin_click(ScintillaObject *sci, int m, bool enable);
void sci_goto_pos           (ScintillaObject *sci, int pos);
bool sci_has_selection      (ScintillaObject *sci);
void sci_redo               (ScintillaObject *sci);
void sci_reset_undo_history (ScintillaObject *sci);
void sci_select             (ScintillaObject *sci, int pos1, int pos2, bool additive=false);
void sci_show_ws            (ScintillaObject *sci, bool show);
void sci_toggle_fold        (ScintillaObject *sci, int line);
void sci_undo               (ScintillaObject *sci);
void sci_zoom_in            (ScintillaObject *sci);
void sci_zoom_out           (ScintillaObject *sci);

// GETs
int  sci_get_column         (ScintillaObject *sci, int pos);
int  sci_get_current_pos    (ScintillaObject *sci);
int  sci_get_foldlevel      (ScintillaObject *sci, int line);
int  sci_get_is_modified    (ScintillaObject *sci);
int  sci_get_length         (ScintillaObject *sci);
int  sci_get_line           (ScintillaObject *sci, int pos);
int  sci_get_line_count     (ScintillaObject *sci);
int  sci_get_line_length    (ScintillaObject *sci, int line);
int  sci_get_line_markers   (ScintillaObject *sci, int line);
int  sci_get_lineend_pos    (ScintillaObject *sci, int line);
int  sci_get_margin_mask    (ScintillaObject *sci, int m);
int  sci_get_margin_width   (ScintillaObject *sci, int m);
int  sci_get_pos            (ScintillaObject *sci, int line);
int  sci_get_pos_from_xy    (ScintillaObject *sci, int x, int y, bool close = false);
int  sci_get_text_height    (ScintillaObject *sci, int line);
int  sci_get_text_width     (ScintillaObject *sci, const char *str);
int  sci_get_x_from_pos     (ScintillaObject *sci, int pos);
int  sci_get_y_from_pos     (ScintillaObject *sci, int pos);
int  sci_get_zoom           (ScintillaObject *sci);

// SETs
void sci_set_focus          (ScintillaObject *sci, bool turn_on);
void sci_set_fold_flags     (ScintillaObject *sci, int flags);
void sci_set_font           (ScintillaObject *sci, const char *family, int ptsize, bool bold, bool italic);
void sci_set_margin_mask    (ScintillaObject *sci, int m, int mask);
void sci_set_margin_width   (ScintillaObject *sci, int m, int width);
void sci_set_margin_type    (ScintillaObject *sci, int m, int type);
void sci_set_padding        (ScintillaObject *sci, int left, int right = -1);
void sci_set_readonly       (ScintillaObject *sci, bool ro);
void sci_set_style_bg       (ScintillaObject *sci, int id, XColor *c);
void sci_set_style_fg       (ScintillaObject *sci, int id, XColor *c);
void sci_set_tab_width      (ScintillaObject *sci, int width);

#ifdef __cplusplus
}
#endif

#endif

Added tk/tclconfig/install-sh.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2011-04-20.01; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.

nl='
'
IFS=" ""	$nl"

# set DOITPROG to echo to test this script

# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
  doit_exec=exec
else
  doit_exec=$doit
fi

# Put in absolute file names if you don't have them in your path;
# or use environment vars.

chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}

posix_glob='?'
initialize_posix_glob='
  test "$posix_glob" != "?" || {
    if (set -f) 2>/dev/null; then
      posix_glob=
    else
      posix_glob=:
    fi
  }
'

posix_mkdir=

# Desired mode of installed file.
mode=0755

chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

src=
dst=
dir_arg=
dst_arg=

copy_on_change=false
no_target_directory=

usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
   or: $0 [OPTION]... SRCFILES... DIRECTORY
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
   or: $0 [OPTION]... -d DIRECTORIES...

In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.

Options:
     --help     display this help and exit.
     --version  display version info and exit.

  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -s            $stripprog installed files.
  -S            $stripprog installed files.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;

    -d) dir_arg=true;;

    -g) chgrpcmd="$chgrpprog $2"
	shift;;

    --help) echo "$usage"; exit $?;;

    -m) mode=$2
	case $mode in
	  *' '* | *'	'* | *'
'*	  | *'*'* | *'?'* | *'['*)
	    echo "$0: invalid mode: $mode" >&2
	    exit 1;;
	esac
	shift;;

    -o) chowncmd="$chownprog $2"
	shift;;

    -s) stripcmd=$stripprog;;

    -S) stripcmd="$stripprog $2"
	shift;;

    -t) dst_arg=$2
	shift;;

    -T) no_target_directory=true;;

    --version) echo "$0 $scriptversion"; exit $?;;

    --)	shift
	break;;

    -*)	echo "$0: invalid option: $1" >&2
	exit 1;;

    *)  break;;
  esac
  shift
done

if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  # When -d is used, all remaining arguments are directories to create.
  # When -t is used, the destination is already specified.
  # Otherwise, the last argument is the destination.  Remove it from $@.
  for arg
  do
    if test -n "$dst_arg"; then
      # $@ is not empty: it contains at least $arg.
      set fnord "$@" "$dst_arg"
      shift # fnord
    fi
    shift # arg
    dst_arg=$arg
  done
fi

if test $# -eq 0; then
  if test -z "$dir_arg"; then
    echo "$0: no input file specified." >&2
    exit 1
  fi
  # It's OK to call `install-sh -d' without argument.
  # This can happen when creating conditional directories.
  exit 0
fi

if test -z "$dir_arg"; then
  do_exit='(exit $ret); exit $ret'
  trap "ret=129; $do_exit" 1
  trap "ret=130; $do_exit" 2
  trap "ret=141; $do_exit" 13
  trap "ret=143; $do_exit" 15

  # Set umask so as not to create temps with too-generous modes.
  # However, 'strip' requires both read and write access to temps.
  case $mode in
    # Optimize common cases.
    *644) cp_umask=133;;
    *755) cp_umask=22;;

    *[0-7])
      if test -z "$stripcmd"; then
	u_plus_rw=
      else
	u_plus_rw='% 200'
      fi
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
    *)
      if test -z "$stripcmd"; then
	u_plus_rw=
      else
	u_plus_rw=,u+rw
      fi
      cp_umask=$mode$u_plus_rw;;
  esac
fi

for src
do
  # Protect names starting with `-'.
  case $src in
    -*) src=./$src;;
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
  else

    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
    # might cause directories to be created, which would be especially bad
    # if $src (and thus $dsttmp) contains '*'.
    if test ! -f "$src" && test ! -d "$src"; then
      echo "$0: $src does not exist." >&2
      exit 1
    fi

    if test -z "$dst_arg"; then
      echo "$0: no destination specified." >&2
      exit 1
    fi

    dst=$dst_arg
    # Protect names starting with `-'.
    case $dst in
      -*) dst=./$dst;;
    esac

    # If destination is a directory, append the input filename; won't work
    # if double slashes aren't ignored.
    if test -d "$dst"; then
      if test -n "$no_target_directory"; then
	echo "$0: $dst_arg: Is a directory" >&2
	exit 1
      fi
      dstdir=$dst
      dst=$dstdir/`basename "$src"`
      dstdir_status=0
    else
      # Prefer dirname, but fall back on a substitute if dirname fails.
      dstdir=`
	(dirname "$dst") 2>/dev/null ||
	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	     X"$dst" : 'X\(//\)[^/]' \| \
	     X"$dst" : 'X\(//\)$' \| \
	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
	echo X"$dst" |
	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)[^/].*/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\).*/{
		   s//\1/
		   q
		 }
		 s/.*/./; q'
      `

      test -d "$dstdir"
      dstdir_status=$?
    fi
  fi

  obsolete_mkdir_used=false

  if test $dstdir_status != 0; then
    case $posix_mkdir in
      '')
	# Create intermediate dirs using mode 755 as modified by the umask.
	# This is like FreeBSD 'install' as of 1997-10-28.
	umask=`umask`
	case $stripcmd.$umask in
	  # Optimize common cases.
	  *[2367][2367]) mkdir_umask=$umask;;
	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;

	  *[0-7])
	    mkdir_umask=`expr $umask + 22 \
	      - $umask % 100 % 40 + $umask % 20 \
	      - $umask % 10 % 4 + $umask % 2
	    `;;
	  *) mkdir_umask=$umask,go-w;;
	esac

	# With -d, create the new directory with the user-specified mode.
	# Otherwise, rely on $mkdir_umask.
	if test -n "$dir_arg"; then
	  mkdir_mode=-m$mode
	else
	  mkdir_mode=
	fi

	posix_mkdir=false
	case $umask in
	  *[123567][0-7][0-7])
	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
	    ;;
	  *)
	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0

	    if (umask $mkdir_umask &&
		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
	    then
	      if test -z "$dir_arg" || {
		   # Check for POSIX incompatibilities with -m.
		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
		   # other-writeable bit of parent directory when it shouldn't.
		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
		   case $ls_ld_tmpdir in
		     d????-?r-*) different_mode=700;;
		     d????-?--*) different_mode=755;;
		     *) false;;
		   esac &&
		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
		   }
		 }
	      then posix_mkdir=:
	      fi
	      rmdir "$tmpdir/d" "$tmpdir"
	    else
	      # Remove any dirs left behind by ancient mkdir implementations.
	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
	    fi
	    trap '' 0;;
	esac;;
    esac

    if
      $posix_mkdir && (
	umask $mkdir_umask &&
	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
      )
    then :
    else

      # The umask is ridiculous, or mkdir does not conform to POSIX,
      # or it failed possibly due to a race condition.  Create the
      # directory the slow way, step by step, checking for races as we go.

      case $dstdir in
	/*) prefix='/';;
	-*) prefix='./';;
	*)  prefix='';;
      esac

      eval "$initialize_posix_glob"

      oIFS=$IFS
      IFS=/
      $posix_glob set -f
      set fnord $dstdir
      shift
      $posix_glob set +f
      IFS=$oIFS

      prefixes=

      for d
      do
	test -z "$d" && continue

	prefix=$prefix$d
	if test -d "$prefix"; then
	  prefixes=
	else
	  if $posix_mkdir; then
	    (umask=$mkdir_umask &&
	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
	    # Don't fail if two instances are running concurrently.
	    test -d "$prefix" || exit 1
	  else
	    case $prefix in
	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
	      *) qprefix=$prefix;;
	    esac
	    prefixes="$prefixes '$qprefix'"
	  fi
	fi
	prefix=$prefix/
      done

      if test -n "$prefixes"; then
	# Don't fail if two instances are running concurrently.
	(umask $mkdir_umask &&
	 eval "\$doit_exec \$mkdirprog $prefixes") ||
	  test -d "$dstdir" || exit 1
	obsolete_mkdir_used=true
      fi
    fi
  fi

  if test -n "$dir_arg"; then
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  else

    # Make a couple of temp file names in the proper directory.
    dsttmp=$dstdir/_inst.$$_
    rmtmp=$dstdir/_rm.$$_

    # Trap to clean up those temp files at exit.
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0

    # Copy the file name to the temp name.
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&

    # and set any options; do chmod last to preserve setuid bits.
    #
    # If any of these fail, we abort the whole thing.  If we want to
    # ignore errors from any of these, just make sure not to ignore
    # errors from the above "$doit $cpprog $src $dsttmp" command.
    #
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&

    # If -C, don't bother to copy if it wouldn't change the file.
    if $copy_on_change &&
       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&

       eval "$initialize_posix_glob" &&
       $posix_glob set -f &&
       set X $old && old=:$2:$4:$5:$6 &&
       set X $new && new=:$2:$4:$5:$6 &&
       $posix_glob set +f &&

       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
	# Now remove or move aside any old file at destination location.
	# We try this two ways since rm can't unlink itself on some
	# systems and the destination file might be busy for other
	# reasons.  In this case, the final cleanup might fail but the new
	# file should still install successfully.
	{
	  test ! -f "$dst" ||
	  $doit $rmcmd -f "$dst" 2>/dev/null ||
	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
	  } ||
	  { echo "$0: cannot unlink or rename $dst" >&2
	    (exit 1); exit 1
	  }
	} &&

	# Now rename the file to the real destination.
	$doit $mvcmd "$dsttmp" "$dst"
      }
    fi || exit 1

    trap '' 0
  fi
done

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

Added tk/tclconfig/tcl.m4.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
# tcl.m4 --
#
#	This file provides a set of autoconf macros to help TEA-enable
#	a Tcl extension.
#
# Copyright (c) 1999-2000 Ajuba Solutions.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

AC_PREREQ(2.57)

dnl TEA extensions pass us the version of TEA they think they
dnl are compatible with (must be set in TEA_INIT below)
dnl TEA_VERSION="3.9"

# Possible values for key variables defined:
#
# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
# TEA_PLATFORM        - windows unix
#

#------------------------------------------------------------------------
# TEA_PATH_TCLCONFIG --
#
#	Locate the tclConfig.sh file and perform a sanity check on
#	the Tcl compile flags
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-tcl=...
#
#	Defines the following vars:
#		TCL_BIN_DIR	Full path to the directory containing
#				the tclConfig.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_TCLCONFIG], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_INIT])
    #
    # Ok, lets find the tcl configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
			if test -f "${with_tclconfig}"; then
			    AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
			    with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
			fi ;;
		esac
		if test -f "${with_tclconfig}/tclConfig.sh" ; then
		    ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
		else
		    AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
		fi
	    fi

	    # then check for a private Tcl installation
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in \
			../tcl \
			`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
			../../tcl \
			`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
			../../../tcl \
			`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			; do
		    if test -f "$i/Tcl.framework/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
			break
		    fi
		done
	    fi

	    # TEA specific: on Windows, check in common installation locations
	    if test "${TEA_PLATFORM}" = "windows" \
		-a x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d C:/Tcl/lib 2>/dev/null` \
			`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few other private locations
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in \
			${srcdir}/../tcl \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_tclconfig}" = x ; then
	    TCL_BIN_DIR="# no Tcl configs found"
	    AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
	else
	    no_tcl=
	    TCL_BIN_DIR="${ac_cv_c_tclconfig}"
	    AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_PATH_TKCONFIG --
#
#	Locate the tkConfig.sh file
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-tk=...
#
#	Defines the following vars:
#		TK_BIN_DIR	Full path to the directory containing
#				the tkConfig.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_TKCONFIG], [
    #
    # Ok, lets find the tk configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
			if test -f "${with_tkconfig}"; then
			    AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
			    with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
			fi ;;
		esac
		if test -f "${with_tkconfig}/tkConfig.sh" ; then
		    ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
		else
		    AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
		fi
	    fi

	    # then check for a private Tk library
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in \
			../tk \
			`ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
			../../tk \
			`ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
			../../../tk \
			`ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			; do
		    if test -f "$i/Tk.framework/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # TEA specific: on Windows, check in common installation locations
	    if test "${TEA_PLATFORM}" = "windows" \
		-a x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d C:/Tcl/lib 2>/dev/null` \
			`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few other private locations
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in \
			${srcdir}/../tk \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_tkconfig}" = x ; then
	    TK_BIN_DIR="# no Tk configs found"
	    AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
	else
	    no_tk=
	    TK_BIN_DIR="${ac_cv_c_tkconfig}"
	    AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_LOAD_TCLCONFIG --
#
#	Load the tclConfig.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""

    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
        TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
        TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tcl was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tcl.framework installed in an arbitrary location.
	case ${TCL_DEFS} in
	    *TCL_FRAMEWORK*)
		if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
		    for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
			     "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
			if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
			    TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
			    break
			fi
		    done
		fi
		if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
		    TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
		    TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

    AC_SUBST(TCL_VERSION)
    AC_SUBST(TCL_PATCH_LEVEL)
    AC_SUBST(TCL_BIN_DIR)
    AC_SUBST(TCL_SRC_DIR)

    AC_SUBST(TCL_LIB_FILE)
    AC_SUBST(TCL_LIB_FLAG)
    AC_SUBST(TCL_LIB_SPEC)

    AC_SUBST(TCL_STUB_LIB_FILE)
    AC_SUBST(TCL_STUB_LIB_FLAG)
    AC_SUBST(TCL_STUB_LIB_SPEC)

    AC_MSG_CHECKING([platform])
    hold_cc=$CC; CC="$TCL_CC"
    AC_TRY_COMPILE(,[
	    #ifdef _WIN32
		#error win32
	    #endif
    ], TEA_PLATFORM="unix",
	    TEA_PLATFORM="windows"
    )
    CC=$hold_cc
    AC_MSG_RESULT($TEA_PLATFORM)

    # The BUILD_$pkg is to define the correct extern storage class
    # handling when making this package
    AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [],
	    [Building extension source?])
    # Do this here as we have fully defined TEA_PLATFORM now
    if test "${TEA_PLATFORM}" = "windows" ; then
	EXEEXT=".exe"
	CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp"
    fi

    # TEA specific:
    AC_SUBST(CLEANFILES)
    AC_SUBST(TCL_LIBS)
    AC_SUBST(TCL_DEFS)
    AC_SUBST(TCL_EXTRA_CFLAGS)
    AC_SUBST(TCL_LD_FLAGS)
    AC_SUBST(TCL_SHLIB_LD_LIBS)
])

#------------------------------------------------------------------------
# TEA_LOAD_TKCONFIG --
#
#	Load the tkConfig.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		TK_BIN_DIR
#
# Results:
#
#	Sets the following vars that should be in tkConfig.sh:
#		TK_BIN_DIR
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_TKCONFIG], [
    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])

    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/tkConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
    eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""

    # If the TK_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TK_LIB_SPEC will be set to the value
    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
    # instead of TK_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
        TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
        TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tk was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tk.framework installed in an arbitrary location.
	case ${TK_DEFS} in
	    *TK_FRAMEWORK*)
		if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
		    for i in "`cd "${TK_BIN_DIR}"; pwd`" \
			     "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
			if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
			    TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
			    break
			fi
		    done
		fi
		if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
		    TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
		    TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
    eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
    eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
    eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""

    # TEA specific: Ensure windowingsystem is defined
    if test "${TEA_PLATFORM}" = "unix" ; then
	case ${TK_DEFS} in
	    *MAC_OSX_TK*)
		AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
		TEA_WINDOWINGSYSTEM="aqua"
		;;
	    *)
		TEA_WINDOWINGSYSTEM="x11"
		;;
	esac
    elif test "${TEA_PLATFORM}" = "windows" ; then
	TEA_WINDOWINGSYSTEM="win32"
    fi

    AC_SUBST(TK_VERSION)
    AC_SUBST(TK_BIN_DIR)
    AC_SUBST(TK_SRC_DIR)

    AC_SUBST(TK_LIB_FILE)
    AC_SUBST(TK_LIB_FLAG)
    AC_SUBST(TK_LIB_SPEC)

    AC_SUBST(TK_STUB_LIB_FILE)
    AC_SUBST(TK_STUB_LIB_FLAG)
    AC_SUBST(TK_STUB_LIB_SPEC)

    # TEA specific:
    AC_SUBST(TK_LIBS)
    AC_SUBST(TK_XINCLUDES)
])

#------------------------------------------------------------------------
# TEA_PROG_TCLSH
#	Determine the fully qualified path name of the tclsh executable
#	in the Tcl build directory or the tclsh installed in a bin
#	directory. This macro will correctly determine the name
#	of the tclsh executable even if tclsh has not yet been
#	built in the build directory. The tclsh found is always
#	associated with a tclConfig.sh file. This tclsh should be used
#	only for running extension test cases. It should never be
#	or generation of files (like pkgIndex.tcl) at build time.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([TEA_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        # tclConfig.sh is in Tcl build directory
        if test "${TEA_PLATFORM}" = "windows"; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
        else
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
        fi
    else
        # tclConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
        else
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
        fi
        list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TCL_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TCL_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${TCLSH_PROG}" ; then
                REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
                break
            fi
        done
        TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
    fi
    AC_MSG_RESULT([${TCLSH_PROG}])
    AC_SUBST(TCLSH_PROG)
])

#------------------------------------------------------------------------
# TEA_PROG_WISH
#	Determine the fully qualified path name of the wish executable
#	in the Tk build directory or the wish installed in a bin
#	directory. This macro will correctly determine the name
#	of the wish executable even if wish has not yet been
#	built in the build directory. The wish found is always
#	associated with a tkConfig.sh file. This wish should be used
#	only for running extension test cases. It should never be
#	or generation of files (like pkgIndex.tcl) at build time.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		WISH_PROG
#------------------------------------------------------------------------

AC_DEFUN([TEA_PROG_WISH], [
    AC_MSG_CHECKING([for wish])
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        # tkConfig.sh is in Tk build directory
        if test "${TEA_PLATFORM}" = "windows"; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
        else
            WISH_PROG="${TK_BIN_DIR}/wish"
        fi
    else
        # tkConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
        else
            WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}"
        fi
        list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TK_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TK_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${WISH_PROG}" ; then
                REAL_TK_BIN_DIR="`cd "$i"; pwd`/"
                break
            fi
        done
        WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}"
    fi
    AC_MSG_RESULT([${WISH_PROG}])
    AC_SUBST(WISH_PROG)
])

#------------------------------------------------------------------------
# TEA_ENABLE_SHARED --
#
#	Allows the building of shared libraries
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-shared=yes|no
#
#	Defines the following vars:
#		STATIC_BUILD	Used for building import/export libraries
#				on Windows.
#
#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
    fi
    AC_SUBST(SHARED_BUILD)
])

#------------------------------------------------------------------------
# TEA_ENABLE_THREADS --
#
#	Specify if thread support should be enabled.  If "yes" is specified
#	as an arg (optional), threads are enabled by default, "no" means
#	threads are disabled.  "yes" is the default.
#
#	TCL_THREADS is checked so that if you are compiling an extension
#	against a threaded core, your extension must be compiled threaded
#	as well.
#
#	Note that it is legal to have a thread enabled extension run in a
#	threaded or non-threaded Tcl core, but a non-threaded extension may
#	only run in a non-threaded Tcl core.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-threads
#
#	Sets the following vars:
#		THREADS_LIBS	Thread library(s)
#
#	Defines the following vars:
#		TCL_THREADS
#		_REENTRANT
#		_THREAD_SAFE
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_threads+set}" = set; then
	enableval="$enable_threads"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
	TCL_THREADS=1

	if test "${TEA_PLATFORM}" != "windows" ; then
	    # We are always OK on Windows, so check what this platform wants:

	    # USE_THREAD_ALLOC tells us to try the special thread-based
	    # allocator that significantly reduces lock contention
	    AC_DEFINE(USE_THREAD_ALLOC, 1,
		[Do we want to use the threaded memory allocator?])
	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    if test "`uname -s`" = "SunOS" ; then
		AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
			[Do we really want to follow the standard? Yes we do!])
	    fi
	    AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
	    AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
	    if test "$tcl_ok" = "no"; then
		# Check a little harder for __pthread_mutex_init in the same
		# library, as some systems hide it there until pthread.h is
		# defined.  We could alternatively do an AC_TRY_COMPILE with
		# pthread.h, but that will work with libpthread really doesn't
		# exist, like AIX 4.2.  [Bug: 4359]
		AC_CHECK_LIB(pthread, __pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
	    fi

	    if test "$tcl_ok" = "yes"; then
		# The space is needed
		THREADS_LIBS=" -lpthread"
	    else
		AC_CHECK_LIB(pthreads, pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
		if test "$tcl_ok" = "yes"; then
		    # The space is needed
		    THREADS_LIBS=" -lpthreads"
		else
		    AC_CHECK_LIB(c, pthread_mutex_init,
			tcl_ok=yes, tcl_ok=no)
		    if test "$tcl_ok" = "no"; then
			AC_CHECK_LIB(c_r, pthread_mutex_init,
			    tcl_ok=yes, tcl_ok=no)
			if test "$tcl_ok" = "yes"; then
			    # The space is needed
			    THREADS_LIBS=" -pthread"
			else
			    TCL_THREADS=0
			    AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled])
			fi
		    fi
		fi
	    fi
	fi
    else
	TCL_THREADS=0
    fi
    # Do checking message here to not mess up interleaved configure output
    AC_MSG_CHECKING([for building with threads])
    if test "${TCL_THREADS}" = 1; then
	AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
	AC_MSG_RESULT([yes (default)])
    else
	AC_MSG_RESULT([no])
    fi
    # TCL_THREADS sanity checking.  See if our request for building with
    # threads is the same as the way Tcl was built.  If not, warn the user.
    case ${TCL_DEFS} in
	*THREADS=1*)
	    if test "${TCL_THREADS}" = "0"; then
		AC_MSG_WARN([
    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
    that IS thread-enabled.  It is recommended to use --enable-threads.])
	    fi
	    ;;
	*)
	    if test "${TCL_THREADS}" = "1"; then
		AC_MSG_WARN([
    --enable-threads requested, but building against a Tcl that is NOT
    thread-enabled.  This is an OK configuration that will also run in
    a thread-enabled core.])
	    fi
	    ;;
    esac
    AC_SUBST(TCL_THREADS)
])

#------------------------------------------------------------------------
# TEA_ENABLE_SYMBOLS --
#
#	Specify if debugging symbols should be used.
#	Memory (TCL_MEM_DEBUG) debugging can also be enabled.
#
# Arguments:
#	none
#
#	TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives
#	the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted.
#	Requires the following vars to be set in the Makefile:
#		CFLAGS_DEFAULT
#		LDFLAGS_DEFAULT
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-symbols
#
#	Defines the following vars:
#		CFLAGS_DEFAULT	Sets to $(CFLAGS_DEBUG) if true
#				Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false
#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#		DBGX		Formerly used as debug library extension;
#				always blank now.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SYMBOLS], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_CONFIG_CFLAGS])
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
	LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
	AC_MSG_RESULT([no])
    else
	CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
	LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
	if test "$tcl_ok" = "yes"; then
	    AC_MSG_RESULT([yes (standard debugging)])
	fi
    fi
    # TEA specific:
    if test "${TEA_PLATFORM}" != "windows" ; then
	LDFLAGS_DEFAULT="${LDFLAGS}"
    fi
    AC_SUBST(CFLAGS_DEFAULT)
    AC_SUBST(LDFLAGS_DEFAULT)
    AC_SUBST(TCL_DBGX)

    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
	AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
    fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
	    AC_MSG_RESULT([enabled symbols mem debugging])
	else
	    AC_MSG_RESULT([enabled $tcl_ok debugging])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_ENABLE_LANGINFO --
#
#	Allows use of modern nl_langinfo check for better l10n.
#	This is only relevant for Unix.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-langinfo=yes|no (default is yes)
#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [
	    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
		    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
    fi
])

#--------------------------------------------------------------------
# TEA_CONFIG_SYSTEM
#
#	Determine what the system is (some things cannot be easily checked
#	on a feature-driven basis, alas). This can usually be done via the
#	"uname" command.
#
# Arguments:
#	none
#
# Results:
#	Defines the following var:
#
#	system -	System/platform/version identification code.
#--------------------------------------------------------------------

AC_DEFUN([TEA_CONFIG_SYSTEM], [
    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
	# TEA specific:
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		AC_MSG_WARN([can't find uname command])
		tcl_cv_sys_version=unknown
	    else
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
	    fi
	fi
    ])
    system=$tcl_cv_sys_version
])

#--------------------------------------------------------------------
# TEA_CONFIG_CFLAGS
#
#	Try to determine the proper flags to pass to the compiler
#	for building shared libraries and other such nonsense.
#
# Arguments:
#	none
#
# Results:
#
#	Defines and substitutes the following vars:
#
#	DL_OBJS, DL_LIBS - removed for TEA, only needed by core.
#       LDFLAGS -      Flags to pass to the compiler when linking object
#                       files into an executable application binary such
#                       as tclsh.
#       LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
#                       that tell the run-time dynamic linker where to look
#                       for shared libraries such as libtcl.so.  Depends on
#                       the variable LIB_RUNTIME_DIR in the Makefile. Could
#                       be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
#       CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib",
#                       that tell the run-time dynamic linker where to look
#                       for shared libraries such as libtcl.so.  Depends on
#                       the variable LIB_RUNTIME_DIR in the Makefile.
#       SHLIB_CFLAGS -  Flags to pass to cc when compiling the components
#                       of a shared library (may request position-independent
#                       code, among other things).
#       SHLIB_LD -      Base command to use for combining object files
#                       into a shared library.
#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
#                       creating shared libraries.  This symbol typically
#                       goes at the end of the "ld" commands that build
#                       shared libraries. The value of the symbol defaults to
#                       "${LIBS}" if all of the dependent libraries should
#                       be specified when creating a shared library.  If
#                       dependent libraries should not be specified (as on
#                       SunOS 4.x, where they cause the link to fail, or in
#                       general if Tcl and Tk aren't themselves shared
#                       libraries), then this symbol has an empty string
#                       as its value.
#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable
#                       extensions.  An empty string means we don't know how
#                       to use shared libraries on this platform.
#       LIB_SUFFIX -    Specifies everything that comes after the "libfoo"
#                       in a static or shared library name, using the $VERSION variable
#                       to put the version in the right place.  This is used
#                       by platforms that need non-standard library names.
#                       Examples:  ${VERSION}.so.1.1 on NetBSD, since it needs
#                       to have a version after the .so, and ${VERSION}.a
#                       on AIX, since a shared library needs to have
#                       a .a extension whereas shared objects for loadable
#                       extensions have a .so extension.  Defaults to
#                       ${VERSION}${SHLIB_SUFFIX}.
#	CFLAGS_DEBUG -
#			Flags used when running the compiler in debug mode
#	CFLAGS_OPTIMIZE -
#			Flags used when running the compiler in optimize mode
#	CFLAGS -	Additional CFLAGS added as necessary (usually 64-bit)
#--------------------------------------------------------------------

AC_DEFUN([TEA_CONFIG_CFLAGS], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_INIT])

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_TRY_LINK([
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
	    tcl_cv_cc_visibility_hidden=no)
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # TEA specific: Cross-compiling options for Windows/CE builds?

    AS_IF([test "${TEA_PLATFORM}" = windows], [
	AC_MSG_CHECKING([if Windows/CE build is requested])
	AC_ARG_ENABLE(wince,
	    AC_HELP_STRING([--enable-wince],
		[enable Win/CE support (where applicable)]),
	    [doWince=$enableval], [doWince=no])
	AC_MSG_RESULT([$doWince])
    ])

    # Set the variable "system" to hold the name and version number
    # for the system.

    TEA_CONFIG_SYSTEM

    # Require ranlib early so we can override it in special cases below.

    AC_REQUIRE([AC_PROG_RANLIB])

    # Set configuration options based on system name and version.
    # This is similar to Tcl's unix/tcl.m4 except that we've added a
    # "windows" case and removed some core-only vars.

    do64bit_ok=no
    # default to '{$LIBS}' and set to "" on per-platform necessary basis
    SHLIB_LD_LIBS='${LIBS}'
    # When ld needs options to work in 64-bit mode, put them in
    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
    # is disabled by the user. [Bug 1016796]
    LDFLAGS_ARCH=""
    UNSHARED_LIB_SUFFIX=""
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    AS_IF([test "$GCC" = yes], [
	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wno-write-strings -Wall -Wno-missing-braces -Wno-char-subscripts -Wno-long-long -pedantic"
    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
    case $system in
	# TEA specific:
	windows)
	    # This is a 2-stage check to make sure we have the 64-bit SDK
	    # We have to know where the SDK is installed.
	    # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
	    # MACHINE is IX86 for LINK, but this is used by the manifest,
	    # which requires x86|amd64|ia64.
	    MACHINE="X86"
	    if test "$do64bit" != "no" ; then
		if test "x${MSSDK}x" = "xx" ; then
		    MSSDK="C:/Progra~1/Microsoft Platform SDK"
		fi
		MSSDK=`echo "$MSSDK" | sed -e  's!\\\!/!g'`
		PATH64=""
		case "$do64bit" in
		    amd64|x64|yes)
			MACHINE="AMD64" ; # default to AMD64 64-bit build
			PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
			;;
		    ia64)
			MACHINE="IA64"
			PATH64="${MSSDK}/Bin/Win64"
			;;
		esac
		if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
		    AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
		    AC_MSG_WARN([Ensure latest Platform SDK is installed])
		    do64bit="no"
		else
		    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		    do64bit_ok="yes"
		fi
	    fi

	    if test "$doWince" != "no" ; then
		if test "$do64bit" != "no" ; then
		    AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
		fi
		if test "$GCC" = "yes" ; then
		    AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
		fi
		TEA_PATH_CELIB
		# Set defaults for common evc4/PPC2003 setup
		# Currently Tcl requires 300+, possibly 420+ for sockets
		CEVERSION=420; 		# could be 211 300 301 400 420 ...
		TARGETCPU=ARMV4;	# could be ARMV4 ARM MIPS SH3 X86 ...
		ARCH=ARM;		# could be ARM MIPS X86EM ...
		PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
		if test "$doWince" != "yes"; then
		    # If !yes then the user specified something
		    # Reset ARCH to allow user to skip specifying it
		    ARCH=
		    eval `echo $doWince | awk -F, '{ \
	    if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
	    if ([$]1 < 400)   { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
	    if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
	    if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
	    if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
		    }'`
		    if test "x${ARCH}" = "x" ; then
			ARCH=$TARGETCPU;
		    fi
		fi
		OSVERSION=WCE$CEVERSION;
	    	if test "x${WCEROOT}" = "x" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
		    if test ! -d "${WCEROOT}" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
		    fi
		fi
		if test "x${SDKROOT}" = "x" ; then
		    SDKROOT="C:/Program Files/Windows CE Tools"
		    if test ! -d "${SDKROOT}" ; then
			SDKROOT="C:/Windows CE Tools"
		    fi
		fi
		WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
		SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
		if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
		    -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
		    AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
		    doWince="no"
		else
		    # We could PATH_NOSPACE these, but that's not important,
		    # as long as we quote them when used.
		    CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
		    if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
			CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
		    fi
		    CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
    		fi
	    fi

	    if test "$GCC" != "yes" ; then
	        if test "${SHARED_BUILD}" = "0" ; then
		    runtime=-MT
	        else
		    runtime=-MD
	        fi

                if test "$do64bit" != "no" ; then
		    # All this magic is necessary for the Win64 SDK RC1 - hobbs
		    CC="\"${PATH64}/cl.exe\""
		    CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
		    RC="\"${MSSDK}/bin/rc.exe\""
		    lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
		    LINKBIN="\"${PATH64}/link.exe\""
		    CFLAGS_DEBUG="-nologo -Zi -Od -W2 ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		    # Avoid 'unresolved external symbol __security_cookie'
		    # errors, c.f. http://support.microsoft.com/?id=894573
		    TEA_ADD_LIBS([bufferoverflowU.lib])
		elif test "$doWince" != "no" ; then
		    CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
		    if test "${TARGETCPU}" = "X86"; then
			CC="\"${CEBINROOT}/cl.exe\""
		    else
			CC="\"${CEBINROOT}/cl${ARCH}.exe\""
		    fi
		    CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
		    RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
		    arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
		    defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
		    if test "${SHARED_BUILD}" = "1" ; then
			# Static CE builds require static celib as well
		    	defs="${defs} _DLL"
		    fi
		    for i in $defs ; do
			AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
		    done
		    AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
		    AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
		    CFLAGS_DEBUG="-nologo -Zi -Od"
		    CFLAGS_OPTIMIZE="-nologo -Ox"
		    lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
		    lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
		    LINKBIN="\"${CEBINROOT}/link.exe\""
		    AC_SUBST(CELIB_DIR)
		else
		    RC="rc"
		    lflags="-nologo"
    		    LINKBIN="link"
		    CFLAGS_DEBUG="-nologo -Z7 -Od -W2 ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		fi
	    fi

	    if test "$GCC" = "yes"; then
		# mingw gcc mode
		AC_CHECK_TOOL(RC, windres)
		CFLAGS_DEBUG="-g"
		CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
		SHLIB_LD='${CXX} -shared'
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
		LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"

		AC_CACHE_CHECK(for cross-compile version of gcc,
			ac_cv_cross,
			AC_TRY_COMPILE([
			    #ifdef __WIN32__
				#error cross-compiler
			    #endif
			], [],
			ac_cv_cross=yes,
			ac_cv_cross=no)
		      )
		      if test "$ac_cv_cross" = "yes"; then
			case "$do64bit" in
			    amd64|x64|yes)
				CC="x86_64-w64-mingw32-gcc"
				LD="x86_64-w64-mingw32-ld"
				AR="x86_64-w64-mingw32-ar"
				RANLIB="x86_64-w64-mingw32-ranlib"
				RC="x86_64-w64-mingw32-windres"
			    ;;
			    *)
				CC="i686-w64-mingw32-gcc"
				LD="i686-w64-mingw32-ld"
				AR="i686-w64-mingw32-ar"
				RANLIB="i686-w64-mingw32-ranlib"
				RC="i686-w64-mingw32-windres"
			    ;;
			esac
		fi

	    else
		SHLIB_LD="${LINKBIN} -dll ${lflags}"
		# link -lib only works when -lib is the first arg
		STLIB_LD="${LINKBIN} -lib ${lflags}"
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
		PATHTYPE=-w
		# For information on what debugtype is most useful, see:
		# http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
		# and also
		# http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
		# This essentially turns it all on.
		LDFLAGS_DEBUG="-debug -debugtype:cv"
		LDFLAGS_OPTIMIZE="-release"
		if test "$doWince" != "no" ; then
		    LDFLAGS_CONSOLE="-link ${lflags}"
		    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
		else
		    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
		    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
		fi
	    fi

	    SHLIB_SUFFIX=".dll"
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'

	    TCL_LIB_VERSIONS_OK=nodots
    	    ;;
	AIX-*)
	    AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
		    	CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
			;;
		esac
		AC_MSG_RESULT([Using $CC for compiling with threads])
	    ])
	    LIBS="$LIBS -lc"
	    SHLIB_CFLAGS=""
	    SHLIB_SUFFIX=".so"

	    LD_LIBRARY_PATH_VAR="LIBPATH"

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = yes], [
		AS_IF([test "$GCC" = yes], [
		    AC_MSG_WARN([64bit mode not supported with GCC on $system])
		], [
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS -q64"
		    LDFLAGS_ARCH="-q64"
		    RANLIB="${RANLIB} -X64"
		    AR="${AR} -X64"
		    SHLIB_LD_FLAGS="-b64"
		])
	    ])

	    AS_IF([test "`uname -m`" = ia64], [
		# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		AS_IF([test "$GCC" = yes], [
		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		], [
		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
		])
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ], [
		AS_IF([test "$GCC" = yes], [
		    SHLIB_LD='${CXX} -shared -Wl,-bexpall'
		], [
		    SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
		    LDFLAGS="$LDFLAGS -brtl"
		])
		SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	BeOS*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CXX} -nostart'
	    SHLIB_SUFFIX=".so"

	    #-----------------------------------------------------------
	    # Check for inet_ntoa in -lbind, for BeOS (which also needs
	    # -lsocket, even if the network functions are in -lnet which
	    # is always linked to, for compatibility.
	    #-----------------------------------------------------------
	    AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
	    ;;
	BSD/OS-4.*)
	    SHLIB_CFLAGS="-export-dynamic -fPIC"
	    SHLIB_LD='${CXX} -shared'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CXX} -shared'
	    SHLIB_SUFFIX=".dll"
	    EXEEXT=".exe"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CXX} -shared ${CFLAGS} ${LDFLAGS}'
	    AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible
	    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
	    # TEA specific: Needed by Tcl, but not most extensions
	    #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
	    #LIBS="$LIBS -lxnet"               # Use the XOPEN network library

	    AS_IF([test "`uname -m`" = ia64], [
		SHLIB_SUFFIX=".so"
		# Use newer C++ library for C++ extensions
		#if test "$GCC" != "yes" ; then
		#   CPPFLAGS="-AA"
		#fi
	    ], [
		SHLIB_SUFFIX=".sl"
	    ])
	    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
	    AS_IF([test "$tcl_ok" = yes], [
		LDFLAGS="$LDFLAGS -Wl,-E"
		CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
		LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
		LD_LIBRARY_PATH_VAR="SHLIB_PATH"
	    ])
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CXX} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		CFLAGS="$CFLAGS -z"
		# Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
		#CFLAGS="$CFLAGS +DAportable"
		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
	    ])

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = "yes"], [
		AS_IF([test "$GCC" = yes], [
		    case `${CC} -dumpmachine` in
			hppa64*)
			    # 64-bit gcc in use.  Fix flags for GNU ld.
			    do64bit_ok=yes
			    SHLIB_LD='${CXX} -shared'
			    AS_IF([test $doRpath = yes], [
				CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    AC_MSG_WARN([64bit mode not supported with GCC on $system])
			    ;;
		    esac
		], [
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS +DD64"
		    LDFLAGS_ARCH="+DD64"
		])
	    ]) ;;
	IRIX-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [
		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"
	    ], [
		case $system in
		    IRIX-6.3)
			# Use to build 6.2 compatible binaries on 6.3.
			CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
			;;
		    *)
			CFLAGS="$CFLAGS -n32"
			;;
		esac
		LDFLAGS="$LDFLAGS -n32"
	    ])
	    ;;
	IRIX64-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])

	    # Check to enable 64-bit flags for compiler/linker

	    AS_IF([test "$do64bit" = yes], [
	        AS_IF([test "$GCC" = yes], [
	            AC_MSG_WARN([64bit mode not supported by gcc])
	        ], [
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"

	    # TEA specific:
	    CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"

	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CXX} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    #LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    LDFLAGS="$LDFLAGS -Wl,-soname,libscintilla.so"

	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ],[CFLAGS="$CFLAGS -m32"])

	    # The combo of gcc + glibc has a bug related to inlining of
	    # functions like strtod(). The -fno-builtin flag should address
	    # this problem but it does not work. The -fno-inline flag is kind
	    # of overkill but it works. Disable inlining only when one of the
	    # files in compat/*.c is being linked in.

	    AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])

	    ;;
	Lynx*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    CFLAGS_OPTIMIZE=-02
	    SHLIB_LD='${CXX} -shared'
	    LD_FLAGS="-Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    ;;
	OpenBSD-*)
	    arch=`arch -s`
	    case "$arch" in
	    m88k|vax)
		SHLIB_SUFFIX=""
		SHARED_LIB_SUFFIX=""
		;;
	    *)
		SHLIB_CFLAGS="-fPIC"
		SHLIB_LD='${CXX} -shared ${SHLIB_CFLAGS}'
		SHLIB_SUFFIX=".so"
		AS_IF([test $doRpath = yes], [
		    CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
		;;
	    esac
	    case "$arch" in
	    m88k|vax)
		CFLAGS_OPTIMIZE="-O1"
		;;
	    *)
		CFLAGS_OPTIMIZE="-O2"
		;;
	    esac
	    AC_CACHE_CHECK([for ELF], tcl_cv_ld_elf, [
		AC_EGREP_CPP(yes, [
#ifdef __ELF__
	yes
#endif
		], tcl_cv_ld_elf=yes, tcl_cv_ld_elf=no)])
	    AS_IF([test $tcl_cv_ld_elf = yes], [
		#LDFLAGS=-Wl,-export-dynamic
		LDFLAGS=-Wl,-soname,libscintilla.so
	    ], [LDFLAGS=""])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# On OpenBSD:	Compile with -pthread
		#		Don't link with -lpthread
		LIBS=`echo $LIBS | sed s/-lpthread//`
		CFLAGS="$CFLAGS -pthread"
	    ])
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*|FreeBSD-[[3-4]].*)
	    # FreeBSD 3.* and greater have ELF.
	    # NetBSD 2.* has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CXX} -shared ${SHLIB_CFLAGS}'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    case $system in
	    FreeBSD-3.*)
	    	# FreeBSD-3 doesn't handle version numbers with dots.
	    	UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    	SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
	    	TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CXX} -shared"
	    TCL_SHLIB_LD_EXTRAS="-soname \$[@]"
	    SHLIB_SUFFIX=".so"
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
	    # Version numbers are dot-stripped by system policy.
	    TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    SHLIB_CFLAGS="-fno-common"
	    # To avoid discrepancies between what headers configure sees during
	    # preprocessing tests and compiling tests, move any -isysroot and
	    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
	    CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
	    CFLAGS="`echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
				    tcl_cv_cc_arch_ppc64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
				    tcl_cv_cc_arch_x86_64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CXX} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    # TEA specific: link shlib with current and compatibility version flags
	    vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
	    SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
	    SHLIB_SUFFIX=".dylib"
	    # Don't use -prebind when building for Mac OS X 10.4 or later only:
	    AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
		"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
		LDFLAGS="$LDFLAGS -prebind"])
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
			tcl_cv_ld_search_paths_first=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
		tcl_cv_cc_visibility_hidden=yes
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    # TEA specific: for combined 32 & 64 bit fat builds of Tk
	    # extensions, verify that 64-bit build is possible.
	    AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [
		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [
		    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
			LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
			AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
			    tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [
		    AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
			LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
			AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);],
			    tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		# remove 64-bit arch flags from CFLAGS et al. if configuration
		# does not support 64-bit.
		AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [
		    AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
		    for v in CFLAGS CPPFLAGS LDFLAGS; do
			eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
		    done])
	    ])
	    ;;
	OS/390-*)
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy
	    AC_DEFINE(_OE_SOCKETS, 1,	# needed in sys/socket.h
		[Should OS/390 do the right thing with sockets?])
	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    AS_IF([test "$SHARED_BUILD" = 1], [
	        SHLIB_LD='ld -shared -expect_unresolved "*"'
	    ], [
	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'
	    ])
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
	    # see pthread_intro(3) for pthread support on osf1, k.furukawa
	    AS_IF([test "${TCL_THREADS}" = 1], [
		CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
		CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
		LIBS=`echo $LIBS | sed s/-lpthreads//`
		AS_IF([test "$GCC" = yes], [
		    LIBS="$LIBS -lpthread -lmach -lexc"
		], [
		    CFLAGS="$CFLAGS -pthread"
		    LDFLAGS="$LDFLAGS -pthread"
		])
	    ])
	    ;;
	QNX-6*)
	    # QNX RTP
	    # This may work for all QNX, but it was only reported for v6.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="ld -Bshareable -x"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    AS_IF([test "$GCC" = yes], [
		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
	    ], [
	       SHLIB_CFLAGS="-Kpic -belf"
	       LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
	    ])
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SunOS-5.[[0-6]])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CXX} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	SunOS-5*)
	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

	    SHLIB_CFLAGS="-KPIC"

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = yes], [
		arch=`isainfo`
		AS_IF([test "$arch" = "sparcv9 sparc"], [
		    AS_IF([test "$GCC" = yes], [
			AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
			    AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
			], [
			    do64bit_ok=yes
			    CFLAGS="$CFLAGS -m64 -mcpu=v9"
			    LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
			    SHLIB_CFLAGS="-fPIC"
			])
		    ], [
			do64bit_ok=yes
			AS_IF([test "$do64bitVIS" = yes], [
			    CFLAGS="$CFLAGS -xarch=v9a"
			    LDFLAGS_ARCH="-xarch=v9a"
			], [
			    CFLAGS="$CFLAGS -xarch=v9"
			    LDFLAGS_ARCH="-xarch=v9"
			])
			# Solaris 64 uses this as well
			#LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
		    ])
		], [AS_IF([test "$arch" = "amd64 i386"], [
		    AS_IF([test "$GCC" = yes], [
			case $system in
			    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
				do64bit_ok=yes
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
			esac
		    ], [
			do64bit_ok=yes
			case $system in
			    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				CFLAGS="$CFLAGS -xarch=amd64"
				LDFLAGS="$LDFLAGS -xarch=amd64";;
			esac
		    ])
		], [AC_MSG_WARN([64bit mode not supported for $arch])])])
	    ])

	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CXX} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		AS_IF([test "$do64bit_ok" = yes], [
		    AS_IF([test "$arch" = "sparcv9 sparc"], [
			# We need to specify -static-libgcc or we need to
			# add the path to the sparv9 libgcc.
			# JH: static-libgcc is necessary for core Tcl, but may
			# not be necessary for extensions.
			SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
			# for finding sparcv9 libgcc, get the regular libgcc
			# path, remove so name and append 'sparcv9'
			#v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
			#CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
		    ], [AS_IF([test "$arch" = "amd64 i386"], [
			# JH: static-libgcc is necessary for core Tcl, but may
			# not be necessary for extensions.
			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
		    ])])
		])
	    ], [
		case $system in
		    SunOS-5.[[1-9]][[0-9]]*)
			# TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
			SHLIB_LD='${CXX} -G -z text ${LDFLAGS_DEFAULT}';;
		    *)
			SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ])
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CXX} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
	        LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
    esac

    AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
	AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
    ])

dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
dnl # until the end of configure, as configure's compile and link tests use
dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Add in the arch flags late to ensure it wasn't removed.
    # Not necessary in TEA, but this is aligned with core
    LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"

    # If we're running gcc, then change the C flags for compiling shared
    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*) ;;
	    IRIX*) ;;
	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    windows) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
	AC_DEFINE(MODULE_SCOPE, [extern],
	    [No Compiler support for module scope symbols])
	AC_DEFINE(NO_VIZ, [], [No visibility hidden passed to zlib?])
    ])

    AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])
    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])

    if test "${GCC}" = "yes" ; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_TRY_RUN([
	    #define WIN32_LEAN_AND_MEAN
	    #include <windows.h>
	    #undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	],
	    tcl_cv_seh=yes,
	    tcl_cv_seh=no,
	    tcl_cv_seh=no)
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_TRY_COMPILE([
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ],[
		EXCEPTION_DISPOSITION x;
	    ],
		tcl_cv_eh_disposition=yes,
		tcl_cv_eh_disposition=no)
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_TRY_COMPILE([
		#define VOID void
		#define WIN32_LEAN_AND_MEAN
		#include <windows.h>
		#undef WIN32_LEAN_AND_MEAN
	    ], [
		CHAR c;
		SHORT s;
		LONG l;
	    ],
        tcl_cv_winnt_ignore_void=yes,
        tcl_cv_winnt_ignore_void=no)
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi
    fi

    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)

    AC_SUBST(STLIB_LD)
    AC_SUBST(SHLIB_LD)

    AC_SUBST(SHLIB_LD_LIBS)
    AC_SUBST(SHLIB_CFLAGS)
    AC_SUBST(SHLIB_SUFFIX)

    AC_SUBST(LD_LIBRARY_PATH_VAR)

    # These must be called after we do the basic CFLAGS checks and
    # verify any possible 64-bit or similar switches are necessary
    TEA_TCL_EARLY_FLAGS
    TEA_TCL_64BIT_FLAGS
])

#--------------------------------------------------------------------
# TEA_SERIAL_PORT
#
#	Determine which interface to use to talk to the serial port.
#	Note that #include lines must begin in leftmost column for
#	some compilers to recognize them as preprocessor directives,
#	and some build environments have stdin not pointing at a
#	pseudo-terminal (usually /dev/null instead.)
#
# Arguments:
#	none
#
# Results:
#
#	Defines only one of the following vars:
#		HAVE_SYS_MODEM_H
#		USE_TERMIOS
#		USE_TERMIO
#		USE_SGTTY
#--------------------------------------------------------------------

AC_DEFUN([TEA_SERIAL_PORT], [
    AC_CHECK_HEADERS(sys/modem.h)
    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
    AC_TRY_RUN([
#include <termios.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termio.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <sgtty.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termios.h>
#include <errno.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <termio.h>
#include <errno.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <sgtty.h>
#include <errno.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
    fi])
    case $tcl_cv_api_serial in
	termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
	termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
	sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
    esac
])

#--------------------------------------------------------------------
# TEA_MISSING_POSIX_HEADERS
#
#	Supply substitutes for missing POSIX header files.  Special
#	notes:
#	    - stdlib.h doesn't define strtol, strtoul, or
#	      strtod in some versions of SunOS
#	    - some versions of string.h don't declare procedures such
#	      as strstr
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		NO_DIRENT_H
#		NO_ERRNO_H
#		NO_VALUES_H
#		HAVE_LIMITS_H or NO_LIMITS_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#
#		HAVE_STRING_H ?
#
# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
# CHECK on limits.h
#--------------------------------------------------------------------

AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    # TEA specific:
    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
    AC_CHECK_HEADER(limits.h,
	[AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
	[AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
    fi
    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)

    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_HAVE_HEADERS(sys/param.h)
])

#--------------------------------------------------------------------
# TEA_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff
#	(e.g. because there's no xmkmf program) then check through
#	a list of possible directories.  Under some conditions the
#	autoconf macro will return an include directory that contains
#	no include files, so double-check its result just to be safe.
#
#	This should be called after TEA_CONFIG_CFLAGS as setting the
#	LIBS line can confuse some configure macro magic.
#
# Arguments:
#	none
#
# Results:
#
#	Sets the following vars:
#		XINCLUDES
#		XLIBSW
#		PKG_LIBS (appends to)
#--------------------------------------------------------------------

AC_DEFUN([TEA_PATH_X], [
    if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then
	TEA_PATH_UNIX_X
    fi
])

AC_DEFUN([TEA_PATH_UNIX_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_TRY_CPP([#include <X11/XIntrinsic.h>], , not_really_there="yes")
	else
	    if test ! -r $x_includes/X11/Intrinsic.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_TRY_CPP([#include <X11/Intrinsic.h>], found_xincludes="yes", found_xincludes="no")
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Intrinsic.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"
		    break
		fi
	    done
	fi
    else
	if test "$x_includes" != ""; then
	    XINCLUDES="-I$x_includes"
	    found_xincludes="yes"
	fi
    fi
    if test "$found_xincludes" = "no"; then
	AC_MSG_RESULT([couldn't find any!])
    fi

    if test "$no_x" = yes; then
	AC_MSG_CHECKING([for X11 libraries])
	XLIBSW=nope
	dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
	for i in $dirs ; do
	    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
		AC_MSG_RESULT([$i])
		XLIBSW="-L$i -lX11"
		x_libraries="$i"
		break
	    fi
	done
    else
	if test "$x_libraries" = ""; then
	    XLIBSW=-lX11
	else
	    XLIBSW="-L$x_libraries -lX11"
	fi
    fi
    if test "$XLIBSW" = nope ; then
	AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
    fi
    if test "$XLIBSW" = nope ; then
	AC_MSG_RESULT([could not find any!  Using -lX11.])
	XLIBSW=-lX11
    fi
    # TEA specific:
    if test x"${XLIBSW}" != x ; then
	PKG_LIBS="${PKG_LIBS} ${XLIBSW}"
    fi
])

#--------------------------------------------------------------------
# TEA_BLOCKING_STYLE
#
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		HAVE_SYS_IOCTL_H
#		HAVE_SYS_FILIO_H
#		USE_FIONBIO
#		O_NONBLOCK
#--------------------------------------------------------------------

AC_DEFUN([TEA_BLOCKING_STYLE], [
    AC_CHECK_HEADERS(sys/ioctl.h)
    AC_CHECK_HEADERS(sys/filio.h)
    TEA_CONFIG_SYSTEM
    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
    case $system in
	OSF*)
	    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
	    AC_MSG_RESULT([FIONBIO])
	    ;;
	*)
	    AC_MSG_RESULT([O_NONBLOCK])
	    ;;
    esac
])

#--------------------------------------------------------------------
# TEA_TIME_HANDLER
#
#	Checks how the system deals with time.h, what time structures
#	are used on the system, and what fields the structures have.
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		USE_DELTA_FOR_TZ
#		HAVE_TM_GMTOFF
#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#--------------------------------------------------------------------

AC_DEFUN([TEA_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME
    AC_STRUCT_TIMEZONE

    AC_CHECK_FUNCS(gmtime_r localtime_r)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_TRY_COMPILE([#include <time.h>],
	    [extern long timezone;
	    timezone += 1;
	    exit (0);],
	    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_TRY_COMPILE([#include <time.h>],
		[extern time_t timezone;
		timezone += 1;
		exit (0);],
		tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_BUGGY_STRTOD
#
#	Under Solaris 2.4, strtod returns the wrong value for the
#	terminating character under some conditions.  Check for this
#	and if the problem exists use a substitute procedure
#	"fixstrtod" (provided by Tcl) that corrects the error.
#	Also, on Compaq's Tru64 Unix 5.0,
#	strtod(" ") returns 0.0 instead of a failure to convert.
#
# Arguments:
#	none
#
# Results:
#
#	Might defines some of the following vars:
#		strtod (=fixstrtod)
#--------------------------------------------------------------------

AC_DEFUN([TEA_BUGGY_STRTOD], [
    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
    if test "$tcl_strtod" = 1; then
	AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
	    AC_TRY_RUN([
		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(nanString, &term);
		    if ((term != nanString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(spaceString, &term);
		    if (term == (spaceString+1)) {
			exit(1);
		    }
		    exit(0);
		}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
		    tcl_cv_strtod_buggy=buggy)])
	if test "$tcl_cv_strtod_buggy" = buggy; then
	    AC_LIBOBJ([fixstrtod])
	    USE_COMPAT=1
	    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_TCL_LINK_LIBS
#
#	Search for the libraries needed to link the Tcl shell.
#	Things like the math library (-lm) and socket stuff (-lsocket vs.
#	-lnsl) are dealt with here.
#
# Arguments:
#	Requires the following vars to be set in the Makefile:
#		DL_LIBS (not in TEA, only needed in core)
#		LIBS
#		MATH_LIBS
#
# Results:
#
#	Substitutes the following vars:
#		TCL_LIBS
#		MATH_LIBS
#
#	Might append to the following vars:
#		LIBS
#
#	Might define the following vars:
#		HAVE_NET_ERRNO_H
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_LINK_LIBS], [
    #--------------------------------------------------------------------
    # On a few very rare systems, all of the libm.a stuff is
    # already in libc.a.  Set compiler flags accordingly.
    # Also, Linux requires the "ieee" library for math to work
    # right (and it must appear before "-lm").
    #--------------------------------------------------------------------

    AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
    AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])

    #--------------------------------------------------------------------
    # Interactive UNIX requires -linet instead of -lsocket, plus it
    # needs net/errno.h to define the socket-related error codes.
    #--------------------------------------------------------------------

    AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
    AC_CHECK_HEADER(net/errno.h, [
	AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])

    #--------------------------------------------------------------------
    #	Check for the existence of the -lsocket and -lnsl libraries.
    #	The order here is important, so that they end up in the right
    #	order in the command line generated by make.  Here are some
    #	special considerations:
    #	1. Use "connect" and "accept" to check for -lsocket, and
    #	   "gethostbyname" to check for -lnsl.
    #	2. Use each function name only once:  can't redo a check because
    #	   autoconf caches the results of the last check and won't redo it.
    #	3. Use -lnsl and -lsocket only if they supply procedures that
    #	   aren't already present in the normal libraries.  This is because
    #	   IRIX 5.2 has libraries, but they aren't needed and they're
    #	   bogus:  they goof up name resolution if used.
    #	4. On some SVR4 systems, can't use -lsocket without -lnsl too.
    #	   To get around this problem, check for both libraries together
    #	   if -lsocket doesn't work by itself.
    #--------------------------------------------------------------------

    tcl_checkBoth=0
    AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
    if test "$tcl_checkSocket" = 1; then
	AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
	    LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
    fi
    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])

    # TEA specific: Don't perform the eval of the libraries here because
    # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS

    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
    AC_SUBST(TCL_LIBS)
    AC_SUBST(MATH_LIBS)
])

#--------------------------------------------------------------------
# TEA_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    AC_TRY_COMPILE([[#define ]$1[ 1
]$2], $3,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([TEA_TCL_EARLY_FLAGS],[
    AC_MSG_CHECKING([for required early compiler flags])
    tcl_flags=""
    TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
	[char *p = (char *)strtoll; char *q = (char *)strtoull;])
    TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
	[struct stat64 buf; int i = stat64("/", &buf);])
    TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
	[char *p = (char *)open64;])
    if test "x${tcl_flags}" = "x" ; then
	AC_MSG_RESULT([none])
    else
	AC_MSG_RESULT([${tcl_flags}])
    fi
])

#--------------------------------------------------------------------
# TEA_TCL_64BIT_FLAGS
#
#	Check for what is defined in the way of 64-bit features.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		TCL_WIDE_INT_IS_LONG
#		TCL_WIDE_INT_TYPE
#		HAVE_STRUCT_DIRENT64
#		HAVE_STRUCT_STAT64
#		HAVE_TYPE_OFF64_T
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we should use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
    elif test "${tcl_cv_type_64bit}" = "__int64" \
		-a "${TEA_PLATFORM}" = "windows" ; then
	# TEA specific: We actually want to use the default tcl.h checks in
	# this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
	AC_MSG_RESULT([using Tcl header defaults])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <sys/dirent.h>],[struct dirent64 p;],
		tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
],
		tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
],
		tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
	else
	    AC_MSG_RESULT([no])
	fi
    fi
])

##
## Here ends the standard Tcl configuration bits and starts the
## TEA specific functions
##

#------------------------------------------------------------------------
# TEA_INIT --
#
#	Init various Tcl Extension Architecture (TEA) variables.
#	This should be the first called TEA_* macro.
#
# Arguments:
#	none
#
# Results:
#
#	Defines and substs the following vars:
#		CYGPATH
#		EXEEXT
#	Defines only:
#		TEA_VERSION
#		TEA_INITED
#		TEA_PLATFORM (windows or unix)
#
# "cygpath" is used on windows to generate native path names for include
# files. These variables should only be used with the compiler and linker
# since they generate native path names.
#
# EXEEXT
#	Select the executable extension based on the host type.  This
#	is a lightweight replacement for AC_EXEEXT that doesn't require
#	a compiler.
#------------------------------------------------------------------------

AC_DEFUN([TEA_INIT], [
    # TEA extensions pass this us the version of TEA they think they
    # are compatible with.
    TEA_VERSION="3.9"

    AC_MSG_CHECKING([for correct TEA configuration])
    if test x"${PACKAGE_NAME}" = x ; then
	AC_MSG_ERROR([
The PACKAGE_NAME variable must be defined by your TEA configure.in])
    fi
    if test x"$1" = x ; then
	AC_MSG_ERROR([
TEA version not specified.])
    elif test "$1" != "${TEA_VERSION}" ; then
	AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
    else
	AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
    fi

    # If the user did not set CFLAGS, set it now to keep macros
    # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
    if test "${CFLAGS+set}" != "set" ; then
	CFLAGS=""
    fi

    case "`uname -s`" in
	*win32*|*WIN32*|*MINGW32_*)
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
	    EXEEXT=".exe"
	    TEA_PLATFORM="windows"
	    ;;
	*CYGWIN_*)
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
	    EXEEXT=".exe"
	    # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
	    ;;
	*)
	    CYGPATH=echo
	    # Maybe we are cross-compiling....
	    case ${host_alias} in
		*mingw32*)
		EXEEXT=".exe"
		TEA_PLATFORM="windows"
		;;
	    *)
		EXEEXT=""
		TEA_PLATFORM="unix"
		;;
	    esac
	    ;;
    esac

    # Check if exec_prefix is set. If not use fall back to prefix.
    # Note when adjusted, so that TEA_PREFIX can correct for this.
    # This is needed for recursive configures, since autoconf propagates
    # $prefix, but not $exec_prefix (doh!).
    if test x$exec_prefix = xNONE ; then
	exec_prefix_default=yes
	exec_prefix=$prefix
    fi

    AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}])

    AC_SUBST(EXEEXT)
    AC_SUBST(CYGPATH)

    # This package name must be replaced statically for AC_SUBST to work
    AC_SUBST(PKG_LIB_FILE)
    # Substitute STUB_LIB_FILE in case package creates a stub library too.
    AC_SUBST(PKG_STUB_LIB_FILE)

    # We AC_SUBST these here to ensure they are subst'ed,
    # in case the user doesn't call TEA_ADD_...
    AC_SUBST(PKG_STUB_SOURCES)
    AC_SUBST(PKG_STUB_OBJECTS)
    AC_SUBST(PKG_TCL_SOURCES)
    AC_SUBST(PKG_HEADERS)
    AC_SUBST(PKG_INCLUDES)
    AC_SUBST(PKG_LIBS)
    AC_SUBST(PKG_CFLAGS)
])

#------------------------------------------------------------------------
# TEA_ADD_SOURCES --
#
#	Specify one or more source files.  Users should check for
#	the right platform before adding to their list.
#	It is not important to specify the directory, as long as it is
#	in the generic, win or unix subdirectory of $(srcdir).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_SOURCES
#		PKG_OBJECTS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_SOURCES], [
    vars="$@"
    for i in $vars; do
	case $i in
	    [\$]*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;
	    *)
		# check for existence - allows for generic/win/unix VPATH
		# To add more dirs here (like 'src'), you have to update VPATH
		# in Makefile.in as well
		if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
		    -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
		    -a ! -f "${srcdir}/macosx/$i" \
		    ; then
		    AC_MSG_ERROR([could not find source file '$i'])
		fi
		PKG_SOURCES="$PKG_SOURCES $i"
		# this assumes it is in a VPATH dir
		i=`basename $i`
		# handle user calling this before or after TEA_SETUP_COMPILER
		if test x"${OBJEXT}" != x ; then
		    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
		else
		    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
		fi
		PKG_OBJECTS="$PKG_OBJECTS $j"
		;;
	esac
    done
    AC_SUBST(PKG_SOURCES)
    AC_SUBST(PKG_OBJECTS)
])

#------------------------------------------------------------------------
# TEA_ADD_STUB_SOURCES --
#
#	Specify one or more source files.  Users should check for
#	the right platform before adding to their list.
#	It is not important to specify the directory, as long as it is
#	in the generic, win or unix subdirectory of $(srcdir).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_STUB_SOURCES
#		PKG_STUB_OBJECTS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_STUB_SOURCES], [
    vars="$@"
    for i in $vars; do
	# check for existence - allows for generic/win/unix VPATH
	if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
	    -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
	    -a ! -f "${srcdir}/macosx/$i" \
	    ; then
	    AC_MSG_ERROR([could not find stub source file '$i'])
	fi
	PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
	# this assumes it is in a VPATH dir
	i=`basename $i`
	# handle user calling this before or after TEA_SETUP_COMPILER
	if test x"${OBJEXT}" != x ; then
	    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
	else
	    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
	fi
	PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
    done
    AC_SUBST(PKG_STUB_SOURCES)
    AC_SUBST(PKG_STUB_OBJECTS)
])

#------------------------------------------------------------------------
# TEA_ADD_TCL_SOURCES --
#
#	Specify one or more Tcl source files.  These should be platform
#	independent runtime files.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_TCL_SOURCES
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_TCL_SOURCES], [
    vars="$@"
    for i in $vars; do
	# check for existence, be strict because it is installed
	if test ! -f "${srcdir}/$i" ; then
	    AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])
	fi
	PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
    done
    AC_SUBST(PKG_TCL_SOURCES)
])

#------------------------------------------------------------------------
# TEA_ADD_HEADERS --
#
#	Specify one or more source headers.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_HEADERS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_HEADERS], [
    vars="$@"
    for i in $vars; do
	# check for existence, be strict because it is installed
	if test ! -f "${srcdir}/$i" ; then
	    AC_MSG_ERROR([could not find header file '${srcdir}/$i'])
	fi
	PKG_HEADERS="$PKG_HEADERS $i"
    done
    AC_SUBST(PKG_HEADERS)
])

#------------------------------------------------------------------------
# TEA_ADD_INCLUDES --
#
#	Specify one or more include dirs.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_INCLUDES
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_INCLUDES], [
    vars="$@"
    for i in $vars; do
	PKG_INCLUDES="$PKG_INCLUDES $i"
    done
    AC_SUBST(PKG_INCLUDES)
])

#------------------------------------------------------------------------
# TEA_ADD_LIBS --
#
#	Specify one or more libraries.  Users should check for
#	the right platform before adding to their list.  For Windows,
#	libraries provided in "foo.lib" format will be converted to
#	"-lfoo" when using GCC (mingw).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_LIBS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_LIBS], [
    vars="$@"
    for i in $vars; do
	if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
	    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib
	    i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
	fi
	PKG_LIBS="$PKG_LIBS $i"
    done
    AC_SUBST(PKG_LIBS)
])

#------------------------------------------------------------------------
# TEA_ADD_CFLAGS --
#
#	Specify one or more CFLAGS.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_CFLAGS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_CFLAGS], [
    PKG_CFLAGS="$PKG_CFLAGS $@"
    AC_SUBST(PKG_CFLAGS)
])

#------------------------------------------------------------------------
# TEA_ADD_CLEANFILES --
#
#	Specify one or more CLEANFILES.
#
# Arguments:
#	one or more file names to clean target
#
# Results:
#
#	Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_CLEANFILES], [
    CLEANFILES="$CLEANFILES $@"
])

#------------------------------------------------------------------------
# TEA_PREFIX --
#
#	Handle the --prefix=... option by defaulting to what Tcl gave
#
# Arguments:
#	none
#
# Results:
#
#	If --prefix or --exec-prefix was not specified, $prefix and
#	$exec_prefix will be set to the values given to Tcl when it was
#	configured.
#------------------------------------------------------------------------
AC_DEFUN([TEA_PREFIX], [
    if test "${prefix}" = "NONE"; then
	prefix_default=yes
	if test x"${TCL_PREFIX}" != x; then
	    AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])
	    prefix=${TCL_PREFIX}
	else
	    AC_MSG_NOTICE([--prefix defaulting to /usr/local])
	    prefix=/usr/local
	fi
    fi
    if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
	-o x"${exec_prefix_default}" = x"yes" ; then
	if test x"${TCL_EXEC_PREFIX}" != x; then
	    AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])
	    exec_prefix=${TCL_EXEC_PREFIX}
	else
	    AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])
	    exec_prefix=$prefix
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_SETUP_COMPILER_CC --
#
#	Do compiler checks the way we want.  This is just a replacement
#	for AC_PROG_CC in TEA configure.in files to make them cleaner.
#
# Arguments:
#	none
#
# Results:
#
#	Sets up CC var and other standard bits we need to make executables.
#------------------------------------------------------------------------
AC_DEFUN([TEA_SETUP_COMPILER_CC], [
    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
    # in this macro, they need to go into TEA_SETUP_COMPILER instead.

    AC_PROG_CC
    AC_PROG_CPP

    #--------------------------------------------------------------------
    # Checks to see if the make program sets the $MAKE variable.
    #--------------------------------------------------------------------

    AC_PROG_MAKE_SET

    #--------------------------------------------------------------------
    # Find ranlib
    #--------------------------------------------------------------------

    AC_CHECK_TOOL(RANLIB, ranlib)

    #--------------------------------------------------------------------
    # Determines the correct binary file extension (.o, .obj, .exe etc.)
    #--------------------------------------------------------------------

    AC_OBJEXT
    AC_EXEEXT
])

#------------------------------------------------------------------------
# TEA_SETUP_COMPILER --
#
#	Do compiler checks that use the compiler.  This must go after
#	TEA_SETUP_COMPILER_CC, which does the actual compiler check.
#
# Arguments:
#	none
#
# Results:
#
#	Sets up CC var and other standard bits we need to make executables.
#------------------------------------------------------------------------
AC_DEFUN([TEA_SETUP_COMPILER], [
    # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
    AC_REQUIRE([TEA_SETUP_COMPILER_CC])

    #------------------------------------------------------------------------
    # If we're using GCC, see if the compiler understands -pipe. If so, use it.
    # It makes compiling go faster.  (This is only a performance feature.)
    #------------------------------------------------------------------------

    if test -z "$no_pipe" -a -n "$GCC"; then
	AC_CACHE_CHECK([if the compiler understands -pipe],
	    tcl_cv_cc_pipe, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	    AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_pipe = yes; then
	    CFLAGS="$CFLAGS -pipe"
	fi
    fi

    #--------------------------------------------------------------------
    # Common compiler flag setup
    #--------------------------------------------------------------------

    AC_C_BIGENDIAN
    if test "${TEA_PLATFORM}" = "unix" ; then
	TEA_TCL_LINK_LIBS
	TEA_MISSING_POSIX_HEADERS
	# Let the user call this, because if it triggers, they will
	# need a compat/strtod.c that is correct.  Users can also
	# use Tcl_GetDouble(FromObj) instead.
	#TEA_BUGGY_STRTOD
    fi
])

#------------------------------------------------------------------------
# TEA_MAKE_LIB --
#
#	Generate a line that can be used to build a shared/unshared library
#	in a platform independent manner.
#
# Arguments:
#	none
#
#	Requires:
#
# Results:
#
#	Defines the following vars:
#	CFLAGS -	Done late here to note disturb other AC macros
#       MAKE_LIB -      Command to execute to build the Tcl library;
#                       differs depending on whether or not Tcl is being
#                       compiled as a shared library.
#	MAKE_SHARED_LIB	Makefile rule for building a shared library
#	MAKE_STATIC_LIB	Makefile rule for building a static library
#	MAKE_STUB_LIB	Makefile rule for building a stub library
#	VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
#	VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
#------------------------------------------------------------------------

AC_DEFUN([TEA_MAKE_LIB], [
    if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
	MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
	AC_EGREP_CPP([manifest needed], [
#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif
	], [
	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
	MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
	TEA_ADD_CLEANFILES([*.manifest])
	])
	MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)"
    else
	MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
    fi

    if test "${SHARED_BUILD}" = "1" ; then
	MAKE_LIB="${MAKE_SHARED_LIB} "
    else
	MAKE_LIB="${MAKE_STATIC_LIB} "
    fi

    #--------------------------------------------------------------------
    # Shared libraries and static libraries have different names.
    # Use the double eval to make sure any variables in the suffix is
    # substituted. (@@@ Might not be necessary anymore)
    #--------------------------------------------------------------------

    if test "${TEA_PLATFORM}" = "windows" ; then
	if test "${SHARED_BUILD}" = "1" ; then
	    # We force the unresolved linking of symbols that are really in
	    # the private libraries of Tcl and Tk.
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} '`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`'"
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} '`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`'"
	    fi
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	else
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
	if test "$GCC" = "yes"; then
	    PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
	fi
	# These aren't needed on Windows (either MSVC or gcc)
	RANLIB=:
	RANLIB_STUB=:
    else
	RANLIB_STUB="${RANLIB}"
	if test "${SHARED_BUILD}" = "1" ; then
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC} ${TCL_LIB_SPEC}"
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
	    fi
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    RANLIB=:
	else
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
    fi

    # These are escaped so that only CFLAGS is picked up at configure time.
    # The other values will be substituted at make time.
    CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
    if test "${SHARED_BUILD}" = "1" ; then
	CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
    fi

    AC_SUBST(MAKE_LIB)
    AC_SUBST(MAKE_SHARED_LIB)
    AC_SUBST(MAKE_STATIC_LIB)
    AC_SUBST(MAKE_STUB_LIB)
    AC_SUBST(RANLIB_STUB)
    AC_SUBST(VC_MANIFEST_EMBED_DLL)
    AC_SUBST(VC_MANIFEST_EMBED_EXE)
])

#------------------------------------------------------------------------
# TEA_LIB_SPEC --
#
#	Compute the name of an existing object library located in libdir
#	from the given base name and produce the appropriate linker flags.
#
# Arguments:
#	basename	The base name of the library without version
#			numbers, extensions, or "lib" prefixes.
#	extra_dir	Extra directory in which to search for the
#			library.  This location is used first, then
#			$prefix/$exec-prefix, then some defaults.
#
# Requires:
#	TEA_INIT and TEA_PREFIX must be called first.
#
# Results:
#
#	Defines the following vars:
#		${basename}_LIB_NAME	The computed library name.
#		${basename}_LIB_SPEC	The computed linker flags.
#------------------------------------------------------------------------

AC_DEFUN([TEA_LIB_SPEC], [
    AC_MSG_CHECKING([for $1 library])

    # Look in exec-prefix for the library (defined by TEA_PREFIX).

    tea_lib_name_dir="${exec_prefix}/lib"

    # Or in a user-specified location.

    if test x"$2" != x ; then
	tea_extra_lib_dir=$2
    else
	tea_extra_lib_dir=NONE
    fi

    for i in \
	    `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do
	if test -f "$i" ; then
	    tea_lib_name_dir=`dirname $i`
	    $1_LIB_NAME=`basename $i`
	    $1_LIB_PATH_NAME=$i
	    break
	fi
    done

    if test "${TEA_PLATFORM}" = "windows"; then
	$1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\"
    else
	# Strip off the leading "lib" and trailing ".a" or ".so"

	tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'`
	$1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}"
    fi

    if test "x${$1_LIB_NAME}" = x ; then
	AC_MSG_ERROR([not found])
    else
	AC_MSG_RESULT([${$1_LIB_SPEC}])
    fi
])

#------------------------------------------------------------------------
# TEA_PRIVATE_TCL_HEADERS --
#
#	Locate the private Tcl include files
#
# Arguments:
#
#	Requires:
#		TCL_SRC_DIR	Assumes that TEA_LOAD_TCLCONFIG has
#				already been called.
#
# Results:
#
#	Substitutes the following vars:
#		TCL_TOP_DIR_NATIVE
#		TCL_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [
    # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}
    AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS])
    AC_MSG_CHECKING([for Tcl private include files])

    TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`
    TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\"

    # Check to see if tcl<Plat>Port.h isn't already with the public headers
    # Don't look for tclInt.h because that resides with tcl.h in the core
    # sources, but the <plat>Port headers are in a different directory
    if test "${TEA_PLATFORM}" = "windows" -a \
	-f "${ac_cv_c_tclh}/tclWinPort.h"; then
	result="private headers found with public headers"
    elif test "${TEA_PLATFORM}" = "unix" -a \
	-f "${ac_cv_c_tclh}/tclUnixPort.h"; then
	result="private headers found with public headers"
    else
	TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\"
	if test "${TEA_PLATFORM}" = "windows"; then
	    TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\"
	else
	    TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\"
	fi
	# Overwrite the previous TCL_INCLUDES as this should capture both
	# public and private headers in the same set.
	# We want to ensure these are substituted so as not to require
	# any *_NATIVE vars be defined in the Makefile
	TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
	if test "`uname -s`" = "Darwin"; then
            # If Tcl was built as a framework, attempt to use
            # the framework's Headers and PrivateHeaders directories
            case ${TCL_DEFS} in
	    	*TCL_FRAMEWORK*)
		    if test -d "${TCL_BIN_DIR}/Headers" -a \
			    -d "${TCL_BIN_DIR}/PrivateHeaders"; then
			TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}"
		    else
			TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
		    fi
	            ;;
	    esac
	    result="Using ${TCL_INCLUDES}"
	else
	    if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then
		AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}])
	    fi
	    result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}"
	fi
    fi

    AC_SUBST(TCL_TOP_DIR_NATIVE)

    AC_SUBST(TCL_INCLUDES)
    AC_MSG_RESULT([${result}])
])

#------------------------------------------------------------------------
# TEA_PUBLIC_TCL_HEADERS --
#
#	Locate the installed public Tcl header files
#
# Arguments:
#	None.
#
# Requires:
#	CYGPATH must be set
#
# Results:
#
#	Adds a --with-tclinclude switch to configure.
#	Result is cached.
#
#	Substitutes the following vars:
#		TCL_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [
    AC_MSG_CHECKING([for Tcl public headers])

    AC_ARG_WITH(tclinclude, [  --with-tclinclude       directory containing the public Tcl header files], with_tclinclude=${withval})

    AC_CACHE_VAL(ac_cv_c_tclh, [
	# Use the value from --with-tclinclude, if it was given

	if test x"${with_tclinclude}" != x ; then
	    if test -f "${with_tclinclude}/tcl.h" ; then
		ac_cv_c_tclh=${with_tclinclude}
	    else
		AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])
	    fi
	else
	    list=""
	    if test "`uname -s`" = "Darwin"; then
		# If Tcl was built as a framework, attempt to use
		# the framework's Headers directory
		case ${TCL_DEFS} in
		    *TCL_FRAMEWORK*)
			list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`"
			;;
		esac
	    fi

	    # Look in the source dir only if Tcl is not installed,
	    # and in that situation, look there before installed locations.
	    if test -f "${TCL_BIN_DIR}/Makefile" ; then
		list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`"
	    fi

	    # Check order: pkg --prefix location, Tcl's --prefix location,
	    # relative to directory of tclConfig.sh.

	    eval "temp_includedir=${includedir}"
	    list="$list \
		`ls -d ${temp_includedir}        2>/dev/null` \
		`ls -d ${TCL_PREFIX}/include     2>/dev/null` \
		`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
	    if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
		list="$list /usr/local/include /usr/include"
		if test x"${TCL_INCLUDE_SPEC}" != x ; then
		    d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'`
		    list="$list `ls -d ${d} 2>/dev/null`"
		fi
	    fi
	    for i in $list ; do
		if test -f "$i/tcl.h" ; then
		    ac_cv_c_tclh=$i
		    break
		fi
	    done
	fi
    ])

    # Print a message based on how we determined the include path

    if test x"${ac_cv_c_tclh}" = x ; then
	AC_MSG_ERROR([tcl.h not found.  Please specify its location with --with-tclinclude])
    else
	AC_MSG_RESULT([${ac_cv_c_tclh}])
    fi

    # Convert to a native path and substitute into the output files.

    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`

    TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"

    AC_SUBST(TCL_INCLUDES)
])

#------------------------------------------------------------------------
# TEA_PRIVATE_TK_HEADERS --
#
#	Locate the private Tk include files
#
# Arguments:
#
#	Requires:
#		TK_SRC_DIR	Assumes that TEA_LOAD_TKCONFIG has
#				 already been called.
#
# Results:
#
#	Substitutes the following vars:
#		TK_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [
    # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}
    AC_REQUIRE([TEA_PUBLIC_TK_HEADERS])
    AC_MSG_CHECKING([for Tk private include files])

    TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`
    TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\"

    # Check to see if tk<Plat>Port.h isn't already with the public headers
    # Don't look for tkInt.h because that resides with tk.h in the core
    # sources, but the <plat>Port headers are in a different directory
    if test "${TEA_PLATFORM}" = "windows" -a \
	-f "${ac_cv_c_tkh}/tkWinPort.h"; then
	result="private headers found with public headers"
    elif test "${TEA_PLATFORM}" = "unix" -a \
	-f "${ac_cv_c_tkh}/tkUnixPort.h"; then
	result="private headers found with public headers"
    else
	TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\"
	TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\"
	if test "${TEA_PLATFORM}" = "windows"; then
	    TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\"
	else
	    TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\"
	fi
	# Overwrite the previous TK_INCLUDES as this should capture both
	# public and private headers in the same set.
	# We want to ensure these are substituted so as not to require
	# any *_NATIVE vars be defined in the Makefile
	TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}"
	# Detect and add ttk subdir
	if test -d "${TK_SRC_DIR}/generic/ttk"; then
	   TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
	fi
	if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
	   TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
	fi
	if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
	   TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
	fi
	if test "`uname -s`" = "Darwin"; then
	    # If Tk was built as a framework, attempt to use
	    # the framework's Headers and PrivateHeaders directories
	    case ${TK_DEFS} in
		*TK_FRAMEWORK*)
			if test -d "${TK_BIN_DIR}/Headers" -a \
				-d "${TK_BIN_DIR}/PrivateHeaders"; then
			    TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}"
			else
			    TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
			fi
			;;
	    esac
	    result="Using ${TK_INCLUDES}"
	else
	    if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then
	       AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}])
	    fi
	    result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}"
	fi
    fi

    AC_SUBST(TK_TOP_DIR_NATIVE)
    AC_SUBST(TK_XLIB_DIR_NATIVE)

    AC_SUBST(TK_INCLUDES)
    AC_MSG_RESULT([${result}])
])

#------------------------------------------------------------------------
# TEA_PUBLIC_TK_HEADERS --
#
#	Locate the installed public Tk header files
#
# Arguments:
#	None.
#
# Requires:
#	CYGPATH must be set
#
# Results:
#
#	Adds a --with-tkinclude switch to configure.
#	Result is cached.
#
#	Substitutes the following vars:
#		TK_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [
    AC_MSG_CHECKING([for Tk public headers])

    AC_ARG_WITH(tkinclude, [  --with-tkinclude        directory containing the public Tk header files], with_tkinclude=${withval})

    AC_CACHE_VAL(ac_cv_c_tkh, [
	# Use the value from --with-tkinclude, if it was given

	if test x"${with_tkinclude}" != x ; then
	    if test -f "${with_tkinclude}/tk.h" ; then
		ac_cv_c_tkh=${with_tkinclude}
	    else
		AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])
	    fi
	else
	    list=""
	    if test "`uname -s`" = "Darwin"; then
		# If Tk was built as a framework, attempt to use
		# the framework's Headers directory.
		case ${TK_DEFS} in
		    *TK_FRAMEWORK*)
			list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`"
			;;
		esac
	    fi

	    # Look in the source dir only if Tk is not installed,
	    # and in that situation, look there before installed locations.
	    if test -f "${TK_BIN_DIR}/Makefile" ; then
		list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`"
	    fi

	    # Check order: pkg --prefix location, Tk's --prefix location,
	    # relative to directory of tkConfig.sh, Tcl's --prefix location,
	    # relative to directory of tclConfig.sh.

	    eval "temp_includedir=${includedir}"
	    list="$list \
		`ls -d ${temp_includedir}        2>/dev/null` \
		`ls -d ${TK_PREFIX}/include      2>/dev/null` \
		`ls -d ${TK_BIN_DIR}/../include  2>/dev/null` \
		`ls -d ${TCL_PREFIX}/include     2>/dev/null` \
		`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
	    if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
		list="$list /usr/local/include /usr/include"
		if test x"${TK_INCLUDE_SPEC}" != x ; then
		    d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'`
		    list="$list `ls -d ${d} 2>/dev/null`"
		fi
	    fi
	    for i in $list ; do
		if test -f "$i/tk.h" ; then
		    ac_cv_c_tkh=$i
		    break
		fi
	    done
	fi
    ])

    # Print a message based on how we determined the include path

    if test x"${ac_cv_c_tkh}" = x ; then
	AC_MSG_ERROR([tk.h not found.  Please specify its location with --with-tkinclude])
    else
	AC_MSG_RESULT([${ac_cv_c_tkh}])
    fi

    # Convert to a native path and substitute into the output files.

    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`

    #TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
    TK_INCLUDES=-I\'${INCLUDE_DIR_NATIVE}\'

    AC_SUBST(TK_INCLUDES)

    if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
	# On Windows and Aqua, we need the X compat headers
	AC_MSG_CHECKING([for X11 header files])
	if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
	    INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
	    TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
	    AC_SUBST(TK_XINCLUDES)
	fi
	AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])
    fi
])

#------------------------------------------------------------------------
# TEA_PATH_CONFIG --
#
#	Locate the ${1}Config.sh file and perform a sanity check on
#	the ${1} compile flags.  These are used by packages like
#	[incr Tk] that load *Config.sh files from more than Tcl and Tk.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-$1=...
#
#	Defines the following vars:
#		$1_BIN_DIR	Full path to the directory containing
#				the $1Config.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_CONFIG], [
    #
    # Ok, lets find the $1 configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-$1
    #

    if test x"${no_$1}" = x ; then
	# we reset no_$1 in case something fails here
	no_$1=true
	AC_ARG_WITH($1, [  --with-$1              directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})
	AC_MSG_CHECKING([for $1 configuration])
	AC_CACHE_VAL(ac_cv_c_$1config,[

	    # First check to see if --with-$1 was specified.
	    if test x"${with_$1config}" != x ; then
		case ${with_$1config} in
		    */$1Config.sh )
			if test -f ${with_$1config}; then
			    AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])
			    with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'`
			fi;;
		esac
		if test -f "${with_$1config}/$1Config.sh" ; then
		    ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`
		else
		    AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])
		fi
	    fi

	    # then check for a private $1 installation
	    if test x"${ac_cv_c_$1config}" = x ; then
		for i in \
			../$1 \
			`ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			../../$1 \
			`ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			../../../$1 \
			`ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			${srcdir}/../$1 \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			; do
		    if test -f "$i/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i; pwd)`
			break
		    fi
		    if test -f "$i/unix/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i/unix; pwd)`
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_$1config}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i; pwd)`
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_$1config}" = x ; then
	    $1_BIN_DIR="# no $1 configs found"
	    AC_MSG_WARN([Cannot find $1 configuration definitions])
	    exit 0
	else
	    no_$1=
	    $1_BIN_DIR=${ac_cv_c_$1config}
	    AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_LOAD_CONFIG --
#
#	Load the $1Config.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		$1_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		$1_SRC_DIR
#		$1_LIB_FILE
#		$1_LIB_SPEC
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_CONFIG], [
    AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])

    if test -f "${$1_BIN_DIR}/$1Config.sh" ; then
        AC_MSG_RESULT([loading])
	. "${$1_BIN_DIR}/$1Config.sh"
    else
        AC_MSG_RESULT([file not found])
    fi

    #
    # If the $1_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable $1_LIB_SPEC will be set to the value
    # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC
    # instead of $1_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    #

    if test -f "${$1_BIN_DIR}/Makefile" ; then
	AC_MSG_WARN([Found Makefile - using build library specs for $1])
        $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}
        $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}
        $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}
        $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC}
        $1_LIBRARY_PATH=${$1_LIBRARY_PATH}
    fi

    AC_SUBST($1_VERSION)
    AC_SUBST($1_BIN_DIR)
    AC_SUBST($1_SRC_DIR)

    AC_SUBST($1_LIB_FILE)
    AC_SUBST($1_LIB_SPEC)

    AC_SUBST($1_STUB_LIB_FILE)
    AC_SUBST($1_STUB_LIB_SPEC)
    AC_SUBST($1_STUB_LIB_PATH)

    # Allow the caller to prevent this auto-check by specifying any 2nd arg
    AS_IF([test "x$2" = x], [
	# Check both upper and lower-case variants
	# If a dev wanted non-stubs libs, this function could take an option
	# to not use _STUB in the paths below
	AS_IF([test "x${$1_STUB_LIB_SPEC}" = x],
	    [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)],
	    [TEA_LOAD_CONFIG_LIB($1_STUB)])
    ])
])

#------------------------------------------------------------------------
# TEA_LOAD_CONFIG_LIB --
#
#	Helper function to load correct library from another extension's
#	${PACKAGE}Config.sh.
#
# Results:
#	Adds to LIBS the appropriate extension library
#------------------------------------------------------------------------
AC_DEFUN([TEA_LOAD_CONFIG_LIB], [
    AC_MSG_CHECKING([For $1 library for LIBS])
    # This simplifies the use of stub libraries by automatically adding
    # the stub lib to your path.  Normally this would add to SHLIB_LD_LIBS,
    # but this is called before CONFIG_CFLAGS.  More importantly, this adds
    # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD.
    if test "x${$1_LIB_SPEC}" != "x" ; then
	if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then
	    TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"])
	    AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}])
	else
	    TEA_ADD_LIBS([${$1_LIB_SPEC}])
	    AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}])
	fi
    else
	AC_MSG_RESULT([file not found])
    fi
])

#------------------------------------------------------------------------
# TEA_EXPORT_CONFIG --
#
#	Define the data to insert into the ${PACKAGE}Config.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		$1
#
# Results:
#	Substitutes the following vars:
#------------------------------------------------------------------------

AC_DEFUN([TEA_EXPORT_CONFIG], [
    #--------------------------------------------------------------------
    # These are for $1Config.sh
    #--------------------------------------------------------------------

    # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib)
    eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}"
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
	eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}"
    else
	eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
    fi
    $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
    $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
    $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
    $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
    $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
    $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"

    AC_SUBST($1_BUILD_LIB_SPEC)
    AC_SUBST($1_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_SPEC)
    AC_SUBST($1_STUB_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_PATH)
    AC_SUBST($1_STUB_LIB_PATH)

    AC_SUBST(MAJOR_VERSION)
    AC_SUBST(MINOR_VERSION)
    AC_SUBST(PATCHLEVEL)
])


#------------------------------------------------------------------------
# TEA_PATH_CELIB --
#
#	Locate Keuchel's celib emulation layer for targeting Win/CE
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-celib=...
#
#	Defines the following vars:
#		CELIB_DIR	Full path to the directory containing
#				the include and platform lib files
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_CELIB], [
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-celib

    if test x"${no_celib}" = x ; then
	# we reset no_celib in case something fails here
	no_celib=true
	AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR], with_celibconfig=${withval})
	AC_MSG_CHECKING([for Windows/CE celib directory])
	AC_CACHE_VAL(ac_cv_c_celibconfig,[
	    # First check to see if --with-celibconfig was specified.
	    if test x"${with_celibconfig}" != x ; then
		if test -d "${with_celibconfig}/inc" ; then
		    ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
		else
		    AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
		fi
	    fi

	    # then check for a celib library
	    if test x"${ac_cv_c_celibconfig}" = x ; then
		for i in \
			../celib-palm-3.0 \
			../celib \
			../../celib-palm-3.0 \
			../../celib \
			`ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
			${srcdir}/../celib-palm-3.0 \
			${srcdir}/../celib \
			`ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
			; do
		    if test -d "$i/inc" ; then
			ac_cv_c_celibconfig=`(cd $i; pwd)`
			break
		    fi
		done
	    fi
	])
	if test x"${ac_cv_c_celibconfig}" = x ; then
	    AC_MSG_ERROR([Cannot find celib support library directory])
	else
	    no_celib=
	    CELIB_DIR=${ac_cv_c_celibconfig}
	    CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
	    AC_MSG_RESULT([found $CELIB_DIR])
	fi
    fi
])


# Local Variables:
# mode: autoconf
# End:

Added tk/test/widget-test.tcl.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
# location of Tk text widget source code:
# /u/prod_dev/tcltk/src/8.5.a5/tk/generic/tkText.c

set DO_TEXT  0 ;# create a std Tk Text widget?
set DO_SBAR  1 ;# create scrollbar?
set DO_FILE  1 ;# load a file?
set DO_FOCUS 1 ;# put focus into widget?
set DO_LANG  1 ;# use syntax highlighting?
set DO_BINDS 1 ;# do we load the default bindings?
set DO_LNUMS 1 ;# show line numbers?
set DO_IMGS  1 ;# show image-based markers?
set DO_FOLD  1 ;# show fold margin

# load the shared library
set SUFFIX ""
if {[info exists ::env(WINDIR)] && [info exists ::tcl_platform(debug)]} {
    set SUFFIX "g"
}

lappend auto_path [file normalize ../../build/usr/lib]
package require ScintillaTk

##################
# TEST
##################
set curr_loc ""
proc moveupdate {args} {
   set ix [$::sci index insert]
   ::scan $ix {%d.%d} row col
   set ::curr_loc [format "RC: %d, %d" $row $col]
}
proc addedupdate {args} {
#   puts "ADDED UPDATE: args=$args"
   eval $::sci margin filln LINENUMBERS $args
}
proc clicked {args} {
   ::lassign $args margin line x y btn shift ctrl alt
   puts "MARGIN CLICK: margin=$margin line=$line X,Y=$x,$y btn=$btn shift=$shift ctrl=$ctrl alt=$alt"
}
set scif .cf
destroy $scif .t

# create the widget
frame $scif
set sci $scif.c
scintilla $sci
set rpad [frame $scif.rpad -width 4] ;# << "internal" pad on RHS of text area
$scif config -bg [$sci cget -bg]
$rpad config -bg [$sci cget -bg]
pack $rpad -side right -fill y
pack $sci -side left -fill both -expand 1

# configure callbacks
$sci config -moveupdatec moveupdate -linesa addedupdate

# configure appearance
$sci tag config exec -margin -fg red


# configure the margins we want
$sci margin config 0 -type text      -alias cov1
$sci margin config 1 -type symbol    -alias cov2          -clickc clicked
$sci margin config 2 -type lnums_alt -alias LINENUMBERS   -clickc clicked
$sci margin config 3 -type symbol    -alias marks -wid 18 -clickc clicked
$sci margin config 4 -type fold

if {$DO_SBAR} {
   ttk::scrollbar .vsb -command "$sci yview"
   ttk::scrollbar .hsb -command "$sci xview" -orient horizontal
   $sci config -yscrollcommand ".vsb set"
   $sci config -xscrollcommand ".hsb set"

   frame .f
   button .f.b1 -text "-" -command "$sci zoomout" -repeatdelay 500 -repeatint 100
   button .f.b2 -text "+" -command "$sci zoomin"  -repeatdelay 500 -repeatint 100
   label .f.loc -textvariable ::curr_loc -font {-family courier} -relief sunken
   label .f.l -text "Zoom:"
   pack .f.loc -side right
   pack .f.l .f.b1 .f.b2 -side left

   grid $scif  -row 0 -column 0 -sticky nswe
   grid .vsb -row 0 -column 1 -sticky ns
   grid .hsb -row 1 -column 0 -sticky we
   grid .f   -row 2 -column 0 -sticky we
   grid rowconfig    . 0 -weight 1
   grid columnconfig . 0 -weight 1
} else {
   pack $scif -fill both -expand 1
}

set lang "none"

if {[llength $argv] > 0} {
	set f [lindex $argv 0]
} else {
set EX .
set f $EX/PlatTK.cxx
}

if {$DO_LANG} {
switch [::file extension $f] {
   .tcl                 {$sci config -lang tcl}
   .sv - .svh - .v      {$sci config -lang verilog}
   .c - .cxx - .cpp     {$sci config -lang cpp}
   .vhd - .vhdl         {$sci config -lang vhdl}
   .htm - .html - .rmdb {$sci config -lang html}
}
}
if {$DO_TEXT} {
   toplevel .t
   wm title .t "Tk Text"
   ttk::scrollbar .t.vsb -command ".t.t yview"
   ttk::scrollbar .t.hsb -command ".t.t xview" -orient horizontal
   text .t.t -wrap none -yscrollc ".t.vsb set" -xscrollc ".t.hsb set"
   grid .t.t   -row 0 -column 0 -sticky nswe
   grid .t.vsb -row 0 -column 1 -sticky ns
   grid .t.hsb -row 1 -column 0 -sticky we
   grid rowconfig    .t 0 -weight 1
   grid columnconfig .t 0 -weight 1
#    pack .t.vsb -side right -fill y    -expand 0
#    pack .t.t   -side left  -fill both -expand 1
}
if {$DO_FILE} {
   set fd [open $f r]
   puts [format "FILE LOAD TIME1: %s" [lrange [time [list $sci insert end [read $fd]]] 0 1]]
   if {$DO_TEXT} {
      seek $fd 0
      puts [format "FILE LOAD TIME2: %s" [lrange [time [list .t.t insert end [read $fd]]] 0 1]]
   }
   close $fd
   if {$DO_LNUMS} {
      $sci margin show LINENUMBERS ;# do it here so we'll know how many lines are in the file
   }
   wm title . "Scintilla TK ($f)"
} else {
   wm title . "Scintilla TK"
}
if {$DO_FOCUS} {
   focus $sci
}
. config -bg red ;# <<< this will show if we're missing something in the paint code

set xpm_pointer {/* XPM */
static char * InlineData[] = {
"16 16 14 1",
"  s None c None",
". c #0080ff",
"# c #006ce0",
"a c #0000c0",
"b c #3b9bff",
"c c #3b70ea",
"d c #0076ef",
"e c #58a8ff",
"f c #002cc0",
"g c #168aff",
"h c #162ad0",
"i c #0042c0",
"j c #0058c0",
"k c #2c54e0",
"                ",
"       j        ",
"       #b       ",
"       #.b      ",
"       #..g     ",
"j######d...ge   ",
"j............b  ",
"j#############j ",
"jaaaaaaaaaaaahj ",
"jaaaaaaaaaaak   ",
"ajjjjjjfaaac    ",
"       fahc     ",
"       fh       ",
"       i        ",
"                ",
"                "};}
set xpm_rightarrow {/* XPM */
static char * InlineData[] = {
"16 16 76 2",
"   s None c None",
".. c #0543df",
"#. c #083bcc",
"a. c #0850e2",
"b. c #0659f0",
"c. c #065af4",
"d. c #073dc7",
"e. c #0551eb",
"f. c #3d9cfd",
"g. c #0127b7",
"h. c #0360fb",
"i. c #065cf8",
"j. c #7bbefd",
"k. c #1789fd",
"l. c #0127b3",
"m. c #0668fc",
"n. c #025df4",
"o. c #0752eb",
"p. c #3c96fc",
"q. c #0f68fb",
"r. c #0649e2",
"s. c #0940cb",
"t. c #247ffc",
"u. c #0637c2",
"v. c #3090fc",
"w. c #0638c6",
"x. c #063cd6",
"y. c #064fe4",
"z. c #55acfd",
"A. c #093bc9",
"B. c #91c4fd",
"C. c #0350ed",
"D. c #71b9fd",
"E. c #419efd",
"F. c #083fcc",
"G. c #0841d4",
"H. c #022fc2",
"I. c #0460f8",
"J. c #4fa5fd",
"K. c #69b2fd",
"L. c #3291fc",
"M. c #084fe0",
"N. c #57adfd",
"O. c #0548df",
"P. c #0550e9",
"Q. c #022abc",
"R. c #0e79fe",
"S. c #a1ccfd",
"T. c #0740d1",
"U. c #0743dd",
"V. c #0748db",
"W. c #0749df",
"X. c #0128b9",
"Y. c #073cd3",
"Z. c #1074fc",
"0. c #0750e5",
"1. c #33a5fd",
"2. c #0335c5",
"3. c #074deb",
"4. c #0457f0",
"5. c #032fbf",
"6. c #025ffa",
"7. c #093ac7",
"8. c #b6d5fc",
"9. c #3c92fc",
".# c #064ae4",
"## c #1e7cfc",
"a# c #0535c1",
"b# c #4fa9fd",
"c# c #2796fd",
"d# c #0650e6",
"e# c #0351ef",
"f# c #43a3fd",
"g# c #0842d6",
"h# c #086ffc",
"i# c #4db5fd",
"                                ",
"                  a.5.          ",
"                  y.9.5.        ",
"                  d#p.J.a#      ",
"    W.M.0.o.b.i.q.t.f.b#K.u.    ",
"    g#U..#o.c.q.##v.E.z.D.B.w.  ",
"    g#U..#3.c.q.##L.f#N.j.S.8.d.",
"    7.7.7.7.#.x.O.e#6.h#k.1.i#2.",
"    7.7.7.7.A.Y...C.n.m.R.c#H.  ",
"    G.G.G.G.G.V.r.P.4.h.Z.Q.    ",
"                  T.P.I.X.      ",
"                  F.e.g.        ",
"                  s.l.          ",
"                                ",
"                                ",
"                                "};}
set xpm_rainbow {/* XPM */
static char * InlineData[] = {
"16 16 199 2",
"   s None c None",
".. c #faceac",
"#. c #f8ed8d",
"a. c #1d6494",
"b. c #fc0e2b",
"c. c #1a8693",
"d. c #f53780",
"e. c #705fbd",
"f. c #f9dd9d",
"g. c #f24dac",
"h. c #6c43ff",
"i. c #ed6ae7",
"j. c #f054bb",
"k. c #9955ff",
"l. c #4457a7",
"m. c #695eba",
"n. c #ebf388",
"o. c #245297",
"p. c #f348a1",
"q. c #12e190",
"r. c #ff81fa",
"s. c #fda0db",
"t. c #f8e496",
"u. c #f479ff",
"v. c #1c7094",
"w. c #f056bf",
"x. c #35fd8d",
"y. c #fbbdbd",
"z. c #ca6eea",
"A. c #f24ba9",
"B. c #eb73fa",
"C. c #4458a7",
"D. c #fca9d3",
"E. c #fcafcc",
"F. c #f63479",
"G. c #facead",
"H. c #fca7d4",
"I. c #1b7b94",
"J. c #ff82fa",
"K. c #37fd8d",
"L. c #bcf589",
"M. c #189f92",
"N. c #ebf289",
"O. c #c46de7",
"P. c #1e6694",
"Q. c #fa1d49",
"R. c #f3459a",
"S. c #b1f68a",
"T. c #baf689",
"U. c #fbb0cc",
"V. c #ed6eef",
"W. c #199592",
"X. c #de71f4",
"Y. c #705fbe",
"Z. c #edf289",
"0. c #5039ff",
"1. c #f6367d",
"2. c #bb62ff",
"3. c #f9db9f",
"4. c #f6f288",
"5. c #ef5fd2",
"6. c #ca68ff",
"7. c #f43d8c",
"8. c #3efc8d",
"9. c #f3479e",
".# c #f348a2",
"## c #ec70f3",
"a# c #f8265c",
"b# c #ee65dd",
"c# c #d16fee",
"d# c #f05ac7",
"e# c #73fa8c",
"f# c #7ff98b",
"g# c #f53985",
"h# c #17ab92",
"i# c #1b7f93",
"j# c #fbbdbe",
"k# c #f92255",
"l# c #ed68e5",
"m# c #bc63ff",
"n# c #fc163b",
"o# c #1a8a93",
"p# c #f151b5",
"q# c #8b64cb",
"r# c #f3469f",
"s# c #17ac92",
"t# c #fcabcf",
"u# c #8c64cb",
"v# c #fad2a8",
"w# c #c9f489",
"x# c #32549f",
"y# c #4758a8",
"z# c #f058c4",
"A# c #50fb8c",
"B# c #11fe8e",
"C# c #f7ef8a",
"D# c #12dd8f",
"E# c #7ff88c",
"F# c #10f28f",
"G# c #eb75ff",
"H# c #fd95e6",
"I# c #85f98b",
"J# c #9f58ff",
"K# c #f152b5",
"L# c #d870f2",
"M# c #f9d9a1",
"N# c #fc1334",
"O# c #f8265d",
"P# c #f53c89",
"Q# c #af5eff",
"R# c #1b8193",
"S# c #f7306f",
"T# c #f059c4",
"U# c #ec6be9",
"V# c #a158ff",
"W# c #f24eae",
"X# c #ee60d3",
"Y# c #fb1a43",
"Z# c #3b56a2",
"0# c #ed6ced",
"1# c #9352ff",
"2# c #18a392",
"3# c #ef5fcf",
"4# c #fd9cdf",
"5# c #fbc3b8",
"6# c #c3f58a",
"7# c #59fa8c",
"8# c #1e5694",
"9# c #fa2152",
".a c #b36adf",
"#a c #f9daa1",
"aa c #1c6b94",
"ba c #f82861",
"ca c #f73377",
"da c #cdf589",
"ea c #f53982",
"fa c #fd7cff",
"ga c #ee63db",
"ha c #ee62d7",
"ia c #e070ff",
"ja c #19fe8e",
"ka c #50fb8d",
"la c #fac2b9",
"ma c #1a8d93",
"na c #f8ef8b",
"oa c #11ea8f",
"pa c #1a8393",
"qa c #fd95e7",
"ra c #fda3d8",
"sa c #17b191",
"ta c #eb70f5",
"ua c #f82a65",
"va c #a0f68a",
"wa c #f347a0",
"xa c #f9d9a2",
"ya c #ee77ff",
"za c #95f78b",
"Aa c #d4f489",
"Ba c #10f58f",
"Ca c #f73174",
"Da c #f73070",
"Ea c #f059c5",
"Fa c #96f78b",
"Ga c #a167d6",
"Ha c #f44191",
"Ia c #f054ba",
"Ja c #ed6ae6",
"Ka c #fac9b2",
"La c #f6377f",
"Ma c #3c30ff",
"Na c #fac1ba",
"Oa c #3455a0",
"Pa c #a0f78a",
"Qa c #8262c6",
"Ra c #3d30ff",
"Sa c #ec71f5",
"Ta c #ec72f9",
"Ua c #18a891",
"Va c #3555a0",
"Wa c #f8275e",
"Xa c #f14faf",
"Ya c #fe091f",
"Za c #fbbfbb",
"0a c #a2f78a",
"1a c #a969d9",
"2a c #ee62d8",
"3a c #1c7093",
"4a c #fb1c48",
"5a c #f72e6d",
"6a c #5c5cb3",
"7a c #3c31ff",
"8a c #d36cff",
"9a c #a7f68a",
".b c #22fe8e",
"#b c #fac8b3",
"ab c #2efd8d",
"bb c #fca1da",
"cb c #3d31ff",
"db c #ef5dcd",
"    cbcb7acbcb1#J#cbRacbcbcb    ",
"  7a7acb6.bb#bM#3.G.U.ya7aRaMa  ",
"7acbcbqaf.vaK.oaq..bf##.E.V#cbcb",
"7a7as.n..bpax#m.e.y#3aD#S.y.1#7a",
"cbJ.naBa8#.a0#b#gai.L#l.s#T.H.cb",
"0.Kakaa.c#haK#p.r#W#dbSaZ#F#t.8a",
"G#4.h#Qab#g.eaS#5a1.wa3#O.i#0a4#",
"H#9aI.X.z#7.ua4aY#a#d.p#V.o.A#j#",
"raI#P.SaIaLak#b.YaQ.CaA.l#l.ab#b",
"4#zav.Taw.g#O#n#N#9#F.XaU#Va8.5#",
"r.AaW.1aX#9.cabaWaDaHaT#B.aaE#t#",
"Q#M#jaOa##d#.#7.P#R.j.JaY.saZ.fa",
"7as.L.2#6ata2ad#Ea5.0#q#R#e#Nacb",
"Rak.laFaUao.u#z.c#GaC.ma7##aiacb",
"  cb2.Zadax.h#o#c.M.B#Pav#u.cb  ",
"    cbh.H#..C#w#6#N.xaD.m#cb    "};}

puts "LOADED widget.tcl"

if {$DO_IMGS} {
    if {![catch {package require Img} oops]} {

		set img1 [image create photo -data $xpm_pointer]
		$sci marker configure pointer -image $img1

		set img2 [image create photo -data $xpm_rightarrow]
		$sci marker configure rightarrow -image $img2
	} else {

		$sci marker configure pointer -xpm $xpm_pointer

		$sci marker configure rightarrow -xpm $xpm_rightarrow
	}

    # here's an example of using the raw XPM data directly
    $sci marker configure rainbow -xpm $xpm_rainbow

    $sci margin marker 3 add pointer 16
    $sci margin marker 3 add rainbow 17
    $sci margin marker 3 add rightarrow 19
}

if {$DO_FOLD} {
	$sci margin show fold
}

Added tk/test/widget-text-test.tcl.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
#
# Taken from Tk tests for the text widget
#

proc test {tname desc args} {
	global testlist
	set match 0
	foreach t $testlist {
		if {[set match [string match $t $tname]]} {
			break
		}
	}
	if {!$match} return

	foreach {opt val} $args {
		switch -- $opt {
			-setup {
				set setup $val
			}
			-body {
				set script $val
			}
			-cleanup {
				set cleanup $val
			}
			-result {
				set expected $val
			}
			default {
				lappend leftover $opt $val
			}
		}
	}
	if {[info exists leftover]} {
		lassign $leftover script expected
	}
	puts -nonewline "# $tname - $desc..."
	if {[info exists setup]} {
		if {[catch {uplevel $setup} rv]} {
			puts "\nError: $rv"
			return
		}
	}
	if {[catch {uplevel $script} rv]} {
		puts " Error: $rv"
	} elseif {[string compare $rv $expected]} {
		puts " Error: mismatch. Exptected: \"$expected\" Got: \"$rv\""
	} else {
		puts " Pass"
	}
	if {[info exists cleanup]} {
		if {[catch {uplevel $cleanup} rv]} {
			puts "Cleanup Error: $rv"
			return
		}
	}
}

proc deleteWindows {} {
	catch {
		foreach c [winfo children .] {
			destroy $c
		}
	}
}


# load the shared library
lappend auto_path [file normalize ../../build/usr/lib]
package require ScintillaTk

scintilla .t
pack .t

catch {destroy .t2}
scintilla .t2
set i 0


if {[llength $argv] > 0} {
	set testlist $argv
} else {
	set testlist *
}

foreach test {
    {-autoseparators yes 1 nah}
    {-background #ff00ff #ff00ff <gorp>}
    {-bd 4 4 foo}
    {-bg blue blue #xx}
    {-blockcursor 0 0 xx}
    {-borderwidth 7 7 ++}
    {-cursor watch watch lousy}
    {-exportselection no 0 maybe}
    {-fg red red stupid}
    {-font fixed fixed {}}
    {-foreground #012 #012 bogus}
    {-height 5 5 bad}
    {-highlightbackground #123 #123 bogus}
    {-highlightcolor #234 #234 bogus}
    {-highlightthickness -2 0 bad}
    {-inactiveselectbackground #ffff01234567 #ffff01234567 bogus}
    {-insertbackground green green <bogus>}
    {-insertborderwidth 45 45 bogus}
    {-insertofftime 100 100 2.4}
    {-insertontime 47 47 e1}
    {-insertwidth 2.3 2 47d}
    {-maxundo 5 5 noway}
    {-padx 3.4 3 2.4.}
    {-pady 82 82 bogus}
    {-relief raised raised bumpy}
    {-selectbackground #ffff01234567 #ffff01234567 bogus}
    {-selectborderwidth 21 21 3x}
    {-selectforeground yellow yellow #12345}
    {-spacing1 20 20 1.3x}
    {-spacing1 -5 0 bogus}
    {-spacing2 5 5 bogus}
    {-spacing2 -1 0 bogus}
    {-spacing3 20 20 bogus}
    {-spacing3 -10 0 bogus}
    {-state d disabled foo}
    {-tabs {1i 2i 3i 4i} {1i 2i 3i 4i} bad_tabs}
    {-tabstyle wordprocessor wordprocessor garbage}
    {-undo 1 1 eh}
    {-width 73 73 2.4}
    {-wrap w word bad_wrap}
} {
    test text-1.[incr i] {text options} {
	set result {}
	lappend result [catch {.t2 configure [lindex $test 0] [lindex $test 3]}]
	.t2 configure [lindex $test 0] [lindex $test 1]
	lappend result [.t2 cget [lindex $test 0]]
    } [list 1 [lindex $test 2]]
}
test text-1.[incr i] {text options} {
    .t2 configure -takefocus "any old thing"
    .t2 cget -takefocus
} {any old thing}
test text-1.[incr i] {text options} {
    .t2 configure -xscrollcommand "x scroll command"
    .t2 configure -xscrollcommand
} {-xscrollcommand xScrollCommand ScrollCommand {} {x scroll command}}
test text-1.[incr i] {text options} {
    .t2 configure -yscrollcommand "test command"
    .t2 configure -yscrollcommand
} {-yscrollcommand yScrollCommand ScrollCommand {} {test command}}
test text-1.[incr i] {text options} {
    set result {}
    foreach i [.t2 configure] {
	lappend result [lindex $i 4]
    }
    set result
} {1 blue {} {} 0 7 watch {} 0 {} fixed #012 5 #123 #234 0 #ffff01234567 green 45 100 47 2 5 3 82 raised #ffff01234567 21 yellow 0 0 0 0 {} disabled {1i 2i 3i 4i} wordprocessor {any old thing} 1 73 word {x scroll command} {test command}}

test text-2.1 {Tk_TextCmd procedure} {
    list [catch {text} msg] $msg
} {1 {wrong # args: should be "text pathName ?options?"}}
test text-2.2 {Tk_TextCmd procedure} {
    list [catch {scintilla foobar} msg] $msg
} {1 {bad window path name "foobar"}}
test text-2.3 {Tk_TextCmd procedure} {
    catch {destroy .t2}
    list [catch {scintilla .t2 -gorp nofun} msg] $msg [winfo exists .t2]
} {1 {unknown option "-gorp"} 0}
test text-2.4 {Tk_TextCmd procedure} {
    catch {destroy .t2}
    list [catch {scintilla .t2 -bd 2 -fg red} msg] $msg \
	[lindex [.t2 config -bd] 4] [lindex [.t2 config -fg] 4]
} {0 .t2 2 red}
if {$tcl_platform(platform) == "windows"} {
    set relief flat
} elseif {[tk windowingsystem] eq "aqua"} {
    set relief solid
} else {
    set relief raised
}
test text-2.5 {Tk_TextCmd procedure} {
    catch {destroy .t2}
    scintilla .t2
    .t2 tag cget sel -relief 
} $relief
test text-2.6 {Tk_TextCmd procedure} {
    catch {destroy .t2}
    list [scintilla .t2] [winfo class .t2]
} {.t2 Scintilla}

test text-3.1 {TextWidgetCmd procedure, basics} {
    list [catch {.t} msg] $msg
} {1 {wrong # args: should be ".t option ?arg arg ...?"}}
test text-3.2 {TextWidgetCmd procedure} {
    list [catch {.t gorp 1.0 z 1.2} msg] $msg
} {1 {bad option "gorp": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}

test text-4.1 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
test text-4.2 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox a b} msg] $msg
} {1 {wrong # args: should be ".t bbox index"}}
test text-4.3 {TextWidgetCmd procedure, "bbox" option} {
    list [catch {.t bbox bad_mark} msg] $msg
} {1 {bad text index "bad_mark"}}

test text-5.1 {TextWidgetCmd procedure, "cget" option} {
    list [catch {.t cget} msg] $msg
} {1 {wrong # args: should be ".t cget option"}}
test text-5.2 {TextWidgetCmd procedure, "cget" option} {
    list [catch {.t cget a b} msg] $msg
} {1 {wrong # args: should be ".t cget option"}}
test text-5.3 {TextWidgetCmd procedure, "cget" option} {
    list [catch {.t cget -gorp} msg] $msg
} {1 {unknown option "-gorp"}}
test text-5.4 {TextWidgetCmd procedure, "cget" option} {
    .t configure -bd 17
    .t cget -bd
} {17}
.t configure -borderwidth [lindex [.t configure -borderwidth] 3]

test text-6.1 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare a b} msg] $msg
} {1 {wrong # args: should be ".t compare index1 op index2"}}
test text-6.2 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare a b c d} msg] $msg
} {1 {wrong # args: should be ".t compare index1 op index2"}}
test text-6.3 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare @x == 1.0} msg] $msg
} {1 {bad text index "@x"}}
test text-6.4 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 < @y} msg] $msg
} {1 {bad text index "@y"}}
test text-6.5 {TextWidgetCmd procedure, "compare" option} {
    list [.t compare 1.1 < 1.0] [.t compare 1.1 < 1.1] [.t compare 1.1 < 1.2]
} {0 0 1}
test text-6.6 {TextWidgetCmd procedure, "compare" option} {
    list [.t compare 1.1 <= 1.0] [.t compare 1.1 <= 1.1] [.t compare 1.1 <= 1.2]
} {0 1 1}
test text-6.7 {TextWidgetCmd procedure, "compare" option} {
    list [.t compare 1.1 == 1.0] [.t compare 1.1 == 1.1] [.t compare 1.1 == 1.2]
} {0 1 0}
test text-6.8 {TextWidgetCmd procedure, "compare" option} {
    list [.t compare 1.1 >= 1.0] [.t compare 1.1 >= 1.1] [.t compare 1.1 >= 1.2]
} {1 1 0}
test text-6.9 {TextWidgetCmd procedure, "compare" option} {
    list [.t compare 1.1 > 1.0] [.t compare 1.1 > 1.1] [.t compare 1.1 > 1.2]
} {1 0 0}
test text-6.10 {TextWidgetCmd procedure, "compare" option} {
    list [.t com 1.1 != 1.0] [.t compare 1.1 != 1.1] [.t compare 1.1 != 1.2]
} {1 0 1}
test text-6.11 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 <x 1.2} msg] $msg
} {1 {bad comparison operator "<x": must be <, <=, ==, >=, >, or !=}}
test text-6.12 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 >> 1.2} msg] $msg
} {1 {bad comparison operator ">>": must be <, <=, ==, >=, >, or !=}}
test text-6.13 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t compare 1.0 z 1.2} msg] $msg
} {1 {bad comparison operator "z": must be <, <=, ==, >=, >, or !=}}
test text-6.14 {TextWidgetCmd procedure, "compare" option} {
    list [catch {.t co 1.0 z 1.2} msg] $msg
} {1 {ambiguous option "co": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}

# "configure" option is already covered above

test text-7.1 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t debug 0 1} msg] $msg
} {1 {wrong # args: should be ".t debug boolean"}}
test text-7.2 {TextWidgetCmd procedure, "debug" option} {
    list [catch {.t de 0 1} msg] $msg
} {1 {ambiguous option "de": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
test text-7.3 {TextWidgetCmd procedure, "debug" option} {
    .t debug true
    .t deb
} 1
test text-7.4 {TextWidgetCmd procedure, "debug" option} {
    .t debug false
    .t debug
} 0
catch {.t debug}

test text-8.1 {TextWidgetCmd procedure, "delete" option} {
    list [catch {.t delete} msg] $msg
} {1 {wrong # args: should be ".t delete index1 ?index2 ...?"}}
test text-8.2 {TextWidgetCmd procedure, "delete" option} {
    list [catch {.t delete a b c} msg] $msg
} {1 {bad text index "a"}}
test text-8.3 {TextWidgetCmd procedure, "delete" option} {
    list [catch {.t delete @x 2.2} msg] $msg
} {1 {bad text index "@x"}}
test text-8.4 {TextWidgetCmd procedure, "delete" option} {
    list [catch {.t delete 2.3 @y} msg] $msg
} {1 {bad text index "@y"}}
test text-8.5 {TextWidgetCmd procedure, "delete" option} {
    .t configure -state disabled
    .t delete 2.3
    .t g 2.0 2.end
} abcdefghijklm
.t configure -state normal
test text-8.6 {TextWidgetCmd procedure, "delete" option} {
    .t delete 2.3
    .t get 2.0 2.end
} abcefghijklm
test text-8.7 {TextWidgetCmd procedure, "delete" option} {
    .t delete 2.1 2.3
    .t get 2.0 2.end
} aefghijklm
test text-8.8 {TextWidgetCmd procedure, "delete" option} {
    # All indices are checked before we actually delete anything
    list [catch {.t delete 2.1 2.3 foo} msg] $msg \
	    [.t get 2.0 2.end]
} {1 {bad text index "foo"} aefghijklm}
set prevtext [.t get 1.0 end-1c]
test text-8.9 {TextWidgetCmd procedure, "delete" option} {
    # auto-forward one byte if the last "pair" is just one
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.1 2.3 2.3
    .t get 1.0 end-1c
} foo\naefghijklm
test text-8.10 {TextWidgetCmd procedure, "delete" option} {
    # all indices will be ordered before deletion
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.3 2.7 2.9 2.4
    .t get 1.0 end-1c
} foo\ndfgjklm
test text-8.11 {TextWidgetCmd procedure, "delete" option} {
    # and check again with even pairs
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.2 2.7 2.9 2.4 2.5
    .t get 1.0 end-1c
} foo\ncdfgjklm
test text-8.12 {TextWidgetCmd procedure, "delete" option} {
    # we should get the longest range on equal start indices
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.2 2.0 2.5 2.0 2.3 2.8 2.7
    .t get 1.0 end-1c
} foo\nfghijklm
test text-8.13 {TextWidgetCmd procedure, "delete" option} {
    # we should get the longest range on equal start indices
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.2 1.2 2.6 2.0 2.5
    .t get 1.0 end-1c
} foghijklm
test text-8.14 {TextWidgetCmd procedure, "delete" option} {
    # we should get the longest range on equal start indices
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.2 2.0 2.5 1.1 2.3 2.8 2.7
    .t get 1.0 end-1c
} ffghijklm
test text-8.15 {TextWidgetCmd procedure, "delete" option} {
    # we should get the watch for overlapping ranges - they should
    # essentially be merged into one span.
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.6 2.2 2.8
    .t get 1.0 end-1c
} foo\nijklm
test text-8.16 {TextWidgetCmd procedure, "delete" option} {
    # we should get the watch for overlapping ranges - they should
    # essentially be merged into one span.
    .t delete 1.0 end; .t insert 1.0 "foo\nabcdefghijklm"
    .t delete 2.0 2.6 2.2 2.4
    .t get 1.0 end-1c
} foo\nghijklm
.t delete 1.0 end; .t insert 1.0 $prevtext
test text-8.17 {TextWidgetCmd procedure, "replace" option} {
    list [catch {.t replace 1.3 2.3} err] $err
} {1 {wrong # args: should be ".t replace index1 index2 chars ?tagList chars tagList ...?"}}
test text-8.18 {TextWidgetCmd procedure, "replace" option} {
    list [catch {.t replace 3.1 2.3 foo} err] $err
} {1 {Index "2.3" before "3.1" in the text}}
test text-8.19 {TextWidgetCmd procedure, "replace" option} {
    list [catch {.t replace 2.1 2.3 foo} err] $err
} {0 {}}
.t delete 1.0 end; .t insert 1.0 $prevtext
test text-8.20 {TextWidgetCmd procedure, "replace" option with undo} {
    .t configure -undo 0
    .t configure -undo 1
    # Ensure it is treated as a single undo action
    .t replace 2.1 2.3 foo
    .t edit undo
    .t configure -undo 0
    string equal [.t get 1.0 end-1c] $prevtext
} {1}
test text-8.21 {TextWidgetCmd procedure, "replace" option with undo} {
    .t configure -undo 0
    .t configure -undo 1
    .t replace 2.1 2.3 foo
    # Ensure we can override a text widget and intercept undo
    # actions.  If in the future a different mechanism is available
    # to do this, then we should be able to change this test.  The
    # behaviour tested for here is not, strictly speaking, documented.
    rename .t test.t
    set res {}
    proc .t {args} { lappend ::res $args ; uplevel 1 test.t $args }
    .t edit undo
    rename .t {}
    rename test.t .t
    .t configure -undo 0
    set res
} {{edit undo} {delete 2.1 2.4} {mark set insert 2.1} {see insert} {insert 2.1 ef} {mark set insert 2.3} {see insert}}
test text-8.22 {TextWidgetCmd procedure, "replace" option with undo} {
    .t configure -undo 0
    .t configure -undo 1
    # Ensure that undo (even composite undo like 'replace')
    # works when the widget shows nothing useful.
    .t replace 2.1 2.3 foo
    .t configure -start 1 -end 1
    .t edit undo
    .t configure -start {} -end {}
    .t configure -undo 0
    if {![string equal [.t get 1.0 end-1c] $prevtext]} {
	set res [list [.t get 1.0 end-1c] ne $prevtext]
    } else {
	set res 1
    }
} {1}
.t delete 1.0 end; .t insert 1.0 $prevtext
test text-8.23 {TextWidgetCmd procedure, "replace" option with peers, undo} {
    .t configure -undo 0
    .t configure -undo 1
    .t peer create .tt -undo 1
    # Ensure that undo (even composite undo like 'replace')
    # works when the the event took place in one peer, which
    # is then deleted, before the undo takes place in another peer.
    .tt replace 2.1 2.3 foo
    .tt configure -start 1 -end 1
    destroy .tt
    .t edit undo
    .t configure -start {} -end {}
    .t configure -undo 0
    if {![string equal [.t get 1.0 end-1c] $prevtext]} {
	set res [list [.t get 1.0 end-1c] ne $prevtext]
    } else {
        set res 1
    }
} {1}
.t delete 1.0 end; .t insert 1.0 $prevtext
test text-8.24 {TextWidgetCmd procedure, "replace" option with peers, undo} {
    .t configure -undo 0
    .t configure -undo 1
    .t peer create .tt -undo 1
    # Ensure that undo (even composite undo like 'replace')
    # works when the the event took place in one peer, which
    # is then deleted, before the undo takes place in another peer
    # which isn't showing everything.
    .tt replace 2.1 2.3 foo
    set res [.tt get 2.1 2.4]
    .tt configure -start 1 -end 1
    destroy .tt
    .t configure -start 3 -end 4
    # msg will actually be set to a silently ignored error message here,
    # (that the .tt command doesn't exist), but that is not important.
    lappend res [catch {.t edit undo} msg]
    .t configure -undo 0
    .t configure -start {} -end {}
    if {![string equal [.t get 1.0 end-1c] $prevtext]} {
	lappend res [list [.t get 1.0 end-1c] ne $prevtext]
    } else {
	lappend res 1
    }
} {foo 0 1}
test text-8.25 {TextWidgetCmd procedure, "replace" option crash} -setup {
    destroy .tt
} -body {
    scintilla .tt
    .tt insert 0.0 foo\n
    .tt replace end-1l end bar
} -cleanup {
    destroy .tt
} -result {}

.t delete 1.0 end; .t insert 1.0 $prevtext

test text-9.1 {TextWidgetCmd procedure, "get" option} {
    list [catch {.t get} msg] $msg
} {1 {wrong # args: should be ".t get ?-displaychars? ?--? index1 ?index2 ...?"}}
test text-9.2 {TextWidgetCmd procedure, "get" option} {
    list [catch {.t get a b c} msg] $msg
} {1 {bad text index "a"}}
test text-9.3 {TextWidgetCmd procedure, "get" option} {
    list [catch {.t get @q 3.1} msg] $msg
} {1 {bad text index "@q"}}
test text-9.4 {TextWidgetCmd procedure, "get" option} {
    list [catch {.t get 3.1 @r} msg] $msg
} {1 {bad text index "@r"}}
test text-9.5 {TextWidgetCmd procedure, "get" option} {
    .t get 5.7 5.3
} {}
test text-9.6 {TextWidgetCmd procedure, "get" option} {
    .t get 5.3 5.5
} { G}
test text-9.7 {TextWidgetCmd procedure, "get" option} {
    .t get 5.3 end
} { GIrl .#@? x_yz
!@#$%
Line 7
}
.t mark set a 5.3
.t mark set b 5.3
.t mark set c 5.5
test text-9.8 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.7
} {y GIr}
test text-9.9 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2
} {y}
test text-9.10 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4
} {y }
test text-9.11 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.4
} {{y } G}
test text-9.12 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.4 5.5
} {{y } G}
test text-9.13 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.5 "5.5+5c"
} {{y } {Irl .}}
test text-9.14 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.4 5.5 end-3c
} {{y } G { }}
test text-9.15 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.4 5.5 end-3c end
} {{y } G { 7
}}
test text-9.16 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.3 5.4 5.3
} {y}
test text-9.17 {TextWidgetCmd procedure, "get" option} {
    .t index "5.2 +3 indices"
} {5.5}
test text-9.17a {TextWidgetCmd procedure, "get" option} {
    .t index "5.2 +3chars"
} {5.5}
test text-9.17b {TextWidgetCmd procedure, "get" option} {
    .t index "5.2 +3displayindices"
} {5.5}
catch {.t tag configure elide -elide 1}
.t tag add elide 5.2 5.4
test text-9.18 {TextWidgetCmd procedure, "get" option} {
    list [catch {.t get 5.2 5.4 5.5 foo} msg] $msg
} {1 {bad text index "foo"}}
test text-9.19 {TextWidgetCmd procedure, "get" option} {
    .t get 5.2 5.4 5.4 5.5 end-3c end
} {{y } G { 7
}}
test text-9.20 {TextWidgetCmd procedure, "get" option} {
    .t get -displaychars 5.2 5.4 5.4 5.5 end-3c end
} {{} G { 7
}}
test text-9.21 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.1 +4indices"] [.t index "5.1+4d indices"]
} {5.5 5.7}
test text-9.22 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.1 +4a chars"] [.t index "5.1+4d chars"]
} {5.5 5.7}
test text-9.23 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.5 -4indices"] [.t index "5.7-4d indices"]
} {5.1 5.1}
test text-9.24 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.5 -4a chars"] [.t index "5.7-4d chars"]
} {5.1 5.1}
catch {.t window create 5.4}
test text-9.25 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.1 +4indices"] [.t index "5.1+4d indices"]
} {5.5 5.7}
test text-9.25a {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.1 +4a chars"] [.t index "5.1+4d chars"]
} {5.6 5.8}
test text-9.26 {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.5 -4indices"] [.t index "5.7-4d indices"]
} {5.1 5.1}
test text-9.26a {TextWidgetCmd procedure, "get" option} {
    list [.t index "5.6 -4a chars"] [.t index "5.8-4d chars"]
} {5.1 5.1}
.t delete 5.4 
.t tag add elide 5.5 5.6
test text-9.27 {TextWidgetCmd procedure, "get" option} {
    .t get -displaychars 5.2 5.8
} {Grl}
.t tag delete elide
.t mark unset a
.t mark unset b
.t mark unset c
test text-9.2.1 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count} msg] $msg
} {1 {wrong # args: should be ".t count ?options? index1 index2"}}
test text-9.2.2.1 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count blah 1.0 2.0} msg] $msg
} {1 {bad option "blah" must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}}
test text-9.2.2 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count a b} msg] $msg
} {1 {bad text index "a"}}
test text-9.2.3 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count @q 3.1} msg] $msg
} {1 {bad text index "@q"}}
test text-9.2.4 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count 3.1 @r} msg] $msg
} {1 {bad text index "@r"}}
test text-9.2.5 {TextWidgetCmd procedure, "count" option} {
    .t count 5.7 5.3
} {-4}
test text-9.2.6 {TextWidgetCmd procedure, "count" option} {
    .t count 5.3 5.5
} {2}
test text-9.2.7 {TextWidgetCmd procedure, "count" option} {
    .t count 5.3 end
} {29}
.t mark set a 5.3
.t mark set b 5.3
.t mark set c 5.5
test text-9.2.8 {TextWidgetCmd procedure, "count" option} {
    .t count 5.2 5.7
} {5}
test text-9.2.9 {TextWidgetCmd procedure, "count" option} {
    .t count 5.2 5.3
} {1}
test text-9.2.10 {TextWidgetCmd procedure, "count" option} {
    .t count 5.2 5.4
} {2}
test text-9.2.17 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count 5.2 foo} msg] $msg
} {1 {bad text index "foo"}}
catch {.t tag configure elide -elide 1}
.t tag add elide 2.2 3.4
.t tag add elide 4.0 4.1
test text-9.2.18 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.0 3.0
} {2}
test text-9.2.19 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.2 3.0
} {0}
test text-9.2.20 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.0 4.2
} {5}
# Create one visible and one invisible window
frame .t.w1
frame .t.w2
.t mark set a 2.2
# Creating this window here means that the elidden text
# now starts at 2.3, but 'a' is automatically moved to 2.3
catch {
	.t window create 2.1 -window .t.w1
	.t window create 3.1 -window .t.w2
}
test text-9.2.21 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.0 3.0
} {3}
test text-9.2.22 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.2 3.0
} {1}
test text-9.2.23 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices a 3.0
} {0}
test text-9.2.24 {TextWidgetCmd procedure, "count" option} {
    .t count -displayindices 2.0 4.2
} {6}
test text-9.2.25 {TextWidgetCmd procedure, "count" option} {
    .t count -displaychars 2.0 3.0
} {2}
test text-9.2.26 {TextWidgetCmd procedure, "count" option} {
    .t count -displaychars 2.2 3.0
} {1}
test text-9.2.27 {TextWidgetCmd procedure, "count" option} {
    .t count -displaychars a 3.0
} {0}
test text-9.2.28 {TextWidgetCmd procedure, "count" option} {
    .t count -displaychars 2.0 4.2
} {5}
test text-9.2.29 {TextWidgetCmd procedure, "count" option} {
    list [.t count -indices 2.2 3.0] [.t count 2.2 3.0]
} {10 10}
test text-9.2.30 {TextWidgetCmd procedure, "count" option} {
    list [.t count -indices a 3.0] [.t count a 3.0]
} {9 9}
test text-9.2.31 {TextWidgetCmd procedure, "count" option} {
    .t count -indices 2.0 4.2
} {21}
test text-9.2.32 {TextWidgetCmd procedure, "count" option} {
    .t count -chars 2.2 3.0
} {10}
test text-9.2.33 {TextWidgetCmd procedure, "count" option} {
    .t count -chars a 3.0
} {9}
test text-9.2.34 {TextWidgetCmd procedure, "count" option} {
    .t count -chars 2.0 4.2
} {19}
destroy .t.w1
destroy .t.w2
set current [.t get 1.0 end-1c]
.t delete 1.0 end
.t insert end [string repeat "abcde " 50]\n
.t insert end [string repeat "fghij " 50]\n
.t insert end [string repeat "klmno " 50]
test text-9.2.35 {TextWidgetCmd procedure, "count" option} {
    .t count -lines 1.0 end
} {3}
test text-9.2.36 {TextWidgetCmd procedure, "count" option} {
    .t count -lines end 1.0
} {-3}
test text-9.2.37 {TextWidgetCmd procedure, "count" option} {
    list [catch {.t count -lines 1.0 2.0 3.0} res] $res
} {1 {bad option "1.0" must be -chars, -displaychars, -displayindices, -displaylines, -indices, -lines, -update, -xpixels, or -ypixels}}
test text-9.2.38 {TextWidgetCmd procedure, "count" option} {
    .t count -lines end end
} {0}
test text-9.2.39 {TextWidgetCmd procedure, "count" option} {
    .t count -lines 1.5 2.5
} {1}
test text-9.2.40 {TextWidgetCmd procedure, "count" option} {
    .t count -lines 2.5 "2.5 lineend"
} {0}
test text-9.2.41 {TextWidgetCmd procedure, "count" option} {
    .t count -lines 2.7 "1.0 lineend"
} {-1}
test text-9.2.42 {TextWidgetCmd procedure, "count" option} {
    set old_wrap [.t cget -wrap]
    .t configure -wrap none
    set res [.t count -displaylines 1.0 end]
    .t configure -wrap $old_wrap
    set res
} {3}
test text-9.2.43 {TextWidgetCmd procedure, "count" option} {
    .t count -lines -chars -indices -displaylines 1.0 end
} {3 903 903 45}
catch {.t configure -wrap none}

# Newer tags are higher priority
catch {
	.t tag configure elide1 -elide 0
	.t tag configure elide2 -elide 1
	.t tag configure elide3 -elide 0
	.t tag configure elide4 -elide 1
}

test text-0.2.44.0 {counting with tag priority eliding} {
    .t delete 1.0 end
    .t insert end "hello"
    list [.t count -displaychars 1.0 1.0] \
      [.t count -displaychars 1.0 1.1] \
      [.t count -displaychars 1.0 1.2] \
      [.t count -displaychars 1.0 1.3] \
      [.t count -displaychars 1.0 1.4] \
      [.t count -displaychars 1.0 1.5] \
      [.t count -displaychars 1.0 1.6] \
      [.t count -displaychars 1.0 2.6] \
} {0 1 2 3 4 5 5 6}
test text-0.2.44 {counting with tag priority eliding} {
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide1 1.2 1.4
    .t count -displaychars 1.0 1.5
} {5}
test text-0.2.45 {counting with tag priority eliding} {
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.2 1.4
    .t count -displaychars 1.0 1.5
} {3}
test text-0.2.46 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.2 1.4
    .t tag add elide1 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide1 1.2 1.4
    .t tag add elide2 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
} {3 3}
test text-0.2.47 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.2 1.4
    .t tag add elide3 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide3 1.2 1.4
    .t tag add elide3 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
} {5 5}
test text-0.2.48 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.2 1.4
    .t tag add elide3 1.2 1.4
    .t tag add elide4 1.2 1.4
    .t tag add elide1 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide1 1.2 1.4
    .t tag add elide4 1.2 1.4
    .t tag add elide2 1.2 1.4
    .t tag add elide3 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
} {3 3}
test text-0.2.49 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.2 1.4
    .t tag add elide3 1.2 1.4
    .t tag add elide1 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide1 1.2 1.4
    .t tag add elide2 1.2 1.4
    .t tag add elide3 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
} {5 5}
test text-0.2.50 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide2 1.0 1.5
    .t tag add elide1 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    lappend res [.t count -displaychars 1.1 1.5]
    lappend res [.t count -displaychars 1.2 1.5]
    lappend res [.t count -displaychars 1.3 1.5]
    .t delete 1.0 end
    .t insert end "hello"
    .t tag add elide1 1.0 1.5
    .t tag add elide2 1.2 1.4
    lappend res [.t count -displaychars 1.0 1.5]
    lappend res [.t count -displaychars 1.1 1.5]
    lappend res [.t count -displaychars 1.2 1.5]
    lappend res [.t count -displaychars 1.3 1.5]
} {0 0 0 0 3 2 1 1}
test text-0.2.51 {counting with tag priority eliding} {
    set res {}
    .t delete 1.0 end
    .t tag configure WELCOME -elide 1
    .t tag configure SYSTEM -elide 0
    .t tag configure TRAFFIC -elide 1
    .t insert end "\n" {SYSTEM TRAFFIC}
    .t insert end "\n" WELCOME
    lappend res [.t count -displaychars 1.0 end]
    lappend res [.t count -displaychars 1.0 end-1c]
    lappend res [.t count -displaychars 1.0 1.2]
    lappend res [.t count -displaychars 2.0 end]
    lappend res [.t count -displaychars 2.0 end-1c]
    lappend res [.t index "1.0 +1 indices"]
    lappend res [.t index "1.0 +1 display indices"]
    lappend res [.t index "1.0 +1 display chars"]
    lappend res [.t index end] 
    lappend res [.t index "end -1 indices"]
    lappend res [.t index "end -1 display indices"]
    lappend res [.t index "end -1 display chars"]
    lappend res [.t index "end -2 indices"]
    lappend res [.t index "end -2 display indices"]
    lappend res [.t index "end -2 display chars"]
} {1 0 0 1 0 2.0 4.0 4.0 4.0 3.0 3.0 3.0 2.0 1.0 1.0}

.t delete 1.0 end
.t insert end $current
unset current

test text-10.1 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t index} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.2 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t ind a b} msg] $msg
} {1 {wrong # args: should be ".t index index"}}
test text-10.3 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t in a b} msg] $msg
} {1 {ambiguous option "in": must be bbox, cget, compare, configure, count, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, peer, replace, scan, search, see, tag, window, xview, or yview}}
test text-10.4 {TextWidgetCmd procedure, "index" option} {
    list [catch {.t index @xyz} msg] $msg
} {1 {bad text index "@xyz"}}
test text-10.5 {TextWidgetCmd procedure, "index" option} {
    .t index 1.2
} 1.2

test text-11.1 {TextWidgetCmd procedure, "insert" option} {
    list [catch {.t insert 1.2} msg] $msg
} {1 {wrong # args: should be ".t insert index chars ?tagList chars tagList ...?"}}
test text-11.2 {TextWidgetCmd procedure, "insert" option} {
    .t config -state disabled
    .t insert 1.2 xyzzy
    .t get 1.0 1.end
} {Line 1}
.t config -state normal
test text-11.3 {TextWidgetCmd procedure, "insert" option} {
    .t insert 1.2 xyzzy
    .t get 1.0 1.end
} {Lixyzzyne 1}
test text-11.4 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "Sample text" x
    .t tag ranges x
} {1.0 1.11}
test text-11.5 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "Sample text" x
    .t insert 1.2 "XYZ" y
    list [.t tag ranges x] [.t tag ranges y]
} {{1.0 1.2 1.5 1.14} {1.2 1.5}}
test text-11.6 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "Sample text" {x y z}
    list [.t tag ranges x] [.t tag ranges y] [.t tag ranges z]
} {{1.0 1.11} {1.0 1.11} {1.0 1.11}}
test text-11.7 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "Sample text" {x y z}
    .t insert 1.3 "A" {a b z}
    list [.t tag ranges a] [.t tag ranges b] [.t tag ranges x] [.t tag ranges y] [.t tag ranges z]
} {{1.3 1.4} {1.3 1.4} {1.0 1.3 1.4 1.12} {1.0 1.3 1.4 1.12} {1.0 1.12}}
test text-11.8 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    list [catch {.t insert 1.0 "Sample text" "a \{b"} msg] $msg
} {1 {unmatched open brace in list}}
test text-11.9 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "First" bold " " {} second "x y z" " third"
    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges x] \
	    [.t tag ranges y] [.t tag ranges z]
} {{First second third} {1.0 1.5} {1.6 1.12} {1.6 1.12} {1.6 1.12}}
test text-11.10 {TextWidgetCmd procedure, "insert" option} {
    .t delete 1.0 end
    .t insert 1.0 "First" bold " second" silly
    list [.t get 1.0 1.end] [.t tag ranges bold] [.t tag ranges silly]
} {{First second} {1.0 1.5} {1.5 1.12}}

# Edit, mark, scan, search, see, tag, window, xview, and yview actions are tested elsewhere.

test text-12.1 {ConfigureText procedure} {
    list [catch {.t2 configure -state foobar} msg] $msg
} {1 {bad state "foobar": must be disabled or normal}}
test text-12.2 {ConfigureText procedure} {
    .t2 configure -spacing1 -2 -spacing2 1 -spacing3 1
    list [.t2 cget -spacing1] [.t2 cget -spacing2] [.t2 cget -spacing3]
} {0 1 1}
test text-12.3 {ConfigureText procedure} {
    .t2 configure -spacing1 1 -spacing2 -1 -spacing3 1
    list [.t2 cget -spacing1] [.t2 cget -spacing2] [.t2 cget -spacing3]
} {1 0 1}
test text-12.4 {ConfigureText procedure} {
    .t2 configure -spacing1 1 -spacing2 1 -spacing3 -3
    list [.t2 cget -spacing1] [.t2 cget -spacing2] [.t2 cget -spacing3]
} {1 1 0}
test text-12.5 {ConfigureText procedure} {
    set x [list [catch {.t2 configure -tabs {30 foo}} msg] $msg $errorInfo]
    .t2 configure -tabs {10 20 30}
    set x
} {1 {bad tab alignment "foo": must be left, right, center, or numeric} {bad tab alignment "foo": must be left, right, center, or numeric
    (while processing -tabs option)
    invoked from within
".t2 configure -tabs {30 foo}"}}
test text-12.6 {ConfigureText procedure} {
    .t2 configure -tabs {10 20 30}
    .t2 configure -tabs {}
    .t2 cget -tabs
} {}
test text-12.7 {ConfigureText procedure} {
    list [catch {.t2 configure -wrap bogus} msg] $msg
} {1 {bad wrap "bogus": must be char, none, or word}}
test text-12.8 {ConfigureText procedure} {
    .t2 configure -selectborderwidth 17 -selectforeground #332211 \
	    -selectbackground #abc
    list [lindex [.t2 tag config sel -borderwidth] 4] \
	[lindex [.t2 tag config sel -foreground] 4] \
	[lindex [.t2 tag config sel -background] 4]
} {17 #332211 #abc}
test text-12.9 {ConfigureText procedure} {
    .t2 configure -selectborderwidth {}
    .t2 tag cget sel -borderwidth
} {}
test text-12.10 {ConfigureText procedure} {
    list [catch {.t2 configure -selectborderwidth foo} msg] $msg
} {1 {bad screen distance "foo"}}
test text-12.11 {ConfigureText procedure} {
    catch {destroy .t2}
    .t.e select to 2
    scintilla .t2 -exportselection 1
    selection get
} {ab}
test text-12.12 {ConfigureText procedure} {
    catch {destroy .t2}
    .t.e select to 2
    scintilla .t2 -exportselection 0
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    selection get
} {ab}
test text-12.13 {ConfigureText procedure} {
    catch {destroy .t2}
    .t.e select to 1
    scintilla .t2 -exportselection 1
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    selection get
} {1234}
test text-12.14 {ConfigureText procedure} {
    catch {destroy .t2}
    .t.e select to 1
    scintilla .t2 -exportselection 0
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    .t2 configure -exportselection 1
    selection get
} {1234}
test text-12.15 {ConfigureText procedure} {
    catch {destroy .t2}
    scintilla .t2 -exportselection 1
    .t2 insert insert 1234657890
    .t2 tag add sel 1.0 1.4
    set result [selection get]
    .t2 configure -exportselection 0
    lappend result [catch {selection get} msg] $msg
} {1234 1 {PRIMARY selection doesn't exist or form "STRING" not defined}}
test text-12.16 {ConfigureText procedure} {fonts} {
    # This test is non-portable because the window size will vary depending
    # on the font size, which can vary.
    catch {destroy .t2}
    toplevel .t2
    scintilla .t2.t -width 20 -height 10
    pack append .t2 .t2.t top
    wm geometry .t2 +0+0
    update
    wm geometry .t2
} {150x140+0+0}
test text-12.17 {ConfigureText procedure} {
    # This test was failing Windows because the title bar on .t2
    # was a certain minimum size and it was interfering with the size
    # requested by the -setgrid.  The "overrideredirect" gets rid of the
    # titlebar so the toplevel can shrink to the appropriate size.
    catch {destroy .t2}
    toplevel .t2
    wm overrideredirect .t2 1
    scintilla .t2.t -width 20 -height 10 -setgrid 1
    pack append .t2 .t2.t top
    wm geometry .t2 +0+0
    update
    wm geometry .t2
} {20x10+0+0}
test text-12.18 {ConfigureText procedure} {
    # This test was failing on Windows because the title bar on .t2
    # was a certain minimum size and it was interfering with the size
    # requested by the -setgrid.  The "overrideredirect" gets rid of the
    # titlebar so the toplevel can shrink to the appropriate size.
    catch {destroy .t2}
    toplevel .t2
    wm overrideredirect .t2 1
    scintilla .t2.t -width 20 -height 10 -setgrid 1
    pack append .t2 .t2.t top
    wm geometry .t2 +0+0
    update
    set result [wm geometry .t2]
    wm geometry .t2 15x8
    update
    lappend result [wm geometry .t2]
    .t2.t configure -wrap word
    update
    lappend result [wm geometry .t2]
} {20x10+0+0 15x8+0+0 15x8+0+0}

test text-13.1 {TextWorldChanged procedure, spacing options} fonts {
    catch {destroy .t2}
    scintilla .t2 -width 20 -height 10
    set result [winfo reqheight .t2]
    .t2 configure -spacing1 2
    lappend result [winfo reqheight .t2]
    .t2  configure -spacing3 1
    lappend result [winfo reqheight .t2]
    .t2 configure -spacing1 0
    lappend result [winfo reqheight .t2]
} {140 160 170 150}

test text-14.1 {TextEventProc procedure} {
    scintilla .tx1 -bg #543210
    rename .tx1 .tx2
    set x {}
    lappend x [winfo exists .tx1]
    lappend x [.tx2 cget -bg]
    destroy .tx1
    lappend x [info command .tx*] [winfo exists .tx1] [winfo exists .tx2]
} {1 #543210 {} 0 0}

test text-15.1 {TextCmdDeletedProc procedure} {
    scintilla .tx1
    rename .tx1 {}
    list [info command .tx*] [winfo exists .tx1]
} {{} 0}
test text-15.2 {TextCmdDeletedProc procedure, disabling -setgrid} fonts {
    catch {destroy .top}
    toplevel .top
    wm geom .top +0+0
    scintilla .top.t -setgrid 1 -width 20 -height 10
    pack .top.t
    update
    set x [wm geometry .top]
    rename .top.t {}
    update
    lappend x [wm geometry .top]
    destroy .top
    set x
} {20x10+0+0 150x140+0+0}

test text-16.1 {InsertChars procedure} {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 2.0 abcd\n
    .t2 get 1.0 end
} {abcd

}
test text-16.2 {InsertChars procedure} {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 1.0 abcd\n
    .t2 insert end 123\n
    .t2 get 1.0 end
} {abcd
123

}
test text-16.3 {InsertChars procedure} {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 1.0 abcd\n
    .t2 insert 10.0 123
    .t2 get 1.0 end
} {abcd
123
}
test text-16.4 {InsertChars procedure, inserting on top visible line} {
    catch {destroy .t2}
    scintilla .t2 -width 20 -height 4 -wrap word
    pack .t2
    .t2 insert insert "Now is the time for all great men to come to the "
    .t2 insert insert "aid of their party.\n"
    .t2 insert insert "Now is the time for all great men.\n"
    .t2 see end
    update
    .t2 insert 1.0 "Short\n"
    .t2 index @0,0
} {2.56}
test text-16.5 {InsertChars procedure, inserting on top visible line} {
    catch {destroy .t2}
    scintilla .t2 -width 20 -height 4 -wrap word
    pack .t2
    .t2 insert insert "Now is the time for all great men to come to the "
    .t2 insert insert "aid of their party.\n"
    .t2 insert insert "Now is the time for all great men.\n"
    .t2 see end
    update
    .t2 insert 1.55 "Short\n"
    .t2 index @0,0
} {2.0}
test text-16.6 {InsertChars procedure, inserting on top visible line} {
    catch {destroy .t2}
    scintilla .t2 -width 20 -height 4 -wrap word
    pack .t2
    .t2 insert insert "Now is the time for all great men to come to the "
    .t2 insert insert "aid of their party.\n"
    .t2 insert insert "Now is the time for all great men.\n"
    .t2 see end
    update
    .t2 insert 1.56 "Short\n"
    .t2 index @0,0
} {1.56}
test text-16.7 {InsertChars procedure, inserting on top visible line} {
    catch {destroy .t2}
    scintilla .t2 -width 20 -height 4 -wrap word
    pack .t2
    .t2 insert insert "Now is the time for all great men to come to the "
    .t2 insert insert "aid of their party.\n"
    .t2 insert insert "Now is the time for all great men.\n"
    .t2 see end
    update
    .t2 insert 1.57 "Short\n"
    .t2 index @0,0
} {1.56}
catch {destroy .t2}

proc setup {} {
    .t delete 1.0 end
    .t insert 1.0 "Line 1
abcde
12345
Line 4"
}

.t delete 1.0 end
test text-17.1 {DeleteChars procedure} {
    .t get 1.0 end
} {
}
test text-17.2 {DeleteChars procedure} {
    list [catch {.t delete foobar} msg] $msg
} {1 {bad text index "foobar"}}
test text-17.3 {DeleteChars procedure} {
    list [catch {.t delete 1.0 lousy} msg] $msg
} {1 {bad text index "lousy"}}
test text-17.4 {DeleteChars procedure} {
    setup
    .t delete 2.1
    .t get 1.0 end
} {Line 1
acde
12345
Line 4
}
test text-17.5 {DeleteChars procedure} {
    setup
    .t delete 2.3
    .t get 1.0 end
} {Line 1
abce
12345
Line 4
}
test text-17.6 {DeleteChars procedure} {
    setup
    .t delete 2.end
    .t get 1.0 end
} {Line 1
abcde12345
Line 4
}
test text-17.7 {DeleteChars procedure} {
    setup
    .t tag add sel 4.2 end
    .t delete 4.2 end
    list [.t tag ranges sel] [.t get 1.0 end]
} {{} {Line 1
abcde
12345
Li
}}
test text-17.8 {DeleteChars procedure} {
    setup
    .t tag add sel 1.0 end
    .t delete 4.0 end
    list [.t tag ranges sel] [.t get 1.0 end]
} {{1.0 3.5} {Line 1
abcde
12345
}}
test text-17.9 {DeleteChars procedure} {
    setup
    .t delete 2.2 2.2
    .t get 1.0 end
} {Line 1
abcde
12345
Line 4
}
test text-17.10 {DeleteChars procedure} {
    setup
    .t delete 2.3 2.1
    .t get 1.0 end
} {Line 1
abcde
12345
Line 4
}
test text-17.11 {DeleteChars procedure} {
    catch {destroy .t2}
    toplevel .t2
    scintilla .t2.t -width 20 -height 5
    pack append .t2 .t2.t top
    wm geometry .t2 +0+0
    .t2.t insert 1.0 "abc\n123\nx\ny\nz\nq\nr\ns"
    update
    .t2.t delete 1.0 3.0
    list [.t2.t index @0,0] [.t2.t get @0,0]
} {1.0 x}
test text-17.12 {DeleteChars procedure} {
    catch {destroy .t2}
    toplevel .t2
    scintilla .t2.t -width 20 -height 5
    pack append .t2 .t2.t top
    wm geometry .t2 +0+0
    .t2.t insert 1.0 "abc\n123\nx\ny\nz\nq\nr\ns"
    .t2.t yview 3.0
    update
    .t2.t delete 2.0 4.0
    list [.t2.t index @0,0] [.t2.t get @0,0]
} {2.0 y}
catch {destroy .t2}
toplevel .t2
scintilla .t2.t -width 1 -height 10 ;#-wrap char
frame .t2.f -width 200 -height 20 -relief raised -bd 2
pack .t2.f .t2.t -side left
wm geometry .t2 +0+0
update
test text-17.13 {DeleteChars procedure, updates affecting topIndex} {
    .t2.t delete 1.0 end
    .t2.t insert end "abcde\n12345\nqrstuv"
    .t2.t yview 2.1
    .t2.t delete 1.4 2.3
    .t2.t index @0,0
} {1.2}
test text-17.14 {DeleteChars procedure, updates affecting topIndex} {
    .t2.t delete 1.0 end
    .t2.t insert end "abcde\n12345\nqrstuv"
    .t2.t yview 2.1
    .t2.t delete 2.3 2.4
    .t2.t index @0,0
} {2.0}
test text-17.15 {DeleteChars procedure, updates affecting topIndex} {
    .t2.t delete 1.0 end
    .t2.t insert end "abcde\n12345\nqrstuv"
    .t2.t yview 1.3
    .t2.t delete 1.0 1.2
    .t2.t index @0,0
} {1.1}
test text-17.16 {DeleteChars procedure, updates affecting topIndex} {
    catch {destroy .t2}
    toplevel .t2
    scintilla .t2.t -width 6 -height 10 -wrap word
    frame .t2.f -width 200 -height 20 -relief raised -bd 2
    pack .t2.f .t2.t -side left
    wm geometry .t2 +0+0
    update
    .t2.t insert end "abc def\n01 2345 678 9101112\nLine 3\nLine 4\nLine 5\n6\n7\n8\n"
    .t2.t yview 2.4
    .t2.t delete 2.5
    set x [.t2.t index @0,0]
    .t2.t delete 2.5
    list $x [.t2.t index @0,0]
} {2.3 2.0}

.t delete 1.0 end
foreach i {a b c d e f g h i j k l m n o p q r s t u v w x y z} {
    .t insert end $i.0$i.1$i.2$i.3$i.4\n
}
test text-18.1 {TextFetchSelection procedure} {
    .t tag add sel 1.3 3.4
    selection get
} {a.1a.2a.3a.4
b.0b.1b.2b.3b.4
c.0c}
test text-18.2 {TextFetchSelection procedure} {
    .t tag add x 1.2
    .t tag add x 1.4
    .t tag add x 2.0
    .t tag add x 2.3
    .t tag remove sel 1.0 end
    .t tag add sel 1.0 3.4
    selection get
} {a.0a.1a.2a.3a.4
b.0b.1b.2b.3b.4
c.0c}
test text-18.3 {TextFetchSelection procedure} {
    .t tag remove sel 1.0 end
    .t tag add sel 13.3
    selection get
} {m}
test text-18.4 {TextFetchSelection procedure} {
    .t tag remove x 1.0 end
    .t tag add sel 1.0 3.4
    .t tag remove sel 1.0 end
    .t tag add sel 1.2 1.5
    .t tag add sel 2.4 3.1
    .t tag add sel 10.0 10.end
    .t tag add sel 13.3
    selection get
} {0a..1b.2b.3b.4
cj.0j.1j.2j.3j.4m}
set x ""
for {set i 1} {$i < 200} {incr i} {
    append x "This is line $i, padded to just about 53 characters.\n"
}
test text-18.5 {TextFetchSelection procedure, long selections} {
    .t delete 1.0 end
    .t insert end $x
    .t tag add sel 1.0 end
    selection get
} $x\n

test text-19.1 {TkTextLostSelection procedure} unix {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 1.0 "abc\ndef\nghijk\n1234"
    .t2 tag add sel 1.2 3.3
    .t.e select to 1
    .t2 tag ranges sel
} {}
test text-19.2 {TkTextLostSelection procedure} win {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 1.0 "abc\ndef\nghijk\n1234"
    .t2 tag add sel 1.2 3.3
    .t.e select to 1
    .t2 tag ranges sel
} {1.2 3.3}
catch {destroy .t2}
test text-19.3 {TkTextLostSelection procedure} {
    catch {destroy .t2}
    scintilla .t2
    .t2 insert 1.0 "abcdef\nghijk\n1234"
    .t2 tag add sel 1.0 1.3
    set x [selection get]
    selection clear
    lappend x [catch {selection get} msg] $msg
    .t2 tag add sel 1.0 1.3
    lappend x [selection get]
} {abc 1 {PRIMARY selection doesn't exist or form "STRING" not defined} abc}

.t delete 1.0 end
.t insert end "xxyz xyz x. the\nfoo -forward bar xxxxx BaR foo\nxyz xxyzx"
test text-20.1 {TextSearchCmd procedure, argument parsing} {
    list [catch {.t search -} msg] $msg
} {1 {bad switch "-": must be --, -all, -backward, -count, -elide, -exact, -forward, -nocase, -nolinestop, -overlap, -regexp, or -strictlimits}}
test text-20.2 {TextSearchCmd procedure, -backwards option} {
    .t search -backwards xyz 1.4
} {1.1}
test text-20.2.1 {TextSearchCmd procedure, -all option} {
    .t search -all xyz 1.4
} {1.5 3.0 3.5 1.1}
test text-20.3 {TextSearchCmd procedure, -forwards option} {
    .t search -forwards xyz 1.4
} {1.5}
test text-20.4 {TextSearchCmd procedure, -exact option} {
    .t search -f -exact x. 1.0
} {1.9}
test text-20.5 {TextSearchCmd procedure, -regexp option} {
    .t search -b -regexp x.z 1.4
} {1.1}
test text-20.6 {TextSearchCmd procedure, -count option} {
    set length unmodified
    list [.t search -count length x. 1.4] $length
} {1.9 2}
test text-20.7 {TextSearchCmd procedure, -count option} {
    list [catch {.t search -count} msg] $msg
} {1 {no value given for "-count" option}}
test text-20.8 {TextSearchCmd procedure, -nocase option} {
    list [.t search -nocase BaR 1.1] [.t search BaR 1.1]
} {2.13 2.23}
test text-20.9 {TextSearchCmd procedure, -n ambiguous option} {
    list [catch {.t search -n BaR 1.1} msg] $msg
} {1 {bad switch "-n": must be --, -all, -backward, -count, -elide, -exact, -forward, -nocase, -nolinestop, -overlap, -regexp, or -strictlimits}}
test text-20.9.1 {TextSearchCmd procedure, -nocase option} {
    .t search -noc BaR 1.1
} {2.13}
test text-20.9.2 {TextSearchCmd procedure, -nolinestop option} {
    list [catch {.t search -nolinestop BaR 1.1} msg] $msg
} {1 {the "-nolinestop" option requires the "-regexp" option to be present}}
test text-20.9.3 {TextSearchCmd procedure, -nolinestop option} {
    set msg ""
    list [.t search -nolinestop -regexp -count msg e.*o 1.1] $msg
} {1.14 32}
test text-20.10 {TextSearchCmd procedure, -- option} {
    .t search -- -forward 1.0
} {2.4}
test text-20.11 {TextSearchCmd procedure, argument parsing} {
    list [catch {.t search abc} msg] $msg
} {1 {wrong # args: should be ".t search ?switches? pattern index ?stopIndex?"}}
test text-20.12 {TextSearchCmd procedure, argument parsing} {
    list [catch {.t search abc d e f} msg] $msg
} {1 {wrong # args: should be ".t search ?switches? pattern index ?stopIndex?"}}
test text-20.13 {TextSearchCmd procedure, check index} {
    list [catch {.t search abc gorp} msg] $msg
} {1 {bad text index "gorp"}}
test text-20.14 {TextSearchCmd procedure, startIndex == "end"} {
    .t search non-existent end
} {}
test text-20.15 {TextSearchCmd procedure, startIndex == "end"} {
    .t search non-existent end
} {}
test text-20.16 {TextSearchCmd procedure, bad stopIndex} {
    list [catch {.t search abc 1.0 lousy} msg] $msg
} {1 {bad text index "lousy"}}
test text-20.17 {TextSearchCmd procedure, pattern case conversion} {
    list [.t search -nocase BAR 1.1] [.t search BAR 1.1]
} {2.13 {}}
test text-20.18 {TextSearchCmd procedure, bad regular expression pattern} {
    list [catch {.t search -regexp a( 1.0} msg] $msg
} {1 {couldn't compile regular expression pattern: parentheses () not balanced}}
test text-20.19 {TextSearchCmd procedure, skip dummy last line} {
    .t search -backwards BaR end 1.0
} {2.23}
test text-20.20 {TextSearchCmd procedure, skip dummy last line} {
    .t search -backwards \n end 1.0
} {3.9}
test text-20.21 {TextSearchCmd procedure, skip dummy last line} {
    .t search \n end
} {1.15}
test text-20.22 {TextSearchCmd procedure, skip dummy last line} {
    .t search -back \n 1.0
} {3.9}
test text-20.23 {TextSearchCmd procedure, extract line contents} {
    .t tag add foo 1.2
    .t tag add x 1.3
    .t mark set silly 1.2
    .t search xyz 3.6
} {1.1}
test text-20.24 {TextSearchCmd procedure, stripping newlines} {
    .t search the\n 1.0
} {1.12}
test text-20.25 {TextSearchCmd procedure, handling newlines} {
    .t search -regexp the\n 1.0
} {1.12}
test text-20.26 {TextSearchCmd procedure, stripping newlines} {
    .t search -regexp {the$} 1.0
} {1.12}
test text-20.27 {TextSearchCmd procedure, handling newlines} {
    .t search -regexp \n 1.0
} {1.15}
test text-20.28 {TextSearchCmd procedure, line case conversion} {
    list [.t search -nocase bar 2.18] [.t search bar 2.18]
} {2.23 2.13}
test text-20.29 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search -backwards xyz 1.6
} {1.5}
test text-20.30 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search -backwards xyz 1.5
} {1.1}
test text-20.31 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search xyz 1.5
} {1.5}
test text-20.32 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search xyz 1.6
} {3.0}
test text-20.33 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search {} 1.end
} {1.15}
test text-20.34 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search f 1.end
} {2.0}
test text-20.35 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search {} end
} {1.0}
test text-20.35a {TextSearchCmd procedure, regexp finds empty lines} {
    # Test for fix of bug #1643
    .t insert end "\n"
    tk::TextSetCursor .t 4.0
    .t search -forward -regexp {^$} insert end
} {4.0}
    
catch {destroy .t2}
toplevel .t2
wm geometry .t2 +0+0
scintilla .t2.t -width 30 -height 10
pack .t2.t
.t2.t insert 1.0 "This is a line\nand this is another"
.t2.t insert end "\nand this is yet another"
frame .t2.f -width 20 -height 20 -bd 2 -relief raised
catch {.t2.t window create 2.5 -window .t2.f}
test text-20.36 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search his 2.6
} {2.6}
test text-20.37 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search this 2.6
} {3.4}
test text-20.38 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search is 2.6
} {2.7}
test text-20.39 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search his 2.7
} {3.5}
test text-20.40 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search -backwards "his is another" 2.6
} {2.6}
test text-20.41 {TextSearchCmd procedure, firstChar and lastChar} {
    .t2.t search -backwards "his is" 2.6
} {1.1}
destroy .t2
test text-20.42 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search -backwards forw 2.5
} {2.5}
test text-20.43 {TextSearchCmd procedure, firstChar and lastChar} {
    .t search forw 2.5
} {2.5}
test text-20.44 {TextSearchCmd procedure, firstChar and lastChar} {
    catch {destroy .t2}
    scintilla .t2
    list [.t2 search a 1.0] [.t2 search -backward a 1.0]
} {{} {}}
test text-20.45 {TextSearchCmd procedure, regexp match length} {
    set length unchanged
    list [.t search -regexp -count length x(.)(.*)z 1.1] $length
} {1.1 7}
test text-20.46 {TextSearchCmd procedure, regexp match length} {
    set length unchanged
    list [.t search -regexp -backward -count length fo* 2.5] $length
} {2.0 3}
test text-20.47 {TextSearchCmd procedure, checking stopIndex} {
    list [.t search bar 2.1 2.13] [.t search bar 2.1 2.14] \
	    [.t search bar 2.12 2.14] [.t search bar 2.14 2.14]
} {{} 2.13 2.13 {}}
test text-20.48 {TextSearchCmd procedure, checking stopIndex} {
    list [.t search -backwards bar 2.20 2.13] \
      [.t search -backwards bar 2.20 2.14] \
      [.t search -backwards bar 2.14 2.13] \
      [.t search -backwards bar 2.13 2.13]
} {2.13 {} 2.13 {}}
test text-20.48.1 {TextSearchCmd procedure, checking stopIndex} {
    list [.t search -backwards -strict bar 2.20 2.13] \
      [.t search -backwards -strict bar 2.20 2.14] \
      [.t search -backwards -strict bar 2.14 2.13] \
      [.t search -backwards -strict bar 2.13 2.13]
} {2.13 {} {} {}}
test text-20.49 {TextSearchCmd procedure, embedded windows and index/count} {
    frame .t.f1 -width 20 -height 20 -relief raised -bd 2
    frame .t.f2 -width 20 -height 20 -relief raised -bd 2
    frame .t.f3 -width 20 -height 20 -relief raised -bd 2
    frame .t.f4 -width 20 -height 20 -relief raised -bd 2
    .t window create 2.10 -window .t.f3
    .t window create 2.8 -window .t.f2
    .t window create 2.8 -window .t.f1
    .t window create 2.1 -window .t.f4
    set result ""
    lappend result [.t search -count x forward 1.0] $x
    lappend result [.t search -count x wa 1.0] $x
    .t delete 2.1
    .t delete 2.8 2.10
    .t delete 2.10
    set result
} {2.6 10 2.11 2}
test text-20.50 {TextSearchCmd procedure, error setting variable} {
    catch {unset a}
    set a 44
    list [catch {.t search -count a(2) xyz 1.0} msg] $msg
} {1 {can't set "a(2)": variable isn't array}}
test text-20.51 {TextSearchCmd procedure, wrap-around} {
    .t search -backwards xyz 1.1
} {3.5}
test text-20.52 {TextSearchCmd procedure, wrap-around} {
    .t search -backwards xyz 1.1 1.0
} {}
test text-20.53 {TextSearchCmd procedure, wrap-around} {
    .t search xyz 3.6
} {1.1}
test text-20.54 {TextSearchCmd procedure, wrap-around} {
    .t search xyz 3.6 end
} {}
test text-20.55 {TextSearchCmd procedure, no match} {
    .t search non_existent 3.5
} {}
test text-20.56 {TextSearchCmd procedure, no match} {
    .t search -regexp non_existent 3.5
} {}
test text-20.57 {TextSearchCmd procedure, special cases} {
    .t search -back x 1.1
} {1.0}
test text-20.58 {TextSearchCmd procedure, special cases} {
    .t search -back x 1.0
} {3.8}
test text-20.59 {TextSearchCmd procedure, special cases} {
    .t search \n {end-2c}
} {3.9}
test text-20.60 {TextSearchCmd procedure, special cases} {
    .t search \n end
} {1.15}
test text-20.61 {TextSearchCmd procedure, special cases} {
    .t search x 1.0
} {1.0}
test text-20.62 {TextSearchCmd, freeing copy of pattern} {
    # This test doesn't return a result, but it will generate
    # a core leak if the pattern copy isn't properly freed.
    # (actually in Tk 8.5 objectification means there is no
    # longer a copy of the pattern, but we leave this test in
    # anyway).
    set p abcdefg1234567890
    set p $p$p$p$p$p$p$p$p
    set p $p$p$p$p$p
    .t search -nocase $p 1.0
} {}
test text-20.63 {TextSearchCmd, unicode} {
    .t delete 1.0 end
    .t insert end "foo\u30c9\u30cabar"
    .t search \u30c9\u30ca 1.0
} 1.3
test text-20.64 {TextSearchCmd, unicode} {
    .t delete 1.0 end
    .t insert end "foo\u30c9\u30cabar"
    list [.t search -count n \u30c9\u30ca 1.0] $n
} {1.3 2}
test text-20.65 {TextSearchCmd, unicode with non-text segments} {
    .t delete 1.0 end
    button .b1 -text baz
    .t insert end "foo\u30c9"
    .t window create end -window .b1
    .t insert end "\u30cabar"
    set result [list [.t search -count n \u30c9\u30ca 1.0] $n]
    destroy .b1
    set result
} {1.3 3}
test text-20.66 {TextSearchCmd, hidden text does not affect match index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "12345H7890"
    .t2 search 7 1.0
} 1.6
test text-20.67 {TextSearchCmd, hidden text does not affect match index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "12345H7890"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.5
    .t2 search 7 1.0
} 1.6
test text-20.68 {TextSearchCmd, hidden text does not affect match index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nbarbaz\nbazboo"
    .t2 search boo 1.0
} 3.3
test text-20.69 {TextSearchCmd, hidden text does not affect match index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nbarbaz\nbazboo"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 2.0 3.0
    .t2 search boo 1.0
} 3.3
test text-20.70 {TextSearchCmd, -regexp -nocase searches} {
    catch {destroy .t}
    pack [scintilla .t]
    .t insert end "word1 word2"
    set res [.t search -nocase -regexp {\mword.} 1.0 end]
    destroy .t
    set res
} 1.0
test text-20.71 {TextSearchCmd, -regexp -nocase searches} {
    catch {destroy .t}
    pack [scintilla .t]
    .t insert end "word1 word2"
    set res [.t search -nocase -regexp {word.\M} 1.0 end]
    destroy .t
    set res
} 1.0
test text-20.72 {TextSearchCmd, -regexp -nocase searches} {
    catch {destroy .t}
    pack [scintilla .t]
    .t insert end "word1 word2"
    set res [.t search -nocase -regexp {word.\W} 1.0 end]
    destroy .t
    set res
} 1.0
test text-20.73 {TextSearchCmd, hidden text and start index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search bar 1.3
} 1.3
test text-20.74 {TextSearchCmd, hidden text shouldn't influence start index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.0 1.2
    .t2 search bar 1.3
} 1.3
test text-20.75 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    list [.t2 search -count foo foar 1.3] $foo
} {1.0 6}
test text-20.75.1 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    list \
      [.t2 search -strict -count foo foar 1.3] \
      [.t2 search -strict -count foo foar 2.3] $foo
} {{} 1.0 6}
test text-20.76 {TextSearchCmd, hidden text and start index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -regexp bar 1.3
} 1.3
test text-20.77 {TextSearchCmd, hidden text shouldn't influence start index} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.0 1.2
    .t2 search -regexp bar 1.3
} 1.3
test text-20.78 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    list [.t2 search -regexp -count foo foar 1.3] $foo
} {1.0 6}
test text-20.78.1 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    list [.t2 search -count foo foar 1.3] $foo
} {1.0 6}
test text-20.78.2 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    .t2 search -strict -count foo foar 1.3
} {}
test text-20.78.3 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    .t2 tag add hidden 2.2 2.4
    list [.t2 search -regexp -all -count foo foar 1.3] $foo
} {{2.0 3.0 1.0} {6 4 6}}
test text-20.78.4 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    .t2 tag add hidden 2.2 2.4
    list [.t2 search -all -count foo foar 1.3] $foo
} {{2.0 3.0 1.0} {6 4 6}}
test text-20.78.5 {TextSearchCmd, hidden text inside match must count in length} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoar"
    .t2 tag configure hidden -elide true
    .t2 tag add hidden 1.2 1.4
    .t2 tag add hidden 2.2 2.4
    list [.t2 search -strict -all -count foo foar 1.3] $foo
} {{2.0 3.0} {6 4}}
test text-20.78.6 {TextSearchCmd, single line with -all} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end " X\n X\n X\n X\n X\n X\n"
    .t2 search -all -regexp { +| *\n} 1.0 end
} {1.0 1.2 2.0 2.2 3.0 3.2 4.0 4.2 5.0 5.2 6.0 6.2 7.0}
test text-20.79 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -count foo foobar\nfoo 1.0] $foo
} {1.0 10}
test text-20.80 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -count foo bar\nfoo 1.0] $foo
} {1.3 7}
test text-20.81 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -count foo \nfoo 1.0] $foo
} {1.6 4}
test text-20.82 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -count foo bar\nfoobar\nfoo 1.0] $foo
} {1.3 14}
test text-20.83 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -count foo bar\nfoobar\nfoobanearly 1.0
} {}
test text-20.84 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -regexp -count foo foobar\nfoo 1.0] $foo
} {1.0 10}
test text-20.85 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -regexp -count foo bar\nfoo 1.0] $foo
} {1.3 7}
test text-20.86 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -regexp -count foo \nfoo 1.0] $foo
} {1.6 4}
test text-20.87 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -regexp -count foo bar\nfoobar\nfoo 1.0] $foo
} {1.3 14}
test text-20.88 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -regexp -count foo bar\nfoobar\nfoobanearly 1.0
} {}
test text-20.89 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfaoobar\nfoobar"
    .t2 search -regexp -count foo bar\nfoo 1.0
} {2.4}
test text-20.90 {TextSearchCmd, multiline matching end of window} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfaoobar\nfoobar"
    .t2 search -regexp -count foo bar\nfoobar\n\n 1.0
} {}
test text-20.91 {TextSearchCmd, multiline matching end of window} {
    deleteWindows
    pack [scintilla .t2]
    .t2 search "\n\n" 1.0
} {}
test text-20.92 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -count foo foobar\nfoo end] $foo
} {2.0 10}
test text-20.93 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -count foo bar\nfoo 1.0] $foo
} {2.3 7}
test text-20.94 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -count foo \nfoo 1.0] $foo
} {2.6 4}
test text-20.95 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -count foo bar\nfoobar\nfoo 1.0] $foo
} {1.3 14}
test text-20.96 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -backwards -count foo bar\nfoobar\nfoobanearly 1.0
} {}
test text-20.97 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -regexp -count foo foobar\nfoo end] $foo
} {2.0 10}
test text-20.97.1 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -regexp -count foo foobar\nfo end] $foo
} {2.0 9}
test text-20.98 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -regexp -count foo bar\nfoo 1.0] $foo
} {2.3 7}
test text-20.99 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -regexp -count foo \nfoo 1.0] $foo
} {2.6 4}
test text-20.100 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    list [.t2 search -backwards -regexp -count foo bar\nfoobar\nfoo 1.0] $foo
} {1.3 14}
test text-20.101 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -backwards -regexp -count foo bar\nfoobar\nfoobanearly 1.0
} {}
test text-20.102 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfaoobar\nfoobar"
    .t2 search -backwards -regexp -count foo bar\nfoo 1.0
} {2.4}
test text-20.103 {TextSearchCmd, multiline matching end of window} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfaoobar\nfoobar"
    .t2 search -backwards -regexp -count foo bar\nfoobar\n\n 1.0
} {}
test text-20.104 {TextSearchCmd, multiline matching end of window} {
    deleteWindows
    pack [scintilla .t2]
    .t2 search -backwards "\n\n" 1.0
} {}
test text-20.105 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 {    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t2 search -forwards -regexp $markExpr 1.41 end
} {}
test text-20.106 {TextSearchCmd, multiline regexp matching} {
    # Practical example which used to crash Tk, but only after the
    # search is complete.  This is memory corruption caused by
    # a bug in Tcl's handling of string objects.
    # (Tcl bug 635200)
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 {static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t2 search -forwards -regexp $markExpr 1.41 end
} {}
test text-20.107 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 {
static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
			    Tcl_Obj *objPtr));
static Tcl_Obj*         FSNormalizeAbsolutePath 
			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t2 search -backwards -all -regexp $markExpr end
} {2.0}
test text-20.108 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -all -regexp -count foo bar\nfoo 1.0
} {1.3 2.3}
test text-20.109 {TextSearchCmd, multiline matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -all -backwards -regexp -count foo bar\nfoo 1.0
} {2.3 1.3}
test text-20.110 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -- "blah" 3.3 1.3
} {}
test text-20.111 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "foobar\nfoobar\nfoobar"
    .t2 search -backwards -- "blah" 1.3 3.3
} {}
test text-20.112 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -backwards -regexp -- "\[\]\")\}\[(\{\]" "1.32" 1.0
} {1.31}
test text-20.113 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -regexp -- "\[\]\")\}\[(\{\]" 1.30 "1.0 lineend"
} {1.31}
test text-20.114 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -backwards -all -regexp -- "\[\]\")\}\[(\{\]" "1.32" 1.0
} {1.31 1.29 1.3}
test text-20.115 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -all -regexp -- "\[\]\")\}\[(\{\]" 1.0 "1.0 lineend"
} {1.3 1.29 1.31}
test text-20.116 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -backwards -- "\{" "1.32" 1.0
} {1.31}
test text-20.117 {TextSearchCmd, wrapping and limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert end "if (stringPtr->uallocated > 0) \{x"
    .t2 search -- "\{" 1.30 "1.0 lineend"
} {1.31}
test text-20.118 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 {

void
Tcl_SetObjLength(objPtr, length)
    register Tcl_Obj *objPtr;	/* Pointer to object.  This object must
				 * not currently be shared. */
    register int length;	/* Number of bytes desired for string
				 * representation of object, not including
				 * terminating null byte. */
\{
    char *new;
}
    set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
    append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
    append markExpr "\[ \n\t\r\]*\\()"
    .t2 search -all -regexp -- $markExpr 1.0
} {4.0}
test text-20.119 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    set markExpr {^[a-z]+}
    # This should not match, and should not wrap
    .t2 search -regexp -- $markExpr end end
} {}
test text-20.120 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    set markExpr {^[a-z]+}
    # This should not match, and should not wrap
    .t2 search -regexp -- $markExpr end+10c end
} {}
test text-20.121 {TextSearchCmd, multiline regexp matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    set markExpr {^[a-z]+}
    # This should not match, and should not wrap
    .t2 search -regexp -backwards -- $markExpr 1.0 1.0
} {}
test text-20.122 {TextSearchCmd, regexp linestop} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    .t2 search -regexp -- {i.*x} 1.0
} {2.6}
test text-20.123 {TextSearchCmd, multiline regexp nolinestop matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    .t2 search -regexp -nolinestop -- {i.*x} 1.0
} {1.1}
test text-20.124 {TextSearchCmd, regexp linestop} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    .t2 search -regexp -all -overlap -- {i.*x} 1.0
} {2.6}
test text-20.124.1 {TextSearchCmd, regexp linestop} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    .t2 search -regexp -all -- {i.*x} 1.0
} {2.6}
test text-20.125 {TextSearchCmd, multiline regexp nolinestop matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    list [.t2 search -regexp -all -overlap -count c -nolinestop -- {i.*x} 1.0] $c
} {{1.1 2.6} {26 10}}
test text-20.125.1 {TextSearchCmd, multiline regexp nolinestop matching} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "first line\nlast line of text"
    list [.t2 search -regexp -all -count c -nolinestop -- {i.*x} 1.0] $c
} {1.1 26}
test text-20.126 {TextSearchCmd, stop at end of line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "  \t\n   last line of text"
    .t2 search -regexp -nolinestop -- {[^ \t]} 1.0
} {1.3}
test text-20.127 {TextSearchCmd, overlapping all matches} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde abcde"
    list [.t2 search -regexp -all -overlap -count c -- {\w+} 1.0] $c
} {{1.0 1.6} {5 5}}
test text-20.127.1 {TextSearchCmd, non-overlapping all matches} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde abcde"
    list [.t2 search -regexp -all -count c -- {\w+} 1.0] $c
} {{1.0 1.6} {5 5}}
test text-20.128 {TextSearchCmd, stop at end of line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde abcde"
    list [.t2 search -backwards -regexp -all -count c -- {\w+} 1.0] $c
} {{1.6 1.0} {5 5}}
test text-20.129 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -regexp -count c -- {Z\w+} 1.21 1.5] $c
} {1.8 8}
test text-20.130 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -all -overlap -regexp -count c -- {Z\w+} 1.21 1.5] $c
} {1.8 8}
test text-20.130.1 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -all -regexp -count c -- {Z\w+} 1.21 1.5] $c
} {1.8 8}
test text-20.131 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -overlap -all -regexp -count c -- {Z\w+} 1.21 1.1] $c
} {1.4 12}
test text-20.131.1 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -overlap -all -regexp -count c -- {Z[^Z]+Z} 1.21 1.1] $c
} {{1.8 1.4} {5 5}}
test text-20.131.2 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    list [.t2 search -backwards -all -regexp -count c -- {Z\w+} 1.21 1.1] $c
} {1.4 12}
test text-20.132 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again\n"
    list [.t2 search -backwards -all -overlap -regexp -count c -- {Z\w+} 2.21 1.5] $c
} {{2.4 1.8} {12 8}}
test text-20.132.1 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again\n"
    list [.t2 search -backwards -all -regexp -count c -- {Z\w+} 2.21 1.5] $c
} {{2.4 1.8} {12 8}}
test text-20.133 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again\n"
    list [.t2 search -backwards -overlap -all -regexp -count c -- {Z\w+} 2.21 1.1] $c
} {{2.4 1.4} {12 12}}
test text-20.133.1 {TextSearchCmd, backwards search stop index } {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again"
    .t2 insert 1.0 "bla ZabcZdefZghi and some text again\n"
    list [.t2 search -backwards -all -regexp -count c -- {Z\w+} 2.21 1.1] $c
} {{2.4 1.4} {12 12}}
test text-20.134 {TextSearchCmd, search -all example} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 {

See the package: supersearch for more information.


See the package: incrementalSearch for more information.

package: Brws .


See the package: marks for more information.

}
    set pat {package: ([a-zA-Z0-9][-a-zA-Z0-9._+#/]*)}
    list [.t2 search -nolinestop -regexp -nocase -all -forwards \
      -count c -- $pat 1.0 end] $c
} {{3.8 6.8 8.0 11.8} {20 26 13 14}}
test text-20.135 {TextSearchCmd, backwards search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foobarfoobaaaaaaaaaaarfoo"
    .t2 search -backwards -regexp {fooba+rfoo} end
} {1.6}
test text-20.135.1 {TextSearchCmd, backwards search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foobarfoobaaaaaaaaaaarfoo"
    .t2 search -backwards -overlap -all -regexp {fooba+rfoo} end
} {1.6 1.0}
test text-20.135.2 {TextSearchCmd, backwards search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foobarfoobaaaaaaaaaaarfoo"
    .t2 search -backwards -all -regexp {fooba+rfoo} end
} {1.6}
test text-20.135.3 {TextSearchCmd, forwards search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foobarfoobaaaaaaaaaaarfoo"
    .t2 search -all -overlap -regexp {fooba+rfoo} end
} {1.0 1.6}
test text-20.135.4 {TextSearchCmd, forwards search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foobarfoobaaaaaaaaaaarfoo"
    .t2 search -all -regexp {fooba+rfoo} end
} {1.0}
test text-20.136 {TextSearchCmd, forward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abababab"
    .t2 search -exact -overlap -all {abab} 1.0
} {1.0 1.2 1.4}
test text-20.136.1 {TextSearchCmd, forward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abababab"
    .t2 search -exact -all {abab} 1.0
} {1.0 1.4}
test text-20.137 {TextSearchCmd, backward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "ababababab"
    .t2 search -exact -overlap -backwards -all {abab} end
} {1.6 1.4 1.2 1.0}
test text-20.137.1 {TextSearchCmd, backward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "ababababab"
    .t2 search -exact -backwards -all {abab} end
} {1.6 1.2}
test text-20.137.2 {TextSearchCmd, backward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abababababab"
    .t2 search -exact -backwards -all {abab} end
} {1.8 1.4 1.0}
test text-20.138 {TextSearchCmd, forward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -exact -overlap -all "foo\nbar\nfoo" 1.0
} {1.0 3.0 5.0}
test text-20.138.1 {TextSearchCmd, forward exact search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -exact -all "foo\nbar\nfoo" 1.0
} {1.0 5.0}
test text-20.139 {TextSearchCmd, backward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -exact -overlap -backward -all "foo\nbar\nfoo" end
} {5.0 3.0 1.0}
test text-20.140 {TextSearchCmd, backward exact search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -exact -backward -all "foo\nbar\nfoo" end
} {5.0 1.0}
test text-20.141 {TextSearchCmd, backward exact search overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -regexp -backward -overlap -all "foo\nbar\nfoo" end
} {5.0 3.0 1.0}
test text-20.142 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "foo\nbar\nfoo\nbar\nfoo\nbar\nfoo\n"
    .t2 search -regexp -backward -all "foo\nbar\nfoo" end
} {5.0 1.0}
test text-20.142a {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -- {(\$)?[\w:_]+} 1.9
} {1.7}
test text-20.143 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -- {(\$)?[\w:_]+} 1.9 1.5
} {1.7}
test text-20.144 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -- {(\$)?[\w:_]+} 1.9 1.7
} {1.7}
test text-20.145 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -- {(\$)?[\w:_]+} 1.9 1.8
} {1.8}
test text-20.146 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -all -- {(\$)?[\w:_]+} 1.9 1.3
} {1.7 1.3}
test text-20.147 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -all -- {(\$)?[\w:_]+} 1.9 1.13
} {}
test text-20.148 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -all -- {(\$)?[\w:_]+} 2.0 1.3
} {1.12 1.7 1.3}
test text-20.149 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 " aasda asdj werwer"
    .t2 search -regexp -backward -all -- {(\$)?[\w:_]+} 1.3
} {1.1 1.12 1.7 1.3}
test text-20.150 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\n"
    .t2 search -regexp -backward -all -- {(\w+\n)+} end
} {1.0}
test text-20.151 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\n"
    .t2 search -regexp -backward -all -- {(\w+\n)+} end 1.5
} {2.0}
test text-20.152 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    .t2 search -regexp -backward -all -- {(\w+\n\w)+} end 1.5
} {2.0}
test text-20.153 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -all -count foo -- {(\w+\n)+} 1.0] $foo
} {1.0 20}
test text-20.154 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    set res {}
    lappend res \
      [list [.t2 search -regexp -all -count foo -- {(\w+\n)+} 1.0] $foo] \
      [list [.t2 search -regexp -all -count foo -- {(\w+)+} 1.0] $foo]
} {{1.0 20} {{1.0 2.0 3.0 4.0} {5 5 5 1}}}
test text-20.155 {TextSearchCmd, regexp search greedy} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -all -nolinestop -count foo -- {.*} 1.0] $foo
} {1.0 20}
test text-20.156 {TextSearchCmd, regexp search greedy} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -all -count foo -- {.*} 1.0] $foo
} {{1.0 2.0 3.0 4.0} {5 5 5 1}}
test text-20.157 {TextSearchCmd, regexp search greedy multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -count foo -- {(\w+\n\w)+} 1.0] $foo
} {1.0 19}
test text-20.158 {TextSearchCmd, regexp search greedy multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -backwards -count foo -- {(\w+\n\w)+} end] $foo
} {1.0 19}
test text-20.159 {TextSearchCmd, regexp search greedy multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -all -backwards -count foo -- {(\w+\n\w)+} end] $foo
} {1.0 19}
test text-20.160 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    .t2 search -regexp -backward -all -- {(\w+\n\w)+} end 1.5
} {2.0}
test text-20.161 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    .t2 search -regexp -backward -all -- {(\w+\n\w)+} end 1.3
} {1.3}
test text-20.162 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -forward -count foo -- {(\w+\n\w)+} 1.3] $foo
} {1.3 16}
test text-20.163 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -forward -all -count foo -- {(\w+\n\w)+} 1.3] $foo
    # This result is somewhat debatable -- the two results do overlap,
    # but only because the search has totally wrapped around back to
    # the start.
} {{1.3 1.0} {16 19}}
test text-20.164 {TextSearchCmd, backward regexp search no-overlaps} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "abcde\nabcde\nabcde\na"
    list [.t2 search -regexp -forward -all -count foo -- {(\w+\n\w)+} 1.0 1.3] $foo
} {1.0 19}
test text-20.165 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\naaaa\nbbbb\n"
    list [.t2 search -regexp -forward -all -count foo -- {(a+\n(b+\n))+} 1.0] $foo
} {1.0 20}
test text-20.166 {TextSearchCmd, regexp search complex cases} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\naaaa\nbbbb\n"
    list [.t2 search -regexp -forward -all -count foo \
      -- {(a+\n(b+\n))+} 1.0] $foo
} {1.0 20}
test text-20.167 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n"
    set foo {}
    list [.t2 search -regexp -forward -all -count foo \
      -- {(b+\nc+\nb+)\na+} 1.0] $foo
} {2.0 19}
test text-20.168 {TextSearchCmd, regexp search multi-line} {knownBug} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n"
    set foo {}
    list [.t2 search -regexp -forward -all -count foo \
      -- {(a+|b+\nc+\nb+)\na+} 1.0] $foo
} {2.0 19}
test text-20.169 {TextSearchCmd, regexp search multi-line} {knownBug} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n"
    set foo {}
    list [.t2 search -regexp -forward -all -count foo \
      -- {(a+|b+\nc+\nb+)+\na+} 1.0] $foo
} {2.0 19}
test text-20.170 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\ncccc\nbbbb\naaaa\n"
    set foo {}
    list [.t2 search -regexp -forward -all -count foo \
      -- {((a+|b+\nc+\nb+)+\n)+a+} 1.0] $foo
} {1.0 24}
test text-20.171 {TextSearchCmd, regexp search multi-line} {knownBug} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\nbbbb\nbbbb\nbbbb\n"
    list [.t2 search -regexp -backward -all -count foo \
      -- {b+\n|a+\n(b+\n)+} end] $foo
} {1.0 25}
test text-20.172 {TextSearchCmd, regexp search multi-line} {knownBug} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aaaa\nbbbb\nbbbb\nbbbb\nbbbb\n"
    .t2 search -regexp -backward -- {b+\n|a+\n(b+\n)+} end
    # Should match at 1.0 for a true greedy match
} {1.0}
test text-20.172.1 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "line0\nline1\nline1\nline1\nline1\nline2\nline2\nline2\nline3\n"
    .t2 search -nolinestop -regexp -nocase -forwards -- {^(.*)\n(\1\n)+} 1.0 end
    # Matches at 6.0 currently
} {2.0}
test text-20.173 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "\naaaxxx\nyyy\n"
    set res {}
    lappend res [.t2 search -count c -regexp -- {x*\ny*} 2.0] $c
    lappend res [.t2 search -count c -regexp -- {x*\ny*} 2.1] $c
    set res
} {2.3 7 2.3 7}
test text-20.174 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "\naaa\n\n\n\n\nxxx\n"
    set res {}
    lappend res [.t2 search -count c -regexp -- {\n+} 2.0] $c
    lappend res [.t2 search -count c -regexp -- {\n+} 2.1] $c
    set res
} {2.3 5 2.3 5}
test text-20.175 {TextSearchCmd, regexp search multi-line} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "\naaa\n\n\t  \n\t\t\t  \n\nxxx\n"
    set res {}
    lappend res [.t2 search -count c -regexp -- {(\n+(\t+ *)*)+} 2.0] $c
    set res
} {2.3 13}
test text-20.176 {TextSearchCmd, empty search range} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\na\na\n"
    .t2 search -- a 2.0 1.0
} {}
test text-20.177 {TextSearchCmd, empty search range} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\na\na\n"
    .t2 search -backwards -- a 1.0 2.0
} {}
test text-20.178 {TextSearchCmd, empty search range} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\na\na\n"
    .t2 search -- a 1.0 1.0
} {}
test text-20.179 {TextSearchCmd, empty search range} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\na\na\n"
    .t2 search -backwards -- a 2.0 2.0
} {}
test text-20.180 {TextSearchCmd, elide up to match} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\nb\nc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search -regexp a 1.0]
    lappend res [.t2 search -regexp b 1.0]
    lappend res [.t2 search -regexp c 1.0]
    .t2 tag add e 1.0 2.0
    lappend res [.t2 search -regexp a 1.0]
    lappend res [.t2 search -regexp b 1.0]
    lappend res [.t2 search -regexp c 1.0]
    lappend res [.t2 search -elide -regexp a 1.0]
    lappend res [.t2 search -elide -regexp b 1.0]
    lappend res [.t2 search -elide -regexp c 1.0]
} {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}
test text-20.181 {TextSearchCmd, elide up to match, backwards} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\nb\nc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search -backward -regexp a 1.0]
    lappend res [.t2 search -backward -regexp b 1.0]
    lappend res [.t2 search -backward -regexp c 1.0]
    .t2 tag add e 1.0 2.0
    lappend res [.t2 search -backward -regexp a 1.0]
    lappend res [.t2 search -backward -regexp b 1.0]
    lappend res [.t2 search -backward -regexp c 1.0]
    lappend res [.t2 search -backward -elide -regexp a 1.0]
    lappend res [.t2 search -backward -elide -regexp b 1.0]
    lappend res [.t2 search -backward -elide -regexp c 1.0]
} {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}
test text-20.182 {TextSearchCmd, elide up to match} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\nb\nc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search a 1.0]
    lappend res [.t2 search b 1.0]
    lappend res [.t2 search c 1.0]
    .t2 tag add e 1.0 2.0
    lappend res [.t2 search a 1.0]
    lappend res [.t2 search b 1.0]
    lappend res [.t2 search c 1.0]
    lappend res [.t2 search -elide a 1.0]
    lappend res [.t2 search -elide b 1.0]
    lappend res [.t2 search -elide c 1.0]
} {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}
test text-20.183 {TextSearchCmd, elide up to match, backwards} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "a\nb\nc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search -backward a 1.0]
    lappend res [.t2 search -backward b 1.0]
    lappend res [.t2 search -backward c 1.0]
    .t2 tag add e 1.0 2.0
    lappend res [.t2 search -backward a 1.0]
    lappend res [.t2 search -backward b 1.0]
    lappend res [.t2 search -backward c 1.0]
    lappend res [.t2 search -backward -elide a 1.0]
    lappend res [.t2 search -backward -elide b 1.0]
    lappend res [.t2 search -backward -elide c 1.0]
} {1.0 2.0 3.0 {} 2.0 3.0 1.0 2.0 3.0}
test text-20.184 {TextSearchCmd, elide up to match} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aa\nbb\ncc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search ab 1.0]
    lappend res [.t2 search bc 1.0]
    .t2 tag add e 1.1 2.1
    lappend res [.t2 search ab 1.0]
    lappend res [.t2 search b 1.0]
    .t2 tag remove e 1.0 end
    .t2 tag add e 2.1 3.1
    lappend res [.t2 search bc 1.0]
    lappend res [.t2 search c 1.0]
    .t2 tag remove e 1.0 end
    .t2 tag add e 2.1 3.0
    lappend res [.t2 search bc 1.0]
    lappend res [.t2 search c 1.0]
} {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}
test text-20.185 {TextSearchCmd, elide up to match} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "aa\nbb\ncc"
    .t2 tag configure e -elide 1
    set res {}
    lappend res [.t2 search -regexp ab 1.0]
    lappend res [.t2 search -regexp bc 1.0]
    .t2 tag add e 1.1 2.1
    lappend res [.t2 search -regexp ab 1.0]
    lappend res [.t2 search -regexp b 1.0]
    .t2 tag remove e 1.0 end
    .t2 tag add e 2.1 3.1
    lappend res [.t2 search -regexp bc 1.0]
    lappend res [.t2 search -regexp c 1.0]
    .t2 tag remove e 1.0 end
    .t2 tag add e 2.1 3.0
    lappend res [.t2 search -regexp bc 1.0]
    lappend res [.t2 search -regexp c 1.0]
} {{} {} 1.0 2.1 2.0 3.1 2.0 3.0}
test text-20.186 {TextSearchCmd, strict limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -- "world" 1.3 1.8
} {}
test text-20.187 {TextSearchCmd, strict limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -- "world" 1.3 1.10
} {}
test text-20.188 {TextSearchCmd, strict limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -- "world" 1.3 1.11
} {1.6}
test text-20.189 {TextSearchCmd, strict limits backwards} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -backward -- "world" 2.3 1.8
} {}
test text-20.190 {TextSearchCmd, strict limits backwards} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -backward -- "world" 2.3 1.6
} {1.6}
test text-20.191 {TextSearchCmd, strict limits backwards} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -strictlimits -backward -- "world" 2.3 1.7
} {}
test text-20.192 {TextSearchCmd, strict limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -regexp -strictlimits -- "world" 1.3 1.8
} {}
test text-20.193 {TextSearchCmd, strict limits} {
    deleteWindows
    pack [scintilla .t2]
    .t2 insert 1.0 "Hello world!\nThis is a test\n"
    .t2 search -regexp -strictlimits -backward -- "world" 2.3 1.8
} {}

deleteWindows
#scintilla .t2 -highlightthickness 0 -borderwidth 0 -relief flat -padx 0 -width 100
 scintilla .t2 -highlightthickness 0 -borderwidth 0 -relief flat         -width 100
pack .t2
.t2 insert end "1\t2\t3\t4\t55.5"

test text-21.1 {TkTextGetTabs procedure} {
    list [catch {.t2 configure -tabs "\{{}"} msg] $msg
} {1 {unmatched open brace in list}}
test text-21.2 {TkTextGetTabs procedure} {
    list [catch {.t2 configure -tabs xyz} msg] $msg
} {1 {bad screen distance "xyz"}}
test text-21.3 {TkTextGetTabs procedure} {
    .t2 configure -tabs {100 200}
    update idletasks
    list [lindex [.t2 bbox 1.2] 0] [lindex [.t2 bbox 1.4] 0]
} {100 200}
test text-21.4 {TkTextGetTabs procedure} {
    .t2 configure -tabs {100 right 200 left 300 center 400 numeric}
    update idletasks
    list [expr [lindex [.t2 bbox 1.2] 0] + [lindex [.t2 bbox 1.2] 2]] \
	    [lindex [.t2 bbox 1.4] 0] \
	    [expr [lindex [.t2 bbox 1.6] 0] + [lindex [.t2 bbox 1.6] 2]/2] \
	    [lindex [.t2 bbox 1.10] 0]
} {100 200 300 400}
test text-21.5 {TkTextGetTabs procedure} {
    .t2 configure -tabs {105 r 205 l 305 c 405 n}
    update idletasks
    list [expr [lindex [.t2 bbox 1.2] 0] + [lindex [.t2 bbox 1.2] 2]] \
	    [lindex [.t2 bbox 1.4] 0] \
	    [expr [lindex [.t2 bbox 1.6] 0] + [lindex [.t2 bbox 1.6] 2]/2] \
	    [lindex [.t2 bbox 1.10] 0]
} {105 205 305 405}
test text-21.6 {TkTextGetTabs procedure} {
    list [catch {.t2 configure -tabs {100 left 200 lork}} msg] $msg
} {1 {bad tab alignment "lork": must be left, right, center, or numeric}}
test text-21.7 {TkTextGetTabs procedure} {
    list [catch {.t2 configure -tabs {100 !44 200 lork}} msg] $msg
} {1 {bad screen distance "!44"}}

deleteWindows
scintilla .t
pack .t
.t insert 1.0 "One Line"
.t mark set insert 1.0

test text-22.1 {TextDumpCmd procedure, bad args} {
    list [catch {.t dump} msg] $msg
} {1 {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}}
test text-22.2 {TextDumpCmd procedure, bad args} {
    list [catch {.t dump -all} msg] $msg
} {1 {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}}
test text-22.3 {TextDumpCmd procedure, bad args} {
    list [catch {.t dump -command} msg] $msg
} {1 {Usage: .t dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?}}
test text-22.4 {TextDumpCmd procedure, bad args} {
    list [catch {.t dump -bogus} msg] $msg
} {1 {bad option "-bogus": must be -all, -command, -image, -mark, -tag, -text, or -window}}
test text-22.5 {TextDumpCmd procedure, bad args} {
    list [catch {.t dump bogus} msg] $msg
} {1 {bad text index "bogus"}}
test text-22.6 {TextDumpCmd procedure, one index} {
    .t dump -text 1.2
} {text e 1.2}
test text-22.7 {TextDumpCmd procedure, two indices} {
    .t dump -text 1.0 1.end
} {text {One Line} 1.0}
test text-22.8 {TextDumpCmd procedure, "end" index} {
    .t dump -text 1.end end
} {text {
} 1.8}
test text-22.9 {TextDumpCmd procedure, same indices} {
    .t dump 1.5 1.5
} {}
test text-22.10 {TextDumpCmd procedure, negative range} {
    .t dump 1.5 1.0
} {}
.t delete 1.0 end
.t insert end "Line One\nLine Two\nLine Three\nLine Four"
.t mark set insert 1.0
.t mark set current 1.0
test text-22.11 {TextDumpCmd procedure, stop at begin-line} {
    .t dump -text 1.0 2.0
} {text {Line One
} 1.0}
test text-22.12 {TextDumpCmd procedure, span multiple lines} {
    .t dump -text 1.5 3.end
} {text {One
} 1.5 text {Line Two
} 2.0 text {Line Three} 3.0}
.t tag add x 2.0 2.end
.t tag add y 1.0 end
.t mark set m 2.4
.t mark set n 4.0
.t mark set END end
test text-22.13 {TextDumpCmd procedure, tags only} {
    .t dump -tag 2.1 2.8
} {}
test text-22.14 {TextDumpCmd procedure, tags only} {
    .t dump -tag 2.0 2.8
} {tagon x 2.0}
test text-22.15 {TextDumpCmd procedure, tags only} {
    .t dump -tag 1.0 4.end
} {tagon y 1.0 tagon x 2.0 tagoff x 2.8}
test text-22.16 {TextDumpCmd procedure, tags only} {
    .t dump -tag 1.0 end
} {tagon y 1.0 tagon x 2.0 tagoff x 2.8 tagoff y 5.0}
.t mark set insert 1.0
.t mark set current 1.0
test text-22.17 {TextDumpCmd procedure, marks only} {
    .t dump -mark 1.1 1.8
} {}
test text-22.18 {TextDumpCmd procedure, marks only} {
    .t dump -mark 2.0 2.8
} {mark m 2.4}
test text-22.19 {TextDumpCmd procedure, marks only} {
    .t dump -mark 1.1 4.end
} {mark m 2.4 mark n 4.0}
test text-22.20 {TextDumpCmd procedure, marks only} {
    .t dump -mark 1.0 end
} {mark current 1.0 mark insert 1.0 mark m 2.4 mark n 4.0 mark END 5.0}
button .hello -text Hello
catch {.t window create 3.end -window .hello}
for {set i 0} {$i < 100} {incr i} {
    .t insert end "-\n"
}
catch {.t window create 100.0 -create { }}
test text-22.21 {TextDumpCmd procedure, windows only} {
    .t dump -window 1.0 5.0
} {window .hello 3.10}
test text-22.22 {TextDumpCmd procedure, windows only} {
    .t dump -window 5.0 end
} {window {} 100.0}
.t delete 1.0 end
eval {.t mark unset} [.t mark names]
.t insert end "Line One\nLine Two\nLine Three\nLine Four"
.t mark set insert 1.0
.t mark set current 1.0
.t tag add x 2.0 2.end
.t mark set m 2.4
proc Append {varName key value index} {
    upvar #0 $varName x
    lappend x $key $index $value
}
test text-22.23 {TextDumpCmd procedure, command script} {
    set x {}
    .t dump -command {Append x} -all 1.0 end
    set x
} {mark 1.0 current mark 1.0 insert text 1.0 {Line One
} tagon 2.0 x text 2.0 Line mark 2.4 m text 2.4 { Two} tagoff 2.8 x text 2.8 {
} text 3.0 {Line Three
} text 4.0 {Line Four
}}
test text-22.24 {TextDumpCmd procedure, command script} {
    set x {}
    .t dump -mark -command {Append x} 1.0 end
    set x
} {mark 1.0 current mark 1.0 insert mark 2.4 m}
catch {unset x}
test text-22.25 {TextDumpCmd procedure, unicode characters} {
    catch {destroy .t}
    scintilla .t
    .t delete 1.0 end
    .t insert 1.0 \xb1\xb1\xb1
    .t dump -all 1.0 2.0
} "text \xb1\xb1\xb1 1.0 mark insert 1.3 mark current 1.3 text {\n} 1.3"
test text-22.26 {TextDumpCmd procedure, unicode characters} {
    catch {destroy .t}
    scintilla .t
    .t delete 1.0 end
    .t insert 1.0 abc\xb1\xb1\xb1
    .t dump -all 1.0 2.0
} "text abc\xb1\xb1\xb1 1.0 mark insert 1.6 mark current 1.6 text {\n} 1.6"

set l [interp hidden]
deleteWindows

test text-23.1 {text widget vs hidden commands} {
    catch {destroy .t}
    scintilla .t
    interp hide {} .t
    destroy .t
    list [winfo children .] [interp hidden]
} [list {} $l]

test text-24.1 {bug fix - 1642} {
    catch {destroy .t}
    scintilla .t
    pack .t
    .t insert end "line 1\n"
    .t insert end "line 2\n"
    .t insert end "line 3\n"
    .t insert end "line 4\n"
    .t insert end "line 5\n"
    tk::TextSetCursor .t 3.0
    .t search -backward -regexp "\$" insert 1.0
} {2.6}

test text-25.1 {TextEditCmd procedure, argument parsing} {
    list [catch {.t edit} msg] $msg
} {1 {wrong # args: should be ".t edit option ?arg arg ...?"}}
test text-25.2 {TextEditCmd procedure, argument parsing} {
    list [catch {.t edit gorp} msg] $msg
} {1 {bad edit option "gorp": must be modified, redo, reset, separator, or undo}}
test text-25.3 {TextEditUndo procedure, undoing changes} {
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "should be gone after undo\n"
    .t edit undo
    .t get 1.0 end
} "line\n\n"
test text-25.4 {TextEditRedo procedure, redoing changes} {
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "should be back after redo\n"
    .t edit undo
    .t edit redo
    .t get 1.0 end
} "line\nshould be back after redo\n\n"
test text-25.5 {TextEditUndo procedure, resetting stack} {
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "should be back after redo\n"
    .t edit reset
    catch {.t edit undo} msg
    set msg
} "nothing to undo"
test text-25.6 {TextEditCmd procedure, insert separator} {
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    .t insert end "line 1\n"
    .t edit separator
    .t insert end "line 2\n"
    .t edit undo
    .t get 1.0 end
} "line 1\n\n"
test text-25.7 {-autoseparators configuration option} {
    catch {destroy .t}
    scintilla .t -undo 1 -autoseparators 0
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "line 2\n"
    .t edit undo
    .t get 1.0 end
} "\n"
test text-25.8 {TextEditCmd procedure, modified flag} {
    catch {destroy .t}
    scintilla .t
    pack .t
    .t insert end "line 1\n"
    .t edit modified
} {1}
test text-25.9 {TextEditCmd procedure, reset modified flag} {
    catch {destroy .t}
    scintilla .t
    pack .t
    .t insert end "line 1\n"
    .t edit modified 0
    .t edit modified
} {0}
test text-25.10 {TextEditCmd procedure, set modified flag} {
    catch {destroy .t}
    scintilla .t
    pack .t
    .t edit modified 1
    .t edit modified
} {1}
test text-25.10.1 {TextEditCmd procedure, set modified flag repeat} {
    catch {destroy .t}
    scintilla .t
    pack .t
    set ::retval {}
    bind .t <<Modified>> "lappend ::retval modified"
    # Shouldn't require [update idle] to trigger event [Bug 1809538]
    lappend ::retval [.t edit modified]
    .t edit modified 1
    update idletasks
    lappend ::retval [.t edit modified]
    .t edit modified 1 ; # binding should only fire once [Bug 1799782]
    update idletasks
    lappend ::retval [.t edit modified]
} {0 modified 1 1}
test text-25.11 {<<Modified>> virtual event} {
    set ::retval unmodified
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    bind .t <<Modified>> "set ::retval modified"
    update idletasks
    .t insert end "nothing special\n"
    set ::retval
} {modified}
test text-25.11.1 {<<Modified>> virtual event - insert before Modified} {
    set ::retval {}
    destroy .t
    pack [scintilla .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    update idletasks
    .t insert end "nothing special"
    set ::retval
} {nothing special}
test text-25.11.2 {<<Modified>> virtual event - delete before Modified} {
    # Bug 1737288, make sure we delete chars before triggering <<Modified>>
    set ::retval {}
    destroy .t
    pack [scintilla .t -undo 1]
    bind .t <<Modified>> { set ::retval [.t get 1.0 end-1c] }
    .t insert end "nothing special"
    .t edit modified 0
    .t delete 1.0 1.2
    set ::retval
} {thing special}
test text-25.12 {<<Selection>> virtual event} {
    set ::retval no_selection
    catch {destroy .t}
    scintilla .t -undo 1
    pack .t
    bind .t <<Selection>> "set ::retval selection_changed"
    update idletasks
    .t insert end "nothing special\n"
    .t tag add sel 1.0 1.1
    set ::retval
} {selection_changed}
test text-25.13 {-maxundo configuration option} {
    catch {destroy .t}
    scintilla .t -undo 1  -autoseparators 1 -maxundo 2
    pack .t
    .t insert end "line 1\n"
    .t delete 1.4 1.6
    .t insert end "line 2\n"
    catch {.t edit undo}
    catch {.t edit undo}
    catch {.t edit undo}
    .t get 1.0 end
} "line 1\n\n"
test text-25.15 {bug fix 1536735 - undo with empty text} {
    catch {destroy .t}
    scintilla .t -undo 1
    set r [.t edit modified]
    .t delete 1.0
    lappend r [.t edit modified]
    lappend r [catch {.t edit undo}]
    lappend r [.t edit modified]
} {0 0 1 0}
test text-25.18 {patch 1469210 - inserting after undo} -setup {
    destroy .t
} -body {
    scintilla .t -undo 1
    .t insert end foo
    .t edit modified 0
    .t edit undo
    .t insert end bar
    .t edit modified
} -cleanup {
    destroy .t
} -result 1

test text-26.1 {bug fix - 624372, ControlUtfProc long lines} {
    destroy .t
    pack [scintilla .t -wrap none]
    .t insert end [string repeat "\1" 500]
} {}

test text-27.1 {tabs - must be positive and must be increasing} {
    destroy .t
    pack [scintilla .t -wrap none]
    list [catch {.t configure -tabs {0}} msg] $msg
} {1 {tab stop "0" is not at a positive distance}}
test text-27.2 {tabs - must be positive and must be increasing} {
    destroy .t
    pack [scintilla .t -wrap none]
    list [catch {.t configure -tabs {-5}} msg] $msg
} {1 {tab stop "-5" is not at a positive distance}}
test text-27.3 {tabs - must be positive and must be increasing} {knownBug} {
    # This bug will be fixed in Tk 9.0, when we can allow a minor
    # incompatibility with Tk 8.x
    destroy .t
    pack [scintilla .t -wrap none]
    list [catch {.t configure -tabs {10c 5c}} msg] $msg
} {1 {tabs must be monotonically increasing, but "5c" is smaller than or equal to the previous tab}}
test text-27.4 {tabs - must be positive and must be increasing} {
    destroy .t
    pack [scintilla .t -wrap none]
    .t insert end "a\tb\tc\td\te"
    catch {.t configure -tabs {10c 5c}}
    update ; update ; update
    # This test must simply not go into an infinite loop to succeed
    set result 1
} {1}

test text-28.0 {repeated insert and scroll} {
    foreach subcmd {
	{moveto 1}
	{scroll 1 pages}
	{scroll 100 pixels}
	{scroll 10 units}
    } {
	destroy .t
	pack [scintilla .t]
	for {set i 0} {$i < 30} {incr i} {
	    .t insert end "blabla\n"
	    eval .t yview $subcmd
	}
    }
    # This test must simply not crash to succeed
    set result 1
} {1}

test text-29.0 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    pack [.t peer create .tt.t]
    destroy .t .tt
} {}
test text-29.1 {peer widgets} {
    destroy .t .t1 .t2
    toplevel .t1
    toplevel .t2
    pack [scintilla .t]
    pack [.t peer create .t1.t]
    pack [.t peer create .t2.t]
    .t insert end "abcd\nabcd"
    update
    destroy .t1
    update
    .t insert end "abcd\nabcd"
    update
    destroy .t .t2
    update
} {}
test text-29.2 {peer widgets} {
    destroy .t .t1 .t2
    toplevel .t1
    toplevel .t2
    pack [scintilla .t]
    pack [.t peer create .t1.t]
    pack [.t peer create .t2.t]
    .t insert end "abcd\nabcd"
    update
    destroy .t
    update
    .t2.t insert end "abcd\nabcd"
    update
    destroy .t .t2
    update
} {}
test text-29.3 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    update
    destroy .t .tt
} {}
test text-29.4 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    pack [.tt.t peer create .tt.t2]
    set res [list [.tt.t index end] [.tt.t2 index end]]
    update
    destroy .t .tt
    set res
} {7.0 7.0}
test text-29.4.1 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    pack [.tt.t peer create .tt.t2 -start {} -end {}]
    set res [list [.tt.t index end] [.tt.t2 index end]]
    update
    destroy .t .tt
    set res
} {7.0 21.0}
test text-29.5 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    update ; update
    set p1 [.tt.t count -update -ypixels 1.0 end]
    set p2 [.t count -update -ypixels 5.0 11.0]
    if {$p1 == $p2} { 
	set res "ok" 
    } else {
        set res "$p1 and $p2 not equal"
    }
    destroy .t .tt
    set res
} {ok}
test text-29.6 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    update ; update
    .t delete 3.0 6.0
    set res [.tt.t index end]
    destroy .t .tt
    set res
} {6.0}
test text-29.7 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    update ; update
    .t delete 8.0 12.0
    set res [.tt.t index end]
    destroy .t .tt
    set res
} {4.0}
test text-29.8 {peer widgets} {
    destroy .t .tt
    toplevel .tt
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    pack [.t peer create .tt.t -start 5 -end 11]
    update ; update
    .t delete 3.0 13.0
    set res [.tt.t index end]
    destroy .t .tt
    set res
} {1.0}
test text-29.9 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    set res {}
    lappend res [.t tag ranges sel]
    .t configure -start 10 -end 20
    lappend res [.t tag ranges sel]
    destroy .t
    set res
} {{1.0 100.0} {1.0 11.0}}
test text-29.10 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    set res {}
    lappend res [.t tag ranges sel]
    .t configure -start 11
    lappend res [.t tag ranges sel]
    destroy .t
    set res
} {{1.0 100.0} {1.0 90.0}}
test text-29.11 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 end-1c
    set res {}
    lappend res [.t tag ranges sel]
    .t configure -end 90
    lappend res [.t tag ranges sel]
    destroy .t
    set res
} {{1.0 100.0} {1.0 90.0}}
test text-29.12 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 3.0 5.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 
    set res {}
    lappend res [.t tag prevrange sel 1.0]
    .t configure -start 6 -end 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    destroy .t
    set res
} {{} {1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}
test text-29.13 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 3.0 9.0 11.0 13.0 15.0 17.0 19.0 
    set res {}
    .t configure -start 6 -end 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    destroy .t
    set res
} {{4.0 6.0} next {4.0 6.0} {} {} {} prev {} {} {} {}}
test text-29.14 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 1.0 7.0 9.0 11.0 13.0 15.0 17.0 19.0 
    set res {}
    .t configure -start 6 -end 12
    lappend res [.t tag ranges sel]
    lappend res "next" [.t tag nextrange sel 4.0] \
      [.t tag nextrange sel 5.0] [.t tag nextrange sel 6.0] \
      [.t tag nextrange sel 7.0]
    lappend res "prev" [.t tag prevrange sel 1.0] \
      [.t tag prevrange sel 2.0] [.t tag prevrange sel 3.0] \
      [.t tag prevrange sel 4.0]
    destroy .t
    set res
} {{1.0 2.0 4.0 6.0} next {4.0 6.0} {} {} {} prev {} {1.0 2.0} {1.0 2.0} {1.0 2.0}}
test text-29.15 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    set res {}
    .t tag add sel 1.0 11.0
    lappend res [.t tag ranges sel]
    lappend res [catch {.t configure -start 15 -end 10}]
    lappend res [.t tag ranges sel]
    .t configure -start 6 -end 12
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    lappend res [.t tag ranges sel]
    destroy .t
    set res
} {{1.0 11.0} 1 {1.0 11.0} {1.0 6.0} {1.0 11.0}}
test text-29.16 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    set res {}
    .t tag add sel 1.0 11.0
    lappend res [.t index sel.first]
    lappend res [.t index sel.last]
    destroy .t
    set res
} {1.0 11.0} 
test text-29.17 {peer widgets} {
    destroy .t
    pack [scintilla .t]
    for {set i 1} {$i < 20} {incr i} {
	.t insert end "Line $i\n"
    }
    set res {}
    .t tag delete sel
    set res [list [catch {.t index sel.first} msg] $msg]
    destroy .t
    set res
} {1 {text doesn't contain any characters tagged with "sel"}} 

proc makeText {} {
    set w .g
    set font "Times 11"
    destroy .g
    toplevel .g
    frame $w.f -highlightthickness 2 -borderwidth 2 -relief sunken
    set t $w.f.text
    scintilla $t -yscrollcommand "$w.scroll set" -setgrid true -font $font -width 70 \
	    -height 35 -wrap word -highlightthickness 0 -borderwidth 0
    pack $t -expand  yes -fill both
    scrollbar $w.scroll -command "$t yview"
    pack $w.scroll -side right -fill y
    pack $w.f -expand yes -fill both
    $t tag configure center -justify center -spacing1 5m -spacing3 5m
    $t tag configure buttons -lmargin1 1c -lmargin2 1c -rmargin 1c \
	    -spacing1 3m -spacing2 0 -spacing3 0
    for {set i 0} {$i < 40} {incr i} {
	$t insert end "${i}word "
    }
    return $t
}

test text-30.1 {line heights on creation} {
    set w [makeText]
    update ; after 1000 ; update
    set before [$w count -ypixels 1.0 2.0]
    $w insert 1.0 "a"
    update
    set after [$w count -ypixels 1.0 2.0]
    destroy .g
    if {$before != $after} {
	set res "Count changed: $before $after"
    } else {
        set res "ok"
    }
} {ok}

destroy .t
scintilla .t
test text-31.1 {TextWidgetCmd procedure, "peer" option} {
    list [catch {.t peer foo 1} msg] $msg
} {1 {bad peer option "foo": must be create or names}}
test text-31.2 {TextWidgetCmd procedure, "peer" option} {
    list [catch {.t peer names foo} msg] $msg
} {1 {wrong # args: should be ".t peer names"}}
test text-31.3 {TextWidgetCmd procedure, "peer" option} {
    list [catch {.t p names} msg] $msg
} {0 {}}
test text-31.4 {TextWidgetCmd procedure, "peer" option} {
    .t peer names
} {}
test text-31.5 {TextWidgetCmd procedure, "peer" option} {
    list [catch {.t peer create foo} msg] $msg
} {1 {bad window path name "foo"}}
test text-31.6 {TextWidgetCmd procedure, "peer" option} {
    .t peer create .t2
    set res {}
    lappend res [.t peer names]
    lappend res [.t2 peer names]
    destroy .t2
    lappend res [.t peer names]
} {.t2 .t {}}
test text-31.7 {peer widget -start, -end} {
    set res [list [catch {.t configure -start 10 -end 5} msg] $msg]
    .t configure -start {} -end {}
    set res
} {0 {}}
test text-31.8 {peer widget -start, -end} {
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    list [catch {.t configure -start 10 -end 5} msg] $msg
} {1 {-startline must be less than or equal to -endline}}
test text-31.9 {peer widget -start, -end} {
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    set res [list [catch {.t configure -start 5 -end 10} msg] $msg]
    .t configure -start {} -end {}
    set res
} {0 {}}
test text-31.10 {peer widget -start, -end} {
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    set res [.t index end]
    lappend res [catch {.t configure -start 5 -end 10 -tab foo}]
    lappend res [.t index end]
    lappend res [catch {.t configure -tab foo -start 15 -end 20}]
    lappend res [.t index end]
    .t configure -start {} -end {}
    lappend res [.t index end]
    set res
} {101.0 1 101.0 1 101.0 101.0}
test text-31.11 {peer widget -start, -end} {
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    set res [.t index end]
    lappend res [catch {.t configure -start 5 -end 15}]
    lappend res [.t index end]
    lappend res [catch {.t configure -start 10 -end 40}]
    lappend res [.t index end]
    .t configure -start {} -end {}
    lappend res [.t index end]
    set res
} {101.0 0 11.0 0 31.0 101.0}

test text-32.1 {peer widget -start, -end and selection} {
    .t delete 1.0 end
    for {set i 1} {$i < 100} {incr i} {
	.t insert end "Line $i\n"
    }
    .t tag add sel 10.0 20.0
    set res {}
    lappend res [.t tag ranges sel]
    .t configure -start 5 -end 30
    lappend res [.t tag ranges sel]
    .t configure -start 5 -end 15
    lappend res [.t tag ranges sel]
    .t configure -start 15 -end 30
    lappend res [.t tag ranges sel]
    .t configure -start 15 -end 16
    lappend res [.t tag ranges sel]
    .t configure -start 25 -end 30
    lappend res [.t tag ranges sel]
    .t configure -start {} -end {}
    lappend res [.t tag ranges sel]
    set res
} {{10.0 20.0} {6.0 16.0} {6.0 11.0} {1.0 6.0} {1.0 2.0} {} {10.0 20.0}}

test text-33.1 {widget dump -command alters tags} {
    .t delete 1.0 end
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    proc Dumpy {key value index} {
      #puts "KK: $key, $value"
      .t tag add $value [list $index linestart] [list $index lineend]
    }
    .t dump -all -command Dumpy 1.0 end
    set result "ok"
} {ok}
test text-33.2 {widget dump -command makes massive changes} {
    .t delete 1.0 end
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    proc Dumpy {key value index} {
      #puts "KK: $key, $value"
      .t delete 1.0 end
    }
    .t dump -all -command Dumpy 1.0 end
    set result "ok"
} {ok}
test text-33.3 {widget dump -command destroys widget} {
    .t delete 1.0 end
    .t insert end "abc\n" a "---" {} "def" b "   \n" {} "ghi\n" c
    .t tag configure b -background red
    proc Dumpy {key value index} {
      #puts "KK: $key, $value"
      destroy .t
    }
    .t dump -all -command Dumpy 1.0 end
    set result "ok"
} {ok}

exit

Added version.txt.



>
1
330

Added win32/CheckD2D.cxx.







>
>
>
1
2
3
// This file is compiled to check whether Direct2D and DirectWrite headers are available.
#include <d2d1.h>
#include <dwrite.h>

Added win32/PlatWin.cxx.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
// Scintilla source code edit control
/** @file PlatWin.cxx
 ** Implementation of platform facilities on Windows.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <math.h>

#include <vector>
#include <map>

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#undef WINVER
#define WINVER 0x0500
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>

#if defined(NTDDI_WIN7) && !defined(DISABLE_D2D)
#define USE_D2D 1
#endif

#if defined(USE_D2D)
#include <d2d1.h>
#include <dwrite.h>
#endif

#include "Platform.h"
#include "UniConversion.h"
#include "XPM.h"
#include "FontQuality.h"

#ifndef IDC_HAND
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif

// Take care of 32/64 bit pointers
#ifdef GetWindowLongPtr
static void *PointerFromWindow(HWND hWnd) {
	return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
	::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
}
#else
static void *PointerFromWindow(HWND hWnd) {
	return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
	::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
}

#ifndef GWLP_USERDATA
#define GWLP_USERDATA GWL_USERDATA
#endif

#ifndef GWLP_WNDPROC
#define GWLP_WNDPROC GWL_WNDPROC
#endif

#ifndef LONG_PTR
#define LONG_PTR LONG
#endif

static LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong) {
	return ::SetWindowLong(hWnd, nIndex, dwNewLong);
}

static LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) {
	return ::GetWindowLong(hWnd, nIndex);
}
#endif

// Declarations needed for functions dynamically loaded as not available on all Windows versions.
typedef BOOL (WINAPI *AlphaBlendSig)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
typedef HMONITOR (WINAPI *MonitorFromPointSig)(POINT, DWORD);
typedef HMONITOR (WINAPI *MonitorFromRectSig)(LPCRECT, DWORD);
typedef BOOL (WINAPI *GetMonitorInfoSig)(HMONITOR, LPMONITORINFO);

static CRITICAL_SECTION crPlatformLock;
static HINSTANCE hinstPlatformRes = 0;
static bool onNT = false;

static HMODULE hDLLImage = 0;
static AlphaBlendSig AlphaBlendFn = 0;

static HMODULE hDLLUser32 = 0;
static HMONITOR (WINAPI *MonitorFromPointFn)(POINT, DWORD) = 0;
static HMONITOR (WINAPI *MonitorFromRectFn)(LPCRECT, DWORD) = 0;
static BOOL (WINAPI *GetMonitorInfoFn)(HMONITOR, LPMONITORINFO) = 0;

static HCURSOR reverseArrowCursor = NULL;

bool IsNT() {
	return onNT;
}

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

Point Point::FromLong(long lpoint) {
	return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
}

static RECT RectFromPRectangle(PRectangle prc) {
	RECT rc = {static_cast<LONG>(prc.left), static_cast<LONG>(prc.top),
		static_cast<LONG>(prc.right), static_cast<LONG>(prc.bottom)};
	return rc;
}

#if defined(USE_D2D)
IDWriteFactory *pIDWriteFactory = 0;
ID2D1Factory *pD2DFactory = 0;

bool LoadD2D() {
	static bool triedLoadingD2D = false;
	static HMODULE hDLLD2D = 0;
	static HMODULE hDLLDWrite = 0;
	if (!triedLoadingD2D) {
		typedef HRESULT (WINAPI *D2D1CFSig)(D2D1_FACTORY_TYPE factoryType, REFIID riid,
			CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, IUnknown **factory);
		typedef HRESULT (WINAPI *DWriteCFSig)(DWRITE_FACTORY_TYPE factoryType, REFIID iid,
			IUnknown **factory);

		hDLLD2D = ::LoadLibraryEx(TEXT("D2D1.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
		if (hDLLD2D) {
			D2D1CFSig fnD2DCF = (D2D1CFSig)::GetProcAddress(hDLLD2D, "D2D1CreateFactory");
			if (fnD2DCF) {
				// A single threaded factory as Scintilla always draw on the GUI thread
				fnD2DCF(D2D1_FACTORY_TYPE_SINGLE_THREADED,
					__uuidof(ID2D1Factory),
					0,
					reinterpret_cast<IUnknown**>(&pD2DFactory));
			}
		}
		hDLLDWrite = ::LoadLibraryEx(TEXT("DWRITE.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
		if (hDLLDWrite) {
			DWriteCFSig fnDWCF = (DWriteCFSig)::GetProcAddress(hDLLDWrite, "DWriteCreateFactory");
			if (fnDWCF) {
				fnDWCF(DWRITE_FACTORY_TYPE_SHARED,
					__uuidof(IDWriteFactory),
					reinterpret_cast<IUnknown**>(&pIDWriteFactory));
			}
		}
	}
	triedLoadingD2D = true;
	return pIDWriteFactory && pD2DFactory;
}
#endif

struct FormatAndMetrics {
	int technology;
	HFONT hfont;
#if defined(USE_D2D)
	IDWriteTextFormat *pTextFormat;
#endif
	int extraFontFlag;
	FLOAT yAscent;
	FLOAT yDescent;
	FLOAT yInternalLeading;
	FormatAndMetrics(HFONT hfont_, int extraFontFlag_) : 
		technology(SCWIN_TECH_GDI), hfont(hfont_), 
#if defined(USE_D2D)
		pTextFormat(0),
#endif
		extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1), yInternalLeading(0) {
	}
#if defined(USE_D2D)
	FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_, FLOAT yInternalLeading_) : 
		technology(SCWIN_TECH_DIRECTWRITE), hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_), yInternalLeading(yInternalLeading_) {
	}
#endif
	~FormatAndMetrics() {
		if (hfont)
			::DeleteObject(hfont);
#if defined(USE_D2D)
		if (pTextFormat)
			pTextFormat->Release();
		pTextFormat = 0;
#endif
		extraFontFlag = 0;
		yAscent = 2;
		yDescent = 1;
		yInternalLeading = 0;
	}
	HFONT HFont();
};

HFONT FormatAndMetrics::HFont() {
	LOGFONTW lf;
	memset(&lf, 0, sizeof(lf));
#if defined(USE_D2D)
	if (technology == SCWIN_TECH_GDI) {
		if (0 == ::GetObjectW(hfont, sizeof(lf), &lf)) {
			return 0;
		}
	} else {
		HRESULT hr = pTextFormat->GetFontFamilyName(lf.lfFaceName, LF_FACESIZE);
		if (!SUCCEEDED(hr)) {
			return 0;
		}
		lf.lfWeight = pTextFormat->GetFontWeight();
		lf.lfItalic = pTextFormat->GetFontStyle() == DWRITE_FONT_STYLE_ITALIC;
		lf.lfHeight = -static_cast<int>(pTextFormat->GetFontSize());
	}
#else
	if (0 == ::GetObjectW(hfont, sizeof(lf), &lf)) {
		return 0;
	}
#endif
	return ::CreateFontIndirectW(&lf);
}

#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif

static BYTE Win32MapFontQuality(int extraFontFlag) {
	switch (extraFontFlag & SC_EFF_QUALITY_MASK) {

		case SC_EFF_QUALITY_NON_ANTIALIASED:
			return NONANTIALIASED_QUALITY;

		case SC_EFF_QUALITY_ANTIALIASED:
			return ANTIALIASED_QUALITY;

		case SC_EFF_QUALITY_LCD_OPTIMIZED:
			return CLEARTYPE_QUALITY;

		default:
			return SC_EFF_QUALITY_DEFAULT;
	}
}

#if defined(USE_D2D)
static D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) {
	switch (extraFontFlag & SC_EFF_QUALITY_MASK) {

		case SC_EFF_QUALITY_NON_ANTIALIASED:
			return D2D1_TEXT_ANTIALIAS_MODE_ALIASED;

		case SC_EFF_QUALITY_ANTIALIASED:
			return D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;

		case SC_EFF_QUALITY_LCD_OPTIMIZED:
			return D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;

		default:
			return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
	}
}
#endif

static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) {
	memset(&lf, 0, sizeof(lf));
	// The negative is to allow for leading
	lf.lfHeight = -(abs(static_cast<int>(size + 0.5)));
	lf.lfWeight = weight;
	lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
	lf.lfCharSet = static_cast<BYTE>(characterSet);
	lf.lfQuality = Win32MapFontQuality(extraFontFlag);
	strncpy(lf.lfFaceName, faceName, sizeof(lf.lfFaceName));
}

/**
 * Create a hash from the parameters for a font to allow easy checking for identity.
 * If one font is the same as another, its hash will be the same, but if the hash is the
 * same then they may still be different.
 */
static int HashFont(const FontParameters &fp) {
	return
		static_cast<int>(fp.size) ^
		(fp.characterSet << 10) ^
		((fp.extraFontFlag & SC_EFF_QUALITY_MASK) << 9) ^
		((fp.weight/100) << 12) ^
		(fp.italic ? 0x20000000 : 0) ^
		(fp.technology << 15) ^
		fp.faceName[0];
}

class FontCached : Font {
	FontCached *next;
	int usage;
	float size;
	LOGFONTA lf;
	int technology;
	int hash;
	FontCached(const FontParameters &fp);
	~FontCached() {}
	bool SameAs(const FontParameters &fp);
	virtual void Release();

	static FontCached *first;
public:
	static FontID FindOrCreate(const FontParameters &fp);
	static void ReleaseId(FontID fid_);
};

FontCached *FontCached::first = 0;

FontCached::FontCached(const FontParameters &fp) :
	next(0), usage(0), size(1.0), hash(0) {
	SetLogFont(lf, fp.faceName, fp.characterSet, fp.size, fp.weight, fp.italic, fp.extraFontFlag);
	technology = fp.technology;
	hash = HashFont(fp);
	fid = 0;
	if (technology == SCWIN_TECH_GDI) {
		HFONT hfont = ::CreateFontIndirectA(&lf);
		fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag));
	} else {
#if defined(USE_D2D)
		IDWriteTextFormat *pTextFormat;
		const int faceSize = 200;
		WCHAR wszFace[faceSize];
		UTF16FromUTF8(fp.faceName, static_cast<unsigned int>(strlen(fp.faceName))+1, wszFace, faceSize);
		FLOAT fHeight = fp.size;
		DWRITE_FONT_STYLE style = fp.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
		HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL,
			static_cast<DWRITE_FONT_WEIGHT>(fp.weight),
			style,
			DWRITE_FONT_STRETCH_NORMAL, fHeight, L"en-us", &pTextFormat);
		if (SUCCEEDED(hr)) {
			pTextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);

			const int maxLines = 2;
			DWRITE_LINE_METRICS lineMetrics[maxLines];
			UINT32 lineCount = 0;
			FLOAT yAscent = 1.0f;
			FLOAT yDescent = 1.0f;
			FLOAT yInternalLeading = 0.0f;
			IDWriteTextLayout *pTextLayout = 0;
			hr = pIDWriteFactory->CreateTextLayout(L"X", 1, pTextFormat,
					100.0f, 100.0f, &pTextLayout);
			if (SUCCEEDED(hr)) {
				hr = pTextLayout->GetLineMetrics(lineMetrics, maxLines, &lineCount);
				if (SUCCEEDED(hr)) {
					yAscent = lineMetrics[0].baseline;
					yDescent = lineMetrics[0].height - lineMetrics[0].baseline;

					FLOAT emHeight;
					hr = pTextLayout->GetFontSize(0, &emHeight);
					if (SUCCEEDED(hr)) {
						yInternalLeading = lineMetrics[0].height - emHeight;
					}
				}
				pTextLayout->Release();
			}
			fid = reinterpret_cast<void *>(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, yAscent, yDescent, yInternalLeading));
		}
#endif
	}
	usage = 1;
}

bool FontCached::SameAs(const FontParameters &fp) {
	return
		(size == fp.size) &&
		(lf.lfWeight == fp.weight) &&
		(lf.lfItalic == static_cast<BYTE>(fp.italic ? 1 : 0)) &&
		(lf.lfCharSet == fp.characterSet) &&
		(lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) &&
		(technology == fp.technology) &&
		0 == strcmp(lf.lfFaceName,fp.faceName);
}

void FontCached::Release() {
	delete reinterpret_cast<FormatAndMetrics *>(fid);
	fid = 0;
}

FontID FontCached::FindOrCreate(const FontParameters &fp) {
	FontID ret = 0;
	::EnterCriticalSection(&crPlatformLock);
	int hashFind = HashFont(fp);
	for (FontCached *cur=first; cur; cur=cur->next) {
		if ((cur->hash == hashFind) &&
			cur->SameAs(fp)) {
			cur->usage++;
			ret = cur->fid;
		}
	}
	if (ret == 0) {
		FontCached *fc = new FontCached(fp);
		if (fc) {
			fc->next = first;
			first = fc;
			ret = fc->fid;
		}
	}
	::LeaveCriticalSection(&crPlatformLock);
	return ret;
}

void FontCached::ReleaseId(FontID fid_) {
	::EnterCriticalSection(&crPlatformLock);
	FontCached **pcur=&first;
	for (FontCached *cur=first; cur; cur=cur->next) {
		if (cur->fid == fid_) {
			cur->usage--;
			if (cur->usage == 0) {
				*pcur = cur->next;
				cur->Release();
				cur->next = 0;
				delete cur;
			}
			break;
		}
		pcur=&cur->next;
	}
	::LeaveCriticalSection(&crPlatformLock);
}

Font::Font() {
	fid = 0;
}

Font::~Font() {
}

#define FONTS_CACHED

void Font::Create(const FontParameters &fp) {
	Release();
	if (fp.faceName)
		fid = FontCached::FindOrCreate(fp);
}

void Font::Release() {
	if (fid)
		FontCached::ReleaseId(fid);
	fid = 0;
}

// Buffer to hold strings and string position arrays without always allocating on heap.
// May sometimes have string too long to allocate on stack. So use a fixed stack-allocated buffer
// when less than safe size otherwise allocate on heap and free automatically.
template<typename T, int lengthStandard>
class VarBuffer {
	T bufferStandard[lengthStandard];
	// Private so VarBuffer objects can not be copied
	VarBuffer(const VarBuffer &);
	VarBuffer &operator=(const VarBuffer &);
public:
	T *buffer;
	VarBuffer(size_t length) : buffer(0) {
		if (length > lengthStandard) {
			buffer = new T[length];
		} else {
			buffer = bufferStandard;
		}
	}
	~VarBuffer() {
		if (buffer != bufferStandard) {
			delete []buffer;
			buffer = 0;
		}
	}
};

const int stackBufferLength = 10000;
class TextWide : public VarBuffer<wchar_t, stackBufferLength> {
public:
	int tlen;
	TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
		VarBuffer<wchar_t, stackBufferLength>(len) {
		if (unicodeMode) {
			tlen = UTF16FromUTF8(s, len, buffer, len);
		} else {
			// Support Asian string display in 9x English
			tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
		}
	}
};
typedef VarBuffer<XYPOSITION, stackBufferLength> TextPositions;

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class SurfaceGDI : public Surface {
	bool unicodeMode;
	HDC hdc;
	bool hdcOwned;
	HPEN pen;
	HPEN penOld;
	HBRUSH brush;
	HBRUSH brushOld;
	HFONT font;
	HFONT fontOld;
	HBITMAP bitmap;
	HBITMAP bitmapOld;
	int maxWidthMeasure;
	int maxLenText;

	int codePage;
	// If 9x OS and current code page is same as ANSI code page.
	bool win9xACPSame;

	void BrushColor(ColourDesired back);
	void SetFont(Font &font_);

	// Private so SurfaceGDI objects can not be copied
	SurfaceGDI(const SurfaceGDI &);
	SurfaceGDI &operator=(const SurfaceGDI &);
public:
	SurfaceGDI();
	virtual ~SurfaceGDI();

	void Init(WindowID wid);
	void Init(SurfaceID sid, WindowID wid);
	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);

	void Release();
	bool Initialised();
	void PenColour(ColourDesired fore);
	int LogPixelsY();
	int DeviceHeightFont(int points);
	void MoveTo(int x_, int y_);
	void LineTo(int x_, int y_);
	void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back);
	void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back);
	void FillRectangle(PRectangle rc, ColourDesired back);
	void FillRectangle(PRectangle rc, Surface &surfacePattern);
	void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back);
	void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags);
	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back);
	void Copy(PRectangle rc, Point from, Surface &surfaceSource);

	void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
	void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
	XYPOSITION WidthText(Font &font_, const char *s, int len);
	XYPOSITION WidthChar(Font &font_, char ch);
	XYPOSITION Ascent(Font &font_);
	XYPOSITION Descent(Font &font_);
	XYPOSITION InternalLeading(Font &font_);
	XYPOSITION ExternalLeading(Font &font_);
	XYPOSITION Height(Font &font_);
	XYPOSITION AverageCharWidth(Font &font_);

	void SetClip(PRectangle rc);
	void FlushCachedState();

	void SetUnicodeMode(bool unicodeMode_);
	void SetDBCSMode(int codePage_);
};

#ifdef SCI_NAMESPACE
} //namespace Scintilla
#endif

SurfaceGDI::SurfaceGDI() :
	unicodeMode(false),
	hdc(0), 	hdcOwned(false),
	pen(0), 	penOld(0),
	brush(0), brushOld(0),
	font(0), 	fontOld(0),
	bitmap(0), bitmapOld(0) {
	// Windows 9x has only a 16 bit coordinate system so break after 30000 pixels
	maxWidthMeasure = IsNT() ? INT_MAX : 30000;
	// There appears to be a 16 bit string length limit in GDI on NT and a limit of
	// 8192 characters on Windows 95.
	maxLenText = IsNT() ? 65535 : 8192;

	codePage = 0;
	win9xACPSame = false;
}

SurfaceGDI::~SurfaceGDI() {
	Release();
}

void SurfaceGDI::Release() {
	if (penOld) {
		::SelectObject(reinterpret_cast<HDC>(hdc), penOld);
		::DeleteObject(pen);
		penOld = 0;
	}
	pen = 0;
	if (brushOld) {
		::SelectObject(reinterpret_cast<HDC>(hdc), brushOld);
		::DeleteObject(brush);
		brushOld = 0;
	}
	brush = 0;
	if (fontOld) {
		// Fonts are not deleted as they are owned by a Font object
		::SelectObject(reinterpret_cast<HDC>(hdc), fontOld);
		fontOld = 0;
	}
	font = 0;
	if (bitmapOld) {
		::SelectObject(reinterpret_cast<HDC>(hdc), bitmapOld);
		::DeleteObject(bitmap);
		bitmapOld = 0;
	}
	bitmap = 0;
	if (hdcOwned) {
		::DeleteDC(reinterpret_cast<HDC>(hdc));
		hdc = 0;
		hdcOwned = false;
	}
}

bool SurfaceGDI::Initialised() {
	return hdc != 0;
}

void SurfaceGDI::Init(WindowID) {
	Release();
	hdc = ::CreateCompatibleDC(NULL);
	hdcOwned = true;
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceGDI::Init(SurfaceID sid, WindowID) {
	Release();
	hdc = reinterpret_cast<HDC>(sid);
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceGDI::InitPixMap(int width, int height, Surface *surface_, WindowID) {
	Release();
	hdc = ::CreateCompatibleDC(static_cast<SurfaceGDI *>(surface_)->hdc);
	hdcOwned = true;
	bitmap = ::CreateCompatibleBitmap(static_cast<SurfaceGDI *>(surface_)->hdc, width, height);
	bitmapOld = static_cast<HBITMAP>(::SelectObject(hdc, bitmap));
	::SetTextAlign(reinterpret_cast<HDC>(hdc), TA_BASELINE);
}

void SurfaceGDI::PenColour(ColourDesired fore) {
	if (pen) {
		::SelectObject(hdc, penOld);
		::DeleteObject(pen);
		pen = 0;
		penOld = 0;
	}
	pen = ::CreatePen(0,1,fore.AsLong());
	penOld = static_cast<HPEN>(::SelectObject(reinterpret_cast<HDC>(hdc), pen));
}

void SurfaceGDI::BrushColor(ColourDesired back) {
	if (brush) {
		::SelectObject(hdc, brushOld);
		::DeleteObject(brush);
		brush = 0;
		brushOld = 0;
	}
	// Only ever want pure, non-dithered brushes
	ColourDesired colourNearest = ::GetNearestColor(hdc, back.AsLong());
	brush = ::CreateSolidBrush(colourNearest.AsLong());
	brushOld = static_cast<HBRUSH>(::SelectObject(hdc, brush));
}

void SurfaceGDI::SetFont(Font &font_) {
	if (font_.GetID() != font) {
		FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
		PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_GDI);
		if (fontOld) {
			::SelectObject(hdc, pfm->hfont);
		} else {
			fontOld = static_cast<HFONT>(::SelectObject(hdc, pfm->hfont));
		}
		font = reinterpret_cast<HFONT>(pfm->hfont);
	}
}

int SurfaceGDI::LogPixelsY() {
	return ::GetDeviceCaps(hdc, LOGPIXELSY);
}

int SurfaceGDI::DeviceHeightFont(int points) {
	return ::MulDiv(points, LogPixelsY(), 72);
}

void SurfaceGDI::MoveTo(int x_, int y_) {
	::MoveToEx(hdc, x_, y_, 0);
}

void SurfaceGDI::LineTo(int x_, int y_) {
	::LineTo(hdc, x_, y_);
}

void SurfaceGDI::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back) {
	PenColour(fore);
	BrushColor(back);
	std::vector<POINT> outline;
	for (int i=0;i<npts;i++) {
		POINT pt = {static_cast<LONG>(pts[i].x), static_cast<LONG>(pts[i].y)};
		outline.push_back(pt);
	}
	::Polygon(hdc, &outline[0], npts);
}

void SurfaceGDI::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) {
	PenColour(fore);
	BrushColor(back);
	::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
}

void SurfaceGDI::FillRectangle(PRectangle rc, ColourDesired back) {
	// Using ExtTextOut rather than a FillRect ensures that no dithering occurs.
	// There is no need to allocate a brush either.
	RECT rcw = RectFromPRectangle(rc);
	::SetBkColor(hdc, back.AsLong());
	::ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rcw, TEXT(""), 0, NULL);
}

void SurfaceGDI::FillRectangle(PRectangle rc, Surface &surfacePattern) {
	HBRUSH br;
	if (static_cast<SurfaceGDI &>(surfacePattern).bitmap)
		br = ::CreatePatternBrush(static_cast<SurfaceGDI &>(surfacePattern).bitmap);
	else	// Something is wrong so display in red
		br = ::CreateSolidBrush(RGB(0xff, 0, 0));
	RECT rcw = RectFromPRectangle(rc);
	::FillRect(hdc, &rcw, br);
	::DeleteObject(br);
}

void SurfaceGDI::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) {
	PenColour(fore);
	BrushColor(back);
	::RoundRect(hdc,
		rc.left + 1, rc.top,
		rc.right - 1, rc.bottom,
		8, 8);
}

// Plot a point into a DWORD buffer symetrically to all 4 qudrants
static void AllFour(DWORD *pixels, int width, int height, int x, int y, DWORD val) {
	pixels[y*width+x] = val;
	pixels[y*width+width-1-x] = val;
	pixels[(height-1-y)*width+x] = val;
	pixels[(height-1-y)*width+width-1-x] = val;
}

#ifndef AC_SRC_OVER
#define AC_SRC_OVER                 0x00
#endif
#ifndef AC_SRC_ALPHA
#define AC_SRC_ALPHA		0x01
#endif

static DWORD dwordFromBGRA(byte b, byte g, byte r, byte a) {
	union {
		byte pixVal[4];
		DWORD val;
	} converter;
	converter.pixVal[0] = b;
	converter.pixVal[1] = g;
	converter.pixVal[2] = r;
	converter.pixVal[3] = a;
	return converter.val;
}

void SurfaceGDI::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int /* flags*/ ) {
	if (AlphaBlendFn && rc.Width() > 0) {
		HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
		int width = rc.Width();
		int height = rc.Height();
		// Ensure not distorted too much by corners when small
		cornerSize = Platform::Minimum(cornerSize, (Platform::Minimum(width, height) / 2) - 2);
		BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
		void *image = 0;
		HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih,
			DIB_RGB_COLORS, &image, NULL, 0);

		if (hbmMem) {
			HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem);

			DWORD valEmpty = dwordFromBGRA(0,0,0,0);
			DWORD valFill = dwordFromBGRA(
				static_cast<byte>(GetBValue(fill.AsLong()) * alphaFill / 255),
				static_cast<byte>(GetGValue(fill.AsLong()) * alphaFill / 255),
				static_cast<byte>(GetRValue(fill.AsLong()) * alphaFill / 255),
				static_cast<byte>(alphaFill));
			DWORD valOutline = dwordFromBGRA(
				static_cast<byte>(GetBValue(outline.AsLong()) * alphaOutline / 255),
				static_cast<byte>(GetGValue(outline.AsLong()) * alphaOutline / 255),
				static_cast<byte>(GetRValue(outline.AsLong()) * alphaOutline / 255),
				static_cast<byte>(alphaOutline));
			DWORD *pixels = reinterpret_cast<DWORD *>(image);
			for (int y=0; y<height; y++) {
				for (int x=0; x<width; x++) {
					if ((x==0) || (x==width-1) || (y == 0) || (y == height-1)) {
						pixels[y*width+x] = valOutline;
					} else {
						pixels[y*width+x] = valFill;
					}
				}
			}
			for (int c=0;c<cornerSize; c++) {
				for (int x=0;x<c+1; x++) {
					AllFour(pixels, width, height, x, c-x, valEmpty);
				}
			}
			for (int x=1;x<cornerSize; x++) {
				AllFour(pixels, width, height, x, cornerSize-x, valOutline);
			}

			BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

			AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, width, height, hMemDC, 0, 0, width, height, merge);

			SelectBitmap(hMemDC, hbmOld);
			::DeleteObject(hbmMem);
		}
		::DeleteDC(hMemDC);
	} else {
		BrushColor(outline);
		RECT rcw = RectFromPRectangle(rc);
		FrameRect(hdc, &rcw, brush);
	}
}

void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
	if (AlphaBlendFn && rc.Width() > 0) {
		HDC hMemDC = ::CreateCompatibleDC(reinterpret_cast<HDC>(hdc));
		if (rc.Width() > width)
			rc.left += static_cast<int>((rc.Width() - width) / 2);
		rc.right = rc.left + width;
		if (rc.Height() > height)
			rc.top += static_cast<int>((rc.Height() - height) / 2);
		rc.bottom = rc.top + height;

		BITMAPINFO bpih = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
		unsigned char *image = 0;
		HBITMAP hbmMem = CreateDIBSection(reinterpret_cast<HDC>(hMemDC), &bpih,
			DIB_RGB_COLORS, reinterpret_cast<void **>(&image), NULL, 0);
		if (hbmMem) {
			HBITMAP hbmOld = SelectBitmap(hMemDC, hbmMem);
		
			for (int y=height-1; y>=0; y--) {
				for (int x=0; x<width; x++) {
					unsigned char *pixel = image + (y*width+x) * 4;
					unsigned char alpha = pixelsImage[3];
					// Input is RGBA, output is BGRA with premultiplied alpha
					pixel[2] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255);
					pixel[1] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255);
					pixel[0] = static_cast<unsigned char>((*pixelsImage++) * alpha / 255);
					pixel[3] = static_cast<unsigned char>(*pixelsImage++);
				}
			}
		
			BLENDFUNCTION merge = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

			AlphaBlendFn(reinterpret_cast<HDC>(hdc), rc.left, rc.top, rc.Width(), rc.Height(), hMemDC, 0, 0, width, height, merge);

			SelectBitmap(hMemDC, hbmOld);
			::DeleteObject(hbmMem);
		}
		::DeleteDC(hMemDC);

	}
}

void SurfaceGDI::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {
	PenColour(fore);
	BrushColor(back);
	::Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
}

void SurfaceGDI::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
	::BitBlt(hdc,
		rc.left, rc.top, rc.Width(), rc.Height(),
		static_cast<SurfaceGDI &>(surfaceSource).hdc, from.x, from.y, SRCCOPY);
}

typedef VarBuffer<int, stackBufferLength> TextPositionsI;

void SurfaceGDI::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions) {
	SetFont(font_);
	RECT rcw = RectFromPRectangle(rc);
	SIZE sz={0,0};
	int pos = 0;
	int x = rc.left;

	// Text drawing may fail if the text is too big.
	// If it does fail, slice up into segments and draw each segment.
	const int maxSegmentLength = 0x200;

	if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
		// Use ANSI calls
		int lenDraw = Platform::Minimum(len, maxLenText);
		if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s, lenDraw, NULL)) {
			while (lenDraw > pos) {
				int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos);
				if (!::ExtTextOutA(hdc, x, ybase, fuOptions, &rcw, s+pos, seglen, NULL)) {
					PLATFORM_ASSERT(false);
					return;
				}
				::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz);
				x += sz.cx;
				pos += seglen;
			}
		}
	} else {
		// Use Unicode calls
		const TextWide tbuf(s, len, unicodeMode, codePage);
		if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL)) {
			while (tbuf.tlen > pos) {
				int seglen = Platform::Minimum(maxSegmentLength, tbuf.tlen - pos);
				if (!::ExtTextOutW(hdc, x, ybase, fuOptions, &rcw, tbuf.buffer+pos, seglen, NULL)) {
					PLATFORM_ASSERT(false);
					return;
				}
				::GetTextExtentPoint32W(hdc, tbuf.buffer+pos, seglen, &sz);
				x += sz.cx;
				pos += seglen;
			}
		}
	}
}

void SurfaceGDI::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore, ColourDesired back) {
	::SetTextColor(hdc, fore.AsLong());
	::SetBkColor(hdc, back.AsLong());
	DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
}

void SurfaceGDI::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore, ColourDesired back) {
	::SetTextColor(hdc, fore.AsLong());
	::SetBkColor(hdc, back.AsLong());
	DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
}

void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore) {
	// Avoid drawing spaces in transparent mode
	for (int i=0;i<len;i++) {
		if (s[i] != ' ') {
			::SetTextColor(hdc, fore.AsLong());
			::SetBkMode(hdc, TRANSPARENT);
			DrawTextCommon(rc, font_, ybase, s, len, 0);
			::SetBkMode(hdc, OPAQUE);
			return;
		}
	}
}

XYPOSITION SurfaceGDI::WidthText(Font &font_, const char *s, int len) {
	SetFont(font_);
	SIZE sz={0,0};
	if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
		::GetTextExtentPoint32A(hdc, s, Platform::Minimum(len, maxLenText), &sz);
	} else {
		const TextWide tbuf(s, len, unicodeMode, codePage);
		::GetTextExtentPoint32W(hdc, tbuf.buffer, tbuf.tlen, &sz);
	}
	return sz.cx;
}

void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
	SetFont(font_);
	SIZE sz={0,0};
	int fit = 0;
	if (unicodeMode) {
		const TextWide tbuf(s, len, unicodeMode, codePage);
		TextPositionsI poses(tbuf.tlen);
		fit = tbuf.tlen;
		if (!::GetTextExtentExPointW(hdc, tbuf.buffer, tbuf.tlen, maxWidthMeasure, &fit, poses.buffer, &sz)) {
			// Likely to have failed because on Windows 9x where function not available
			// So measure the character widths by measuring each initial substring
			// Turns a linear operation into a qudratic but seems fast enough on test files
			for (int widthSS=0; widthSS < tbuf.tlen; widthSS++) {
				::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
				poses.buffer[widthSS] = sz.cx;
			}
		}
		// Map the widths given for UTF-16 characters back onto the UTF-8 input string
		int ui=0;
		const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
		int i=0;
		while (ui<fit) {
			unsigned char uch = us[i];
			unsigned int lenChar = 1;
			if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
				lenChar = 4;
				ui++;
			} else if (uch >= (0x80 + 0x40 + 0x20)) {
				lenChar = 3;
			} else if (uch >= (0x80)) {
				lenChar = 2;
			}
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = poses.buffer[ui];
			}
			ui++;
		}
		int lastPos = 0;
		if (i > 0)
			lastPos = positions[i-1];
		while (i<len) {
			positions[i++] = lastPos;
		}
	} else if (IsNT() || (codePage==0) || win9xACPSame) {
		// Zero positions to avoid random behaviour on failure.
		memset(positions, 0, len * sizeof(*positions));
		// len may be larger than platform supports so loop over segments small enough for platform
		int startOffset = 0;
		while (len > 0) {
			int lenBlock = Platform::Minimum(len, maxLenText);
			TextPositionsI poses(len);
			if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, poses.buffer, &sz)) {
				// Eeek - a NULL DC or other foolishness could cause this.
				return;
			} else if (fit < lenBlock) {
				// For some reason, such as an incomplete DBCS character
				// Not all the positions are filled in so make them equal to end.
				if (fit == 0)
					poses.buffer[fit++] = 0;
				for (int i = fit;i<lenBlock;i++)
					poses.buffer[i] = poses.buffer[fit-1];
			}
			for (int i=0;i<lenBlock;i++)
				positions[i] = poses.buffer[i] + startOffset;
			startOffset = poses.buffer[lenBlock-1];
			len -= lenBlock;
			positions += lenBlock;
			s += lenBlock;
		}
	} else {
		// Support Asian string display in 9x English
		const TextWide tbuf(s, len, unicodeMode, codePage);
		TextPositionsI poses(tbuf.tlen);
		for (int widthSS=0; widthSS<tbuf.tlen; widthSS++) {
			::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
			poses.buffer[widthSS] = sz.cx;
		}

		int ui = 0;
		for (int i=0;i<len;) {
			if (::IsDBCSLeadByteEx(codePage, s[i])) {
				positions[i] = poses.buffer[ui];
				positions[i+1] = poses.buffer[ui];
				i += 2;
			} else {
				positions[i] = poses.buffer[ui];
				i++;
			}

			ui++;
		}
	}
}

XYPOSITION SurfaceGDI::WidthChar(Font &font_, char ch) {
	SetFont(font_);
	SIZE sz;
	::GetTextExtentPoint32A(hdc, &ch, 1, &sz);
	return sz.cx;
}

XYPOSITION SurfaceGDI::Ascent(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmAscent;
}

XYPOSITION SurfaceGDI::Descent(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmDescent;
}

XYPOSITION SurfaceGDI::InternalLeading(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmInternalLeading;
}

XYPOSITION SurfaceGDI::ExternalLeading(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmExternalLeading;
}

XYPOSITION SurfaceGDI::Height(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmHeight;
}

XYPOSITION SurfaceGDI::AverageCharWidth(Font &font_) {
	SetFont(font_);
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	return tm.tmAveCharWidth;
}

void SurfaceGDI::SetClip(PRectangle rc) {
	::IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}

void SurfaceGDI::FlushCachedState() {
	pen = 0;
	brush = 0;
	font = 0;
}

void SurfaceGDI::SetUnicodeMode(bool unicodeMode_) {
	unicodeMode=unicodeMode_;
}

void SurfaceGDI::SetDBCSMode(int codePage_) {
	// No action on window as automatically handled by system.
	codePage = codePage_;
	win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP());
}

#if defined(USE_D2D)

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

class SurfaceD2D : public Surface {
	bool unicodeMode;
	int x, y;

	int codePage;

	ID2D1RenderTarget *pRenderTarget;
	bool ownRenderTarget;
	int clipsActive;

	IDWriteTextFormat *pTextFormat;
	FLOAT yAscent;
	FLOAT yDescent;
	FLOAT yInternalLeading;

	ID2D1SolidColorBrush *pBrush;

	int logPixelsY;
	float dpiScaleX;
	float dpiScaleY;

	void SetFont(Font &font_);

	// Private so SurfaceD2D objects can not be copied
	SurfaceD2D(const SurfaceD2D &);
	SurfaceD2D &operator=(const SurfaceD2D &);
public:
	SurfaceD2D();
	virtual ~SurfaceD2D();

	void SetScale();
	void Init(WindowID wid);
	void Init(SurfaceID sid, WindowID wid);
	void InitPixMap(int width, int height, Surface *surface_, WindowID wid);

	void Release();
	bool Initialised();

	HRESULT FlushDrawing();

	void PenColour(ColourDesired fore);
	void D2DPenColour(ColourDesired fore, int alpha=255);
	int LogPixelsY();
	int DeviceHeightFont(int points);
	void MoveTo(int x_, int y_);
	void LineTo(int x_, int y_);
	void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back);
	void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back);
	void FillRectangle(PRectangle rc, ColourDesired back);
	void FillRectangle(PRectangle rc, Surface &surfacePattern);
	void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back);
	void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int flags);
	void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage);
	void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back);
	void Copy(PRectangle rc, Point from, Surface &surfaceSource);

	void DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions);
	void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back);
	void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore);
	void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions);
	XYPOSITION WidthText(Font &font_, const char *s, int len);
	XYPOSITION WidthChar(Font &font_, char ch);
	XYPOSITION Ascent(Font &font_);
	XYPOSITION Descent(Font &font_);
	XYPOSITION InternalLeading(Font &font_);
	XYPOSITION ExternalLeading(Font &font_);
	XYPOSITION Height(Font &font_);
	XYPOSITION AverageCharWidth(Font &font_);

	void SetClip(PRectangle rc);
	void FlushCachedState();

	void SetUnicodeMode(bool unicodeMode_);
	void SetDBCSMode(int codePage_);
};

#ifdef SCI_NAMESPACE
} //namespace Scintilla
#endif

SurfaceD2D::SurfaceD2D() :
	unicodeMode(false),
	x(0), y(0) {

	codePage = 0;

	pRenderTarget = NULL;
	ownRenderTarget = false;
	clipsActive = 0;

	// From selected font
	pTextFormat = NULL;
	yAscent = 2;
	yDescent = 1;
	yInternalLeading = 0;

	pBrush = NULL;

	logPixelsY = 72;
	dpiScaleX = 1.0;
	dpiScaleY = 1.0;
}

SurfaceD2D::~SurfaceD2D() {
	Release();
}

void SurfaceD2D::Release() {
	if (pBrush) {
		pBrush->Release();
		pBrush = 0;
	}
	if (pRenderTarget) {
		while (clipsActive) {
			pRenderTarget->PopAxisAlignedClip();
			clipsActive--;
		}
		if (ownRenderTarget) {
			pRenderTarget->Release();
		}
		pRenderTarget = 0;
	}
}

void SurfaceD2D::SetScale() {
	HDC hdcMeasure = ::CreateCompatibleDC(NULL);
	logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY);
	dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / 96.0f;
	dpiScaleY = logPixelsY / 96.0f;
	::DeleteDC(hdcMeasure);
}

bool SurfaceD2D::Initialised() {
	return pRenderTarget != 0;
}

HRESULT SurfaceD2D::FlushDrawing() {
	return pRenderTarget->Flush();
}

void SurfaceD2D::Init(WindowID /* wid */) {
	Release();
	SetScale();
}

void SurfaceD2D::Init(SurfaceID sid, WindowID) {
	Release();
	SetScale();
	pRenderTarget = reinterpret_cast<ID2D1RenderTarget *>(sid);
}

void SurfaceD2D::InitPixMap(int width, int height, Surface *surface_, WindowID) {
	Release();
	SetScale();
	SurfaceD2D *psurfOther = static_cast<SurfaceD2D *>(surface_);
	ID2D1BitmapRenderTarget *pCompatibleRenderTarget = NULL;
	D2D1_SIZE_F desiredSize = D2D1::SizeF(width, height);
	D2D1_PIXEL_FORMAT desiredFormat = psurfOther->pRenderTarget->GetPixelFormat();
	desiredFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
	HRESULT hr = psurfOther->pRenderTarget->CreateCompatibleRenderTarget(
		&desiredSize, NULL, &desiredFormat, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &pCompatibleRenderTarget);
	if (SUCCEEDED(hr)) {
		pRenderTarget = pCompatibleRenderTarget;
		pRenderTarget->BeginDraw();
		ownRenderTarget = true;
	}
}

void SurfaceD2D::PenColour(ColourDesired fore) {
	D2DPenColour(fore);
}

void SurfaceD2D::D2DPenColour(ColourDesired fore, int alpha) {
	if (pRenderTarget) {
		D2D_COLOR_F col;
		col.r = (fore.AsLong() & 0xff) / 255.0;
		col.g = ((fore.AsLong() & 0xff00) >> 8) / 255.0;
		col.b = (fore.AsLong() >> 16) / 255.0;
		col.a = alpha / 255.0;
		if (pBrush) {
			pBrush->SetColor(col);
		} else {
			HRESULT hr = pRenderTarget->CreateSolidColorBrush(col, &pBrush);
			if (!SUCCEEDED(hr) && pBrush) {						
				pBrush->Release();
				pBrush = 0;
			}
		}
	}
}

void SurfaceD2D::SetFont(Font &font_) {
	FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font_.GetID());
	PLATFORM_ASSERT(pfm->technology == SCWIN_TECH_DIRECTWRITE);
	pTextFormat = pfm->pTextFormat;
	yAscent = pfm->yAscent;
	yDescent = pfm->yDescent;
	yInternalLeading = pfm->yInternalLeading;
	if (pRenderTarget) {
		pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfm->extraFontFlag));
	}
}

int SurfaceD2D::LogPixelsY() {
	return logPixelsY;
}

int SurfaceD2D::DeviceHeightFont(int points) {
	return ::MulDiv(points, LogPixelsY(), 72);
}

void SurfaceD2D::MoveTo(int x_, int y_) {
	x = x_;
	y = y_;
}

static int Delta(int difference) {
	if (difference < 0)
		return -1;
	else if (difference > 0)
		return 1;
	else
		return 0;
}

static int RoundFloat(float f) {
	return int(f+0.5);
}

void SurfaceD2D::LineTo(int x_, int y_) {
	if (pRenderTarget) {
		int xDiff = x_ - x;
		int xDelta = Delta(xDiff);
		int yDiff = y_ - y;
		int yDelta = Delta(yDiff);
		if ((xDiff == 0) || (yDiff == 0)) {
			// Horizontal or vertical lines can be more precisely drawn as a filled rectangle
			int xEnd = x_ - xDelta;
			int left = Platform::Minimum(x, xEnd);
			int width = abs(x - xEnd) + 1;
			int yEnd = y_ - yDelta;
			int top = Platform::Minimum(y, yEnd);
			int height = abs(y - yEnd) + 1;
			D2D1_RECT_F rectangle1 = D2D1::RectF(left, top, left+width, top+height);
			pRenderTarget->FillRectangle(&rectangle1, pBrush);
		} else if ((abs(xDiff) == abs(yDiff))) {
			// 45 degree slope
			pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5), 
				D2D1::Point2F(x_ + 0.5 - xDelta, y_ + 0.5 - yDelta), pBrush);
		} else {
			// Line has a different slope so difficult to avoid last pixel
			pRenderTarget->DrawLine(D2D1::Point2F(x + 0.5, y + 0.5), 
				D2D1::Point2F(x_ + 0.5, y_ + 0.5), pBrush);
		}
		x = x_;
		y = y_;
	}
}

void SurfaceD2D::Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		ID2D1Factory *pFactory = 0;
		pRenderTarget->GetFactory(&pFactory);
		ID2D1PathGeometry *geometry=0;
		HRESULT hr = pFactory->CreatePathGeometry(&geometry);
		if (SUCCEEDED(hr)) {
			ID2D1GeometrySink *sink = 0;
			hr = geometry->Open(&sink);
			if (SUCCEEDED(hr)) {
				sink->BeginFigure(D2D1::Point2F(pts[0].x + 0.5f, pts[0].y + 0.5f), D2D1_FIGURE_BEGIN_FILLED);
				for (size_t i=1; i<static_cast<size_t>(npts); i++) {
					sink->AddLine(D2D1::Point2F(pts[i].x + 0.5f, pts[i].y + 0.5f));
				}
				sink->EndFigure(D2D1_FIGURE_END_CLOSED);
				sink->Close();
				sink->Release();

				D2DPenColour(back);
				pRenderTarget->FillGeometry(geometry,pBrush);
				D2DPenColour(fore);
				pRenderTarget->DrawGeometry(geometry,pBrush);
			}

			geometry->Release();
		}
	}
}

void SurfaceD2D::RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left) + 0.5, rc.top+0.5, RoundFloat(rc.right) - 0.5, rc.bottom-0.5);
		D2DPenColour(back);
		pRenderTarget->FillRectangle(&rectangle1, pBrush);
		D2DPenColour(fore);
		pRenderTarget->DrawRectangle(&rectangle1, pBrush);
	}
}

void SurfaceD2D::FillRectangle(PRectangle rc, ColourDesired back) {
	if (pRenderTarget) {
		D2DPenColour(back);
        D2D1_RECT_F rectangle1 = D2D1::RectF(RoundFloat(rc.left), rc.top, RoundFloat(rc.right), rc.bottom);
        pRenderTarget->FillRectangle(&rectangle1, pBrush);
	}
}

void SurfaceD2D::FillRectangle(PRectangle rc, Surface &surfacePattern) {
	SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfacePattern);
	surfOther.FlushDrawing();
	ID2D1Bitmap *pBitmap = NULL;
	ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
		surfOther.pRenderTarget);
	HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
	if (SUCCEEDED(hr)) {
		ID2D1BitmapBrush *pBitmapBrush = NULL;
		D2D1_BITMAP_BRUSH_PROPERTIES brushProperties =
	        D2D1::BitmapBrushProperties(D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_WRAP,
			D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR);
		// Create the bitmap brush.
		hr = pRenderTarget->CreateBitmapBrush(pBitmap, brushProperties, &pBitmapBrush);
		pBitmap->Release();
		if (SUCCEEDED(hr)) {
			pRenderTarget->FillRectangle(
				D2D1::RectF(rc.left, rc.top, rc.right, rc.bottom),
				pBitmapBrush);
			pBitmapBrush->Release();
		}
	}
}

void SurfaceD2D::RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
			D2D1::RectF(rc.left+1.0, rc.top+1.0, rc.right-1.0, rc.bottom-1.0),
			8, 8);
		D2DPenColour(back);
		pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);

		D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
			D2D1::RectF(rc.left + 0.5, rc.top+0.5, rc.right - 0.5, rc.bottom-0.5),
			8, 8);
		D2DPenColour(fore);
		pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
	}
}

void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
		ColourDesired outline, int alphaOutline, int /* flags*/ ) {
	if (pRenderTarget) {
		if (cornerSize == 0) {
			// When corner size is zero, draw square rectangle to prevent blurry pixels at corners
			D2D1_RECT_F rectFill = D2D1::RectF(RoundFloat(rc.left) + 1.0, rc.top + 1.0, RoundFloat(rc.right) - 1.0, rc.bottom - 1.0);
			D2DPenColour(fill, alphaFill);
			pRenderTarget->FillRectangle(rectFill, pBrush);

			D2D1_RECT_F rectOutline = D2D1::RectF(RoundFloat(rc.left) + 0.5, rc.top + 0.5, RoundFloat(rc.right) - 0.5, rc.bottom - 0.5);
			D2DPenColour(outline, alphaOutline);
			pRenderTarget->DrawRectangle(rectOutline, pBrush);
		} else {
			D2D1_ROUNDED_RECT roundedRectFill = D2D1::RoundedRect(
				D2D1::RectF(RoundFloat(rc.left) + 1.0, rc.top + 1.0, RoundFloat(rc.right) - 1.0, rc.bottom - 1.0),
				cornerSize, cornerSize);
			D2DPenColour(fill, alphaFill);
			pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);

			D2D1_ROUNDED_RECT roundedRect = D2D1::RoundedRect(
				D2D1::RectF(RoundFloat(rc.left) + 0.5, rc.top + 0.5, RoundFloat(rc.right) - 0.5, rc.bottom - 0.5),
				cornerSize, cornerSize);
			D2DPenColour(outline, alphaOutline);
			pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush);
		}
	}
}

void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
	if (pRenderTarget) {
		if (rc.Width() > width)
			rc.left += static_cast<int>((rc.Width() - width) / 2);
		rc.right = rc.left + width;
		if (rc.Height() > height)
			rc.top += static_cast<int>((rc.Height() - height) / 2);
		rc.bottom = rc.top + height;

		std::vector<unsigned char> image(height * width * 4);
		for (int y=0; y<height; y++) {
			for (int x=0; x<width; x++) {
				unsigned char *pixel = &image[0] + (y*width+x) * 4;
				unsigned char alpha = pixelsImage[3];
				// Input is RGBA, output is BGRA with premultiplied alpha
				pixel[2] = (*pixelsImage++) * alpha / 255;
				pixel[1] = (*pixelsImage++) * alpha / 255;
				pixel[0] = (*pixelsImage++) * alpha / 255;
				pixel[3] = *pixelsImage++;
			}
		}

		ID2D1Bitmap *bitmap = 0;
		D2D1_SIZE_U size = D2D1::SizeU(width, height);
		D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM,	
		    D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0};
		HRESULT hr = pRenderTarget->CreateBitmap(size, &image[0],
                  width * 4, &props, &bitmap);
		if (SUCCEEDED(hr)) {
			D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
			pRenderTarget->DrawBitmap(bitmap, rcDestination);
		}
		bitmap->Release();
	}
}

void SurfaceD2D::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		FLOAT radius = rc.Width() / 2.0f - 1.0f;
		D2D1_ELLIPSE ellipse = D2D1::Ellipse(
			D2D1::Point2F((rc.left + rc.right) / 2.0f, (rc.top + rc.bottom) / 2.0f),
			radius,radius);

		PenColour(back);
		pRenderTarget->FillEllipse(ellipse, pBrush);
		PenColour(fore);
		pRenderTarget->DrawEllipse(ellipse, pBrush);
	}
}

void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
	SurfaceD2D &surfOther = static_cast<SurfaceD2D &>(surfaceSource);
	surfOther.FlushDrawing();
	ID2D1BitmapRenderTarget *pCompatibleRenderTarget = reinterpret_cast<ID2D1BitmapRenderTarget *>(
		surfOther.pRenderTarget);
	ID2D1Bitmap *pBitmap = NULL;
	HRESULT hr = pCompatibleRenderTarget->GetBitmap(&pBitmap);
	if (SUCCEEDED(hr)) {
		D2D1_RECT_F rcDestination = {rc.left, rc.top, rc.right, rc.bottom};
		D2D1_RECT_F rcSource = {from.x, from.y, from.x + rc.Width(), from.y + rc.Height()};
		pRenderTarget->DrawBitmap(pBitmap, rcDestination, 1.0f, 
			D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, rcSource);
		pRenderTarget->Flush();
		pBitmap->Release();
	}
}

void SurfaceD2D::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions) {
	SetFont(font_);

	// Use Unicode calls
	const TextWide tbuf(s, len, unicodeMode, codePage);
	if (pRenderTarget && pTextFormat && pBrush) {
		if (fuOptions & ETO_CLIPPED) {
			D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom};
			pRenderTarget->PushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED);
		}
		
		// Explicitly creating a text layout appears a little faster 
		IDWriteTextLayout *pTextLayout;
		HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat,
				rc.Width(), rc.Height(), &pTextLayout);
		if (SUCCEEDED(hr)) {
			D2D1_POINT_2F origin = {rc.left, ybase-yAscent};
			pRenderTarget->DrawTextLayout(origin, pTextLayout, pBrush, D2D1_DRAW_TEXT_OPTIONS_NONE);
			pTextLayout->Release();
		}

		if (fuOptions & ETO_CLIPPED) {
			pRenderTarget->PopAxisAlignedClip();
		}
	}
}

void SurfaceD2D::DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		FillRectangle(rc, back);
		D2DPenColour(fore);
		DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE);
	}
}

void SurfaceD2D::DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore, ColourDesired back) {
	if (pRenderTarget) {
		FillRectangle(rc, back);
		D2DPenColour(fore);
		DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED);
	}
}

void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len,
	ColourDesired fore) {
	// Avoid drawing spaces in transparent mode
	for (int i=0;i<len;i++) {
		if (s[i] != ' ') {
			if (pRenderTarget) {
				D2DPenColour(fore);
				DrawTextCommon(rc, font_, ybase, s, len, 0);
			}
			return;
		}
	}
}

XYPOSITION SurfaceD2D::WidthText(Font &font_, const char *s, int len) {
	FLOAT width = 1.0;
	SetFont(font_);
	const TextWide tbuf(s, len, unicodeMode, codePage);
	if (pIDWriteFactory && pTextFormat) {
		// Create a layout
		IDWriteTextLayout *pTextLayout = 0;
		HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 1000.0, 1000.0, &pTextLayout);
		if (SUCCEEDED(hr)) {
			DWRITE_TEXT_METRICS textMetrics;
			pTextLayout->GetMetrics(&textMetrics);
			width = textMetrics.widthIncludingTrailingWhitespace;
			pTextLayout->Release();
		}
	}
	return width;
}

void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
	SetFont(font_);
	int fit = 0;
	const TextWide tbuf(s, len, unicodeMode, codePage);
	TextPositions poses(tbuf.tlen);
	fit = tbuf.tlen;
	const int clusters = 1000;
	DWRITE_CLUSTER_METRICS clusterMetrics[clusters];
	UINT32 count = 0;
	if (pIDWriteFactory && pTextFormat) {
		SetFont(font_);
		// Create a layout
		IDWriteTextLayout *pTextLayout = 0;
		HRESULT hr = pIDWriteFactory->CreateTextLayout(tbuf.buffer, tbuf.tlen, pTextFormat, 10000.0, 1000.0, &pTextLayout);
		if (!SUCCEEDED(hr))
			return;
		// For now, assuming WCHAR == cluster
		pTextLayout->GetClusterMetrics(clusterMetrics, clusters, &count);
		FLOAT position = 0.0f;
		size_t ti=0;
		for (size_t ci=0;ci<count;ci++) {
			position += clusterMetrics[ci].width;
			for (size_t inCluster=0; inCluster<clusterMetrics[ci].length; inCluster++) {
				//poses.buffer[ti++] = int(position + 0.5);
				poses.buffer[ti++] = position;
			}
		}
		PLATFORM_ASSERT(ti == static_cast<size_t>(tbuf.tlen));
		pTextLayout->Release();
	}
	if (unicodeMode) {
		// Map the widths given for UTF-16 characters back onto the UTF-8 input string
		int ui=0;
		const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
		int i=0;
		while (ui<fit) {
			unsigned char uch = us[i];
			unsigned int lenChar = 1;
			if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) {
				lenChar = 4;
				ui++;
			} else if (uch >= (0x80 + 0x40 + 0x20)) {
				lenChar = 3;
			} else if (uch >= (0x80)) {
				lenChar = 2;
			}
			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {
				positions[i++] = poses.buffer[ui];
			}
			ui++;
		}
		int lastPos = 0;
		if (i > 0)
			lastPos = positions[i-1];
		while (i<len) {
			positions[i++] = lastPos;
		}
	} else if (codePage == 0) {

		// One character per position
		PLATFORM_ASSERT(len == tbuf.tlen);
		for (size_t kk=0;kk<static_cast<size_t>(len);kk++) {
			positions[kk] = poses.buffer[kk];
		}

	} else {

		// May be more than one byte per position
		int ui = 0;
		for (int i=0;i<len;) {
			if (::IsDBCSLeadByteEx(codePage, s[i])) {
				positions[i] = poses.buffer[ui];
				positions[i+1] = poses.buffer[ui];
				i += 2;
			} else {
				positions[i] = poses.buffer[ui];
				i++;
			}

			ui++;
		}
	}
}

XYPOSITION SurfaceD2D::WidthChar(Font &font_, char ch) {
	FLOAT width = 1.0;
	SetFont(font_);
	if (pIDWriteFactory && pTextFormat) {
		// Create a layout
		IDWriteTextLayout *pTextLayout = 0;
		const WCHAR wch = ch;
		HRESULT hr = pIDWriteFactory->CreateTextLayout(&wch, 1, pTextFormat, 1000.0, 1000.0, &pTextLayout);
		if (SUCCEEDED(hr)) {
			DWRITE_TEXT_METRICS textMetrics;
			pTextLayout->GetMetrics(&textMetrics);
			width = textMetrics.widthIncludingTrailingWhitespace;
			pTextLayout->Release();
		}
	}
	return width;
}

XYPOSITION SurfaceD2D::Ascent(Font &font_) {
	SetFont(font_);
	return ceil(yAscent);
}

XYPOSITION SurfaceD2D::Descent(Font &font_) {
	SetFont(font_);
	return ceil(yDescent);
}

XYPOSITION SurfaceD2D::InternalLeading(Font &font_) {
	SetFont(font_);
	return floor(yInternalLeading);
}

XYPOSITION SurfaceD2D::ExternalLeading(Font &) {
	// Not implemented, always return one
	return 1;
}

XYPOSITION SurfaceD2D::Height(Font &font_) {
	return Ascent(font_) + Descent(font_);
}

XYPOSITION SurfaceD2D::AverageCharWidth(Font &font_) {
	FLOAT width = 1.0;
	SetFont(font_);
	if (pIDWriteFactory && pTextFormat) {
		// Create a layout
		IDWriteTextLayout *pTextLayout = 0;
		const WCHAR wszAllAlpha[] = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		HRESULT hr = pIDWriteFactory->CreateTextLayout(wszAllAlpha, static_cast<UINT32>(wcslen(wszAllAlpha)), 
			pTextFormat, 1000.0, 1000.0, &pTextLayout);
		if (SUCCEEDED(hr)) {
			DWRITE_TEXT_METRICS textMetrics;
			pTextLayout->GetMetrics(&textMetrics);
			width = textMetrics.width / wcslen(wszAllAlpha);
			pTextLayout->Release();
		}
	}
	return width;
}

void SurfaceD2D::SetClip(PRectangle rc) {
	if (pRenderTarget) {
		D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom};
		pRenderTarget->PushAxisAlignedClip(rcClip, D2D1_ANTIALIAS_MODE_ALIASED);
		clipsActive++;
	}
}

void SurfaceD2D::FlushCachedState() {
}

void SurfaceD2D::SetUnicodeMode(bool unicodeMode_) {
	unicodeMode=unicodeMode_;
}

void SurfaceD2D::SetDBCSMode(int codePage_) {
	// No action on window as automatically handled by system.
	codePage = codePage_;
}
#endif

Surface *Surface::Allocate(int technology) {
#if defined(USE_D2D)
	if (technology == SCWIN_TECH_GDI)
		return new SurfaceGDI;
	else
		return new SurfaceD2D;
#else
	return new SurfaceGDI;
#endif
}

Window::~Window() {
}

void Window::Destroy() {
	if (wid)
		::DestroyWindow(reinterpret_cast<HWND>(wid));
	wid = 0;
}

bool Window::HasFocus() {
	return ::GetFocus() == wid;
}

PRectangle Window::GetPosition() {
	RECT rc;
	::GetWindowRect(reinterpret_cast<HWND>(wid), &rc);
	return PRectangle(rc.left, rc.top, rc.right, rc.bottom);
}

void Window::SetPosition(PRectangle rc) {
	::SetWindowPos(reinterpret_cast<HWND>(wid),
		0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER|SWP_NOACTIVATE);
}

static RECT RectFromMonitor(HMONITOR hMonitor) {
	if (GetMonitorInfoFn) {
		MONITORINFO mi = {0};
		mi.cbSize = sizeof(mi);
		if (GetMonitorInfoFn(hMonitor, &mi)) {
			return mi.rcWork;
		}
	}
	RECT rc = {0, 0, 0, 0};
	::SystemParametersInfoA(SPI_GETWORKAREA, 0, &rc, 0);
	return rc;
}

void Window::SetPositionRelative(PRectangle rc, Window w) {
	LONG style = ::GetWindowLong(reinterpret_cast<HWND>(wid), GWL_STYLE);
	if (style & WS_POPUP) {
		POINT ptOther = {0, 0};
		::ClientToScreen(reinterpret_cast<HWND>(w.GetID()), &ptOther);
		rc.Move(ptOther.x, ptOther.y);

		RECT rcMonitor = RectFromPRectangle(rc);

		HMONITOR hMonitor = NULL;
		if (MonitorFromRectFn)
			hMonitor = MonitorFromRectFn(&rcMonitor, MONITOR_DEFAULTTONEAREST);
		// If hMonitor is NULL, that's just the main screen anyways.
		//::GetMonitorInfo(hMonitor, &mi);
		RECT rcWork = RectFromMonitor(hMonitor);
		
		if (rcWork.left < rcWork.right) {
			// Now clamp our desired rectangle to fit inside the work area
			// This way, the menu will fit wholly on one screen. An improvement even
			// if you don't have a second monitor on the left... Menu's appears half on
			// one screen and half on the other are just U.G.L.Y.!
			if (rc.right > rcWork.right)
				rc.Move(rcWork.right - rc.right, 0);
			if (rc.bottom > rcWork.bottom)
				rc.Move(0, rcWork.bottom - rc.bottom);
			if (rc.left < rcWork.left)
				rc.Move(rcWork.left - rc.left, 0);
			if (rc.top < rcWork.top)
				rc.Move(0, rcWork.top - rc.top);
		}
	}
	SetPosition(rc);
}

PRectangle Window::GetClientPosition() {
	RECT rc={0,0,0,0};
	if (wid)
		::GetClientRect(reinterpret_cast<HWND>(wid), &rc);
	return  PRectangle(rc.left, rc.top, rc.right, rc.bottom);
}

void Window::Show(bool show) {
	if (show)
		::ShowWindow(reinterpret_cast<HWND>(wid), SW_SHOWNOACTIVATE);
	else
		::ShowWindow(reinterpret_cast<HWND>(wid), SW_HIDE);
}

void Window::InvalidateAll() {
	::InvalidateRect(reinterpret_cast<HWND>(wid), NULL, FALSE);
}

void Window::InvalidateRectangle(PRectangle rc) {
	RECT rcw = RectFromPRectangle(rc);
	::InvalidateRect(reinterpret_cast<HWND>(wid), &rcw, FALSE);
}

static LRESULT Window_SendMessage(Window *w, UINT msg, WPARAM wParam=0, LPARAM lParam=0) {
	return ::SendMessage(reinterpret_cast<HWND>(w->GetID()), msg, wParam, lParam);
}

void Window::SetFont(Font &font) {
	Window_SendMessage(this, WM_SETFONT,
		reinterpret_cast<WPARAM>(font.GetID()), 0);
}

static void FlipBitmap(HBITMAP bitmap, int width, int height) {
	HDC hdc = ::CreateCompatibleDC(NULL);
	if (hdc != NULL) {
		HGDIOBJ prevBmp = ::SelectObject(hdc, bitmap);
		::StretchBlt(hdc, width - 1, 0, -width, height, hdc, 0, 0, width, height, SRCCOPY);
		::SelectObject(hdc, prevBmp);
		::DeleteDC(hdc);
	}
}

static HCURSOR GetReverseArrowCursor() {
	if (reverseArrowCursor != NULL)
		return reverseArrowCursor;

	::EnterCriticalSection(&crPlatformLock);
	HCURSOR cursor = reverseArrowCursor;
	if (cursor == NULL) {
		cursor = ::LoadCursor(NULL, IDC_ARROW);
		ICONINFO info;
		if (::GetIconInfo(cursor, &info)) {
			BITMAP bmp;
			if (::GetObject(info.hbmMask, sizeof(bmp), &bmp)) {
				FlipBitmap(info.hbmMask, bmp.bmWidth, bmp.bmHeight);
				if (info.hbmColor != NULL)
					FlipBitmap(info.hbmColor, bmp.bmWidth, bmp.bmHeight);
				info.xHotspot = (DWORD)bmp.bmWidth - 1 - info.xHotspot;

				reverseArrowCursor = ::CreateIconIndirect(&info);
				if (reverseArrowCursor != NULL)
					cursor = reverseArrowCursor;
			}

			::DeleteObject(info.hbmMask);
			if (info.hbmColor != NULL)
				::DeleteObject(info.hbmColor);
		}
	}
	::LeaveCriticalSection(&crPlatformLock);
	return cursor;
}

void Window::SetCursor(Cursor curs) {
	switch (curs) {
	case cursorText:
		::SetCursor(::LoadCursor(NULL,IDC_IBEAM));
		break;
	case cursorUp:
		::SetCursor(::LoadCursor(NULL,IDC_UPARROW));
		break;
	case cursorWait:
		::SetCursor(::LoadCursor(NULL,IDC_WAIT));
		break;
	case cursorHoriz:
		::SetCursor(::LoadCursor(NULL,IDC_SIZEWE));
		break;
	case cursorVert:
		::SetCursor(::LoadCursor(NULL,IDC_SIZENS));
		break;
	case cursorHand:
		::SetCursor(::LoadCursor(NULL,IDC_HAND));
		break;
	case cursorReverseArrow:
		::SetCursor(GetReverseArrowCursor());
		break;
	case cursorArrow:
	case cursorInvalid:	// Should not occur, but just in case.
		::SetCursor(::LoadCursor(NULL,IDC_ARROW));
		break;
	}
}

void Window::SetTitle(const char *s) {
	::SetWindowTextA(reinterpret_cast<HWND>(wid), s);
}

/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
   coordinates */
PRectangle Window::GetMonitorRect(Point pt) {
	// MonitorFromPoint and GetMonitorInfo are not available on Windows 95 and NT 4.
	PRectangle rcPosition = GetPosition();
	POINT ptDesktop = {static_cast<LONG>(pt.x + rcPosition.left),
		static_cast<LONG>(pt.y + rcPosition.top)};
	HMONITOR hMonitor = NULL;
	if (MonitorFromPointFn)
		hMonitor = MonitorFromPointFn(ptDesktop, MONITOR_DEFAULTTONEAREST);

	RECT rcWork = RectFromMonitor(hMonitor);
	if (rcWork.left < rcWork.right) {
		PRectangle rcMonitor(
			rcWork.left - rcPosition.left,
			rcWork.top - rcPosition.top,
			rcWork.right - rcPosition.left,
			rcWork.bottom - rcPosition.top);
		return rcMonitor;
	} else {
		return PRectangle();
	}
}

struct ListItemData {
	const char *text;
	int pixId;
};

#define _ROUND2(n,pow2) \
	( ( (n) + (pow2) - 1) & ~((pow2) - 1) )

class LineToItem {
	char *words;
	int wordsCount;
	int wordsSize;

	ListItemData *data;
	int len;
	int count;

private:
	void FreeWords() {
		delete []words;
		words = NULL;
		wordsCount = 0;
		wordsSize = 0;
	}
	char *AllocWord(const char *word);

public:
	LineToItem() : words(NULL), wordsCount(0), wordsSize(0), data(NULL), len(0), count(0) {
	}
	~LineToItem() {
		Clear();
	}
	void Clear() {
		FreeWords();
		delete []data;
		data = NULL;
		len = 0;
		count = 0;
	}

	ListItemData *Append(const char *text, int value);

	ListItemData Get(int index) const {
		if (index >= 0 && index < count) {
			return data[index];
		} else {
			ListItemData missing = {"", -1};
			return missing;
		}
	}
	int Count() const {
		return count;
	}

	ListItemData *AllocItem();

	void SetWords(char *s) {
		words = s;	// N.B. will be deleted on destruction
	}
};

char *LineToItem::AllocWord(const char *text) {
	int chars = static_cast<int>(strlen(text) + 1);
	int newCount = wordsCount + chars;
	if (newCount > wordsSize) {
		wordsSize = _ROUND2(newCount * 2, 8192);
		char *wordsNew = new char[wordsSize];
		memcpy(wordsNew, words, wordsCount);
		int offset = wordsNew - words;
		for (int i=0; i<count; i++)
			data[i].text += offset;
		delete []words;
		words = wordsNew;
	}
	char *s = &words[wordsCount];
	wordsCount = newCount;
	strncpy(s, text, chars);
	return s;
}

ListItemData *LineToItem::AllocItem() {
	if (count >= len) {
		int lenNew = _ROUND2((count+1) * 2, 1024);
		ListItemData *dataNew = new ListItemData[lenNew];
		memcpy(dataNew, data, count * sizeof(ListItemData));
		delete []data;
		data = dataNew;
		len = lenNew;
	}
	ListItemData *item = &data[count];
	count++;
	return item;
}

ListItemData *LineToItem::Append(const char *text, int imageIndex) {
	ListItemData *item = AllocItem();
	item->text = AllocWord(text);
	item->pixId = imageIndex;
	return item;
}

const TCHAR ListBoxX_ClassName[] = TEXT("ListBoxX");

ListBox::ListBox() {
}

ListBox::~ListBox() {
}

class ListBoxX : public ListBox {
	int lineHeight;
	FontID fontCopy;
	int technology;
	RGBAImageSet images;
	LineToItem lti;
	HWND lb;
	bool unicodeMode;
	int desiredVisibleRows;
	unsigned int maxItemCharacters;
	unsigned int aveCharWidth;
	Window *parent;
	int ctrlID;
	CallBackAction doubleClickAction;
	void *doubleClickActionData;
	const char *widestItem;
	unsigned int maxCharWidth;
	int resizeHit;
	PRectangle rcPreSize;
	Point dragOffset;
	Point location;	// Caret location at which the list is opened
	int wheelDelta; // mouse wheel residue

	HWND GetHWND() const;
	void AppendListItem(const char *startword, const char *numword);
	void AdjustWindowRect(PRectangle *rc) const;
	int ItemHeight() const;
	int MinClientWidth() const;
	int TextOffset() const;
	Point GetClientExtent() const;
	POINT MinTrackSize() const;
	POINT MaxTrackSize() const;
	void SetRedraw(bool on);
	void OnDoubleClick();
	void ResizeToCursor();
	void StartResize(WPARAM);
	int NcHitTest(WPARAM, LPARAM) const;
	void CentreItem(int);
	void Paint(HDC);
	static LRESULT PASCAL ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);

	static const Point ItemInset;	// Padding around whole item
	static const Point TextInset;	// Padding around text
	static const Point ImageInset;	// Padding around image

public:
	ListBoxX() : lineHeight(10), fontCopy(0), technology(0), lb(0), unicodeMode(false),
		desiredVisibleRows(5), maxItemCharacters(0), aveCharWidth(8),
		parent(NULL), ctrlID(0), doubleClickAction(NULL), doubleClickActionData(NULL),
		widestItem(NULL), maxCharWidth(1), resizeHit(0), wheelDelta(0) {
	}
	virtual ~ListBoxX() {
		if (fontCopy) {
			::DeleteObject(fontCopy);
			fontCopy = 0;
		}
	}
	virtual void SetFont(Font &font);
	virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_, int technology_);
	virtual void SetAverageCharWidth(int width);
	virtual void SetVisibleRows(int rows);
	virtual int GetVisibleRows() const;
	virtual PRectangle GetDesiredRect();
	virtual int CaretFromEdge();
	virtual void Clear();
	virtual void Append(char *s, int type = -1);
	virtual int Length();
	virtual void Select(int n);
	virtual int GetSelection();
	virtual int Find(const char *prefix);
	virtual void GetValue(int n, char *value, int len);
	virtual void RegisterImage(int type, const char *xpm_data);
	virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage);
	virtual void ClearRegisteredImages();
	virtual void SetDoubleClickAction(CallBackAction action, void *data) {
		doubleClickAction = action;
		doubleClickActionData = data;
	}
	virtual void SetList(const char *list, char separator, char typesep);
	void Draw(DRAWITEMSTRUCT *pDrawItem);
	LRESULT WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
	static LRESULT PASCAL StaticWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
};

const Point ListBoxX::ItemInset(0, 0);
const Point ListBoxX::TextInset(2, 0);
const Point ListBoxX::ImageInset(1, 0);

ListBox *ListBox::Allocate() {
	ListBoxX *lb = new ListBoxX();
	return lb;
}

void ListBoxX::Create(Window &parent_, int ctrlID_, Point location_, int lineHeight_, bool unicodeMode_, int technology_) {
	parent = &parent_;
	ctrlID = ctrlID_;
	location = location_;
	lineHeight = lineHeight_;
	unicodeMode = unicodeMode_;
	technology = technology_;
	HWND hwndParent = reinterpret_cast<HWND>(parent->GetID());
	HINSTANCE hinstanceParent = GetWindowInstance(hwndParent);
	// Window created as popup so not clipped within parent client area
	wid = ::CreateWindowEx(
		WS_EX_WINDOWEDGE, ListBoxX_ClassName, TEXT(""),
		WS_POPUP | WS_THICKFRAME,
		100,100, 150,80, hwndParent,
		NULL,
		hinstanceParent,
		this);

	POINT locationw = {static_cast<LONG>(location.x), static_cast<LONG>(location.y)};
	::MapWindowPoints(hwndParent, NULL, &locationw, 1);
	location = Point(locationw.x, locationw.y);
}

void ListBoxX::SetFont(Font &font) {
	if (font.GetID()) {
		if (fontCopy) {
			::DeleteObject(fontCopy);
			fontCopy = 0;
		}
		FormatAndMetrics *pfm = reinterpret_cast<FormatAndMetrics *>(font.GetID());
		fontCopy = pfm->HFont();
		::SendMessage(lb, WM_SETFONT, reinterpret_cast<WPARAM>(fontCopy), 0);
	}
}

void ListBoxX::SetAverageCharWidth(int width) {
	aveCharWidth = width;
}

void ListBoxX::SetVisibleRows(int rows) {
	desiredVisibleRows = rows;
}

int ListBoxX::GetVisibleRows() const {
	return desiredVisibleRows;
}

HWND ListBoxX::GetHWND() const {
	return reinterpret_cast<HWND>(GetID());
}

PRectangle ListBoxX::GetDesiredRect() {
	PRectangle rcDesired = GetPosition();

	int rows = Length();
	if ((rows == 0) || (rows > desiredVisibleRows))
		rows = desiredVisibleRows;
	rcDesired.bottom = rcDesired.top + ItemHeight() * rows;

	int width = MinClientWidth();
	HDC hdc = ::GetDC(lb);
	HFONT oldFont = SelectFont(hdc, fontCopy);
	SIZE textSize = {0, 0};
	int len = static_cast<int>(widestItem ? strlen(widestItem) : 0);
	if (unicodeMode) {
		const TextWide tbuf(widestItem, len, unicodeMode);
		::GetTextExtentPoint32W(hdc, tbuf.buffer, tbuf.tlen, &textSize);
	} else {
		::GetTextExtentPoint32A(hdc, widestItem, len, &textSize);
	}
	TEXTMETRIC tm;
	::GetTextMetrics(hdc, &tm);
	maxCharWidth = tm.tmMaxCharWidth;
	SelectFont(hdc, oldFont);
	::ReleaseDC(lb, hdc);

	int widthDesired = Platform::Maximum(textSize.cx, (len + 1) * tm.tmAveCharWidth);
	if (width < widthDesired)
		width = widthDesired;

	rcDesired.right = rcDesired.left + TextOffset() + width + (TextInset.x * 2);
	if (Length() > rows)
		rcDesired.right += ::GetSystemMetrics(SM_CXVSCROLL);

	AdjustWindowRect(&rcDesired);
	return rcDesired;
}

int ListBoxX::TextOffset() const {
	int pixWidth = images.GetWidth();
	return pixWidth == 0 ? ItemInset.x : ItemInset.x + pixWidth + (ImageInset.x * 2);
}

int ListBoxX::CaretFromEdge() {
	PRectangle rc;
	AdjustWindowRect(&rc);
	return TextOffset() + TextInset.x + (0 - rc.left) - 1;
}

void ListBoxX::Clear() {
	::SendMessage(lb, LB_RESETCONTENT, 0, 0);
	maxItemCharacters = 0;
	widestItem = NULL;
	lti.Clear();
}

void ListBoxX::Append(char *s, int type) {
	int index = ::SendMessage(lb, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(s));
	if (index < 0)
		return;
	ListItemData *newItem = lti.Append(s, type);
	unsigned int len = static_cast<unsigned int>(strlen(s));
	if (maxItemCharacters < len) {
		maxItemCharacters = len;
		widestItem = newItem->text;
	}
}

int ListBoxX::Length() {
	return lti.Count();
}

void ListBoxX::Select(int n) {
	// We are going to scroll to centre on the new selection and then select it, so disable
	// redraw to avoid flicker caused by a painting new selection twice in unselected and then
	// selected states
	SetRedraw(false);
	CentreItem(n);
	::SendMessage(lb, LB_SETCURSEL, n, 0);
	SetRedraw(true);
}

int ListBoxX::GetSelection() {
	return ::SendMessage(lb, LB_GETCURSEL, 0, 0);
}

// This is not actually called at present
int ListBoxX::Find(const char *) {
	return LB_ERR;
}

void ListBoxX::GetValue(int n, char *value, int len) {
	ListItemData item = lti.Get(n);
	strncpy(value, item.text, len);
	value[len-1] = '\0';
}

void ListBoxX::RegisterImage(int type, const char *xpm_data) {
	XPM xpmImage(xpm_data);
	images.Add(type, new RGBAImage(xpmImage));
}

void ListBoxX::RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) {
	images.Add(type, new RGBAImage(width, height, 1.0, pixelsImage));
}

void ListBoxX::ClearRegisteredImages() {
	images.Clear();
}

void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
	if ((pDrawItem->itemAction == ODA_SELECT) || (pDrawItem->itemAction == ODA_DRAWENTIRE)) {
		RECT rcBox = pDrawItem->rcItem;
		rcBox.left += TextOffset();
		if (pDrawItem->itemState & ODS_SELECTED) {
			RECT rcImage = pDrawItem->rcItem;
			rcImage.right = rcBox.left;
			// The image is not highlighted
			::FillRect(pDrawItem->hDC, &rcImage, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
			::FillRect(pDrawItem->hDC, &rcBox, reinterpret_cast<HBRUSH>(COLOR_HIGHLIGHT+1));
			::SetBkColor(pDrawItem->hDC, ::GetSysColor(COLOR_HIGHLIGHT));
			::SetTextColor(pDrawItem->hDC, ::GetSysColor(COLOR_HIGHLIGHTTEXT));
		} else {
			::FillRect(pDrawItem->hDC, &pDrawItem->rcItem, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
			::SetBkColor(pDrawItem->hDC, ::GetSysColor(COLOR_WINDOW));
			::SetTextColor(pDrawItem->hDC, ::GetSysColor(COLOR_WINDOWTEXT));
		}

		ListItemData item = lti.Get(pDrawItem->itemID);
		int pixId = item.pixId;
		const char *text = item.text;
		int len = static_cast<int>(strlen(text));

		RECT rcText = rcBox;
		::InsetRect(&rcText, TextInset.x, TextInset.y);

		if (unicodeMode) {
			const TextWide tbuf(text, len, unicodeMode);
			::DrawTextW(pDrawItem->hDC, tbuf.buffer, tbuf.tlen, &rcText, DT_NOPREFIX|DT_END_ELLIPSIS|DT_SINGLELINE|DT_NOCLIP);
		} else {
			::DrawTextA(pDrawItem->hDC, text, len, &rcText, DT_NOPREFIX|DT_END_ELLIPSIS|DT_SINGLELINE|DT_NOCLIP);
		}
		if (pDrawItem->itemState & ODS_SELECTED) {
			::DrawFocusRect(pDrawItem->hDC, &rcBox);
		}

		// Draw the image, if any
		RGBAImage *pimage = images.Get(pixId);
		if (pimage) {
			Surface *surfaceItem = Surface::Allocate(technology);
			if (surfaceItem) {
				if (technology == SCWIN_TECH_GDI) {
					surfaceItem->Init(pDrawItem->hDC, pDrawItem->hwndItem);
					int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
					PRectangle rcImage(left, pDrawItem->rcItem.top,
						left + images.GetWidth(), pDrawItem->rcItem.bottom);
					surfaceItem->DrawRGBAImage(rcImage,
						pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
					delete surfaceItem;
					::SetTextAlign(pDrawItem->hDC, TA_TOP);
				} else {
#if defined(USE_D2D)
					D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
						D2D1_RENDER_TARGET_TYPE_DEFAULT,
						D2D1::PixelFormat(
							DXGI_FORMAT_B8G8R8A8_UNORM,
							D2D1_ALPHA_MODE_IGNORE),
						0,
						0,
						D2D1_RENDER_TARGET_USAGE_NONE,
						D2D1_FEATURE_LEVEL_DEFAULT
						);
					ID2D1DCRenderTarget *pDCRT = 0;
					HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT);
					if (SUCCEEDED(hr)) {
						RECT rcWindow;
						GetClientRect(pDrawItem->hwndItem, &rcWindow);
						hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow);
						if (SUCCEEDED(hr)) {
							surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
							pDCRT->BeginDraw();
							int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
							PRectangle rcImage(left, pDrawItem->rcItem.top,
								left + images.GetWidth(), pDrawItem->rcItem.bottom);
							surfaceItem->DrawRGBAImage(rcImage,
								pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
							delete surfaceItem;
							pDCRT->EndDraw();
							pDCRT->Release();
						}
					}
#endif
				}
			}
		}
	}
}

void ListBoxX::AppendListItem(const char *startword, const char *numword) {
	ListItemData *item = lti.AllocItem();
	item->text = startword;
	if (numword) {
		int pixId = 0;
		char ch;
		while ((ch = *++numword) != '\0') {
			pixId = 10 * pixId + (ch - '0');
		}
		item->pixId = pixId;
	} else {
		item->pixId = -1;
	}

	unsigned int len = static_cast<unsigned int>(strlen(item->text));
	if (maxItemCharacters < len) {
		maxItemCharacters = len;
		widestItem = item->text;
	}
}

void ListBoxX::SetList(const char *list, char separator, char typesep) {
	// Turn off redraw while populating the list - this has a significant effect, even if
	// the listbox is not visible.
	SetRedraw(false);
	Clear();
	size_t size = strlen(list);
	char *words = new char[size+1];
	lti.SetWords(words);
	memcpy(words, list, size+1);
	char *startword = words;
	char *numword = NULL;
	for (size_t i=0; i < size; i++) {
		if (words[i] == separator) {
			words[i] = '\0';
			if (numword)
				*numword = '\0';
			AppendListItem(startword, numword);
			startword = words + i + 1;
			numword = NULL;
		} else if (words[i] == typesep) {
			numword = words + i;
		}
	}
	if (startword) {
		if (numword)
			*numword = '\0';
		AppendListItem(startword, numword);
	}

	// Finally populate the listbox itself with the correct number of items
	int count = lti.Count();
	::SendMessage(lb, LB_INITSTORAGE, count, 0);
	for (int j=0; j<count; j++) {
		::SendMessage(lb, LB_ADDSTRING, 0, j+1);
	}
	SetRedraw(true);
}

void ListBoxX::AdjustWindowRect(PRectangle *rc) const {
	RECT rcw = RectFromPRectangle(*rc);
	::AdjustWindowRectEx(&rcw, WS_THICKFRAME, false, WS_EX_WINDOWEDGE);
	*rc = PRectangle(rcw.left, rcw.top, rcw.right, rcw.bottom);
}

int ListBoxX::ItemHeight() const {
	int itemHeight = lineHeight + (TextInset.y * 2);
	int pixHeight = images.GetHeight() + (ImageInset.y * 2);
	if (itemHeight < pixHeight) {
		itemHeight = pixHeight;
	}
	return itemHeight;
}

int ListBoxX::MinClientWidth() const {
	return 12 * (aveCharWidth+aveCharWidth/3);
}

POINT ListBoxX::MinTrackSize() const {
	PRectangle rc(0, 0, MinClientWidth(), ItemHeight());
	AdjustWindowRect(&rc);
	POINT ret = {static_cast<LONG>(rc.Width()), static_cast<LONG>(rc.Height())};
	return ret;
}

POINT ListBoxX::MaxTrackSize() const {
	PRectangle rc(0, 0,
		maxCharWidth * maxItemCharacters + TextInset.x * 2 +
		 TextOffset() + ::GetSystemMetrics(SM_CXVSCROLL),
		ItemHeight() * lti.Count());
	AdjustWindowRect(&rc);
	POINT ret = {static_cast<LONG>(rc.Width()), static_cast<LONG>(rc.Height())};
	return ret;
}

void ListBoxX::SetRedraw(bool on) {
	::SendMessage(lb, WM_SETREDRAW, static_cast<BOOL>(on), 0);
	if (on)
		::InvalidateRect(lb, NULL, TRUE);
}

void ListBoxX::ResizeToCursor() {
	PRectangle rc = GetPosition();
	POINT ptw;
	::GetCursorPos(&ptw);
	Point pt(ptw.x, ptw.y);
	pt.x += dragOffset.x;
	pt.y += dragOffset.y;

	switch (resizeHit) {
		case HTLEFT:
			rc.left = pt.x;
			break;
		case HTRIGHT:
			rc.right = pt.x;
			break;
		case HTTOP:
			rc.top = pt.y;
			break;
		case HTTOPLEFT:
			rc.top = pt.y;
			rc.left = pt.x;
			break;
		case HTTOPRIGHT:
			rc.top = pt.y;
			rc.right = pt.x;
			break;
		case HTBOTTOM:
			rc.bottom = pt.y;
			break;
		case HTBOTTOMLEFT:
			rc.bottom = pt.y;
			rc.left = pt.x;
			break;
		case HTBOTTOMRIGHT:
			rc.bottom = pt.y;
			rc.right = pt.x;
			break;
	}

	POINT ptMin = MinTrackSize();
	POINT ptMax = MaxTrackSize();
	// We don't allow the left edge to move at present, but just in case
	rc.left = Platform::Maximum(Platform::Minimum(rc.left, rcPreSize.right - ptMin.x), rcPreSize.right - ptMax.x);
	rc.top = Platform::Maximum(Platform::Minimum(rc.top, rcPreSize.bottom - ptMin.y), rcPreSize.bottom - ptMax.y);
	rc.right = Platform::Maximum(Platform::Minimum(rc.right, rcPreSize.left + ptMax.x), rcPreSize.left + ptMin.x);
	rc.bottom = Platform::Maximum(Platform::Minimum(rc.bottom, rcPreSize.top + ptMax.y), rcPreSize.top + ptMin.y);

	SetPosition(rc);
}

void ListBoxX::StartResize(WPARAM hitCode) {
	rcPreSize = GetPosition();
	POINT cursorPos;
	::GetCursorPos(&cursorPos);

	switch (hitCode) {
		case HTRIGHT:
		case HTBOTTOM:
		case HTBOTTOMRIGHT:
			dragOffset.x = rcPreSize.right - cursorPos.x;
			dragOffset.y = rcPreSize.bottom - cursorPos.y;
			break;

		case HTTOPRIGHT:
			dragOffset.x = rcPreSize.right - cursorPos.x;
			dragOffset.y = rcPreSize.top - cursorPos.y;
			break;

		// Note that the current hit test code prevents the left edge cases ever firing
		// as we don't want the left edge to be moveable
		case HTLEFT:
		case HTTOP:
		case HTTOPLEFT:
			dragOffset.x = rcPreSize.left - cursorPos.x;
			dragOffset.y = rcPreSize.top - cursorPos.y;
			break;
		case HTBOTTOMLEFT:
			dragOffset.x = rcPreSize.left - cursorPos.x;
			dragOffset.y = rcPreSize.bottom - cursorPos.y;
			break;

		default:
			return;
	}

	::SetCapture(GetHWND());
	resizeHit = hitCode;
}

int ListBoxX::NcHitTest(WPARAM wParam, LPARAM lParam) const {
	int hit = ::DefWindowProc(GetHWND(), WM_NCHITTEST, wParam, lParam);
	// There is an apparent bug in the DefWindowProc hit test code whereby it will
	// return HTTOPXXX if the window in question is shorter than the default
	// window caption height + frame, even if one is hovering over the bottom edge of
	// the frame, so workaround that here
	if (hit >= HTTOP && hit <= HTTOPRIGHT) {
		int minHeight = GetSystemMetrics(SM_CYMINTRACK);
		PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
		int yPos = GET_Y_LPARAM(lParam);
		if ((rc.Height() < minHeight) && (yPos > ((rc.top + rc.bottom)/2))) {
			hit += HTBOTTOM - HTTOP;
		}
	}

	// Nerver permit resizing that moves the left edge. Allow movement of top or bottom edge
	// depending on whether the list is above or below the caret
	switch (hit) {
		case HTLEFT:
		case HTTOPLEFT:
		case HTBOTTOMLEFT:
			hit = HTERROR;
			break;

		case HTTOP:
		case HTTOPRIGHT: {
				PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
				// Valid only if caret below list
				if (location.y < rc.top)
					hit = HTERROR;
			}
			break;

		case HTBOTTOM:
		case HTBOTTOMRIGHT: {
				PRectangle rc = const_cast<ListBoxX*>(this)->GetPosition();
				// Valid only if caret above list
				if (rc.bottom < location.y)
					hit = HTERROR;
			}
			break;
	}

	return hit;
}

void ListBoxX::OnDoubleClick() {

	if (doubleClickAction != NULL) {
		doubleClickAction(doubleClickActionData);
	}
}

Point ListBoxX::GetClientExtent() const {
	PRectangle rc = const_cast<ListBoxX*>(this)->GetClientPosition();
	return Point(rc.Width(), rc.Height());
}

void ListBoxX::CentreItem(int n) {
	// If below mid point, scroll up to centre, but with more items below if uneven
	if (n >= 0) {
		Point extent = GetClientExtent();
		int visible = extent.y/ItemHeight();
		if (visible < Length()) {
			int top = ::SendMessage(lb, LB_GETTOPINDEX, 0, 0);
			int half = (visible - 1) / 2;
			if (n > (top + half))
				::SendMessage(lb, LB_SETTOPINDEX, n - half , 0);
		}
	}
}

// Performs a double-buffered paint operation to avoid flicker
void ListBoxX::Paint(HDC hDC) {
	Point extent = GetClientExtent();
	HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, extent.x, extent.y);
	HDC bitmapDC = ::CreateCompatibleDC(hDC);
	HBITMAP hBitmapOld = SelectBitmap(bitmapDC, hBitmap);
	// The list background is mainly erased during painting, but can be a small
	// unpainted area when at the end of a non-integrally sized list with a
	// vertical scroll bar
	RECT rc = { 0, 0, static_cast<LONG>(extent.x), static_cast<LONG>(extent.y) };
	::FillRect(bitmapDC, &rc, reinterpret_cast<HBRUSH>(COLOR_WINDOW+1));
	// Paint the entire client area and vertical scrollbar
	::SendMessage(lb, WM_PRINT, reinterpret_cast<WPARAM>(bitmapDC), PRF_CLIENT|PRF_NONCLIENT);
	::BitBlt(hDC, 0, 0, extent.x, extent.y, bitmapDC, 0, 0, SRCCOPY);
	// Select a stock brush to prevent warnings from BoundsChecker
	::SelectObject(bitmapDC, GetStockFont(WHITE_BRUSH));
	SelectBitmap(bitmapDC, hBitmapOld);
	::DeleteDC(bitmapDC);
	::DeleteObject(hBitmap);
}

LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	try {
		switch (uMsg) {
		case WM_ERASEBKGND:
			return TRUE;

		case WM_PAINT: {
				PAINTSTRUCT ps;
				HDC hDC = ::BeginPaint(hWnd, &ps);
				ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(::GetParent(hWnd)));
				if (lbx)
					lbx->Paint(hDC);
				::EndPaint(hWnd, &ps);
			}
			return 0;

		case WM_MOUSEACTIVATE:
			// This prevents the view activating when the scrollbar is clicked
			return MA_NOACTIVATE;

		case WM_LBUTTONDOWN: {
				// We must take control of selection to prevent the ListBox activating
				// the popup
				LRESULT lResult = ::SendMessage(hWnd, LB_ITEMFROMPOINT, 0, lParam);
				int item = LOWORD(lResult);
				if (HIWORD(lResult) == 0 && item >= 0) {
					::SendMessage(hWnd, LB_SETCURSEL, item, 0);
				}
			}
			return 0;

		case WM_LBUTTONUP:
			return 0;

		case WM_LBUTTONDBLCLK: {
				ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(::GetParent(hWnd)));
				if (lbx) {
					lbx->OnDoubleClick();
				}
			}
			return 0;

		case WM_MBUTTONDOWN:
			// disable the scroll wheel button click action
			return 0;
		}

		WNDPROC prevWndProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
		if (prevWndProc) {
			return ::CallWindowProc(prevWndProc, hWnd, uMsg, wParam, lParam);
		} else {
			return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
		}
	} catch (...) {
	}
	return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	switch (iMessage) {
	case WM_CREATE: {
			HINSTANCE hinstanceParent = GetWindowInstance(reinterpret_cast<HWND>(parent->GetID()));
			// Note that LBS_NOINTEGRALHEIGHT is specified to fix cosmetic issue when resizing the list
			// but has useful side effect of speeding up list population significantly
			lb = ::CreateWindowEx(
				0, TEXT("listbox"), TEXT(""),
				WS_CHILD | WS_VSCROLL | WS_VISIBLE |
				LBS_OWNERDRAWFIXED | LBS_NODATA | LBS_NOINTEGRALHEIGHT,
				0, 0, 150,80, hWnd,
				reinterpret_cast<HMENU>(ctrlID),
				hinstanceParent,
				0);
			WNDPROC prevWndProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(lb, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ControlWndProc)));
			::SetWindowLongPtr(lb, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(prevWndProc));
		}
		break;

	case WM_SIZE:
		if (lb) {
			SetRedraw(false);
			::SetWindowPos(lb, 0, 0,0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
			// Ensure the selection remains visible
			CentreItem(GetSelection());
			SetRedraw(true);
		}
		break;

	case WM_PAINT: {
			PAINTSTRUCT ps;
			::BeginPaint(hWnd, &ps);
			::EndPaint(hWnd, &ps);
		}
		break;

	case WM_COMMAND:
		// This is not actually needed now - the registered double click action is used
		// directly to action a choice from the list.
		::SendMessage(reinterpret_cast<HWND>(parent->GetID()), iMessage, wParam, lParam);
		break;

	case WM_MEASUREITEM: {
			MEASUREITEMSTRUCT *pMeasureItem = reinterpret_cast<MEASUREITEMSTRUCT *>(lParam);
			pMeasureItem->itemHeight = static_cast<unsigned int>(ItemHeight());
		}
		break;

	case WM_DRAWITEM:
		Draw(reinterpret_cast<DRAWITEMSTRUCT *>(lParam));
		break;

	case WM_DESTROY:
		lb = 0;
		::SetWindowLong(hWnd, 0, 0);
		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);

	case WM_ERASEBKGND:
		// To reduce flicker we can elide background erasure since this window is
		// completely covered by its child.
		return TRUE;

	case WM_GETMINMAXINFO: {
			MINMAXINFO *minMax = reinterpret_cast<MINMAXINFO*>(lParam);
			minMax->ptMaxTrackSize = MaxTrackSize();
			minMax->ptMinTrackSize = MinTrackSize();
		}
		break;

	case WM_MOUSEACTIVATE:
		return MA_NOACTIVATE;

	case WM_NCHITTEST:
		return NcHitTest(wParam, lParam);

	case WM_NCLBUTTONDOWN:
		// We have to implement our own window resizing because the DefWindowProc
		// implementation insists on activating the resized window
		StartResize(wParam);
		return 0;

	case WM_MOUSEMOVE: {
			if (resizeHit == 0) {
				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
			} else {
				ResizeToCursor();
			}
		}
		break;

	case WM_LBUTTONUP:
	case WM_CANCELMODE:
		if (resizeHit != 0) {
			resizeHit = 0;
			::ReleaseCapture();
		}
		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);

	case WM_MOUSEWHEEL:
		wheelDelta -= static_cast<short>(HIWORD(wParam));
		if (abs(wheelDelta) >= WHEEL_DELTA) {
			int nRows = GetVisibleRows();
			int linesToScroll = 1;
			if (nRows > 1) {
				linesToScroll = nRows - 1;
			}
			if (linesToScroll > 3) {
				linesToScroll = 3;
			}
			linesToScroll *= (wheelDelta / WHEEL_DELTA);
			int top = ::SendMessage(lb, LB_GETTOPINDEX, 0, 0) + linesToScroll;
			if (top < 0) {
				top = 0;
			}
			::SendMessage(lb, LB_SETTOPINDEX, top, 0);
			// update wheel delta residue
			if (wheelDelta >= 0)
				wheelDelta = wheelDelta % WHEEL_DELTA;
			else
				wheelDelta = - (-wheelDelta % WHEEL_DELTA);
		}
		break;

	default:
		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
	}

	return 0;
}

LRESULT PASCAL ListBoxX::StaticWndProc(
    HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	if (iMessage == WM_CREATE) {
		CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
		SetWindowPointer(hWnd, pCreate->lpCreateParams);
	}
	// Find C++ object associated with window.
	ListBoxX *lbx = reinterpret_cast<ListBoxX *>(PointerFromWindow(hWnd));
	if (lbx) {
		return lbx->WndProc(hWnd, iMessage, wParam, lParam);
	} else {
		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
	}
}

static bool ListBoxX_Register() {
	WNDCLASSEX wndclassc;
	wndclassc.cbSize = sizeof(wndclassc);
	// We need CS_HREDRAW and CS_VREDRAW because of the ellipsis that might be drawn for
	// truncated items in the list and the appearance/disappearance of the vertical scroll bar.
	// The list repaint is double-buffered to avoid the flicker this would otherwise cause.
	wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
	wndclassc.cbClsExtra = 0;
	wndclassc.cbWndExtra = sizeof(ListBoxX *);
	wndclassc.hInstance = hinstPlatformRes;
	wndclassc.hIcon = NULL;
	wndclassc.hbrBackground = NULL;
	wndclassc.lpszMenuName = NULL;
	wndclassc.lpfnWndProc = ListBoxX::StaticWndProc;
	wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
	wndclassc.lpszClassName = ListBoxX_ClassName;
	wndclassc.hIconSm = 0;

	return ::RegisterClassEx(&wndclassc) != 0;
}

bool ListBoxX_Unregister() {
	return ::UnregisterClass(ListBoxX_ClassName, hinstPlatformRes) != 0;
}

Menu::Menu() : mid(0) {
}

void Menu::CreatePopUp() {
	Destroy();
	mid = ::CreatePopupMenu();
}

void Menu::Destroy() {
	if (mid)
		::DestroyMenu(reinterpret_cast<HMENU>(mid));
	mid = 0;
}

void Menu::Show(Point pt, Window &w) {
	::TrackPopupMenu(reinterpret_cast<HMENU>(mid),
		0, pt.x - 4, pt.y, 0,
		reinterpret_cast<HWND>(w.GetID()), NULL);
	Destroy();
}

static bool initialisedET = false;
static bool usePerformanceCounter = false;
static LARGE_INTEGER frequency;

ElapsedTime::ElapsedTime() {
	if (!initialisedET) {
		usePerformanceCounter = ::QueryPerformanceFrequency(&frequency) != 0;
		initialisedET = true;
	}
	if (usePerformanceCounter) {
		LARGE_INTEGER timeVal;
		::QueryPerformanceCounter(&timeVal);
		bigBit = timeVal.HighPart;
		littleBit = timeVal.LowPart;
	} else {
		bigBit = clock();
	}
}

double ElapsedTime::Duration(bool reset) {
	double result;
	long endBigBit;
	long endLittleBit;

	if (usePerformanceCounter) {
		LARGE_INTEGER lEnd;
		::QueryPerformanceCounter(&lEnd);
		endBigBit = lEnd.HighPart;
		endLittleBit = lEnd.LowPart;
		LARGE_INTEGER lBegin;
		lBegin.HighPart = bigBit;
		lBegin.LowPart = littleBit;
		double elapsed = lEnd.QuadPart - lBegin.QuadPart;
		result = elapsed / static_cast<double>(frequency.QuadPart);
	} else {
		endBigBit = clock();
		endLittleBit = 0;
		double elapsed = endBigBit - bigBit;
		result = elapsed / CLOCKS_PER_SEC;
	}
	if (reset) {
		bigBit = endBigBit;
		littleBit = endLittleBit;
	}
	return result;
}

class DynamicLibraryImpl : public DynamicLibrary {
protected:
	HMODULE h;
public:
	DynamicLibraryImpl(const char *modulePath) {
		h = ::LoadLibraryA(modulePath);
	}

	virtual ~DynamicLibraryImpl() {
		if (h != NULL)
			::FreeLibrary(h);
	}

	// Use GetProcAddress to get a pointer to the relevant function.
	virtual Function FindFunction(const char *name) {
		if (h != NULL) {
			// C++ standard doesn't like casts betwen function pointers and void pointers so use a union
			union {
				FARPROC fp;
				Function f;
			} fnConv;
			fnConv.fp = ::GetProcAddress(h, name);
			return fnConv.f;
		} else
			return NULL;
	}

	virtual bool IsValid() {
		return h != NULL;
	}
};

DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
	return static_cast<DynamicLibrary *>(new DynamicLibraryImpl(modulePath));
}

ColourDesired Platform::Chrome() {
	return ::GetSysColor(COLOR_3DFACE);
}

ColourDesired Platform::ChromeHighlight() {
	return ::GetSysColor(COLOR_3DHIGHLIGHT);
}

const char *Platform::DefaultFont() {
	return "Verdana";
}

int Platform::DefaultFontSize() {
	return 8;
}

unsigned int Platform::DoubleClickTime() {
	return ::GetDoubleClickTime();
}

bool Platform::MouseButtonBounce() {
	return false;
}

void Platform::DebugDisplay(const char *s) {
	::OutputDebugStringA(s);
}

bool Platform::IsKeyDown(int key) {
	return (::GetKeyState(key) & 0x80000000) != 0;
}

long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
	return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam, lParam);
}

long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
	return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam,
		reinterpret_cast<LPARAM>(lParam));
}

bool Platform::IsDBCSLeadByte(int codePage, char ch) {
	return ::IsDBCSLeadByteEx(codePage, ch) != 0;
}

int Platform::DBCSCharLength(int codePage, const char *s) {
	return (::IsDBCSLeadByteEx(codePage, s[0]) != 0) ? 2 : 1;
}

int Platform::DBCSCharMaxLength() {
	return 2;
}

// These are utility functions not really tied to a platform

int Platform::Minimum(int a, int b) {
	if (a < b)
		return a;
	else
		return b;
}

int Platform::Maximum(int a, int b) {
	if (a > b)
		return a;
	else
		return b;
}

//#define TRACE

#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) {
	char buffer[2000];
	va_list pArguments;
	va_start(pArguments, format);
	vsprintf(buffer,format,pArguments);
	va_end(pArguments);
	Platform::DebugDisplay(buffer);
}
#else
void Platform::DebugPrintf(const char *, ...) {
}
#endif

static bool assertionPopUps = true;

bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
	bool ret = assertionPopUps;
	assertionPopUps = assertionPopUps_;
	return ret;
}

void Platform::Assert(const char *c, const char *file, int line) {
	char buffer[2000];
	sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
	if (assertionPopUps) {
		int idButton = ::MessageBoxA(0, buffer, "Assertion failure",
			MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
		if (idButton == IDRETRY) {
			::DebugBreak();
		} else if (idButton == IDIGNORE) {
			// all OK
		} else {
			abort();
		}
	} else {
		strcat(buffer, "\r\n");
		Platform::DebugDisplay(buffer);
		::DebugBreak();
		abort();
	}
}

int Platform::Clamp(int val, int minVal, int maxVal) {
	if (val > maxVal)
		val = maxVal;
	if (val < minVal)
		val = minVal;
	return val;
}

void Platform_Initialise(void *hInstance) {
	OSVERSIONINFO osv = {sizeof(OSVERSIONINFO),0,0,0,0,TEXT("")};
	::GetVersionEx(&osv);
	onNT = osv.dwPlatformId == VER_PLATFORM_WIN32_NT;
	::InitializeCriticalSection(&crPlatformLock);
	hinstPlatformRes = reinterpret_cast<HINSTANCE>(hInstance);
	// This may be called from DllMain, in which case the call to LoadLibrary
	// is bad because it can upset the DLL load order.
	if (!hDLLImage) {
		hDLLImage = ::LoadLibrary(TEXT("Msimg32"));
	}
	if (hDLLImage) {
		AlphaBlendFn = (AlphaBlendSig)::GetProcAddress(hDLLImage, "AlphaBlend");
	}
	if (!hDLLUser32) {
		hDLLUser32 = ::LoadLibrary(TEXT("User32"));
	}
	if (hDLLUser32) {
		MonitorFromPointFn = (MonitorFromPointSig)::GetProcAddress(hDLLUser32, "MonitorFromPoint");
		MonitorFromRectFn = (MonitorFromRectSig)::GetProcAddress(hDLLUser32, "MonitorFromRect");
		GetMonitorInfoFn = (GetMonitorInfoSig)::GetProcAddress(hDLLUser32, "GetMonitorInfoA");
	}

	ListBoxX_Register();
}

void Platform_Finalise() {
	if (reverseArrowCursor != NULL)
		::DestroyCursor(reverseArrowCursor);
	ListBoxX_Unregister();
	::DeleteCriticalSection(&crPlatformLock);
}

Added win32/PlatWin.h.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Scintilla source code edit control
/** @file PlatWin.h
 ** Implementation of platform facilities on Windows.
 **/
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

extern bool IsNT();
extern void Platform_Initialise(void *hInstance);
extern void Platform_Finalise();

#if defined(USE_D2D)
extern bool LoadD2D();
extern ID2D1Factory *pD2DFactory;
extern IDWriteFactory *pIDWriteFactory;
#endif

Added win32/SciTE.properties.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
command.build.SConstruct=scons.bat .
command.name.1.SConstruct=scons clean
command.1.SConstruct=scons.bat --clean .

command.build.*.mak=nmake -f $(FileNameExt) DEBUG=1 QUIET=1
command.name.1.*.mak=nmake clean
command.1.*.mak=nmake -f $(FileNameExt) clean
command.name.2.*.mak=Borland Make
command.2.*.mak=make -f $(FileNameExt)
command.subsystem.2.*.mak=0
command.name.3.*.mak=make clean
command.3.*.mak=make -f $(FileNameExt) clean
command.name.4.*.mak=make debug
command.4.*.mak=make DEBUG=1 -f $(FileNameExt)
command.name.5.*.mak=nmake debug
command.5.*.mak=nmake DEBUG=1 -f $(FileNameExt)
# SciTE.properties is the per directory local options file and can be used to override
# settings made in SciTEGlobal.properties
command.build.*.cxx=nmake -f scintilla.mak DEBUG=1 QUIET=1
command.build.*.h=nmake -f scintilla.mak DEBUG=1 QUIET=1
command.build.*.rc=nmake -f scintilla.mak DEBUG=1 QUIET=1

Added win32/ScintRes.rc.











































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
// Resource file for Scintilla
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <windows.h>

#define VERSION_SCINTILLA "3.3.0"
#define VERSION_WORDS 3, 3, 0, 0

VS_VERSION_INFO VERSIONINFO
FILEVERSION	VERSION_WORDS
PRODUCTVERSION	VERSION_WORDS
FILEFLAGSMASK	0x3fL
FILEFLAGS 0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
	BLOCK	"VarFileInfo"
	BEGIN
		VALUE	"Translation",	0x409,	1200
	END
	BLOCK	"StringFileInfo"
	BEGIN
		BLOCK "040904b0"
		BEGIN
			VALUE	"CompanyName",	"Neil Hodgson neilh@scintilla.org\0"
			VALUE	"FileDescription",	"Scintilla.DLL - a Source Editing Component\0"
			VALUE	"FileVersion",	VERSION_SCINTILLA "\0"
			VALUE	"InternalName",	"Scintilla\0"
			VALUE	"LegalCopyright",	"Copyright 1998-2012 by Neil Hodgson\0"
			VALUE	"OriginalFilename",	"Scintilla.DLL\0"
			VALUE	"ProductName",	"Scintilla\0"
			VALUE	"ProductVersion",	VERSION_SCINTILLA "\0"
		END
	END
END

Added win32/Scintilla.def.





>
>
1
2
EXPORTS
	Scintilla_DirectFunction

Added win32/ScintillaWin.cxx.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
// Scintilla source code edit control
/** @file ScintillaWin.cxx
 ** Windows specific subclass of ScintillaBase.
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <new>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>

#include <string>
#include <vector>
#include <map>

#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#undef WINVER
#define WINVER 0x0500
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>

#if defined(NTDDI_WIN7) && !defined(DISABLE_D2D)
#define USE_D2D 1
#endif

#if defined(USE_D2D)
#include <d2d1.h>
#include <dwrite.h>
#endif

#include "Platform.h"

#include "ILexer.h"
#include "Scintilla.h"

#ifdef SCI_LEXER
#include "SciLexer.h"
#include "LexerModule.h"
#endif
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
#include "PlatWin.h"

#ifdef SCI_LEXER
#include "ExternalLexer.h"
#endif

#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES   104
#endif

#ifndef WM_UNICHAR
#define WM_UNICHAR                      0x0109
#endif

#ifndef UNICODE_NOCHAR
#define UNICODE_NOCHAR                  0xFFFF
#endif

#ifndef WM_IME_STARTCOMPOSITION
#include <imm.h>
#endif

#include <commctrl.h>
#ifndef __DMC__
#include <zmouse.h>
#endif
#include <ole2.h>

#ifndef MK_ALT
#define MK_ALT 32
#endif

#define SC_WIN_IDLE 5001

typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT);

// GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.

const TCHAR scintillaClassName[] = TEXT("Scintilla");
const TCHAR callClassName[] = TEXT("CallTip");

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// Take care of 32/64 bit pointers
#ifdef GetWindowLongPtr
static void *PointerFromWindow(HWND hWnd) {
	return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
	::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
}
static void SetWindowID(HWND hWnd, int identifier) {
	::SetWindowLongPtr(hWnd, GWLP_ID, identifier);
}
#else
static void *PointerFromWindow(HWND hWnd) {
	return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
	::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
}
static void SetWindowID(HWND hWnd, int identifier) {
	::SetWindowLong(hWnd, GWL_ID, identifier);
}
#endif

class ScintillaWin; 	// Forward declaration for COM interface subobjects

typedef void VFunction(void);

/**
 */
class FormatEnumerator {
public:
	VFunction **vtbl;
	int ref;
	int pos;
	CLIPFORMAT formats[2];
	int formatsLen;
	FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_);
};

/**
 */
class DropSource {
public:
	VFunction **vtbl;
	ScintillaWin *sci;
	DropSource();
};

/**
 */
class DataObject {
public:
	VFunction **vtbl;
	ScintillaWin *sci;
	DataObject();
};

/**
 */
class DropTarget {
public:
	VFunction **vtbl;
	ScintillaWin *sci;
	DropTarget();
};

/**
 */
class ScintillaWin :
	public ScintillaBase {

	bool lastKeyDownConsumed;

	bool capturedMouse;
	bool trackedMouseLeave;
	TrackMouseEventSig TrackMouseEventFn;

	unsigned int linesPerScroll;	///< Intellimouse support
	int wheelDelta; ///< Wheel delta from roll

	HRGN hRgnUpdate;

	bool hasOKText;

	CLIPFORMAT cfColumnSelect;
	CLIPFORMAT cfLineSelect;

	HRESULT hrOle;
	DropSource ds;
	DataObject dob;
	DropTarget dt;

	static HINSTANCE hInstance;

#if defined(USE_D2D)
	ID2D1HwndRenderTarget *pRenderTarget;
	bool renderTargetValid;
#endif

	ScintillaWin(HWND hwnd);
	ScintillaWin(const ScintillaWin &);
	virtual ~ScintillaWin();
	ScintillaWin &operator=(const ScintillaWin &);

	virtual void Initialise();
	virtual void Finalise();
	void EnsureRenderTarget();
	void DropRenderTarget();
	HWND MainHWND();

	static sptr_t DirectFunction(
		    ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam);
	static sptr_t PASCAL SWndProc(
		    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);
	static sptr_t PASCAL CTWndProc(
		    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);

	enum { invalidTimerID, standardTimerID, idleTimerID };

	virtual bool DragThreshold(Point ptStart, Point ptNow);
	virtual void StartDrag();
	sptr_t WndPaint(uptr_t wParam);
	sptr_t HandleComposition(uptr_t wParam, sptr_t lParam);
	UINT CodePageOfDocument();
	virtual bool ValidCodePage(int codePage) const;
	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	virtual bool SetIdle(bool on);
	virtual void SetTicking(bool on);
	virtual void SetMouseCapture(bool on);
	virtual bool HaveMouseCapture();
	virtual void SetTrackMouseLeaveEvent(bool on);
	virtual bool PaintContains(PRectangle rc);
	virtual void ScrollText(int linesToMove);
	virtual void UpdateSystemCaret();
	virtual void SetVerticalScrollPos();
	virtual void SetHorizontalScrollPos();
	virtual bool ModifyScrollBars(int nMax, int nPage);
	virtual void NotifyChange();
	virtual void NotifyFocus(bool focus);
	virtual void SetCtrlID(int identifier);
	virtual int GetCtrlID();
	virtual void NotifyParent(SCNotification scn);
	virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
	virtual CaseFolder *CaseFolderForEncoding();
	virtual std::string CaseMapString(const std::string &s, int caseMapping);
	virtual void Copy();
	virtual void CopyAllowLine();
	virtual bool CanPaste();
	virtual void Paste();
	virtual void CreateCallTipWindow(PRectangle rc);
	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
	virtual void ClaimSelection();

	// DBCS
	void ImeStartComposition();
	void ImeEndComposition();

	void AddCharBytes(char b0, char b1);

	void GetIntelliMouseParameters();
	virtual void CopyToClipboard(const SelectionText &selectedText);
	void ScrollMessage(WPARAM wParam);
	void HorizontalScrollMessage(WPARAM wParam);
	void FullPaint();
	void FullPaintDC(HDC dc);
	bool IsCompatibleDC(HDC dc);
	DWORD EffectFromState(DWORD grfKeyState);

	virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw);
	virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi);
	void ChangeScrollPos(int barType, int pos);

	void InsertPasteText(const char *text, int len, SelectionPosition selStart, bool isRectangular, bool isLine);

public:
	// Public for benefit of Scintilla_DirectFunction
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

	/// Implement IUnknown
	STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
	STDMETHODIMP_(ULONG)AddRef();
	STDMETHODIMP_(ULONG)Release();

	/// Implement IDropTarget
	STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
	                       POINTL pt, PDWORD pdwEffect);
	STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect);
	STDMETHODIMP DragLeave();
	STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
	                  POINTL pt, PDWORD pdwEffect);

	/// Implement important part of IDataObject
	STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);

	static bool Register(HINSTANCE hInstance_);
	static bool Unregister();

	friend class DropSource;
	friend class DataObject;
	friend class DropTarget;
	bool DragIsRectangularOK(CLIPFORMAT fmt) {
		return drag.rectangular && (fmt == cfColumnSelect);
	}

private:
	// For use in creating a system caret
	bool HasCaretSizeChanged();
	BOOL CreateSystemCaret();
	BOOL DestroySystemCaret();
	HBITMAP sysCaretBitmap;
	int sysCaretWidth;
	int sysCaretHeight;
	bool keysAlwaysUnicode;
};

HINSTANCE ScintillaWin::hInstance = 0;

ScintillaWin::ScintillaWin(HWND hwnd) {

	lastKeyDownConsumed = false;

	capturedMouse = false;
	trackedMouseLeave = false;
	TrackMouseEventFn = 0;

	linesPerScroll = 0;
	wheelDelta = 0;   // Wheel delta from roll

	hRgnUpdate = 0;

	hasOKText = false;

	// There does not seem to be a real standard for indicating that the clipboard
	// contains a rectangular selection, so copy Developer Studio.
	cfColumnSelect = static_cast<CLIPFORMAT>(
		::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));

	// Likewise for line-copy (copies a full line when no text is selected)
	cfLineSelect = static_cast<CLIPFORMAT>(
		::RegisterClipboardFormat(TEXT("MSDEVLineSelect")));

	hrOle = E_FAIL;

	wMain = hwnd;

	dob.sci = this;
	ds.sci = this;
	dt.sci = this;

	sysCaretBitmap = 0;
	sysCaretWidth = 0;
	sysCaretHeight = 0;

#if defined(USE_D2D)
	pRenderTarget = 0;
	renderTargetValid = true;
#endif

	keysAlwaysUnicode = false;

	caret.period = ::GetCaretBlinkTime();
	if (caret.period < 0)
		caret.period = 0;

	Initialise();
}

ScintillaWin::~ScintillaWin() {}

void ScintillaWin::Initialise() {
	// Initialize COM.  If the app has already done this it will have
	// no effect.  If the app hasnt, we really shouldnt ask them to call
	// it just so this internal feature works.
	hrOle = ::OleInitialize(NULL);

	// Find TrackMouseEvent which is available on Windows > 95
	HMODULE user32 = ::GetModuleHandle(TEXT("user32.dll"));
	if (user32)
		TrackMouseEventFn = (TrackMouseEventSig)::GetProcAddress(user32, "TrackMouseEvent");
	if (TrackMouseEventFn == NULL) {
		// Windows 95 has an emulation in comctl32.dll:_TrackMouseEvent
		HMODULE commctrl32 = ::LoadLibrary(TEXT("comctl32.dll"));
		if (commctrl32 != NULL) {
			TrackMouseEventFn = (TrackMouseEventSig)
				::GetProcAddress(commctrl32, "_TrackMouseEvent");
		}
	}
}

void ScintillaWin::Finalise() {
	ScintillaBase::Finalise();
	SetTicking(false);
	SetIdle(false);
	DropRenderTarget();
	::RevokeDragDrop(MainHWND());
	if (SUCCEEDED(hrOle)) {
		::OleUninitialize();
	}
}

void ScintillaWin::EnsureRenderTarget() {
#if defined(USE_D2D)
	if (!renderTargetValid) {
		DropRenderTarget();
		renderTargetValid = true;
	}
	if (pD2DFactory && !pRenderTarget) {
		RECT rc;
		HWND hw = MainHWND();
		GetClientRect(hw, &rc);

		D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);

		// Create a Direct2D render target.
#if 1
		pD2DFactory->CreateHwndRenderTarget(
			D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(), 96.0, 96.0),
			D2D1::HwndRenderTargetProperties(hw, size),
			&pRenderTarget);
#else
		pD2DFactory->CreateHwndRenderTarget(
			D2D1::RenderTargetProperties(
				D2D1_RENDER_TARGET_TYPE_DEFAULT ,
				D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
				96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT),
			D2D1::HwndRenderTargetProperties(hw, size),
			&pRenderTarget);
#endif
		// Pixmaps were created to be compatible with previous render target so
		// need to be recreated.
		DropGraphics(false);
	}
#endif
}

void ScintillaWin::DropRenderTarget() {
#if defined(USE_D2D)
	if (pRenderTarget) {
		pRenderTarget->Release();
		pRenderTarget = 0;
	}
#endif
}

HWND ScintillaWin::MainHWND() {
	return reinterpret_cast<HWND>(wMain.GetID());
}

bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) {
	int xMove = abs(ptStart.x - ptNow.x);
	int yMove = abs(ptStart.y - ptNow.y);
	return (xMove > ::GetSystemMetrics(SM_CXDRAG)) ||
		(yMove > ::GetSystemMetrics(SM_CYDRAG));
}

void ScintillaWin::StartDrag() {
	inDragDrop = ddDragging;
	DWORD dwEffect = 0;
	dropWentOutside = true;
	IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob);
	IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds);
	//Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
	HRESULT hr = ::DoDragDrop(
	                 pDataObject,
	                 pDropSource,
	                 DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
	//Platform::DebugPrintf("DoDragDrop = %x\n", hr);
	if (SUCCEEDED(hr)) {
		if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) {
			// Remove dragged out text
			ClearSelection();
		}
	}
	inDragDrop = ddNone;
	SetDragPosition(SelectionPosition(invalidPosition));
}

// Avoid warnings everywhere for old style casts by concentrating them here
static WORD LoWord(DWORD l) {
	return LOWORD(l);
}

static WORD HiWord(DWORD l) {
	return HIWORD(l);
}

static int InputCodePage() {
	HKL inputLocale = ::GetKeyboardLayout(0);
	LANGID inputLang = LOWORD(inputLocale);
	char sCodePage[10];
	int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT),
	  LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage));
	if (!res)
		return 0;
	return atoi(sCodePage);
}

#ifndef VK_OEM_2
static const int VK_OEM_2=0xbf;
static const int VK_OEM_3=0xc0;
static const int VK_OEM_4=0xdb;
static const int VK_OEM_5=0xdc;
static const int VK_OEM_6=0xdd;
#endif

/** Map the key codes to their equivalent SCK_ form. */
static int KeyTranslate(int keyIn) {
//PLATFORM_ASSERT(!keyIn);
	switch (keyIn) {
		case VK_DOWN:		return SCK_DOWN;
		case VK_UP:		return SCK_UP;
		case VK_LEFT:		return SCK_LEFT;
		case VK_RIGHT:		return SCK_RIGHT;
		case VK_HOME:		return SCK_HOME;
		case VK_END:		return SCK_END;
		case VK_PRIOR:		return SCK_PRIOR;
		case VK_NEXT:		return SCK_NEXT;
		case VK_DELETE:	return SCK_DELETE;
		case VK_INSERT:		return SCK_INSERT;
		case VK_ESCAPE:	return SCK_ESCAPE;
		case VK_BACK:		return SCK_BACK;
		case VK_TAB:		return SCK_TAB;
		case VK_RETURN:	return SCK_RETURN;
		case VK_ADD:		return SCK_ADD;
		case VK_SUBTRACT:	return SCK_SUBTRACT;
		case VK_DIVIDE:		return SCK_DIVIDE;
		case VK_LWIN:		return SCK_WIN;
		case VK_RWIN:		return SCK_RWIN;
		case VK_APPS:		return SCK_MENU;
		case VK_OEM_2:		return '/';
		case VK_OEM_3:		return '`';
		case VK_OEM_4:		return '[';
		case VK_OEM_5:		return '\\';
		case VK_OEM_6:		return ']';
		default:			return keyIn;
	}
}

LRESULT ScintillaWin::WndPaint(uptr_t wParam) {
	//ElapsedTime et;

	// Redirect assertions to debug output and save current state
	bool assertsPopup = Platform::ShowAssertionPopUps(false);
	paintState = painting;
	PAINTSTRUCT ps;
	PAINTSTRUCT *pps;

	bool IsOcxCtrl = (wParam != 0); // if wParam != 0, it contains
								   // a PAINSTRUCT* from the OCX
	// Removed since this interferes with reporting other assertions as it occurs repeatedly
	//PLATFORM_ASSERT(hRgnUpdate == NULL);
	hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0);
	if (IsOcxCtrl) {
		pps = reinterpret_cast<PAINTSTRUCT*>(wParam);
	} else {
		::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE);
		pps = &ps;
		::BeginPaint(MainHWND(), pps);
	}
	if (technology == SC_TECHNOLOGY_DEFAULT) {
		AutoSurface surfaceWindow(pps->hdc, this);
		if (surfaceWindow) {
			rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
			PRectangle rcClient = GetClientRectangle();
			paintingAllText = rcPaint.Contains(rcClient);
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
		}
	} else {
#if defined(USE_D2D)
		EnsureRenderTarget();
		AutoSurface surfaceWindow(pRenderTarget, this);
		if (surfaceWindow) {
			pRenderTarget->BeginDraw();
			rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
			PRectangle rcClient = GetClientRectangle();
			paintingAllText = rcPaint.Contains(rcClient);
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
			HRESULT hr = pRenderTarget->EndDraw();
			if (hr == D2DERR_RECREATE_TARGET) {
				DropRenderTarget();
			}
		}
#endif
	}
	if (hRgnUpdate) {
		::DeleteRgn(hRgnUpdate);
		hRgnUpdate = 0;
	}

	if (!IsOcxCtrl)
		::EndPaint(MainHWND(), pps);
	if (paintState == paintAbandoned) {
		// Painting area was insufficient to cover new styling or brace highlight positions
		FullPaint();
	}
	paintState = notPainting;

	// Restore debug output state
	Platform::ShowAssertionPopUps(assertsPopup);

	//Platform::DebugPrintf("Paint took %g\n", et.Duration());
	return 0l;
}

sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) {
#ifdef __DMC__
	// Digital Mars compiler does not include Imm library
	return 0;
#else
	if (lParam & GCS_RESULTSTR) {
		HIMC hIMC = ::ImmGetContext(MainHWND());
		if (hIMC) {
			const int maxLenInputIME = 200;
			wchar_t wcs[maxLenInputIME];
			LONG bytes = ::ImmGetCompositionStringW(hIMC,
				GCS_RESULTSTR, wcs, (maxLenInputIME-1)*2);
			int wides = bytes / 2;
			if (IsUnicodeMode()) {
				char utfval[maxLenInputIME * 3];
				unsigned int len = UTF8Length(wcs, wides);
				UTF8FromUTF16(wcs, wides, utfval, len);
				utfval[len] = '\0';
				AddCharUTF(utfval, len);
			} else {
				char dbcsval[maxLenInputIME * 2];
				int size = ::WideCharToMultiByte(InputCodePage(),
					0, wcs, wides, dbcsval, sizeof(dbcsval) - 1, 0, 0);
				for (int i=0; i<size; i++) {
					AddChar(dbcsval[i]);
				}
			}
			// Set new position after converted
			Point pos = PointMainCaret();
			COMPOSITIONFORM CompForm;
			CompForm.dwStyle = CFS_POINT;
			CompForm.ptCurrentPos.x = pos.x;
			CompForm.ptCurrentPos.y = pos.y;
			::ImmSetCompositionWindow(hIMC, &CompForm);
			::ImmReleaseContext(MainHWND(), hIMC);
		}
		return 0;
	}
	return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam);
#endif
}

// Translate message IDs from WM_* and EM_* to SCI_* so can partly emulate Windows Edit control
static unsigned int SciMessageFromEM(unsigned int iMessage) {
	switch (iMessage) {
	case EM_CANPASTE: return SCI_CANPASTE;
	case EM_CANUNDO: return SCI_CANUNDO;
	case EM_EMPTYUNDOBUFFER: return SCI_EMPTYUNDOBUFFER;
	case EM_FINDTEXTEX: return SCI_FINDTEXT;
	case EM_FORMATRANGE: return SCI_FORMATRANGE;
	case EM_GETFIRSTVISIBLELINE: return SCI_GETFIRSTVISIBLELINE;
	case EM_GETLINECOUNT: return SCI_GETLINECOUNT;
	case EM_GETSELTEXT: return SCI_GETSELTEXT;
	case EM_GETTEXTRANGE: return SCI_GETTEXTRANGE;
	case EM_HIDESELECTION: return SCI_HIDESELECTION;
	case EM_LINEINDEX: return SCI_POSITIONFROMLINE;
	case EM_LINESCROLL: return SCI_LINESCROLL;
	case EM_REPLACESEL: return SCI_REPLACESEL;
	case EM_SCROLLCARET: return SCI_SCROLLCARET;
	case EM_SETREADONLY: return SCI_SETREADONLY;
	case WM_CLEAR: return SCI_CLEAR;
	case WM_COPY: return SCI_COPY;
	case WM_CUT: return SCI_CUT;
	case WM_GETTEXT: return SCI_GETTEXT;
	case WM_SETTEXT: return SCI_SETTEXT;
	case WM_GETTEXTLENGTH: return SCI_GETTEXTLENGTH;
	case WM_PASTE: return SCI_PASTE;
	case WM_UNDO: return SCI_UNDO;
	}
	return iMessage;
}

static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {
	if (documentCodePage == SC_CP_UTF8) {
		// The system calls here are a little slow so avoid if known case.
		return SC_CP_UTF8;
	}
	CHARSETINFO ci = { 0, 0, { { 0, 0, 0, 0 }, { 0, 0 } } };
	BOOL bci = ::TranslateCharsetInfo(reinterpret_cast<DWORD*>(static_cast<uptr_t>(characterSet)),
		&ci, TCI_SRCCHARSET);

	UINT cp;
	if (bci)
		cp = ci.ciACP;
	else
		cp = documentCodePage;

	CPINFO cpi;
	if (!IsValidCodePage(cp) && !GetCPInfo(cp, &cpi))
		cp = CP_ACP;

	return cp;
}

UINT ScintillaWin::CodePageOfDocument() {
	return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage);
}

sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	try {
		//Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam);
		iMessage = SciMessageFromEM(iMessage);
		switch (iMessage) {

		case WM_CREATE:
			ctrlID = ::GetDlgCtrlID(reinterpret_cast<HWND>(wMain.GetID()));
			// Get Intellimouse scroll line parameters
			GetIntelliMouseParameters();
			::RegisterDragDrop(MainHWND(), reinterpret_cast<IDropTarget *>(&dt));
			break;

		case WM_COMMAND:
			Command(LoWord(wParam));
			break;

		case WM_PAINT:
			return WndPaint(wParam);

		case WM_PRINTCLIENT: {
				HDC hdc = reinterpret_cast<HDC>(wParam);
				if (!IsCompatibleDC(hdc)) {
					return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
				}
				FullPaintDC(hdc);
			}
			break;

		case WM_VSCROLL:
			ScrollMessage(wParam);
			break;

		case WM_HSCROLL:
			HorizontalScrollMessage(wParam);
			break;

		case WM_SIZE: {
#if defined(USE_D2D)
				if (paintState == notPainting) {
					DropRenderTarget();
				} else {
					renderTargetValid = false;
				}
#endif
				//Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam));
				ChangeSize();
			}
			break;

		case WM_MOUSEWHEEL:
			// if autocomplete list active then send mousewheel message to it
			if (ac.Active()) {
				HWND hWnd = reinterpret_cast<HWND>(ac.lb->GetID());
				::SendMessage(hWnd, iMessage, wParam, lParam);
				break;
			}
			
			// Don't handle datazoom.
			// (A good idea for datazoom would be to "fold" or "unfold" details.
			// i.e. if datazoomed out only class structures are visible, when datazooming in the control
			// structures appear, then eventually the individual statements...)
			if (wParam & MK_SHIFT) {
				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
			}

			// Either SCROLL or ZOOM. We handle the wheel steppings calculation
			wheelDelta -= static_cast<short>(HiWord(wParam));
			if (abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) {
				int linesToScroll = linesPerScroll;
				if (linesPerScroll == WHEEL_PAGESCROLL)
					linesToScroll = LinesOnScreen() - 1;
				if (linesToScroll == 0) {
					linesToScroll = 1;
				}
				linesToScroll *= (wheelDelta / WHEEL_DELTA);
				if (wheelDelta >= 0)
					wheelDelta = wheelDelta % WHEEL_DELTA;
				else
					wheelDelta = - (-wheelDelta % WHEEL_DELTA);

				if (wParam & MK_CONTROL) {
					// Zoom! We play with the font sizes in the styles.
					// Number of steps/line is ignored, we just care if sizing up or down
					if (linesToScroll < 0) {
						KeyCommand(SCI_ZOOMIN);
					} else {
						KeyCommand(SCI_ZOOMOUT);
					}
				} else {
					// Scroll
					ScrollTo(topLine + linesToScroll);
				}
			}
			return 0;

		case WM_TIMER:
			if (wParam == standardTimerID && timer.ticking) {
				Tick();
			} else if (wParam == idleTimerID && idler.state) {
				SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1);
			} else {
				return 1;
			}
			break;

		case SC_WIN_IDLE:
			// wParam=dwTickCountInitial, or 0 to initialize.  lParam=bSkipUserInputTest
			if (idler.state) {
				if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, 0, 0, 0, QS_INPUT|QS_HOTKEY))) {
					if (Idle()) {
						// User input was given priority above, but all events do get a turn.  Other
						// messages, notifications, etc. will get interleaved with the idle messages.

						// However, some things like WM_PAINT are a lower priority, and will not fire
						// when there's a message posted.  So, several times a second, we stop and let
						// the low priority events have a turn (after which the timer will fire again).

						DWORD dwCurrent = GetTickCount();
						DWORD dwStart = wParam ? wParam : dwCurrent;
						const DWORD maxWorkTime = 50;

						if (dwCurrent >= dwStart && dwCurrent > maxWorkTime && dwCurrent - maxWorkTime < dwStart)
							PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0);
					} else {
						SetIdle(false);
					}
				}
			}
			break;

		case WM_GETMINMAXINFO:
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_LBUTTONDOWN: {
#ifndef __DMC__
			// Digital Mars compiler does not include Imm library
			// For IME, set the composition string as the result string.
			HIMC hIMC = ::ImmGetContext(MainHWND());
			::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
			::ImmReleaseContext(MainHWND(), hIMC);
#endif
			//
			//Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam,
			//	Platform::IsKeyDown(VK_SHIFT),
			//	Platform::IsKeyDown(VK_CONTROL),
			//	Platform::IsKeyDown(VK_MENU));
			::SetFocus(MainHWND());
			ButtonDown(Point::FromLong(lParam), ::GetMessageTime(),
				(wParam & MK_SHIFT) != 0,
				(wParam & MK_CONTROL) != 0,
				Platform::IsKeyDown(VK_MENU));
			}
			break;

		case WM_MOUSEMOVE:
			SetTrackMouseLeaveEvent(true);
			ButtonMove(Point::FromLong(lParam));
			break;

		case WM_MOUSELEAVE:
			SetTrackMouseLeaveEvent(false);
			MouseLeave();
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_LBUTTONUP:
			ButtonUp(Point::FromLong(lParam),
				::GetMessageTime(),
				(wParam & MK_CONTROL) != 0);
			break;

		case WM_RBUTTONDOWN:
			::SetFocus(MainHWND());
			if (!PointInSelection(Point::FromLong(lParam))) {
				CancelModes();
				SetEmptySelection(PositionFromLocation(Point::FromLong(lParam)));
			}
			break;

		case WM_SETCURSOR:
			if (LoWord(lParam) == HTCLIENT) {
				if (inDragDrop == ddDragging) {
					DisplayCursor(Window::cursorUp);
				} else {
					// Display regular (drag) cursor over selection
					POINT pt;
					if (0 != ::GetCursorPos(&pt)) {
						::ScreenToClient(MainHWND(), &pt);
						if (PointInSelMargin(Point(pt.x, pt.y))) {
							DisplayCursor(GetMarginCursor(Point(pt.x, pt.y)));
						} else if (PointInSelection(Point(pt.x, pt.y)) && !SelectionEmpty()) {
							DisplayCursor(Window::cursorArrow);
						} else if (PointIsHotspot(Point(pt.x, pt.y))) {
							DisplayCursor(Window::cursorHand);
						} else {
							DisplayCursor(Window::cursorText);
						}
					}
				}
				return TRUE;
			} else {
				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
			}

		case WM_CHAR:
			if (((wParam >= 128) || !iscntrl(wParam)) || !lastKeyDownConsumed) {
				if (::IsWindowUnicode(MainHWND()) || keysAlwaysUnicode) {
					wchar_t wcs[2] = {static_cast<wchar_t>(wParam), 0};
					if (IsUnicodeMode()) {
						// For a wide character version of the window:
						char utfval[4];
						unsigned int len = UTF8Length(wcs, 1);
						UTF8FromUTF16(wcs, 1, utfval, len);
						AddCharUTF(utfval, len);
					} else {
						UINT cpDest = CodePageOfDocument();
						char inBufferCP[20];
						int size = ::WideCharToMultiByte(cpDest,
							0, wcs, 1, inBufferCP, sizeof(inBufferCP) - 1, 0, 0);
						inBufferCP[size] = '\0';
						AddCharUTF(inBufferCP, size);
					}
				} else {
					if (IsUnicodeMode()) {
						AddCharBytes('\0', LOBYTE(wParam));
					} else {
						AddChar(LOBYTE(wParam));
					}
				}
			}
			return 0;

		case WM_UNICHAR:
			if (wParam == UNICODE_NOCHAR) {
				return IsUnicodeMode() ? 1 : 0;
			} else if (lastKeyDownConsumed) {
				return 1;
			} else {
				if (IsUnicodeMode()) {
					char utfval[4];
					wchar_t wcs[2] = {static_cast<wchar_t>(wParam), 0};
					unsigned int len = UTF8Length(wcs, 1);
					UTF8FromUTF16(wcs, 1, utfval, len);
					AddCharUTF(utfval, len);
					return 1;
				} else {
					return 0;
				}
			}

		case WM_SYSKEYDOWN:
		case WM_KEYDOWN: {
			//Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL));
				lastKeyDownConsumed = false;
				int ret = KeyDown(KeyTranslate(wParam),
					Platform::IsKeyDown(VK_SHIFT),
					Platform::IsKeyDown(VK_CONTROL),
					Platform::IsKeyDown(VK_MENU),
					&lastKeyDownConsumed);
				if (!ret && !lastKeyDownConsumed) {
					return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
				}
				break;
			}

		case WM_IME_KEYDOWN:
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_KEYUP:
			//Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam);
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_SETTINGCHANGE:
			//Platform::DebugPrintf("Setting Changed\n");
			InvalidateStyleData();
			// Get Intellimouse scroll line parameters
			GetIntelliMouseParameters();
			break;

		case WM_GETDLGCODE:
			return DLGC_HASSETSEL | DLGC_WANTALLKEYS;

		case WM_KILLFOCUS: {
				HWND wOther = reinterpret_cast<HWND>(wParam);
				HWND wThis = MainHWND();
				HWND wCT = reinterpret_cast<HWND>(ct.wCallTip.GetID());
				if (!wParam ||
					!(::IsChild(wThis, wOther) || (wOther == wCT))) {
					SetFocusState(false);
					DestroySystemCaret();
				}
			}
			break;

		case WM_SETFOCUS:
			SetFocusState(true);
			DestroySystemCaret();
			CreateSystemCaret();
			break;

		case WM_SYSCOLORCHANGE:
			//Platform::DebugPrintf("Setting Changed\n");
			InvalidateStyleData();
			break;

		case WM_IME_STARTCOMPOSITION: 	// dbcs
			ImeStartComposition();
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_IME_ENDCOMPOSITION: 	// dbcs
			ImeEndComposition();
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_IME_COMPOSITION:
			return HandleComposition(wParam, lParam);

		case WM_IME_CHAR: {
				AddCharBytes(HIBYTE(wParam), LOBYTE(wParam));
				return 0;
			}

		case WM_CONTEXTMENU:
			if (displayPopupMenu) {
				Point pt = Point::FromLong(lParam);
				if ((pt.x == -1) && (pt.y == -1)) {
					// Caused by keyboard so display menu near caret
					pt = PointMainCaret();
					POINT spt = {static_cast<int>(pt.x), static_cast<int>(pt.y)};
					::ClientToScreen(MainHWND(), &spt);
					pt = Point(spt.x, spt.y);
				}
				ContextMenu(pt);
				return 0;
			}
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_INPUTLANGCHANGE:
			//::SetThreadLocale(LOWORD(lParam));
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_INPUTLANGCHANGEREQUEST:
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case WM_ERASEBKGND:
			return 1;   // Avoid any background erasure as whole window painted.

		case WM_CAPTURECHANGED:
			capturedMouse = false;
			return 0;

		// These are not handled in Scintilla and its faster to dispatch them here.
		// Also moves time out to here so profile doesn't count lots of empty message calls.

		case WM_MOVE:
		case WM_MOUSEACTIVATE:
		case WM_NCHITTEST:
		case WM_NCCALCSIZE:
		case WM_NCPAINT:
		case WM_NCMOUSEMOVE:
		case WM_NCLBUTTONDOWN:
		case WM_IME_SETCONTEXT:
		case WM_IME_NOTIFY:
		case WM_SYSCOMMAND:
		case WM_WINDOWPOSCHANGING:
		case WM_WINDOWPOSCHANGED:
			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);

		case EM_LINEFROMCHAR:
			if (static_cast<int>(wParam) < 0) {
				wParam = SelectionStart().Position();
			}
			return pdoc->LineFromPosition(wParam);

		case EM_EXLINEFROMCHAR:
			return pdoc->LineFromPosition(lParam);

		case EM_GETSEL:
			if (wParam) {
				*reinterpret_cast<int *>(wParam) = SelectionStart().Position();
			}
			if (lParam) {
				*reinterpret_cast<int *>(lParam) = SelectionEnd().Position();
			}
			return MAKELONG(SelectionStart().Position(), SelectionEnd().Position());

		case EM_EXGETSEL: {
				if (lParam == 0) {
					return 0;
				}
				Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam);
				pCR->cpMin = SelectionStart().Position();
				pCR->cpMax = SelectionEnd().Position();
			}
			break;

		case EM_SETSEL: {
				int nStart = static_cast<int>(wParam);
				int nEnd = static_cast<int>(lParam);
				if (nStart == 0 && nEnd == -1) {
					nEnd = pdoc->Length();
				}
				if (nStart == -1) {
					nStart = nEnd;	// Remove selection
				}
				if (nStart > nEnd) {
					SetSelection(nEnd, nStart);
				} else {
					SetSelection(nStart, nEnd);
				}
				EnsureCaretVisible();
			}
			break;

		case EM_EXSETSEL: {
				if (lParam == 0) {
					return 0;
				}
				Sci_CharacterRange *pCR = reinterpret_cast<Sci_CharacterRange *>(lParam);
				sel.selType = Selection::selStream;
				if (pCR->cpMin == 0 && pCR->cpMax == -1) {
					SetSelection(pCR->cpMin, pdoc->Length());
				} else {
					SetSelection(pCR->cpMin, pCR->cpMax);
				}
				EnsureCaretVisible();
				return pdoc->LineFromPosition(SelectionStart().Position());
			}

		case SCI_GETDIRECTFUNCTION:
			return reinterpret_cast<sptr_t>(DirectFunction);

		case SCI_GETDIRECTPOINTER:
			return reinterpret_cast<sptr_t>(this);

		case SCI_GRABFOCUS:
			::SetFocus(MainHWND());
			break;

		case SCI_SETKEYSUNICODE:
			keysAlwaysUnicode = wParam != 0;
			break;

		case SCI_GETKEYSUNICODE:
			return keysAlwaysUnicode;
		
		case SCI_SETTECHNOLOGY:
			if ((wParam == SC_TECHNOLOGY_DEFAULT) || (wParam == SC_TECHNOLOGY_DIRECTWRITE)) {
				if (technology != static_cast<int>(wParam)) {
					if (static_cast<int>(wParam) == SC_TECHNOLOGY_DIRECTWRITE) {
#if defined(USE_D2D)
						if (!LoadD2D())
							// Failed to load Direct2D or DirectWrite so no effect
							return 0;
#else
						return 0;
#endif
					}
					technology = wParam;
					// Invalidate all cached information including layout.
					DropGraphics(true);
					InvalidateStyleRedraw();
				}
			}
			break;

#ifdef SCI_LEXER
		case SCI_LOADLEXERLIBRARY:
			LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
			break;
#endif

		default:
			return ScintillaBase::WndProc(iMessage, wParam, lParam);
		}
	} catch (std::bad_alloc &) {
		errorStatus = SC_STATUS_BADALLOC;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return 0l;
}

bool ScintillaWin::ValidCodePage(int codePage) const {
	return codePage == 0 || codePage == SC_CP_UTF8 ||
	       codePage == 932 || codePage == 936 || codePage == 949 ||
	       codePage == 950 || codePage == 1361;
}

sptr_t ScintillaWin::DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
	return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
}

void ScintillaWin::SetTicking(bool on) {
	if (timer.ticking != on) {
		timer.ticking = on;
		if (timer.ticking) {
			timer.tickerID = ::SetTimer(MainHWND(), standardTimerID, timer.tickSize, NULL)
				? reinterpret_cast<TickerID>(standardTimerID) : 0;
		} else {
			::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(timer.tickerID));
			timer.tickerID = 0;
		}
	}
	timer.ticksToWait = caret.period;
}

bool ScintillaWin::SetIdle(bool on) {
	// On Win32 the Idler is implemented as a Timer on the Scintilla window.  This
	// takes advantage of the fact that WM_TIMER messages are very low priority,
	// and are only posted when the message queue is empty, i.e. during idle time.
	if (idler.state != on) {
		if (on) {
			idler.idlerID = ::SetTimer(MainHWND(), idleTimerID, 10, NULL)
				? reinterpret_cast<IdlerID>(idleTimerID) : 0;
		} else {
			::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(idler.idlerID));
			idler.idlerID = 0;
		}
		idler.state = idler.idlerID != 0;
	}
	return idler.state;
}

void ScintillaWin::SetMouseCapture(bool on) {
	if (mouseDownCaptures) {
		if (on) {
			::SetCapture(MainHWND());
		} else {
			::ReleaseCapture();
		}
	}
	capturedMouse = on;
}

bool ScintillaWin::HaveMouseCapture() {
	// Cannot just see if GetCapture is this window as the scroll bar also sets capture for the window
	return capturedMouse;
	//return capturedMouse && (::GetCapture() == MainHWND());
}

void ScintillaWin::SetTrackMouseLeaveEvent(bool on) {
	if (on && TrackMouseEventFn && !trackedMouseLeave) {
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = MainHWND();
		TrackMouseEventFn(&tme);
	}
	trackedMouseLeave = on;
}

bool ScintillaWin::PaintContains(PRectangle rc) {
	bool contains = true;
	if ((paintState == painting) && (!rc.Empty())) {
		if (!rcPaint.Contains(rc)) {
			contains = false;
		} else {
			// In bounding rectangle so check more accurately using region
			HRGN hRgnRange = ::CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
			if (hRgnRange) {
				HRGN hRgnDest = ::CreateRectRgn(0, 0, 0, 0);
				if (hRgnDest) {
					int combination = ::CombineRgn(hRgnDest, hRgnRange, hRgnUpdate, RGN_DIFF);
					if (combination != NULLREGION) {
						contains = false;
					}
					::DeleteRgn(hRgnDest);
				}
				::DeleteRgn(hRgnRange);
			}
		}
	}
	return contains;
}

void ScintillaWin::ScrollText(int /* linesToMove */) {
	//Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
	//::ScrollWindow(MainHWND(), 0,
	//	vs.lineHeight * linesToMove, 0, 0);
	//::UpdateWindow(MainHWND());
	Redraw();
}

void ScintillaWin::UpdateSystemCaret() {
	if (hasFocus) {
		if (HasCaretSizeChanged()) {
			DestroySystemCaret();
			CreateSystemCaret();
		}
		Point pos = PointMainCaret();
		::SetCaretPos(pos.x, pos.y);
	}
}

int ScintillaWin::SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) {
	return ::SetScrollInfo(MainHWND(), nBar, lpsi, bRedraw);
}

bool ScintillaWin::GetScrollInfo(int nBar, LPSCROLLINFO lpsi) {
	return ::GetScrollInfo(MainHWND(), nBar, lpsi) ? true : false;
}

// Change the scroll position but avoid repaint if changing to same value
void ScintillaWin::ChangeScrollPos(int barType, int pos) {
	SCROLLINFO sci = {
		sizeof(sci), 0, 0, 0, 0, 0, 0
	};
	sci.fMask = SIF_POS;
	GetScrollInfo(barType, &sci);
	if (sci.nPos != pos) {
		DwellEnd(true);
		sci.nPos = pos;
		SetScrollInfo(barType, &sci, TRUE);
	}
}

void ScintillaWin::SetVerticalScrollPos() {
	ChangeScrollPos(SB_VERT, topLine);
}

void ScintillaWin::SetHorizontalScrollPos() {
	ChangeScrollPos(SB_HORZ, xOffset);
}

bool ScintillaWin::ModifyScrollBars(int nMax, int nPage) {
	bool modified = false;
	SCROLLINFO sci = {
		sizeof(sci), 0, 0, 0, 0, 0, 0
	};
	sci.fMask = SIF_PAGE | SIF_RANGE;
	GetScrollInfo(SB_VERT, &sci);
	int vertEndPreferred = nMax;
	if (!verticalScrollBarVisible)
		nPage = vertEndPreferred + 1;
	if ((sci.nMin != 0) ||
		(sci.nMax != vertEndPreferred) ||
	        (sci.nPage != static_cast<unsigned int>(nPage)) ||
	        (sci.nPos != 0)) {
		sci.fMask = SIF_PAGE | SIF_RANGE;
		sci.nMin = 0;
		sci.nMax = vertEndPreferred;
		sci.nPage = nPage;
		sci.nPos = 0;
		sci.nTrackPos = 1;
		SetScrollInfo(SB_VERT, &sci, TRUE);
		modified = true;
	}

	PRectangle rcText = GetTextRectangle();
	int horizEndPreferred = scrollWidth;
	if (horizEndPreferred < 0)
		horizEndPreferred = 0;
	unsigned int pageWidth = rcText.Width();
	if (!horizontalScrollBarVisible || (wrapState != eWrapNone))
		pageWidth = horizEndPreferred + 1;
	sci.fMask = SIF_PAGE | SIF_RANGE;
	GetScrollInfo(SB_HORZ, &sci);
	if ((sci.nMin != 0) ||
		(sci.nMax != horizEndPreferred) ||
		(sci.nPage != pageWidth) ||
	        (sci.nPos != 0)) {
		sci.fMask = SIF_PAGE | SIF_RANGE;
		sci.nMin = 0;
		sci.nMax = horizEndPreferred;
		sci.nPage = pageWidth;
		sci.nPos = 0;
		sci.nTrackPos = 1;
		SetScrollInfo(SB_HORZ, &sci, TRUE);
		modified = true;
		if (scrollWidth < static_cast<int>(pageWidth)) {
			HorizontalScrollTo(0);
		}
	}
	return modified;
}

void ScintillaWin::NotifyChange() {
	::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
	        MAKELONG(GetCtrlID(), SCEN_CHANGE),
		reinterpret_cast<LPARAM>(MainHWND()));
}

void ScintillaWin::NotifyFocus(bool focus) {
	::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
	        MAKELONG(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
		reinterpret_cast<LPARAM>(MainHWND()));
}

void ScintillaWin::SetCtrlID(int identifier) {
	::SetWindowID(reinterpret_cast<HWND>(wMain.GetID()), identifier);
}

int ScintillaWin::GetCtrlID() {
	return ::GetDlgCtrlID(reinterpret_cast<HWND>(wMain.GetID()));
}

void ScintillaWin::NotifyParent(SCNotification scn) {
	scn.nmhdr.hwndFrom = MainHWND();
	scn.nmhdr.idFrom = GetCtrlID();
	::SendMessage(::GetParent(MainHWND()), WM_NOTIFY,
	              GetCtrlID(), reinterpret_cast<LPARAM>(&scn));
}

void ScintillaWin::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
	//Platform::DebugPrintf("ScintillaWin Double click 0\n");
	ScintillaBase::NotifyDoubleClick(pt, shift, ctrl, alt);
	// Send myself a WM_LBUTTONDBLCLK, so the container can handle it too.
	::SendMessage(MainHWND(),
			  WM_LBUTTONDBLCLK,
			  shift ? MK_SHIFT : 0,
			  MAKELPARAM(pt.x, pt.y));
}

class CaseFolderUTF8 : public CaseFolderTable {
	// Allocate the expandable storage here so that it does not need to be reallocated
	// for each call to Fold.
	std::vector<wchar_t> utf16Mixed;
	std::vector<wchar_t> utf16Folded;
public:
	CaseFolderUTF8() {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
			if (lenMixed > utf16Mixed.size()) {
				utf16Mixed.resize(lenMixed + 8);
			}
			size_t nUtf16Mixed = ::MultiByteToWideChar(65001, 0, mixed,
				static_cast<int>(lenMixed),
				&utf16Mixed[0],
				static_cast<int>(utf16Mixed.size()));

			if (nUtf16Mixed == 0) {
				// Failed to convert -> bad UTF-8
				folded[0] = '\0';
				return 1;
			}

			if (nUtf16Mixed * 4 > utf16Folded.size()) {	// Maximum folding expansion factor of 4
				utf16Folded.resize(nUtf16Mixed * 4 + 8);
			}
			int lenFlat = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
				LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
				&utf16Mixed[0],
				static_cast<int>(nUtf16Mixed),
				&utf16Folded[0],
				static_cast<int>(utf16Folded.size()));

			size_t lenOut = UTF8Length(&utf16Folded[0], lenFlat);
			if (lenOut < sizeFolded) {
				UTF8FromUTF16(&utf16Folded[0], lenFlat, folded, static_cast<int>(lenOut));
				return lenOut;
			} else {
				return 0;
			}
		}
	}
};

class CaseFolderDBCS : public CaseFolderTable {
	// Allocate the expandable storage here so that it does not need to be reallocated
	// for each call to Fold.
	std::vector<wchar_t> utf16Mixed;
	std::vector<wchar_t> utf16Folded;
	UINT cp;
public:
	CaseFolderDBCS(UINT cp_) : cp(cp_) {
		StandardASCII();
	}
	virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
		if ((lenMixed == 1) && (sizeFolded > 0)) {
			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
			return 1;
		} else {
			if (lenMixed > utf16Mixed.size()) {
				utf16Mixed.resize(lenMixed + 8);
			}
			size_t nUtf16Mixed = ::MultiByteToWideChar(cp, 0, mixed,
				static_cast<int>(lenMixed),
				&utf16Mixed[0],
				static_cast<int>(utf16Mixed.size()));

			if (nUtf16Mixed == 0) {
				// Failed to convert -> bad input
				folded[0] = '\0';
				return 1;
			}

			if (nUtf16Mixed * 4 > utf16Folded.size()) {	// Maximum folding expansion factor of 4
				utf16Folded.resize(nUtf16Mixed * 4 + 8);
			}
			int lenFlat = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
				LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
				&utf16Mixed[0],
				static_cast<int>(nUtf16Mixed),
				&utf16Folded[0],
				static_cast<int>(utf16Folded.size()));

			size_t lenOut = ::WideCharToMultiByte(cp, 0,
				&utf16Folded[0], lenFlat,
				NULL, 0, NULL, 0);

			if (lenOut < sizeFolded) {
				::WideCharToMultiByte(cp, 0,
					&utf16Folded[0], lenFlat,
					folded, static_cast<int>(lenOut), NULL, 0);
				return lenOut;
			} else {
				return 0;
			}
		}
	}
};

CaseFolder *ScintillaWin::CaseFolderForEncoding() {
	UINT cpDest = CodePageOfDocument();
	if (cpDest == SC_CP_UTF8) {
		return new CaseFolderUTF8();
	} else {
		if (pdoc->dbcsCodePage == 0) {
			CaseFolderTable *pcf = new CaseFolderTable();
			pcf->StandardASCII();
			// Only for single byte encodings
			UINT cpDoc = CodePageOfDocument();
			for (int i=0x80; i<0x100; i++) {
				char sCharacter[2] = "A";
				sCharacter[0] = static_cast<char>(i);
				wchar_t wCharacter[20];
				unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, sCharacter, 1,
					wCharacter, sizeof(wCharacter)/sizeof(wCharacter[0]));
				if (lengthUTF16 == 1) {
					wchar_t wLower[20];
					int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
						LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
						wCharacter, lengthUTF16, wLower, sizeof(wLower)/sizeof(wLower[0]));
					char sCharacterLowered[20];
					unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
						wLower, charsConverted,
						sCharacterLowered, sizeof(sCharacterLowered), NULL, 0);
					if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
						pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
					}
				}
			}
			return pcf;
		} else {
			return new CaseFolderDBCS(cpDest);
		}
	}
}

std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) {
	if (s.size() == 0)
		return std::string();

	if (caseMapping == cmSame)
		return s;

	UINT cpDoc = CodePageOfDocument();

	unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(),
		static_cast<int>(s.size()), NULL, 0);
	if (lengthUTF16 == 0)	// Failed to convert
		return s;

	DWORD mapFlags = LCMAP_LINGUISTIC_CASING |
		((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE);

	// Many conversions performed by search function are short so optimize this case.
	enum { shortSize=20 };

	if (s.size() > shortSize) {
		// Use dynamic allocations for long strings

		// Change text to UTF-16
		std::vector<wchar_t> vwcText(lengthUTF16);
		::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast<int>(s.size()), &vwcText[0], lengthUTF16);

		// Change case
		int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
			&vwcText[0], lengthUTF16, NULL, 0);
		std::vector<wchar_t> vwcConverted(charsConverted);
		::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
			&vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted);

		// Change back to document encoding
		unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
			&vwcConverted[0], static_cast<int>(vwcConverted.size()),
			NULL, 0, NULL, 0);
		std::vector<char> vcConverted(lengthConverted);
		::WideCharToMultiByte(cpDoc, 0,
			&vwcConverted[0], static_cast<int>(vwcConverted.size()),
			&vcConverted[0], static_cast<int>(vcConverted.size()), NULL, 0);

		return std::string(&vcConverted[0], vcConverted.size());

	} else {
		// Use static allocations for short strings as much faster
		// A factor of 15 for single character strings

		// Change text to UTF-16
		wchar_t vwcText[shortSize];
		::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast<int>(s.size()),
			vwcText, lengthUTF16);

		// Change case
		int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
			vwcText, lengthUTF16, NULL, 0);
		// Full mapping may produce up to 3 characters per input character
		wchar_t vwcConverted[shortSize*3];
		::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, vwcText, lengthUTF16,
			vwcConverted, charsConverted);

		// Change back to document encoding
		unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
			vwcConverted, charsConverted,
			NULL, 0, NULL, 0);
		// Each UTF-16 code unit may need up to 3 bytes in UTF-8
		char vcConverted[shortSize * 3 * 3];
		::WideCharToMultiByte(cpDoc, 0,
			vwcConverted, charsConverted,
			vcConverted, lengthConverted, NULL, 0);

		return std::string(vcConverted, lengthConverted);
	}
}

void ScintillaWin::Copy() {
	//Platform::DebugPrintf("Copy\n");
	if (!sel.Empty()) {
		SelectionText selectedText;
		CopySelectionRange(&selectedText);
		CopyToClipboard(selectedText);
	}
}

void ScintillaWin::CopyAllowLine() {
	SelectionText selectedText;
	CopySelectionRange(&selectedText, true);
	CopyToClipboard(selectedText);
}

bool ScintillaWin::CanPaste() {
	if (!Editor::CanPaste())
		return false;
	if (::IsClipboardFormatAvailable(CF_TEXT))
		return true;
	if (IsUnicodeMode())
		return ::IsClipboardFormatAvailable(CF_UNICODETEXT) != 0;
	return false;
}

class GlobalMemory {
	HGLOBAL hand;
public:
	void *ptr;
	GlobalMemory() : hand(0), ptr(0) {
	}
	GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) {
		if (hand) {
			ptr = ::GlobalLock(hand);
		}
	}
	~GlobalMemory() {
		PLATFORM_ASSERT(!ptr);
	}
	void Allocate(size_t bytes) {
		hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes);
		if (hand) {
			ptr = ::GlobalLock(hand);
		}
	}
	HGLOBAL Unlock() {
		PLATFORM_ASSERT(ptr);
		HGLOBAL handCopy = hand;
		::GlobalUnlock(hand);
		ptr = 0;
		hand = 0;
		return handCopy;
	}
	void SetClip(UINT uFormat) {
		::SetClipboardData(uFormat, Unlock());
	}
	operator bool() const {
		return ptr != 0;
	}
	SIZE_T Size() {
		return ::GlobalSize(hand);
	}
};

void ScintillaWin::InsertPasteText(const char *text, int len, SelectionPosition selStart, bool isRectangular, bool isLine) {
	if (isRectangular) {
		PasteRectangular(selStart, text, len);
	} else {
		char *convertedText = 0;
		if (convertPastes) {
			// Convert line endings of the paste into our local line-endings mode
			convertedText = Document::TransformLineEnds(&len, text, len, pdoc->eolMode);
			text = convertedText;
		}
		if (isLine) {
			int insertPos = pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()));
			pdoc->InsertString(insertPos, text, len);
			// add the newline if necessary
			if ((len > 0) && (text[len-1] != '\n' && text[len-1] != '\r')) {
				const char *endline = StringFromEOLMode(pdoc->eolMode);
				pdoc->InsertString(insertPos + len, endline, static_cast<int>(strlen(endline)));
				len += static_cast<int>(strlen(endline));
			}
			if (sel.MainCaret() == insertPos) {
				SetEmptySelection(sel.MainCaret() + len);
			}
		} else {
			InsertPaste(selStart, text, len);
		}
		delete []convertedText;
	}
}

void ScintillaWin::Paste() {
	if (!::OpenClipboard(MainHWND()))
		return;
	UndoGroup ug(pdoc);
	bool isLine = SelectionEmpty() && (::IsClipboardFormatAvailable(cfLineSelect) != 0);
	ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
	SelectionPosition selStart = sel.IsRectangular() ?
		sel.Rectangular().Start() :
		sel.Range(sel.Main()).Start();
	bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;

	// Always use CF_UNICODETEXT if available
	GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT));
	if (memUSelection) {
		wchar_t *uptr = static_cast<wchar_t *>(memUSelection.ptr);
		if (uptr) {
			unsigned int len;
			char *putf;
			// Default Scintilla behaviour in Unicode mode
			if (IsUnicodeMode()) {
				unsigned int bytes = memUSelection.Size();
				len = UTF8Length(uptr, bytes / 2);
				putf = new char[len + 1];
				UTF8FromUTF16(uptr, bytes / 2, putf, len);
			} else {
				// CF_UNICODETEXT available, but not in Unicode mode
				// Convert from Unicode to current Scintilla code page
				UINT cpDest = CodePageOfDocument();
				len = ::WideCharToMultiByte(cpDest, 0, uptr, -1,
				                            NULL, 0, NULL, NULL) - 1; // subtract 0 terminator
				putf = new char[len + 1];
				::WideCharToMultiByte(cpDest, 0, uptr, -1,
					                      putf, len + 1, NULL, NULL);
			}

			InsertPasteText(putf, len, selStart, isRectangular, isLine);
			delete []putf;
		}
		memUSelection.Unlock();
	} else {
		// CF_UNICODETEXT not available, paste ANSI text
		GlobalMemory memSelection(::GetClipboardData(CF_TEXT));
		if (memSelection) {
			char *ptr = static_cast<char *>(memSelection.ptr);
			if (ptr) {
				unsigned int bytes = memSelection.Size();
				unsigned int len = bytes;
				for (unsigned int i = 0; i < bytes; i++) {
					if ((len == bytes) && (0 == ptr[i]))
						len = i;
				}

				// In Unicode mode, convert clipboard text to UTF-8
				if (IsUnicodeMode()) {
					wchar_t *uptr = new wchar_t[len+1];

					unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0,
					                    ptr, len, uptr, len+1);

					unsigned int mlen = UTF8Length(uptr, ulen);
					char *putf = new char[mlen + 1];
					if (putf) {
						// CP_UTF8 not available on Windows 95, so use UTF8FromUTF16()
						UTF8FromUTF16(uptr, ulen, putf, mlen);
					}

					delete []uptr;

					if (putf) {
						InsertPasteText(putf, mlen, selStart, isRectangular, isLine);
						delete []putf;
					}
				} else {
					InsertPasteText(ptr, len, selStart, isRectangular, isLine);
				}
			}
			memSelection.Unlock();
		}
	}
	::CloseClipboard();
	Redraw();
}

void ScintillaWin::CreateCallTipWindow(PRectangle) {
	if (!ct.wCallTip.Created()) {
		ct.wCallTip = ::CreateWindow(callClassName, TEXT("ACallTip"),
					     WS_POPUP, 100, 100, 150, 20,
					     MainHWND(), 0,
					     GetWindowInstance(MainHWND()),
					     this);
		ct.wDraw = ct.wCallTip;
	}
}

void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) {
	HMENU hmenuPopup = reinterpret_cast<HMENU>(popup.GetID());
	if (!label[0])
		::AppendMenuA(hmenuPopup, MF_SEPARATOR, 0, "");
	else if (enabled)
		::AppendMenuA(hmenuPopup, MF_STRING, cmd, label);
	else
		::AppendMenuA(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
}

void ScintillaWin::ClaimSelection() {
	// Windows does not have a primary selection
}

/// Implement IUnknown

STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("EFE QI");
	*ppv = NULL;
	if (riid == IID_IUnknown)
		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
	if (riid == IID_IEnumFORMATETC)
		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
	if (!*ppv)
		return E_NOINTERFACE;
	FormatEnumerator_AddRef(fe);
	return S_OK;
}
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
	return ++fe->ref;
}
STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
	fe->ref--;
	if (fe->ref > 0)
		return fe->ref;
	delete fe;
	return 0;
}
/// Implement IEnumFORMATETC
STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
	//Platform::DebugPrintf("EFE Next %d %d", fe->pos, celt);
	if (rgelt == NULL) return E_POINTER;
	// We only support one format, so this is simple.
	unsigned int putPos = 0;
	while ((fe->pos < fe->formatsLen) && (putPos < celt)) {
		rgelt->cfFormat = fe->formats[fe->pos];
		rgelt->ptd = 0;
		rgelt->dwAspect = DVASPECT_CONTENT;
		rgelt->lindex = -1;
		rgelt->tymed = TYMED_HGLOBAL;
		fe->pos++;
		putPos++;
	}
	if (pceltFetched)
		*pceltFetched = putPos;
	return putPos ? S_OK : S_FALSE;
}
STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
	fe->pos += celt;
	return S_OK;
}
STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
	fe->pos = 0;
	return S_OK;
}
STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
	FormatEnumerator *pfe;
	try {
		pfe = new FormatEnumerator(fe->pos, fe->formats, fe->formatsLen);
	} catch (...) {
		return E_OUTOFMEMORY;
	}
	return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
	                                       reinterpret_cast<void **>(ppenum));
}

static VFunction *vtFormatEnumerator[] = {
	(VFunction *)(FormatEnumerator_QueryInterface),
	(VFunction *)(FormatEnumerator_AddRef),
	(VFunction *)(FormatEnumerator_Release),
	(VFunction *)(FormatEnumerator_Next),
	(VFunction *)(FormatEnumerator_Skip),
	(VFunction *)(FormatEnumerator_Reset),
	(VFunction *)(FormatEnumerator_Clone)
};

FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_) {
	vtbl = vtFormatEnumerator;
	ref = 0;   // First QI adds first reference...
	pos = pos_;
	formatsLen = formatsLen_;
	for (int i=0; i<formatsLen; i++)
		formats[i] = formats_[i];
}

/// Implement IUnknown
STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
	return ds->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
	return ds->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
	return ds->sci->Release();
}

/// Implement IDropSource
STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
	if (fEsc)
		return DRAGDROP_S_CANCEL;
	if (!(grfKeyState & MK_LBUTTON))
		return DRAGDROP_S_DROP;
	return S_OK;
}

STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
	return DRAGDROP_S_USEDEFAULTCURSORS;
}

static VFunction *vtDropSource[] = {
	(VFunction *)(DropSource_QueryInterface),
	(VFunction *)(DropSource_AddRef),
	(VFunction *)(DropSource_Release),
	(VFunction *)(DropSource_QueryContinueDrag),
	(VFunction *)(DropSource_GiveFeedback)
};

DropSource::DropSource() {
	vtbl = vtDropSource;
	sci = 0;
}

/// Implement IUnkown
STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("DO QI %x\n", pd);
	return pd->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
	return pd->sci->AddRef();
}
STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
	return pd->sci->Release();
}
/// Implement IDataObject
STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
	return pd->sci->GetData(pFEIn, pSTM);
}

STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
	//Platform::DebugPrintf("DOB GetDataHere\n");
	return E_NOTIMPL;
}

STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
	if (pd->sci->DragIsRectangularOK(pFE->cfFormat) &&
	    pFE->ptd == 0 &&
	    (pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
	    pFE->lindex == -1 &&
	    (pFE->tymed & TYMED_HGLOBAL) != 0
	) {
		return S_OK;
	}

	bool formatOK = (pFE->cfFormat == CF_TEXT) ||
		((pFE->cfFormat == CF_UNICODETEXT) && pd->sci->IsUnicodeMode());
	if (!formatOK ||
	    pFE->ptd != 0 ||
	    (pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
	    pFE->lindex != -1 ||
	    (pFE->tymed & TYMED_HGLOBAL) == 0
	) {
		//Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
		//return DATA_E_FORMATETC;
		return S_FALSE;
	}
	//Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
	return S_OK;
}

STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *pd, FORMATETC *, FORMATETC *pFEOut) {
	//Platform::DebugPrintf("DOB GetCanon\n");
	if (pd->sci->IsUnicodeMode())
		pFEOut->cfFormat = CF_UNICODETEXT;
	else
		pFEOut->cfFormat = CF_TEXT;
	pFEOut->ptd = 0;
	pFEOut->dwAspect = DVASPECT_CONTENT;
	pFEOut->lindex = -1;
	pFEOut->tymed = TYMED_HGLOBAL;
	return S_OK;
}

STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
	//Platform::DebugPrintf("DOB SetData\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
	try {
		//Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
		if (dwDirection != DATADIR_GET) {
			*ppEnum = 0;
			return E_FAIL;
		}
		FormatEnumerator *pfe;
		if (pd->sci->IsUnicodeMode()) {
			CLIPFORMAT formats[] = {CF_UNICODETEXT, CF_TEXT};
			pfe = new FormatEnumerator(0, formats, 2);
		} else {
			CLIPFORMAT formats[] = {CF_TEXT};
			pfe = new FormatEnumerator(0, formats, 1);
		}
		return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
											   reinterpret_cast<void **>(ppEnum));
	} catch (std::bad_alloc &) {
		pd->sci->errorStatus = SC_STATUS_BADALLOC;
		return E_OUTOFMEMORY;
	} catch (...) {
		pd->sci->errorStatus = SC_STATUS_FAILURE;
		return E_FAIL;
	}
}

STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
	//Platform::DebugPrintf("DOB DAdvise\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
	//Platform::DebugPrintf("DOB DUnadvise\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
	//Platform::DebugPrintf("DOB EnumDAdvise\n");
	return E_FAIL;
}

static VFunction *vtDataObject[] = {
	(VFunction *)(DataObject_QueryInterface),
	(VFunction *)(DataObject_AddRef),
	(VFunction *)(DataObject_Release),
	(VFunction *)(DataObject_GetData),
	(VFunction *)(DataObject_GetDataHere),
	(VFunction *)(DataObject_QueryGetData),
	(VFunction *)(DataObject_GetCanonicalFormatEtc),
	(VFunction *)(DataObject_SetData),
	(VFunction *)(DataObject_EnumFormatEtc),
	(VFunction *)(DataObject_DAdvise),
	(VFunction *)(DataObject_DUnadvise),
	(VFunction *)(DataObject_EnumDAdvise)
};

DataObject::DataObject() {
	vtbl = vtDataObject;
	sci = 0;
}

/// Implement IUnknown
STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("DT QI %x\n", dt);
	return dt->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
	return dt->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
	return dt->sci->Release();
}

/// Implement IDropTarget by forwarding to Scintilla
STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                                  POINTL pt, PDWORD pdwEffect) {
	try {
		return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
	} catch (...) {
		dt->sci->errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}
STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
	try {
		return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
	} catch (...) {
		dt->sci->errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}
STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
	try {
		return dt->sci->DragLeave();
	} catch (...) {
		dt->sci->errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}
STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                             POINTL pt, PDWORD pdwEffect) {
	try {
		return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
	} catch (...) {
		dt->sci->errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}

static VFunction *vtDropTarget[] = {
	(VFunction *)(DropTarget_QueryInterface),
	(VFunction *)(DropTarget_AddRef),
	(VFunction *)(DropTarget_Release),
	(VFunction *)(DropTarget_DragEnter),
	(VFunction *)(DropTarget_DragOver),
	(VFunction *)(DropTarget_DragLeave),
	(VFunction *)(DropTarget_Drop)
};

DropTarget::DropTarget() {
	vtbl = vtDropTarget;
	sci = 0;
}

/**
 * DBCS: support Input Method Editor (IME).
 * Called when IME Window opened.
 */
void ScintillaWin::ImeStartComposition() {
#ifndef __DMC__
	// Digital Mars compiler does not include Imm library
	if (caret.active) {
		// Move IME Window to current caret position
		HIMC hIMC = ::ImmGetContext(MainHWND());
		Point pos = PointMainCaret();
		COMPOSITIONFORM CompForm;
		CompForm.dwStyle = CFS_POINT;
		CompForm.ptCurrentPos.x = pos.x;
		CompForm.ptCurrentPos.y = pos.y;

		::ImmSetCompositionWindow(hIMC, &CompForm);

		// Set font of IME window to same as surrounded text.
		if (stylesValid) {
			// Since the style creation code has been made platform independent,
			// The logfont for the IME is recreated here.
			int styleHere = (pdoc->StyleAt(sel.MainCaret())) & 31;
			LOGFONTA lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""};
			int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER;
			if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER)	// Hangs if sizeZoomed <= 1
				sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
			AutoSurface surface(this);
			int deviceHeight = sizeZoomed;
			if (surface) {
				deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72;
			}
			// The negative is to allow for leading
			lf.lfHeight = -(abs(deviceHeight / SC_FONT_SIZE_MULTIPLIER));
			lf.lfWeight = vs.styles[styleHere].weight;
			lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
			lf.lfCharSet = DEFAULT_CHARSET;
			lf.lfFaceName[0] = '\0';
			if (vs.styles[styleHere].fontName)
				strcpy(lf.lfFaceName, vs.styles[styleHere].fontName);

			::ImmSetCompositionFontA(hIMC, &lf);
		}
		::ImmReleaseContext(MainHWND(), hIMC);
		// Caret is displayed in IME window. So, caret in Scintilla is useless.
		DropCaret();
	}
#endif
}

/** Called when IME Window closed. */
void ScintillaWin::ImeEndComposition() {
	ShowCaretAtCurrentPosition();
}

void ScintillaWin::AddCharBytes(char b0, char b1) {

	int inputCodePage = InputCodePage();
	if (inputCodePage && IsUnicodeMode()) {
		char utfval[4] = "\0\0\0";
		char ansiChars[3];
		wchar_t wcs[2];
		if (b0) {	// Two bytes from IME
			ansiChars[0] = b0;
			ansiChars[1] = b1;
			ansiChars[2] = '\0';
			::MultiByteToWideChar(inputCodePage, 0, ansiChars, 2, wcs, 1);
		} else {
			ansiChars[0] = b1;
			ansiChars[1] = '\0';
			::MultiByteToWideChar(inputCodePage, 0, ansiChars, 1, wcs, 1);
		}
		unsigned int len = UTF8Length(wcs, 1);
		UTF8FromUTF16(wcs, 1, utfval, len);
		utfval[len] = '\0';
		AddCharUTF(utfval, len ? len : 1);
	} else if (b0) {
		char dbcsChars[3];
		dbcsChars[0] = b0;
		dbcsChars[1] = b1;
		dbcsChars[2] = '\0';
		AddCharUTF(dbcsChars, 2, true);
	} else {
		AddChar(b1);
	}
}

void ScintillaWin::GetIntelliMouseParameters() {
	// This retrieves the number of lines per scroll as configured inthe Mouse Properties sheet in Control Panel
	::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
}

void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
	if (!::OpenClipboard(MainHWND()))
		return;
	::EmptyClipboard();

	GlobalMemory uniText;

	// Default Scintilla behaviour in Unicode mode
	if (IsUnicodeMode()) {
		int uchars = UTF16Length(selectedText.s, selectedText.len);
		uniText.Allocate(2 * uchars);
		if (uniText) {
			UTF16FromUTF8(selectedText.s, selectedText.len, static_cast<wchar_t *>(uniText.ptr), uchars);
		}
	} else {
		// Not Unicode mode
		// Convert to Unicode using the current Scintilla code page
		UINT cpSrc = CodePageFromCharSet(
					selectedText.characterSet, selectedText.codePage);
		int uLen = ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len, 0, 0);
		uniText.Allocate(2 * uLen);
		if (uniText) {
			::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len,
				static_cast<wchar_t *>(uniText.ptr), uLen);
		}
	}

	if (uniText) {
		if (!IsNT()) {
			// Copy ANSI text to clipboard on Windows 9x
			// Convert from Unicode text, so other ANSI programs can
			// paste the text
			// Windows NT, 2k, XP automatically generates CF_TEXT
			GlobalMemory ansiText;
			ansiText.Allocate(selectedText.len);
			if (ansiText) {
				::WideCharToMultiByte(CP_ACP, 0, static_cast<wchar_t *>(uniText.ptr), -1,
					static_cast<char *>(ansiText.ptr), selectedText.len, NULL, NULL);
				ansiText.SetClip(CF_TEXT);
			}
		}
		uniText.SetClip(CF_UNICODETEXT);
	} else {
		// There was a failure - try to copy at least ANSI text
		GlobalMemory ansiText;
		ansiText.Allocate(selectedText.len);
		if (ansiText) {
			memcpy(static_cast<char *>(ansiText.ptr), selectedText.s, selectedText.len);
			ansiText.SetClip(CF_TEXT);
		}
	}

	if (selectedText.rectangular) {
		::SetClipboardData(cfColumnSelect, 0);
	}

	if (selectedText.lineCopy) {
		::SetClipboardData(cfLineSelect, 0);
	}

	::CloseClipboard();
}

void ScintillaWin::ScrollMessage(WPARAM wParam) {
	//DWORD dwStart = timeGetTime();
	//Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);

	SCROLLINFO sci;
	memset(&sci, 0, sizeof(sci));
	sci.cbSize = sizeof(sci);
	sci.fMask = SIF_ALL;

	GetScrollInfo(SB_VERT, &sci);

	//Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
	//sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);

	int topLineNew = topLine;
	switch (LoWord(wParam)) {
	case SB_LINEUP:
		topLineNew -= 1;
		break;
	case SB_LINEDOWN:
		topLineNew += 1;
		break;
	case SB_PAGEUP:
		topLineNew -= LinesToScroll(); break;
	case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
	case SB_TOP: topLineNew = 0; break;
	case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
	case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
	case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
	}
	ScrollTo(topLineNew);
}

void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
	int xPos = xOffset;
	PRectangle rcText = GetTextRectangle();
	int pageWidth = rcText.Width() * 2 / 3;
	switch (LoWord(wParam)) {
	case SB_LINEUP:
		xPos -= 20;
		break;
	case SB_LINEDOWN:	// May move past the logical end
		xPos += 20;
		break;
	case SB_PAGEUP:
		xPos -= pageWidth;
		break;
	case SB_PAGEDOWN:
		xPos += pageWidth;
		if (xPos > scrollWidth - rcText.Width()) {	// Hit the end exactly
			xPos = scrollWidth - rcText.Width();
		}
		break;
	case SB_TOP:
		xPos = 0;
		break;
	case SB_BOTTOM:
		xPos = scrollWidth;
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK: {
			// Do NOT use wParam, its 16 bit and not enough for very long lines. Its still possible to overflow the 32 bit but you have to try harder =]
			SCROLLINFO si;
			si.cbSize = sizeof(si);
			si.fMask = SIF_TRACKPOS;
			if (GetScrollInfo(SB_HORZ, &si)) {
				xPos = si.nTrackPos;
			}
		}
		break;
	}
	HorizontalScrollTo(xPos);
}

/**
 * Redraw all of text area.
 * This paint will not be abandoned.
 */
void ScintillaWin::FullPaint() {
	if (technology == SC_TECHNOLOGY_DEFAULT) {
		HDC hdc = ::GetDC(MainHWND());
		FullPaintDC(hdc);
		::ReleaseDC(MainHWND(), hdc);
	} else {
		FullPaintDC(0);
	}
}

/**
 * Redraw all of text area on the specified DC.
 * This paint will not be abandoned.
 */
void ScintillaWin::FullPaintDC(HDC hdc) {
	paintState = painting;
	rcPaint = GetClientRectangle();
	paintingAllText = true;
	if (technology == SC_TECHNOLOGY_DEFAULT) {
		AutoSurface surfaceWindow(hdc, this);
		if (surfaceWindow) {
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
		}
	} else {
#if defined(USE_D2D)
		EnsureRenderTarget();
		AutoSurface surfaceWindow(pRenderTarget, this);
		if (surfaceWindow) {
			pRenderTarget->BeginDraw();
			Paint(surfaceWindow, rcPaint);
			surfaceWindow->Release();
			HRESULT hr = pRenderTarget->EndDraw();
			if (hr == D2DERR_RECREATE_TARGET) {
				DropRenderTarget();
			}
		}
#endif
	}
	paintState = notPainting;
}

static bool CompareDevCap(HDC hdc, HDC hOtherDC, int nIndex) {
	return ::GetDeviceCaps(hdc, nIndex) == ::GetDeviceCaps(hOtherDC, nIndex);
}

bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) {
	HDC hdc = ::GetDC(MainHWND());
	bool isCompatible =
		CompareDevCap(hdc, hOtherDC, TECHNOLOGY) &&
		CompareDevCap(hdc, hOtherDC, LOGPIXELSY) &&
		CompareDevCap(hdc, hOtherDC, LOGPIXELSX) &&
		CompareDevCap(hdc, hOtherDC, BITSPIXEL) &&
		CompareDevCap(hdc, hOtherDC, PLANES);
	::ReleaseDC(MainHWND(), hdc);
	return isCompatible;
}

DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) {
	// These are the Wordpad semantics.
	DWORD dwEffect;
	if (inDragDrop == ddDragging)	// Internal defaults to move
		dwEffect = DROPEFFECT_MOVE;
	else
		dwEffect = DROPEFFECT_COPY;
	if (grfKeyState & MK_ALT)
		dwEffect = DROPEFFECT_MOVE;
	if (grfKeyState & MK_CONTROL)
		dwEffect = DROPEFFECT_COPY;
	return dwEffect;
}

/// Implement IUnknown
STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
	*ppv = NULL;
	if (riid == IID_IUnknown)
		*ppv = reinterpret_cast<IDropTarget *>(&dt);
	if (riid == IID_IDropSource)
		*ppv = reinterpret_cast<IDropSource *>(&ds);
	if (riid == IID_IDropTarget)
		*ppv = reinterpret_cast<IDropTarget *>(&dt);
	if (riid == IID_IDataObject)
		*ppv = reinterpret_cast<IDataObject *>(&dob);
	if (!*ppv)
		return E_NOINTERFACE;
	return S_OK;
}

STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
	return 1;
}

STDMETHODIMP_(ULONG) ScintillaWin::Release() {
	return 1;
}

/// Implement IDropTarget
STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                                     POINTL, PDWORD pdwEffect) {
	if (pIDataSource == NULL)
		return E_POINTER;
	FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
	hasOKText = (hrHasUText == S_OK);
	if (!hasOKText) {
		FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
		HRESULT hrHasText = pIDataSource->QueryGetData(&fmte);
		hasOKText = (hrHasText == S_OK);
	}
	if (!hasOKText) {
		*pdwEffect = DROPEFFECT_NONE;
		return S_OK;
	}

	*pdwEffect = EffectFromState(grfKeyState);
	return S_OK;
}

STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
	try {
		if (!hasOKText || pdoc->IsReadOnly()) {
			*pdwEffect = DROPEFFECT_NONE;
			return S_OK;
		}

		*pdwEffect = EffectFromState(grfKeyState);

		// Update the cursor.
		POINT rpt = {pt.x, pt.y};
		::ScreenToClient(MainHWND(), &rpt);
		SetDragPosition(SPositionFromLocation(Point(rpt.x, rpt.y), false, false, UserVirtualSpace()));

		return S_OK;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}

STDMETHODIMP ScintillaWin::DragLeave() {
	try {
		SetDragPosition(SelectionPosition(invalidPosition));
		return S_OK;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}

STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                                POINTL pt, PDWORD pdwEffect) {
	try {
		*pdwEffect = EffectFromState(grfKeyState);

		if (pIDataSource == NULL)
			return E_POINTER;

		SetDragPosition(SelectionPosition(invalidPosition));

		STGMEDIUM medium = {0, {0}, 0};

		char *data = 0;
		bool dataAllocated = false;

		FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
		HRESULT hr = pIDataSource->GetData(&fmtu, &medium);
		if (SUCCEEDED(hr) && medium.hGlobal) {
			wchar_t *udata = static_cast<wchar_t *>(::GlobalLock(medium.hGlobal));
			if (udata) {
				if (IsUnicodeMode()) {
					int tlen = ::GlobalSize(medium.hGlobal);
					// Convert UTF-16 to UTF-8
					int dataLen = UTF8Length(udata, tlen/2);
					data = new char[dataLen+1];
					UTF8FromUTF16(udata, tlen/2, data, dataLen);
					dataAllocated = true;
				} else {
					// Convert UTF-16 to ANSI
					//
					// Default Scintilla behavior in Unicode mode
					// CF_UNICODETEXT available, but not in Unicode mode
					// Convert from Unicode to current Scintilla code page
					UINT cpDest = CodePageOfDocument();
					int tlen = ::WideCharToMultiByte(cpDest, 0, udata, -1,
						NULL, 0, NULL, NULL) - 1; // subtract 0 terminator
					data = new char[tlen + 1];
					memset(data, 0, (tlen+1));
					::WideCharToMultiByte(cpDest, 0, udata, -1,
							data, tlen + 1, NULL, NULL);
					dataAllocated = true;
				}
			}
		}

		if (!data) {
			FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
			hr = pIDataSource->GetData(&fmte, &medium);
			if (SUCCEEDED(hr) && medium.hGlobal) {
				data = static_cast<char *>(::GlobalLock(medium.hGlobal));
			}
		}

		if (data && convertPastes) {
			// Convert line endings of the drop into our local line-endings mode
			int len = static_cast<int>(strlen(data));
			char *convertedText = Document::TransformLineEnds(&len, data, len, pdoc->eolMode);
			if (dataAllocated)
				delete []data;
			data = convertedText;
			dataAllocated = true;
		}

		if (!data) {
			//Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
			return hr;
		}

		FORMATETC fmtr = {cfColumnSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
		HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);

		POINT rpt = {pt.x, pt.y};
		::ScreenToClient(MainHWND(), &rpt);
		SelectionPosition movePos = SPositionFromLocation(Point(rpt.x, rpt.y), false, false, UserVirtualSpace());

		DropAt(movePos, data, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);

		::GlobalUnlock(medium.hGlobal);

		// Free data
		if (medium.pUnkForRelease != NULL)
			medium.pUnkForRelease->Release();
		else
			::GlobalFree(medium.hGlobal);

		if (dataAllocated)
			delete []data;

		return S_OK;
	} catch (...) {
		errorStatus = SC_STATUS_FAILURE;
	}
	return E_FAIL;
}

/// Implement important part of IDataObject
STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
	bool formatOK = (pFEIn->cfFormat == CF_TEXT) ||
		((pFEIn->cfFormat == CF_UNICODETEXT) && IsUnicodeMode());
	if (!formatOK ||
	    pFEIn->ptd != 0 ||
	    (pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
	    pFEIn->lindex != -1 ||
	    (pFEIn->tymed & TYMED_HGLOBAL) == 0
	) {
		//Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
		return DATA_E_FORMATETC;
	}
	pSTM->tymed = TYMED_HGLOBAL;
	//Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);

	GlobalMemory text;
	if (pFEIn->cfFormat == CF_UNICODETEXT) {
		int uchars = UTF16Length(drag.s, drag.len);
		text.Allocate(2 * uchars);
		if (text) {
			UTF16FromUTF8(drag.s, drag.len, static_cast<wchar_t *>(text.ptr), uchars);
		}
	} else {
		text.Allocate(drag.len);
		if (text) {
			memcpy(static_cast<char *>(text.ptr), drag.s, drag.len);
		}
	}
	pSTM->hGlobal = text ? text.Unlock() : 0;
	pSTM->pUnkForRelease = 0;
	return S_OK;
}

bool ScintillaWin::Register(HINSTANCE hInstance_) {

	hInstance = hInstance_;
	bool result;

	// Register the Scintilla class
	if (IsNT()) {

		// Register Scintilla as a wide character window
		WNDCLASSEXW wndclass;
		wndclass.cbSize = sizeof(wndclass);
		wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
		wndclass.lpfnWndProc = ScintillaWin::SWndProc;
		wndclass.cbClsExtra = 0;
		wndclass.cbWndExtra = sizeof(ScintillaWin *);
		wndclass.hInstance = hInstance;
		wndclass.hIcon = NULL;
		wndclass.hCursor = NULL;
		wndclass.hbrBackground = NULL;
		wndclass.lpszMenuName = NULL;
		wndclass.lpszClassName = L"Scintilla";
		wndclass.hIconSm = 0;
		result = ::RegisterClassExW(&wndclass) != 0;
	} else {

		// Register Scintilla as a normal character window
		WNDCLASSEX wndclass;
		wndclass.cbSize = sizeof(wndclass);
		wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
		wndclass.lpfnWndProc = ScintillaWin::SWndProc;
		wndclass.cbClsExtra = 0;
		wndclass.cbWndExtra = sizeof(ScintillaWin *);
		wndclass.hInstance = hInstance;
		wndclass.hIcon = NULL;
		wndclass.hCursor = NULL;
		wndclass.hbrBackground = NULL;
		wndclass.lpszMenuName = NULL;
		wndclass.lpszClassName = scintillaClassName;
		wndclass.hIconSm = 0;
		result = ::RegisterClassEx(&wndclass) != 0;
	}

	if (result) {
		// Register the CallTip class
		WNDCLASSEX wndclassc;
		wndclassc.cbSize = sizeof(wndclassc);
		wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
		wndclassc.cbClsExtra = 0;
		wndclassc.cbWndExtra = sizeof(ScintillaWin *);
		wndclassc.hInstance = hInstance;
		wndclassc.hIcon = NULL;
		wndclassc.hbrBackground = NULL;
		wndclassc.lpszMenuName = NULL;
		wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
		wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
		wndclassc.lpszClassName = callClassName;
		wndclassc.hIconSm = 0;

		result = ::RegisterClassEx(&wndclassc) != 0;
	}

	return result;
}

bool ScintillaWin::Unregister() {
	bool result = ::UnregisterClass(scintillaClassName, hInstance) != 0;
	if (::UnregisterClass(callClassName, hInstance) == 0)
		result = false;
	return result;
}

bool ScintillaWin::HasCaretSizeChanged() {
	if (
		( (0 != vs.caretWidth) && (sysCaretWidth != vs.caretWidth) )
		|| ((0 != vs.lineHeight) && (sysCaretHeight != vs.lineHeight))
		) {
		return true;
	}
	return false;
}

BOOL ScintillaWin::CreateSystemCaret() {
	sysCaretWidth = vs.caretWidth;
	if (0 == sysCaretWidth) {
		sysCaretWidth = 1;
	}
	sysCaretHeight = vs.lineHeight;
	int bitmapSize = (((sysCaretWidth + 15) & ~15) >> 3) *
		sysCaretHeight;
	char *bits = new char[bitmapSize];
	memset(bits, 0, bitmapSize);
	sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1,
		1, reinterpret_cast<BYTE *>(bits));
	delete []bits;
	BOOL retval = ::CreateCaret(
		MainHWND(), sysCaretBitmap,
		sysCaretWidth, sysCaretHeight);
	::ShowCaret(MainHWND());
	return retval;
}

BOOL ScintillaWin::DestroySystemCaret() {
	::HideCaret(MainHWND());
	BOOL retval = ::DestroyCaret();
	if (sysCaretBitmap) {
		::DeleteObject(sysCaretBitmap);
		sysCaretBitmap = 0;
	}
	return retval;
}

sptr_t PASCAL ScintillaWin::CTWndProc(
    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
	// Find C++ object associated with window.
	ScintillaWin *sciThis = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
	try {
		// ctp will be zero if WM_CREATE not seen yet
		if (sciThis == 0) {
			if (iMessage == WM_CREATE) {
				// Associate CallTip object with window
				CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
				SetWindowPointer(hWnd, pCreate->lpCreateParams);
				return 0;
			} else {
				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
			}
		} else {
			if (iMessage == WM_NCDESTROY) {
				::SetWindowLong(hWnd, 0, 0);
				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
			} else if (iMessage == WM_PAINT) {
				PAINTSTRUCT ps;
				::BeginPaint(hWnd, &ps);
				Surface *surfaceWindow = Surface::Allocate(sciThis->technology);
				if (surfaceWindow) {
#if defined(USE_D2D)
					ID2D1HwndRenderTarget *pCTRenderTarget = 0;
#endif
					RECT rc;
					GetClientRect(hWnd, &rc);
					// Create a Direct2D render target.
					if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) {
						surfaceWindow->Init(ps.hdc, hWnd);
					} else {
#if defined(USE_D2D)
						pD2DFactory->CreateHwndRenderTarget(
							D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(), 96.0, 96.0),
							D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)),
							&pCTRenderTarget);
						surfaceWindow->Init(pCTRenderTarget, hWnd);
						pCTRenderTarget->BeginDraw();
#endif
					}
					surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage);
					surfaceWindow->SetDBCSMode(sciThis->ct.codePage);
					sciThis->ct.PaintCT(surfaceWindow);
#if defined(USE_D2D)
					if (pCTRenderTarget)
						pCTRenderTarget->EndDraw();
#endif
					surfaceWindow->Release();
					delete surfaceWindow;
#if defined(USE_D2D)
					if (pCTRenderTarget)
						pCTRenderTarget->Release();
#endif
				}
				::EndPaint(hWnd, &ps);
				return 0;
			} else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) {
				POINT pt;
				pt.x = static_cast<short>(LOWORD(lParam));
				pt.y = static_cast<short>(HIWORD(lParam));
				ScreenToClient(hWnd, &pt);
				sciThis->ct.MouseClick(Point(pt.x, pt.y));
				sciThis->CallTipClick();
				return 0;
			} else if (iMessage == WM_LBUTTONDOWN) {
				// This does not fire due to the hit test code
				sciThis->ct.MouseClick(Point::FromLong(lParam));
				sciThis->CallTipClick();
				return 0;
			} else if (iMessage == WM_SETCURSOR) {
				::SetCursor(::LoadCursor(NULL, IDC_ARROW));
				return 0;
			} else if (iMessage == WM_NCHITTEST) {
				return HTCAPTION;
			} else {
				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
			}
		}
	} catch (...) {
		sciThis->errorStatus = SC_STATUS_FAILURE;
	}
	return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}

sptr_t ScintillaWin::DirectFunction(
    ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
	PLATFORM_ASSERT(::GetCurrentThreadId() == ::GetWindowThreadProcessId(sci->MainHWND(), NULL));
	return sci->WndProc(iMessage, wParam, lParam);
}

extern "C"
#ifndef STATIC_BUILD
__declspec(dllexport)
#endif
sptr_t __stdcall Scintilla_DirectFunction(
    ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
	return sci->WndProc(iMessage, wParam, lParam);
}

sptr_t PASCAL ScintillaWin::SWndProc(
    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam) {
	//Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);

	// Find C++ object associated with window.
	ScintillaWin *sci = reinterpret_cast<ScintillaWin *>(PointerFromWindow(hWnd));
	// sci will be zero if WM_CREATE not seen yet
	if (sci == 0) {
		try {
			if (iMessage == WM_CREATE) {
				// Create C++ object associated with window
				sci = new ScintillaWin(hWnd);
				SetWindowPointer(hWnd, sci);
				return sci->WndProc(iMessage, wParam, lParam);
			}
		} catch (...) {
		}
		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
	} else {
		if (iMessage == WM_NCDESTROY) {
			try {
				sci->Finalise();
				delete sci;
			} catch (...) {
			}
			::SetWindowLong(hWnd, 0, 0);
			return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
		} else {
			return sci->WndProc(iMessage, wParam, lParam);
		}
	}
}

// This function is externally visible so it can be called from container when building statically.
// Must be called once only.
int Scintilla_RegisterClasses(void *hInstance) {
	Platform_Initialise(hInstance);
	bool result = ScintillaWin::Register(reinterpret_cast<HINSTANCE>(hInstance));
#ifdef SCI_LEXER
	Scintilla_LinkLexers();
#endif
	return result;
}

// This function is externally visible so it can be called from container when building statically.
int Scintilla_ReleaseResources() {
	bool result = ScintillaWin::Unregister();
	Platform_Finalise();
	return result;
}

#ifndef STATIC_BUILD
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) {
	//Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason);
	if (dwReason == DLL_PROCESS_ATTACH) {
		if (!Scintilla_RegisterClasses(hInstance))
			return FALSE;
	} else if (dwReason == DLL_PROCESS_DETACH) {
		Scintilla_ReleaseResources();
	}
	return TRUE;
}
#endif

Added win32/deps.mak.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
PlatWin.o: PlatWin.cxx ../include/Platform.h \
 ../src/UniConversion.h ../src/XPM.h ../src/FontQuality.h
ScintillaWin.o: ScintillaWin.cxx ../include/Platform.h \
 ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
 ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
 ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
 ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
 ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
 ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
 ../src/Editor.h ../src/ScintillaBase.h ../src/UniConversion.h
AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
 ../lexlib/CharacterSet.h ../src/AutoComplete.h
CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/CallTip.h
Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h ../src/Catalogue.h
CellBuffer.o: ../src/CellBuffer.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/CellBuffer.h
CharClassify.o: ../src/CharClassify.cxx ../src/CharClassify.h
ContractionState.o: ../src/ContractionState.cxx ../include/Platform.h \
 ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
 ../src/ContractionState.h
Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/Decoration.h
Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
 ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \
 ../src/Document.h ../src/RESearch.h ../src/UniConversion.h
Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
 ../src/Decoration.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
 ../src/Editor.h
ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
 ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/WordList.h \
 ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h
Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/Indicator.h
KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
 ../src/KeyMap.h
LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
PerLine.o: ../src/PerLine.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/CellBuffer.h ../src/PerLine.h
PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
 ../src/Decoration.h ../include/ILexer.h ../src/Document.h \
 ../src/Selection.h ../src/PositionCache.h
RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
RunStyles.o: ../src/RunStyles.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h
ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
 ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \
 ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
 ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
 ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \
 ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
 ../src/Selection.h ../src/PositionCache.h ../src/Editor.h \
 ../src/ScintillaBase.h
Selection.o: ../src/Selection.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/Selection.h
Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
 ../src/Style.h
UniConversion.o: ../src/UniConversion.cxx ../src/UniConversion.h
ViewStyle.o: ../src/ViewStyle.cxx ../include/Platform.h \
 ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
 ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
 ../src/Style.h ../src/ViewStyle.h
XPM.o: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
Accessor.o: ../lexlib/Accessor.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h
CharacterSet.o: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h
LexerBase.o: ../lexlib/LexerBase.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/LexerModule.h ../lexlib/LexerBase.h
LexerModule.o: ../lexlib/LexerModule.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h
LexerSimple.o: ../lexlib/LexerSimple.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h
PropSetSimple.o: ../lexlib/PropSetSimple.cxx ../lexlib/PropSetSimple.h
StyleContext.o: ../lexlib/StyleContext.cxx ../include/ILexer.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h
WordList.o: ../lexlib/WordList.cxx ../lexlib/WordList.h
LexAbaqus.o: ../lexers/LexAbaqus.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexAda.o: ../lexers/LexAda.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexAPDL.o: ../lexers/LexAPDL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexAsm.o: ../lexers/LexAsm.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexAsn1.o: ../lexers/LexAsn1.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexASY.o: ../lexers/LexASY.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexAU3.o: ../lexers/LexAU3.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexAVE.o: ../lexers/LexAVE.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexBaan.o: ../lexers/LexBaan.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexBash.o: ../lexers/LexBash.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexBasic.o: ../lexers/LexBasic.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexBullant.o: ../lexers/LexBullant.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCaml.o: ../lexers/LexCaml.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCLW.o: ../lexers/LexCLW.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexCmake.o: ../lexers/LexCmake.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCOBOL.o: ../lexers/LexCOBOL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexConf.o: ../lexers/LexConf.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCPP.o: ../lexers/LexCPP.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexCrontab.o: ../lexers/LexCrontab.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCsound.o: ../lexers/LexCsound.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexCSS.o: ../lexers/LexCSS.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexD.o: ../lexers/LexD.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexEiffel.o: ../lexers/LexEiffel.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexErlang.o: ../lexers/LexErlang.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexEScript.o: ../lexers/LexEScript.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexFlagship.o: ../lexers/LexFlagship.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexForth.o: ../lexers/LexForth.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexFortran.o: ../lexers/LexFortran.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexGAP.o: ../lexers/LexGAP.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexGui4Cli.o: ../lexers/LexGui4Cli.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexHaskell.o: ../lexers/LexHaskell.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexHTML.o: ../lexers/LexHTML.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexInno.o: ../lexers/LexInno.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexKix.o: ../lexers/LexKix.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexLisp.o: ../lexers/LexLisp.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexLout.o: ../lexers/LexLout.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexLua.o: ../lexers/LexLua.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexMagik.o: ../lexers/LexMagik.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMarkdown.o: ../lexers/LexMarkdown.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMatlab.o: ../lexers/LexMatlab.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMetapost.o: ../lexers/LexMetapost.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMMIXAL.o: ../lexers/LexMMIXAL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMPT.o: ../lexers/LexMPT.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexMSSQL.o: ../lexers/LexMSSQL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexMySQL.o: ../lexers/LexMySQL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexNimrod.o: ../lexers/LexNimrod.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexNsis.o: ../lexers/LexNsis.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexOpal.o: ../lexers/LexOpal.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexOthers.o: ../lexers/LexOthers.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexPascal.o: ../lexers/LexPascal.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexPB.o: ../lexers/LexPB.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexPerl.o: ../lexers/LexPerl.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexPLM.o: ../lexers/LexPLM.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexPOV.o: ../lexers/LexPOV.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexPowerPro.o: ../lexers/LexPowerPro.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexPowerShell.o: ../lexers/LexPowerShell.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexProgress.o: ../lexers/LexProgress.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexPS.o: ../lexers/LexPS.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexPython.o: ../lexers/LexPython.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h ../lexlib/LexerBase.h
LexR.o: ../lexers/LexR.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexRebol.o: ../lexers/LexRebol.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexRuby.o: ../lexers/LexRuby.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexScriptol.o: ../lexers/LexScriptol.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexSmalltalk.o: ../lexers/LexSmalltalk.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexSML.o: ../lexers/LexSML.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexSorcus.o: ../lexers/LexSorcus.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexSpecman.o: ../lexers/LexSpecman.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexSpice.o: ../lexers/LexSpice.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexSQL.o: ../lexers/LexSQL.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexTACL.o: ../lexers/LexTACL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexTADS3.o: ../lexers/LexTADS3.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexTAL.o: ../lexers/LexTAL.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexTCL.o: ../lexers/LexTCL.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexTeX.o: ../lexers/LexTeX.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexVB.o: ../lexers/LexVB.cxx ../include/ILexer.h ../include/Scintilla.h \
 ../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
 ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
 ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexVerilog.o: ../lexers/LexVerilog.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexVHDL.o: ../lexers/LexVHDL.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h
LexYAML.o: ../lexers/LexYAML.cxx ../include/ILexer.h \
 ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
 ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
 ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
 ../lexlib/LexerModule.h

Added win32/makefile.































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
# Make file for Scintilla on Windows
# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
# The License.txt file describes the conditions under which this software may be distributed.
# This makefile assumes the mingw32 version of GCC 3.x or 4.x is used and changes will
# be needed to use other compilers.

.SUFFIXES: .cxx
CC = g++
DEL = del /q

COMPONENT = ../bin/Scintilla.dll
LEXCOMPONENT = ../bin/SciLexer.dll
LEXLIB = Lexers.a

vpath %.h ../src ../include ../lexlib
vpath %.cxx ../src ../lexlib ../lexers

LDFLAGS=-shared -static -Wl,--enable-runtime-pseudo-reloc-v2 -mwindows -Wl,--add-stdcall-alias
LIBS=-lstdc++ -limm32 -lole32 -luuid
# Add -MMD to get dependencies
INCLUDEDIRS=-I ../include -I ../src -I../lexlib
CXXBASEFLAGS=-Wall -Wno-missing-braces -Wno-char-subscripts -pedantic $(INCLUDEDIRS) -fno-rtti

ifdef DEBUG
CXXFLAGS=-DDEBUG -g $(CXXBASEFLAGS)
else
CXXFLAGS=-DNDEBUG -Os $(CXXBASEFLAGS)
STRIPFLAG=-s
endif

.cxx.o:
	$(CC) $(CXXFLAGS) -c $<

ALL:	$(COMPONENT) $(LEXCOMPONENT) $(LEXLIB) ScintillaWinS.o

clean:
	$(DEL) *.exe *.o *.obj *.dll *.res *.map

deps:
	$(CC) -MM $(CXXFLAGS) *.cxx ../src/*.cxx ../lexlib/*.cxx ../lexers/*.cxx >deps.mak

LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))


BASEOBJS = \
	AutoComplete.o \
	CallTip.o \
	CellBuffer.o \
	CharacterSet.o \
	CharClassify.o \
	ContractionState.o \
	Decoration.o \
	Document.o \
	Editor.o \
	KeyMap.o \
	Indicator.o \
	LineMarker.o \
	PerLine.o \
	PlatWin.o \
	PositionCache.o \
	PropSetSimple.o \
	RESearch.o \
	RunStyles.o \
	ScintRes.o \
	Selection.o \
	Style.o \
	UniConversion.o \
	ViewStyle.o \
	XPM.o

SOBJS = ScintillaWin.o ScintillaBase.o $(BASEOBJS)

$(COMPONENT): $(SOBJS) Scintilla.def
	$(CC) $(LDFLAGS) -o $@ $(STRIPFLAG) $(SOBJS) $(CXXFLAGS) $(LIBS)

LOBJS = \
	Accessor.o \
	Catalogue.o \
	ExternalLexer.o \
	LexerBase.o \
	LexerModule.o \
	LexerSimple.o \
	ScintillaWinL.o \
	ScintillaBaseL.o \
	StyleContext.o \
	WordList.o \
	$(BASEOBJS) \
	$(LEXOBJS)
$(LEXCOMPONENT): $(LOBJS) Scintilla.def
	$(CC) $(LDFLAGS) -o $@ $(STRIPFLAG) $(LOBJS) $(CXXFLAGS) $(LIBS)

$(LEXLIB): $(LEXOBJS)
	$(AR) rc $@ $^
	ranlib $@

# Automatically generate dependencies for most files with "make deps"
include deps.mak

# These dependencies are maintained by hand as they do not use the default output name

ScintillaBaseL.o: ScintillaBase.cxx Platform.h \
 ILexer.h Scintilla.h SciLexer.h PropSetSimple.h \
 SplitVector.h Partitioning.h RunStyles.h \
 ContractionState.h CellBuffer.h CallTip.h \
 KeyMap.h Indicator.h XPM.h LineMarker.h \
 Style.h ViewStyle.h AutoComplete.h \
 CharClassify.h Decoration.h Document.h \
 Selection.h PositionCache.h Editor.h \
 ScintillaBase.h LexAccessor.h Accessor.h \
 LexerModule.h Catalogue.h

ScintillaWinL.o: ScintillaWin.cxx Platform.h \
 ILexer.h Scintilla.h SplitVector.h \
 Partitioning.h RunStyles.h ContractionState.h \
 CellBuffer.h CallTip.h KeyMap.h Indicator.h \
 XPM.h LineMarker.h Style.h AutoComplete.h \
 ViewStyle.h CharClassify.h Decoration.h \
 Document.h Selection.h PositionCache.h \
 Editor.h ScintillaBase.h UniConversion.h \
 LexAccessor.h Accessor.h \
 LexerModule.h Catalogue.h

ScintillaWinS.o: ScintillaWin.cxx Platform.h \
 ILexer.h Scintilla.h SplitVector.h \
 Partitioning.h RunStyles.h ContractionState.h \
 CellBuffer.h CallTip.h KeyMap.h Indicator.h \
 XPM.h LineMarker.h Style.h AutoComplete.h \
 ViewStyle.h CharClassify.h Decoration.h \
 Document.h Selection.h PositionCache.h \
 Editor.h ScintillaBase.h UniConversion.h

ScintillaBaseL.o:
	$(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o $@

ScintillaWinS.o:
	$(CC) $(CXXFLAGS) -D STATIC_BUILD -c $< -o $@

ScintillaWinL.o:
	$(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o $@

ScintRes.o:	ScintRes.rc
	windres ScintRes.rc $@

Added win32/scintilla.mak.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
# Make file for Scintilla on Windows Visual C++ version
# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
# The License.txt file describes the conditions under which this software may be distributed.
# This makefile is for using Visual C++ with nmake.
# Usage for Microsoft:
#     nmake -f scintilla.mak
# For debug versions define DEBUG on the command line:
#     nmake DEBUG=1 -f scintilla.mak
# The main makefile uses mingw32 gcc and may be more current than this file.

.SUFFIXES: .cxx

DIR_O=.
DIR_BIN=..\bin

COMPONENT=$(DIR_BIN)\Scintilla.dll
LEXCOMPONENT=$(DIR_BIN)\SciLexer.dll
LEXLIB=Lexers.lib

CC=cl
RC=rc
LD=link

CXXFLAGS=-Zi -TP -MP -W4 -EHsc -Zc:forScope -Zc:wchar_t -D_CRT_SECURE_NO_DEPRECATE=1
CXXDEBUG=-Od -MTd -DDEBUG
CXXNDEBUG=-O1 -MT -DNDEBUG -GL
NAME=-Fo
LDFLAGS=-OPT:REF -LTCG -DEBUG
LDDEBUG=
LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.LIB
NOLOGO=-nologo

!IFDEF QUIET
CC=@$(CC)
CXXFLAGS=$(CXXFLAGS) $(NOLOGO)
LDFLAGS=$(LDFLAGS) $(NOLOGO)
!ENDIF

!IF [cl -c -nologo CheckD2D.cxx >NUL:]
CXXFLAGS=$(CXXFLAGS) -DDISABLE_D2D
!MESSAGE Direct2D is not available
!ENDIF

!IFDEF DEBUG
CXXFLAGS=$(CXXFLAGS) $(CXXDEBUG)
LDFLAGS=$(LDDEBUG) $(LDFLAGS)
!ELSE
CXXFLAGS=$(CXXFLAGS) $(CXXNDEBUG)
!ENDIF

INCLUDEDIRS=-I../include -I../src -I../lexlib
CXXFLAGS=$(CXXFLAGS) $(INCLUDEDIRS)

ALL:	$(COMPONENT) $(LEXCOMPONENT) $(LEXLIB) $(DIR_O)\ScintillaWinS.obj

clean:
	-del /q $(DIR_O)\*.obj $(DIR_O)\*.pdb $(COMPONENT) $(LEXCOMPONENT) \
	$(DIR_O)\*.res $(DIR_BIN)\*.map $(DIR_BIN)\*.exp $(DIR_BIN)\*.pdb $(DIR_BIN)\*.lib

SOBJS=\
	$(DIR_O)\AutoComplete.obj \
	$(DIR_O)\CallTip.obj \
	$(DIR_O)\CellBuffer.obj \
	$(DIR_O)\CharacterSet.obj \
	$(DIR_O)\CharClassify.obj \
	$(DIR_O)\ContractionState.obj \
	$(DIR_O)\Decoration.obj \
	$(DIR_O)\Document.obj \
	$(DIR_O)\Editor.obj \
	$(DIR_O)\Indicator.obj \
	$(DIR_O)\KeyMap.obj \
	$(DIR_O)\LineMarker.obj \
	$(DIR_O)\PerLine.obj \
	$(DIR_O)\PlatWin.obj \
	$(DIR_O)\PositionCache.obj \
	$(DIR_O)\PropSetSimple.obj \
	$(DIR_O)\RESearch.obj \
	$(DIR_O)\RunStyles.obj \
	$(DIR_O)\ScintillaBase.obj \
	$(DIR_O)\ScintillaWin.obj \
	$(DIR_O)\Selection.obj \
	$(DIR_O)\Style.obj \
	$(DIR_O)\UniConversion.obj \
	$(DIR_O)\ViewStyle.obj \
	$(DIR_O)\XPM.obj

#++Autogenerated -- run src/LexGen.py to regenerate
#**LEXOBJS=\\\n\(\t$(DIR_O)\\\*.obj \\\n\)
LEXOBJS=\
	$(DIR_O)\LexA68k.obj \
	$(DIR_O)\LexAbaqus.obj \
	$(DIR_O)\LexAda.obj \
	$(DIR_O)\LexAPDL.obj \
	$(DIR_O)\LexAsm.obj \
	$(DIR_O)\LexAsn1.obj \
	$(DIR_O)\LexASY.obj \
	$(DIR_O)\LexAU3.obj \
	$(DIR_O)\LexAVE.obj \
	$(DIR_O)\LexAVS.obj \
	$(DIR_O)\LexBaan.obj \
	$(DIR_O)\LexBash.obj \
	$(DIR_O)\LexBasic.obj \
	$(DIR_O)\LexBullant.obj \
	$(DIR_O)\LexCaml.obj \
	$(DIR_O)\LexCLW.obj \
	$(DIR_O)\LexCmake.obj \
	$(DIR_O)\LexCOBOL.obj \
	$(DIR_O)\LexCoffeeScript.obj \
	$(DIR_O)\LexConf.obj \
	$(DIR_O)\LexCPP.obj \
	$(DIR_O)\LexCrontab.obj \
	$(DIR_O)\LexCsound.obj \
	$(DIR_O)\LexCSS.obj \
	$(DIR_O)\LexD.obj \
	$(DIR_O)\LexECL.obj \
	$(DIR_O)\LexEiffel.obj \
	$(DIR_O)\LexErlang.obj \
	$(DIR_O)\LexEScript.obj \
	$(DIR_O)\LexFlagship.obj \
	$(DIR_O)\LexForth.obj \
	$(DIR_O)\LexFortran.obj \
	$(DIR_O)\LexGAP.obj \
	$(DIR_O)\LexGui4Cli.obj \
	$(DIR_O)\LexHaskell.obj \
	$(DIR_O)\LexHTML.obj \
	$(DIR_O)\LexInno.obj \
	$(DIR_O)\LexKix.obj \
	$(DIR_O)\LexLaTeX.obj \
	$(DIR_O)\LexLisp.obj \
	$(DIR_O)\LexLout.obj \
	$(DIR_O)\LexLua.obj \
	$(DIR_O)\LexMagik.obj \
	$(DIR_O)\LexMarkdown.obj \
	$(DIR_O)\LexMatlab.obj \
	$(DIR_O)\LexMetapost.obj \
	$(DIR_O)\LexMMIXAL.obj \
	$(DIR_O)\LexModula.obj \
	$(DIR_O)\LexMPT.obj \
	$(DIR_O)\LexMSSQL.obj \
	$(DIR_O)\LexMySQL.obj \
	$(DIR_O)\LexNimrod.obj \
	$(DIR_O)\LexNsis.obj \
	$(DIR_O)\LexOpal.obj \
	$(DIR_O)\LexOScript.obj \
	$(DIR_O)\LexOthers.obj \
	$(DIR_O)\LexPascal.obj \
	$(DIR_O)\LexPB.obj \
	$(DIR_O)\LexPerl.obj \
	$(DIR_O)\LexPLM.obj \
	$(DIR_O)\LexPO.obj \
	$(DIR_O)\LexPOV.obj \
	$(DIR_O)\LexPowerPro.obj \
	$(DIR_O)\LexPowerShell.obj \
	$(DIR_O)\LexProgress.obj \
	$(DIR_O)\LexPS.obj \
	$(DIR_O)\LexPython.obj \
	$(DIR_O)\LexR.obj \
	$(DIR_O)\LexRebol.obj \
	$(DIR_O)\LexRuby.obj \
	$(DIR_O)\LexScriptol.obj \
	$(DIR_O)\LexSmalltalk.obj \
	$(DIR_O)\LexSML.obj \
	$(DIR_O)\LexSorcus.obj \
	$(DIR_O)\LexSpecman.obj \
	$(DIR_O)\LexSpice.obj \
	$(DIR_O)\LexSQL.obj \
	$(DIR_O)\LexTACL.obj \
	$(DIR_O)\LexTADS3.obj \
	$(DIR_O)\LexTAL.obj \
	$(DIR_O)\LexTCL.obj \
	$(DIR_O)\LexTCMD.obj \
	$(DIR_O)\LexTeX.obj \
	$(DIR_O)\LexTxt2tags.obj \
	$(DIR_O)\LexVB.obj \
	$(DIR_O)\LexVerilog.obj \
	$(DIR_O)\LexVHDL.obj \
	$(DIR_O)\LexVisualProlog.obj \
	$(DIR_O)\LexYAML.obj \

#--Autogenerated -- end of automatically generated section

LOBJS=\
	$(DIR_O)\Accessor.obj \
	$(DIR_O)\AutoComplete.obj \
	$(DIR_O)\CallTip.obj \
	$(DIR_O)\Catalogue.obj \
	$(DIR_O)\CellBuffer.obj \
	$(DIR_O)\CharacterSet.obj \
	$(DIR_O)\CharClassify.obj \
	$(DIR_O)\ContractionState.obj \
	$(DIR_O)\Decoration.obj \
	$(DIR_O)\Document.obj \
	$(DIR_O)\Editor.obj \
	$(DIR_O)\ExternalLexer.obj \
	$(DIR_O)\Indicator.obj \
	$(DIR_O)\KeyMap.obj \
	$(DIR_O)\LexerBase.obj \
	$(DIR_O)\LexerModule.obj \
	$(DIR_O)\LexerSimple.obj \
	$(DIR_O)\LineMarker.obj \
	$(DIR_O)\PerLine.obj \
	$(DIR_O)\PlatWin.obj \
	$(DIR_O)\PositionCache.obj \
	$(DIR_O)\PropSetSimple.obj \
	$(DIR_O)\RESearch.obj \
	$(DIR_O)\RunStyles.obj \
	$(DIR_O)\ScintillaBaseL.obj \
	$(DIR_O)\ScintillaWinL.obj \
	$(DIR_O)\Selection.obj \
	$(DIR_O)\Style.obj \
	$(DIR_O)\StyleContext.obj \
	$(DIR_O)\UniConversion.obj \
	$(DIR_O)\ViewStyle.obj \
	$(DIR_O)\WordList.obj \
	$(DIR_O)\XPM.obj \
	$(LEXOBJS)

$(DIR_O)\ScintRes.res : ScintRes.rc
	$(RC) -fo$@ $**

$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
	$(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)

$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
	$(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)

$(LEXLIB): $(LEXOBJS)
	LIB /OUT:$@ $(LEXOBJS)

# Define how to build all the objects and what they depend on

{..\src}.cxx{$(DIR_O)}.obj::
	$(CC) $(CXXFLAGS) -c $(NAME)$(DIR_O)\ $<
{..\lexlib}.cxx{$(DIR_O)}.obj::
	$(CC) $(CXXFLAGS) -c $(NAME)$(DIR_O)\ $<
{..\lexers}.cxx{$(DIR_O)}.obj::
	$(CC) $(CXXFLAGS) -c $(NAME)$(DIR_O)\ $<
{.}.cxx{$(DIR_O)}.obj::
	$(CC) $(CXXFLAGS) -c $(NAME)$(DIR_O)\ $<

# Some source files are compiled into more than one object because of different conditional compilation
$(DIR_O)\ScintillaBaseL.obj: ..\src\ScintillaBase.cxx
	$(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ..\src\ScintillaBase.cxx

$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx
	$(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ScintillaWin.cxx

$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx
	$(CC) $(CXXFLAGS) -DSTATIC_BUILD -c $(NAME)$@ ScintillaWin.cxx

# Dependencies

# All lexers depend on this set of headers
LEX_HEADERS= ..\include\ILexer.h ..\include\Scintilla.h ..\include\SciLexer.h \
 ..\lexlib\Accessor.h ..\lexlib\CharacterSet.h ..\lexlib\LexAccessor.h \
 ..\lexlib\LexerModule.h ..\lexlib\StyleContext.h

$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
  ../src/AutoComplete.h
$(DIR_O)\Accessor.obj: ../lexlib/Accessor.cxx ../lexlib/Accessor.h
$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/CallTip.h
$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h
$(DIR_O)\CharacterSet.obj: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h
$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h
$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \
  ../src/ContractionState.h
$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/Decoration.h
$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
  ../src/RESearch.h ../src/PerLine.h
$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
  ../include/Scintilla.h ../include/SciLexer.h \
  ../lexlib/Accessor.h ../src/ExternalLexer.h
$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/Indicator.h
$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/KeyMap.h

#++Autogenerated -- run src/LexGen.py to regenerate
#**\n\($(DIR_O)\\\*.obj: ..\\lexers\\\*.cxx $(LEX_HEADERS)\n\n\)

$(DIR_O)\LexA68k.obj: ..\lexers\LexA68k.cxx $(LEX_HEADERS)

$(DIR_O)\LexAbaqus.obj: ..\lexers\LexAbaqus.cxx $(LEX_HEADERS)

$(DIR_O)\LexAda.obj: ..\lexers\LexAda.cxx $(LEX_HEADERS)

$(DIR_O)\LexAPDL.obj: ..\lexers\LexAPDL.cxx $(LEX_HEADERS)

$(DIR_O)\LexAsm.obj: ..\lexers\LexAsm.cxx $(LEX_HEADERS)

$(DIR_O)\LexAsn1.obj: ..\lexers\LexAsn1.cxx $(LEX_HEADERS)

$(DIR_O)\LexASY.obj: ..\lexers\LexASY.cxx $(LEX_HEADERS)

$(DIR_O)\LexAU3.obj: ..\lexers\LexAU3.cxx $(LEX_HEADERS)

$(DIR_O)\LexAVE.obj: ..\lexers\LexAVE.cxx $(LEX_HEADERS)

$(DIR_O)\LexAVS.obj: ..\lexers\LexAVS.cxx $(LEX_HEADERS)

$(DIR_O)\LexBaan.obj: ..\lexers\LexBaan.cxx $(LEX_HEADERS)

$(DIR_O)\LexBash.obj: ..\lexers\LexBash.cxx $(LEX_HEADERS)

$(DIR_O)\LexBasic.obj: ..\lexers\LexBasic.cxx $(LEX_HEADERS)

$(DIR_O)\LexBullant.obj: ..\lexers\LexBullant.cxx $(LEX_HEADERS)

$(DIR_O)\LexCaml.obj: ..\lexers\LexCaml.cxx $(LEX_HEADERS)

$(DIR_O)\LexCLW.obj: ..\lexers\LexCLW.cxx $(LEX_HEADERS)

$(DIR_O)\LexCmake.obj: ..\lexers\LexCmake.cxx $(LEX_HEADERS)

$(DIR_O)\LexCOBOL.obj: ..\lexers\LexCOBOL.cxx $(LEX_HEADERS)

$(DIR_O)\LexCoffeeScript.obj: ..\lexers\LexCoffeeScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexConf.obj: ..\lexers\LexConf.cxx $(LEX_HEADERS)

$(DIR_O)\LexCPP.obj: ..\lexers\LexCPP.cxx $(LEX_HEADERS)

$(DIR_O)\LexCrontab.obj: ..\lexers\LexCrontab.cxx $(LEX_HEADERS)

$(DIR_O)\LexCsound.obj: ..\lexers\LexCsound.cxx $(LEX_HEADERS)

$(DIR_O)\LexCSS.obj: ..\lexers\LexCSS.cxx $(LEX_HEADERS)

$(DIR_O)\LexD.obj: ..\lexers\LexD.cxx $(LEX_HEADERS)

$(DIR_O)\LexECL.obj: ..\lexers\LexECL.cxx $(LEX_HEADERS)

$(DIR_O)\LexEiffel.obj: ..\lexers\LexEiffel.cxx $(LEX_HEADERS)

$(DIR_O)\LexErlang.obj: ..\lexers\LexErlang.cxx $(LEX_HEADERS)

$(DIR_O)\LexEScript.obj: ..\lexers\LexEScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexFlagship.obj: ..\lexers\LexFlagship.cxx $(LEX_HEADERS)

$(DIR_O)\LexForth.obj: ..\lexers\LexForth.cxx $(LEX_HEADERS)

$(DIR_O)\LexFortran.obj: ..\lexers\LexFortran.cxx $(LEX_HEADERS)

$(DIR_O)\LexGAP.obj: ..\lexers\LexGAP.cxx $(LEX_HEADERS)

$(DIR_O)\LexGui4Cli.obj: ..\lexers\LexGui4Cli.cxx $(LEX_HEADERS)

$(DIR_O)\LexHaskell.obj: ..\lexers\LexHaskell.cxx $(LEX_HEADERS)

$(DIR_O)\LexHTML.obj: ..\lexers\LexHTML.cxx $(LEX_HEADERS)

$(DIR_O)\LexInno.obj: ..\lexers\LexInno.cxx $(LEX_HEADERS)

$(DIR_O)\LexKix.obj: ..\lexers\LexKix.cxx $(LEX_HEADERS)

$(DIR_O)\LexLaTeX.obj: ..\lexers\LexLaTeX.cxx $(LEX_HEADERS)

$(DIR_O)\LexLisp.obj: ..\lexers\LexLisp.cxx $(LEX_HEADERS)

$(DIR_O)\LexLout.obj: ..\lexers\LexLout.cxx $(LEX_HEADERS)

$(DIR_O)\LexLua.obj: ..\lexers\LexLua.cxx $(LEX_HEADERS)

$(DIR_O)\LexMagik.obj: ..\lexers\LexMagik.cxx $(LEX_HEADERS)

$(DIR_O)\LexMarkdown.obj: ..\lexers\LexMarkdown.cxx $(LEX_HEADERS)

$(DIR_O)\LexMatlab.obj: ..\lexers\LexMatlab.cxx $(LEX_HEADERS)

$(DIR_O)\LexMetapost.obj: ..\lexers\LexMetapost.cxx $(LEX_HEADERS)

$(DIR_O)\LexMMIXAL.obj: ..\lexers\LexMMIXAL.cxx $(LEX_HEADERS)

$(DIR_O)\LexModula.obj: ..\lexers\LexModula.cxx $(LEX_HEADERS)

$(DIR_O)\LexMPT.obj: ..\lexers\LexMPT.cxx $(LEX_HEADERS)

$(DIR_O)\LexMSSQL.obj: ..\lexers\LexMSSQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexMySQL.obj: ..\lexers\LexMySQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexNimrod.obj: ..\lexers\LexNimrod.cxx $(LEX_HEADERS)

$(DIR_O)\LexNsis.obj: ..\lexers\LexNsis.cxx $(LEX_HEADERS)

$(DIR_O)\LexOpal.obj: ..\lexers\LexOpal.cxx $(LEX_HEADERS)

$(DIR_O)\LexOScript.obj: ..\lexers\LexOScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexOthers.obj: ..\lexers\LexOthers.cxx $(LEX_HEADERS)

$(DIR_O)\LexPascal.obj: ..\lexers\LexPascal.cxx $(LEX_HEADERS)

$(DIR_O)\LexPB.obj: ..\lexers\LexPB.cxx $(LEX_HEADERS)

$(DIR_O)\LexPerl.obj: ..\lexers\LexPerl.cxx $(LEX_HEADERS)

$(DIR_O)\LexPLM.obj: ..\lexers\LexPLM.cxx $(LEX_HEADERS)

$(DIR_O)\LexPO.obj: ..\lexers\LexPO.cxx $(LEX_HEADERS)

$(DIR_O)\LexPOV.obj: ..\lexers\LexPOV.cxx $(LEX_HEADERS)

$(DIR_O)\LexPowerPro.obj: ..\lexers\LexPowerPro.cxx $(LEX_HEADERS)

$(DIR_O)\LexPowerShell.obj: ..\lexers\LexPowerShell.cxx $(LEX_HEADERS)

$(DIR_O)\LexProgress.obj: ..\lexers\LexProgress.cxx $(LEX_HEADERS)

$(DIR_O)\LexPS.obj: ..\lexers\LexPS.cxx $(LEX_HEADERS)

$(DIR_O)\LexPython.obj: ..\lexers\LexPython.cxx $(LEX_HEADERS)

$(DIR_O)\LexR.obj: ..\lexers\LexR.cxx $(LEX_HEADERS)

$(DIR_O)\LexRebol.obj: ..\lexers\LexRebol.cxx $(LEX_HEADERS)

$(DIR_O)\LexRuby.obj: ..\lexers\LexRuby.cxx $(LEX_HEADERS)

$(DIR_O)\LexScriptol.obj: ..\lexers\LexScriptol.cxx $(LEX_HEADERS)

$(DIR_O)\LexSmalltalk.obj: ..\lexers\LexSmalltalk.cxx $(LEX_HEADERS)

$(DIR_O)\LexSML.obj: ..\lexers\LexSML.cxx $(LEX_HEADERS)

$(DIR_O)\LexSorcus.obj: ..\lexers\LexSorcus.cxx $(LEX_HEADERS)

$(DIR_O)\LexSpecman.obj: ..\lexers\LexSpecman.cxx $(LEX_HEADERS)

$(DIR_O)\LexSpice.obj: ..\lexers\LexSpice.cxx $(LEX_HEADERS)

$(DIR_O)\LexSQL.obj: ..\lexers\LexSQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTACL.obj: ..\lexers\LexTACL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTADS3.obj: ..\lexers\LexTADS3.cxx $(LEX_HEADERS)

$(DIR_O)\LexTAL.obj: ..\lexers\LexTAL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTCL.obj: ..\lexers\LexTCL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTCMD.obj: ..\lexers\LexTCMD.cxx $(LEX_HEADERS)

$(DIR_O)\LexTeX.obj: ..\lexers\LexTeX.cxx $(LEX_HEADERS)

$(DIR_O)\LexTxt2tags.obj: ..\lexers\LexTxt2tags.cxx $(LEX_HEADERS)

$(DIR_O)\LexVB.obj: ..\lexers\LexVB.cxx $(LEX_HEADERS)

$(DIR_O)\LexVerilog.obj: ..\lexers\LexVerilog.cxx $(LEX_HEADERS)

$(DIR_O)\LexVHDL.obj: ..\lexers\LexVHDL.cxx $(LEX_HEADERS)

$(DIR_O)\LexVisualProlog.obj: ..\lexers\LexVisualProlog.cxx $(LEX_HEADERS)

$(DIR_O)\LexYAML.obj: ..\lexers\LexYAML.cxx $(LEX_HEADERS)


#--Autogenerated -- end of automatically generated section

$(DIR_O)\LexerBase.obj: ../lexlib/LexerBase.cxx ../lexlib/LexerBase.h
$(DIR_O)\LexerModule.obj: ../lexlib/LexerModule.cxx ../lexlib/LexerModule.h
$(DIR_O)\LexerSimple.obj: ../lexlib/LexerSimple.cxx ../lexlib/LexerSimple.h
$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/PerLine.h
$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h \
  ../src/UniConversion.h ../src/XPM.h
$(DIR_O)\PositionCache.obj: ../src/PositionCache.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
$(DIR_O)\PropSetSimple.obj: ../lexlib/PropSetSimple.cxx ../include/Platform.h
$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h
$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
  ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
  ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
  ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
  ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
  ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
  ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
  ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
  ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/Selection.h
$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/Style.h
$(DIR_O)\StyleContext.obj: ../lexlib/StyleContext.cxx ../lexlib/Accessor.h \
  ../lexlib/StyleContext.h
$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h
$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h
$(DIR_O)\WordList.obj: ../lexlib/WordList.cxx ../lexlib/WordList.h
$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h

Added win32/scintilla_vc6.mak.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# Make file for Scintilla on Windows Visual C++ version
# Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
# The License.txt file describes the conditions under which this software may be distributed.
# This makefile is for using Visual C++ with nmake.
# Usage for Microsoft:
#     nmake -f scintilla.mak
# For debug versions define DEBUG on the command line:
#     nmake DEBUG=1 -f scintilla.mak
# The main makefile uses mingw32 gcc and may be more current than this file.

.SUFFIXES: .cxx

DIR_O=.
DIR_BIN=..\bin

COMPONENT=$(DIR_BIN)\Scintilla.dll
LEXCOMPONENT=$(DIR_BIN)\SciLexer.dll

CC=cl
RC=rc
LD=link

#-Zc:forScope -Zc:wchar_t
CXXFLAGS=-Zi -TP -W3 -EHsc
# For something scary:-Wp64
CXXDEBUG=-Od -MTd -DDEBUG
CXXNDEBUG=-O1 -MT -DNDEBUG
NAME=-Fo
# If you have problems with lexers being linked, try removing -OPT:REF and replacing with -OPT:NOREF
LDFLAGS=-OPT:NOWIN98 -OPT:REF
LDDEBUG=
LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.LIB
NOLOGO=-nologo

!IFDEF QUIET
CC=@$(CC)
CXXFLAGS=$(CXXFLAGS) $(NOLOGO)
LDFLAGS=$(LDFLAGS) $(NOLOGO)
!ENDIF

!IFDEF DEBUG
CXXFLAGS=$(CXXFLAGS) $(CXXDEBUG)
LDFLAGS=$(LDDEBUG) $(LDFLAGS)
!ELSE
CXXFLAGS=$(CXXFLAGS) $(CXXNDEBUG)
!ENDIF

INCLUDEDIRS=-I../include -I../src -I../lexlib
CXXFLAGS=$(CXXFLAGS) $(INCLUDEDIRS)

ALL:	$(COMPONENT) $(LEXCOMPONENT) $(DIR_O)\ScintillaWinS.obj

clean:
	-del /q $(DIR_O)\*.obj $(DIR_O)\*.pdb $(COMPONENT) $(LEXCOMPONENT) \
	$(DIR_O)\*.res $(DIR_BIN)\*.map $(DIR_BIN)\*.exp $(DIR_BIN)\*.pdb $(DIR_BIN)\*.lib

SOBJS=\
	$(DIR_O)\AutoComplete.obj \
	$(DIR_O)\CallTip.obj \
	$(DIR_O)\CellBuffer.obj \
	$(DIR_O)\CharacterSet.obj \
	$(DIR_O)\CharClassify.obj \
	$(DIR_O)\ContractionState.obj \
	$(DIR_O)\Decoration.obj \
	$(DIR_O)\Document.obj \
	$(DIR_O)\Editor.obj \
	$(DIR_O)\Indicator.obj \
	$(DIR_O)\KeyMap.obj \
	$(DIR_O)\LineMarker.obj \
	$(DIR_O)\PerLine.obj \
	$(DIR_O)\PlatWin.obj \
	$(DIR_O)\PositionCache.obj \
	$(DIR_O)\PropSetSimple.obj \
	$(DIR_O)\RESearch.obj \
	$(DIR_O)\RunStyles.obj \
	$(DIR_O)\ScintillaBase.obj \
	$(DIR_O)\ScintillaWin.obj \
	$(DIR_O)\Selection.obj \
	$(DIR_O)\Style.obj \
	$(DIR_O)\UniConversion.obj \
	$(DIR_O)\ViewStyle.obj \
	$(DIR_O)\XPM.obj

#++Autogenerated -- run src/LexGen.py to regenerate
#**LEXOBJS=\\\n\(\t$(DIR_O)\\\*.obj \\\n\)
LEXOBJS=\
	$(DIR_O)\LexA68k.obj \
	$(DIR_O)\LexAbaqus.obj \
	$(DIR_O)\LexAda.obj \
	$(DIR_O)\LexAPDL.obj \
	$(DIR_O)\LexAsm.obj \
	$(DIR_O)\LexAsn1.obj \
	$(DIR_O)\LexASY.obj \
	$(DIR_O)\LexAU3.obj \
	$(DIR_O)\LexAVE.obj \
	$(DIR_O)\LexAVS.obj \
	$(DIR_O)\LexBaan.obj \
	$(DIR_O)\LexBash.obj \
	$(DIR_O)\LexBasic.obj \
	$(DIR_O)\LexBullant.obj \
	$(DIR_O)\LexCaml.obj \
	$(DIR_O)\LexCLW.obj \
	$(DIR_O)\LexCmake.obj \
	$(DIR_O)\LexCOBOL.obj \
	$(DIR_O)\LexCoffeeScript.obj \
	$(DIR_O)\LexConf.obj \
	$(DIR_O)\LexCPP.obj \
	$(DIR_O)\LexCrontab.obj \
	$(DIR_O)\LexCsound.obj \
	$(DIR_O)\LexCSS.obj \
	$(DIR_O)\LexD.obj \
	$(DIR_O)\LexECL.obj \
	$(DIR_O)\LexEiffel.obj \
	$(DIR_O)\LexErlang.obj \
	$(DIR_O)\LexEScript.obj \
	$(DIR_O)\LexFlagship.obj \
	$(DIR_O)\LexForth.obj \
	$(DIR_O)\LexFortran.obj \
	$(DIR_O)\LexGAP.obj \
	$(DIR_O)\LexGui4Cli.obj \
	$(DIR_O)\LexHaskell.obj \
	$(DIR_O)\LexHTML.obj \
	$(DIR_O)\LexInno.obj \
	$(DIR_O)\LexKix.obj \
	$(DIR_O)\LexLaTeX.obj \
	$(DIR_O)\LexLisp.obj \
	$(DIR_O)\LexLout.obj \
	$(DIR_O)\LexLua.obj \
	$(DIR_O)\LexMagik.obj \
	$(DIR_O)\LexMarkdown.obj \
	$(DIR_O)\LexMatlab.obj \
	$(DIR_O)\LexMetapost.obj \
	$(DIR_O)\LexMMIXAL.obj \
	$(DIR_O)\LexModula.obj \
	$(DIR_O)\LexMPT.obj \
	$(DIR_O)\LexMSSQL.obj \
	$(DIR_O)\LexMySQL.obj \
	$(DIR_O)\LexNimrod.obj \
	$(DIR_O)\LexNsis.obj \
	$(DIR_O)\LexOpal.obj \
	$(DIR_O)\LexOScript.obj \
	$(DIR_O)\LexOthers.obj \
	$(DIR_O)\LexPascal.obj \
	$(DIR_O)\LexPB.obj \
	$(DIR_O)\LexPerl.obj \
	$(DIR_O)\LexPLM.obj \
	$(DIR_O)\LexPO.obj \
	$(DIR_O)\LexPOV.obj \
	$(DIR_O)\LexPowerPro.obj \
	$(DIR_O)\LexPowerShell.obj \
	$(DIR_O)\LexProgress.obj \
	$(DIR_O)\LexPS.obj \
	$(DIR_O)\LexPython.obj \
	$(DIR_O)\LexR.obj \
	$(DIR_O)\LexRebol.obj \
	$(DIR_O)\LexRuby.obj \
	$(DIR_O)\LexScriptol.obj \
	$(DIR_O)\LexSmalltalk.obj \
	$(DIR_O)\LexSML.obj \
	$(DIR_O)\LexSorcus.obj \
	$(DIR_O)\LexSpecman.obj \
	$(DIR_O)\LexSpice.obj \
	$(DIR_O)\LexSQL.obj \
	$(DIR_O)\LexTACL.obj \
	$(DIR_O)\LexTADS3.obj \
	$(DIR_O)\LexTAL.obj \
	$(DIR_O)\LexTCL.obj \
	$(DIR_O)\LexTCMD.obj \
	$(DIR_O)\LexTeX.obj \
	$(DIR_O)\LexTxt2tags.obj \
	$(DIR_O)\LexVB.obj \
	$(DIR_O)\LexVerilog.obj \
	$(DIR_O)\LexVHDL.obj \
	$(DIR_O)\LexVisualProlog.obj \
	$(DIR_O)\LexYAML.obj \

#--Autogenerated -- end of automatically generated section

LOBJS=\
	$(DIR_O)\Accessor.obj \
	$(DIR_O)\AutoComplete.obj \
	$(DIR_O)\CallTip.obj \
	$(DIR_O)\Catalogue.obj \
	$(DIR_O)\CellBuffer.obj \
	$(DIR_O)\CharacterSet.obj \
	$(DIR_O)\CharClassify.obj \
	$(DIR_O)\ContractionState.obj \
	$(DIR_O)\Decoration.obj \
	$(DIR_O)\Document.obj \
	$(DIR_O)\Editor.obj \
	$(DIR_O)\ExternalLexer.obj \
	$(DIR_O)\Indicator.obj \
	$(DIR_O)\KeyMap.obj \
	$(DIR_O)\LexerBase.obj \
	$(DIR_O)\LexerModule.obj \
	$(DIR_O)\LexerSimple.obj \
	$(DIR_O)\LineMarker.obj \
	$(DIR_O)\PerLine.obj \
	$(DIR_O)\PlatWin.obj \
	$(DIR_O)\PositionCache.obj \
	$(DIR_O)\PropSetSimple.obj \
	$(DIR_O)\RESearch.obj \
	$(DIR_O)\RunStyles.obj \
	$(DIR_O)\ScintillaBaseL.obj \
	$(DIR_O)\ScintillaWinL.obj \
	$(DIR_O)\Selection.obj \
	$(DIR_O)\Style.obj \
	$(DIR_O)\StyleContext.obj \
	$(DIR_O)\UniConversion.obj \
	$(DIR_O)\ViewStyle.obj \
	$(DIR_O)\WordList.obj \
	$(DIR_O)\XPM.obj \
	$(LEXOBJS)

$(DIR_O)\ScintRes.res : ScintRes.rc
	$(RC) -fo$@ $**

$(COMPONENT): $(SOBJS) $(DIR_O)\ScintRes.res
	$(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)

$(LEXCOMPONENT): $(LOBJS) $(DIR_O)\ScintRes.res
	$(LD) $(LDFLAGS) -DEF:Scintilla.def -DLL -OUT:$@ $** $(LIBS)

# Define how to build all the objects and what they depend on

{..\src}.cxx{$(DIR_O)}.obj:
	$(CC) $(CXXFLAGS) -c $(NAME)$@ $<
{..\lexlib}.cxx{$(DIR_O)}.obj:
	$(CC) $(CXXFLAGS) -c $(NAME)$@ $<
{..\lexers}.cxx{$(DIR_O)}.obj:
	$(CC) $(CXXFLAGS) -c $(NAME)$@ $<
{.}.cxx{$(DIR_O)}.obj:
	$(CC) $(CXXFLAGS) -c $(NAME)$@ $<

# Some source files are compiled into more than one object because of different conditional compilation
$(DIR_O)\ScintillaBaseL.obj: ..\src\ScintillaBase.cxx
	$(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ..\src\ScintillaBase.cxx

$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx
	$(CC) $(CXXFLAGS) -DSCI_LEXER -c $(NAME)$@ ScintillaWin.cxx

$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx
	$(CC) $(CXXFLAGS) -DSTATIC_BUILD -c $(NAME)$@ ScintillaWin.cxx

# Dependencies

# All lexers depend on this set of headers
LEX_HEADERS= ..\include\ILexer.h ..\include\Scintilla.h ..\include\SciLexer.h \
 ..\lexlib\Accessor.h ..\lexlib\CharacterSet.h ..\lexlib\LexAccessor.h \
 ..\lexlib\LexerModule.h ..\lexlib\StyleContext.h

$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
  ../src/AutoComplete.h
$(DIR_O)\Accessor.obj: ../lexlib/Accessor.cxx ../lexlib/Accessor.h
$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/CallTip.h
$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h
$(DIR_O)\CharacterSet.obj: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h
$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h
$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \
  ../src/ContractionState.h
$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/Decoration.h
$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
  ../src/RESearch.h ../src/PerLine.h
$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
  ../include/Scintilla.h ../include/SciLexer.h \
  ../lexlib/Accessor.h ../src/ExternalLexer.h
$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/Indicator.h
$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/KeyMap.h

#++Autogenerated -- run src/LexGen.py to regenerate
#**\n\($(DIR_O)\\\*.obj: ..\\lexers\\\*.cxx $(LEX_HEADERS)\n\n\)

$(DIR_O)\LexA68k.obj: ..\lexers\LexA68k.cxx $(LEX_HEADERS)

$(DIR_O)\LexAbaqus.obj: ..\lexers\LexAbaqus.cxx $(LEX_HEADERS)

$(DIR_O)\LexAda.obj: ..\lexers\LexAda.cxx $(LEX_HEADERS)

$(DIR_O)\LexAPDL.obj: ..\lexers\LexAPDL.cxx $(LEX_HEADERS)

$(DIR_O)\LexAsm.obj: ..\lexers\LexAsm.cxx $(LEX_HEADERS)

$(DIR_O)\LexAsn1.obj: ..\lexers\LexAsn1.cxx $(LEX_HEADERS)

$(DIR_O)\LexASY.obj: ..\lexers\LexASY.cxx $(LEX_HEADERS)

$(DIR_O)\LexAU3.obj: ..\lexers\LexAU3.cxx $(LEX_HEADERS)

$(DIR_O)\LexAVE.obj: ..\lexers\LexAVE.cxx $(LEX_HEADERS)

$(DIR_O)\LexAVS.obj: ..\lexers\LexAVS.cxx $(LEX_HEADERS)

$(DIR_O)\LexBaan.obj: ..\lexers\LexBaan.cxx $(LEX_HEADERS)

$(DIR_O)\LexBash.obj: ..\lexers\LexBash.cxx $(LEX_HEADERS)

$(DIR_O)\LexBasic.obj: ..\lexers\LexBasic.cxx $(LEX_HEADERS)

$(DIR_O)\LexBullant.obj: ..\lexers\LexBullant.cxx $(LEX_HEADERS)

$(DIR_O)\LexCaml.obj: ..\lexers\LexCaml.cxx $(LEX_HEADERS)

$(DIR_O)\LexCLW.obj: ..\lexers\LexCLW.cxx $(LEX_HEADERS)

$(DIR_O)\LexCmake.obj: ..\lexers\LexCmake.cxx $(LEX_HEADERS)

$(DIR_O)\LexCOBOL.obj: ..\lexers\LexCOBOL.cxx $(LEX_HEADERS)

$(DIR_O)\LexCoffeeScript.obj: ..\lexers\LexCoffeeScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexConf.obj: ..\lexers\LexConf.cxx $(LEX_HEADERS)

$(DIR_O)\LexCPP.obj: ..\lexers\LexCPP.cxx $(LEX_HEADERS)

$(DIR_O)\LexCrontab.obj: ..\lexers\LexCrontab.cxx $(LEX_HEADERS)

$(DIR_O)\LexCsound.obj: ..\lexers\LexCsound.cxx $(LEX_HEADERS)

$(DIR_O)\LexCSS.obj: ..\lexers\LexCSS.cxx $(LEX_HEADERS)

$(DIR_O)\LexD.obj: ..\lexers\LexD.cxx $(LEX_HEADERS)

$(DIR_O)\LexECL.obj: ..\lexers\LexECL.cxx $(LEX_HEADERS)

$(DIR_O)\LexEiffel.obj: ..\lexers\LexEiffel.cxx $(LEX_HEADERS)

$(DIR_O)\LexErlang.obj: ..\lexers\LexErlang.cxx $(LEX_HEADERS)

$(DIR_O)\LexEScript.obj: ..\lexers\LexEScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexFlagship.obj: ..\lexers\LexFlagship.cxx $(LEX_HEADERS)

$(DIR_O)\LexForth.obj: ..\lexers\LexForth.cxx $(LEX_HEADERS)

$(DIR_O)\LexFortran.obj: ..\lexers\LexFortran.cxx $(LEX_HEADERS)

$(DIR_O)\LexGAP.obj: ..\lexers\LexGAP.cxx $(LEX_HEADERS)

$(DIR_O)\LexGui4Cli.obj: ..\lexers\LexGui4Cli.cxx $(LEX_HEADERS)

$(DIR_O)\LexHaskell.obj: ..\lexers\LexHaskell.cxx $(LEX_HEADERS)

$(DIR_O)\LexHTML.obj: ..\lexers\LexHTML.cxx $(LEX_HEADERS)

$(DIR_O)\LexInno.obj: ..\lexers\LexInno.cxx $(LEX_HEADERS)

$(DIR_O)\LexKix.obj: ..\lexers\LexKix.cxx $(LEX_HEADERS)

$(DIR_O)\LexLaTeX.obj: ..\lexers\LexLaTeX.cxx $(LEX_HEADERS)

$(DIR_O)\LexLisp.obj: ..\lexers\LexLisp.cxx $(LEX_HEADERS)

$(DIR_O)\LexLout.obj: ..\lexers\LexLout.cxx $(LEX_HEADERS)

$(DIR_O)\LexLua.obj: ..\lexers\LexLua.cxx $(LEX_HEADERS)

$(DIR_O)\LexMagik.obj: ..\lexers\LexMagik.cxx $(LEX_HEADERS)

$(DIR_O)\LexMarkdown.obj: ..\lexers\LexMarkdown.cxx $(LEX_HEADERS)

$(DIR_O)\LexMatlab.obj: ..\lexers\LexMatlab.cxx $(LEX_HEADERS)

$(DIR_O)\LexMetapost.obj: ..\lexers\LexMetapost.cxx $(LEX_HEADERS)

$(DIR_O)\LexMMIXAL.obj: ..\lexers\LexMMIXAL.cxx $(LEX_HEADERS)

$(DIR_O)\LexModula.obj: ..\lexers\LexModula.cxx $(LEX_HEADERS)

$(DIR_O)\LexMPT.obj: ..\lexers\LexMPT.cxx $(LEX_HEADERS)

$(DIR_O)\LexMSSQL.obj: ..\lexers\LexMSSQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexMySQL.obj: ..\lexers\LexMySQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexNimrod.obj: ..\lexers\LexNimrod.cxx $(LEX_HEADERS)

$(DIR_O)\LexNsis.obj: ..\lexers\LexNsis.cxx $(LEX_HEADERS)

$(DIR_O)\LexOpal.obj: ..\lexers\LexOpal.cxx $(LEX_HEADERS)

$(DIR_O)\LexOScript.obj: ..\lexers\LexOScript.cxx $(LEX_HEADERS)

$(DIR_O)\LexOthers.obj: ..\lexers\LexOthers.cxx $(LEX_HEADERS)

$(DIR_O)\LexPascal.obj: ..\lexers\LexPascal.cxx $(LEX_HEADERS)

$(DIR_O)\LexPB.obj: ..\lexers\LexPB.cxx $(LEX_HEADERS)

$(DIR_O)\LexPerl.obj: ..\lexers\LexPerl.cxx $(LEX_HEADERS)

$(DIR_O)\LexPLM.obj: ..\lexers\LexPLM.cxx $(LEX_HEADERS)

$(DIR_O)\LexPO.obj: ..\lexers\LexPO.cxx $(LEX_HEADERS)

$(DIR_O)\LexPOV.obj: ..\lexers\LexPOV.cxx $(LEX_HEADERS)

$(DIR_O)\LexPowerPro.obj: ..\lexers\LexPowerPro.cxx $(LEX_HEADERS)

$(DIR_O)\LexPowerShell.obj: ..\lexers\LexPowerShell.cxx $(LEX_HEADERS)

$(DIR_O)\LexProgress.obj: ..\lexers\LexProgress.cxx $(LEX_HEADERS)

$(DIR_O)\LexPS.obj: ..\lexers\LexPS.cxx $(LEX_HEADERS)

$(DIR_O)\LexPython.obj: ..\lexers\LexPython.cxx $(LEX_HEADERS)

$(DIR_O)\LexR.obj: ..\lexers\LexR.cxx $(LEX_HEADERS)

$(DIR_O)\LexRebol.obj: ..\lexers\LexRebol.cxx $(LEX_HEADERS)

$(DIR_O)\LexRuby.obj: ..\lexers\LexRuby.cxx $(LEX_HEADERS)

$(DIR_O)\LexScriptol.obj: ..\lexers\LexScriptol.cxx $(LEX_HEADERS)

$(DIR_O)\LexSmalltalk.obj: ..\lexers\LexSmalltalk.cxx $(LEX_HEADERS)

$(DIR_O)\LexSML.obj: ..\lexers\LexSML.cxx $(LEX_HEADERS)

$(DIR_O)\LexSorcus.obj: ..\lexers\LexSorcus.cxx $(LEX_HEADERS)

$(DIR_O)\LexSpecman.obj: ..\lexers\LexSpecman.cxx $(LEX_HEADERS)

$(DIR_O)\LexSpice.obj: ..\lexers\LexSpice.cxx $(LEX_HEADERS)

$(DIR_O)\LexSQL.obj: ..\lexers\LexSQL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTACL.obj: ..\lexers\LexTACL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTADS3.obj: ..\lexers\LexTADS3.cxx $(LEX_HEADERS)

$(DIR_O)\LexTAL.obj: ..\lexers\LexTAL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTCL.obj: ..\lexers\LexTCL.cxx $(LEX_HEADERS)

$(DIR_O)\LexTCMD.obj: ..\lexers\LexTCMD.cxx $(LEX_HEADERS)

$(DIR_O)\LexTeX.obj: ..\lexers\LexTeX.cxx $(LEX_HEADERS)

$(DIR_O)\LexTxt2tags.obj: ..\lexers\LexTxt2tags.cxx $(LEX_HEADERS)

$(DIR_O)\LexVB.obj: ..\lexers\LexVB.cxx $(LEX_HEADERS)

$(DIR_O)\LexVerilog.obj: ..\lexers\LexVerilog.cxx $(LEX_HEADERS)

$(DIR_O)\LexVHDL.obj: ..\lexers\LexVHDL.cxx $(LEX_HEADERS)

$(DIR_O)\LexVisualProlog.obj: ..\lexers\LexVisualProlog.cxx $(LEX_HEADERS)

$(DIR_O)\LexYAML.obj: ..\lexers\LexYAML.cxx $(LEX_HEADERS)


#--Autogenerated -- end of automatically generated section

$(DIR_O)\LexerBase.obj: ../lexlib/LexerBase.cxx ../lexlib/LexerBase.h
$(DIR_O)\LexerModule.obj: ../lexlib/LexerModule.cxx ../lexlib/LexerModule.h
$(DIR_O)\LexerSimple.obj: ../lexlib/LexerSimple.cxx ../lexlib/LexerSimple.h
$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/PerLine.h
$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h \
  ../src/UniConversion.h ../src/XPM.h
$(DIR_O)\PositionCache.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
$(DIR_O)\PropSetSimple.obj: ../lexlib/PropSetSimple.cxx ../include/Platform.h
$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h
$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
  ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
  ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
  ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
  ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
  ../include/Scintilla.h \
  ../src/ContractionState.h ../src/SVector.h ../src/SplitVector.h \
  ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
  ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
  ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
  ../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
  ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/ContractionState.h \
  ../src/SVector.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h \
  ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
  ../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
  ../src/Decoration.h ../src/Document.h ../src/Editor.h \
  ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/Selection.h
$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
  ../src/Style.h
$(DIR_O)\StyleContext.obj: ../lexlib/StyleContext.cxx ../lexlib/Accessor.h \
  ../lexlib/StyleContext.h
$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h
$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \
  ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
  ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
  ../src/Style.h ../src/ViewStyle.h
$(DIR_O)\WordList.obj: ../lexlib/WordList.cxx ../lexlib/WordList.h
$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h

Added zipsrc.bat.









>
>
>
>
1
2
3
4
cd ..
del/q scintilla.zip
zip scintilla.zip scintilla\*.* scintilla\*\*.* scintilla\*\*\*.* scintilla\*\*\*\*.* scintilla\*\*\*\*\*.* -x *.o -x *.obj -x *.dll -x *.lib -x *.res -x *.exp
cd scintilla