Scintilla Tk

Check-in [96ac9a4e73]
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:Update to current 0.29 changes. These changes will work with Scintilla releases from 3.3.4 or greater.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | rel-0.29
Files: files | file ages | folders
SHA1:96ac9a4e7369d4faffccc6e618e7a692bc09a159
User & Date: briang42@easystreet.net 2013-09-16 02:41:33
Context
2014-03-05
22:28
Release version 0.29 Leaf check-in: 2d8231f334 user: briang42@easystreet.net tags: trunk
2013-09-16
02:41
Update to current 0.29 changes. These changes will work with Scintilla releases from 3.3.4 or greater. check-in: 96ac9a4e73 user: briang42@easystreet.net tags: trunk, rel-0.29
01:56
Initial check-in is version 0.26 check-in: f646ef686b user: briang42@easystreet.net tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to tk/Makefile.in.

29
30
31
32
33
34
35





36
37
38
39
40
41
42
...
169
170
171
172
173
174
175


176
177
178
179
180
181
182
...
285
286
287
288
289
290
291

292









293
294
295
296
297
298
299
# 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@
................................................................................
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
#========================================================================

#========================================================================
................................................................................
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







>
>
>
>
>







 







>
>







 







>

>
>
>
>
>
>
>
>
>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
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
# 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.
#========================================================================

LEXSRCS = $(wildcard $(srcdir)/../lexers/Lex*.cxx)
OTHERSRCS = $(wildcard $(srcdir)/../lexers/*.cxx $(srcdir)/../src/*.cxx)
SRCS = $(LEXSRCS) $(OTHERSRCS) $(wildcard $(srcdir)/*.cxx)
#LEXOBJS = $(addsuffix .$(OBJEXT),$(basename $(notdir $(LEXSRCS))))
#SRCOBJS = $(addsuffix .$(OBJEXT),$(basename $(notdir $($OTHERSRCS))))
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@
................................................................................
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)

DEPEND_SWITCHES = -Y -I$(subst /,\\,$(srcdir)) -I$(subst /,\\,$(srcdir)/../include) -I$(subst /,\\,$(srcdir)/../lexlib) -I$(subst /,\\,$(srcdir)/../src)

.SUFFIXES: .cxx .c .$(OBJEXT) .h .a

#========================================================================
# Start of user-definable TARGETS section
#========================================================================

#========================================================================
................................................................................
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)

# Windows has to be different...
depend:
	os=`uname -o`; \
	if test "$$os" = "Cygwin"; then \
		makedepend -o.obj -f- -pFIXDEPEND $(DEPEND_SWITCHES) -- $(DEPS) -- $(SRCS) | sed s/FIXDEPEND.*\\/\\\([^/]*:\\\)/\\\1/ > Makefile.dep ; \
	else \
		makedepend -f- -pFIXDEPEND $(DEPEND_SWITCHES) -- $(DEPS) -- $(SRCS) | sed s/FIXDEPEND.*\\/\\\([^/]*:\\\)/\\\1/ > Makefile.dep ; \
	fi
	if grep q Makefile.dep Makefile; then \
		echo "include Makefile.dep" >>Makefile; \
	fi

#========================================================================
# $(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

Deleted 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/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
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
// 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.
//
// Portions copied from
// tclWinLoad.c, tclLoadDl.c --
//
// Copyright (c) 1995-1997 Sun Microsystems, Inc.
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
//
// 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>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// tkUnixPort.h picks up the definition of TkPutImage
#include <tkUnixPort.h>
}
#endif

// dynamic loader also requires interpreter
extern Tcl_Interp *scintilla_interp;
#endif

#include "Platform.h"

#include "Scintilla.h"
#include "ScintillaTk.h"
#include "UniConversion.h"
#include "XPM.h"

#include "scintilla-ext.h"
using namespace TkSciExt;

#define USE_LOCK 0

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

#if !USE_SOLID_INDICATORS
static unsigned char *RGBAPixMap = NULL;
static size_t RGBAPixMapSize = 0;
#endif

// The following will encapsulate the platform-specific font
class FontHandle {
   int width[128];
   encodingType et;
   int refcount;    // refcount to reduce expensive calls to Tk_GetFont calls
public:
   friend class FontHandleMgr;
   Tk_Font tkfont;
   int characterSet;
   FontHandle(Tk_Font tkfont_) {
      et = singleByte;
      tkfont = tkfont_;
      characterSet = -1;
      ResetWidths(et);
      refcount = 0;
   }
   ~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();
      }
   }
};

// reference counting manager (smart pointer for FontHandle Objects
class FontHandleMgr {
private:
    FontHandle *handle_p;
public:
    FontHandle* GetHandle()  { return handle_p; }
    FontHandle* operator->() { return handle_p; }
    FontHandle& operator*() { return *handle_p; }
    FontHandleMgr(FontHandle*p) { handle_p = p; ++p->refcount; }
    ~FontHandleMgr() {
        if (--handle_p->refcount == 0) {
            delete handle_p;
        }
    }
    FontHandleMgr(FontHandleMgr const &other) { handle_p = other.handle_p; ++handle_p->refcount; }
    FontHandleMgr & operator= (FontHandleMgr const &other) {
        // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
        // (This order properly handles self-assignment)
        // (This order also properly handles recursion, e.g., if a FontHandle contains FontHandleMgr)
        FontHandle* const old = handle_p;
        handle_p = other.handle_p;
        ++handle_p->refcount;
        if (--old->refcount == 0) {
            delete old;
        }
        return *this;
    }
};

// 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());
	FontHandle *h = (reinterpret_cast<FontHandleMgr *>(f.GetID()))->GetHandle();
    return h;
}


///////////////////////////////////////////////////////////
// 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);
private:
    void ImgBlendComplexAlpha(
        XImage *bgImg,                    /* Background image to draw on. */
        const unsigned char *pixelsImage, /* Image instance to draw. */
        int xOffset, int yOffset,         /* X & Y offset into image instance to
                                           * draw. */
        int width, int height);           /* Width & height of image to draw. */
    XImage *GetXImage(PRectangle rc, Tk_ErrorHandler handler);
};
#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 = static_cast<int>(pts[i].x);
            _y = static_cast<int>(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 = static_cast<int>(rc.left);
   int y = static_cast<int>(rc.top);
   int w = static_cast<int>(rc.right - rc.left);
   int h = static_cast<int>(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,
         static_cast<int>(rc.left), static_cast<int>(rc.top),
         static_cast<int>(rc.right - rc.left), static_cast<int>(rc.bottom - rc.top));
      Tcl_DoOneEvent(2); //DRAW NOW!!!!

      } else {
      XFillRectangle(display, pixmap, gc,
         static_cast<int>(rc.left), static_cast<int>(rc.top),
         static_cast<int>(rc.right - rc.left), static_cast<int>(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 = static_cast<int>(rc.left); xTile < rc.right; xTile += widthPat) {
         int widthx = (xTile + widthPat > rc.right) ? static_cast<int>(rc.right - xTile) : widthPat;
         for (int yTile = static_cast<int>(rc.top); yTile < rc.bottom; yTile += heightPat) {
            int heighty = (yTile + heightPat > rc.bottom) ? static_cast<int>(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);
   }
}

inline int CountBits(int mask)  /* Value to count the 1 bits in. */
{
    int n;

    for (n=0 ; mask!=0 ; mask&=mask-1) {
	n++;
    }
    return n;
}

XImage *SurfaceImpl::GetXImage(PRectangle rc, Tk_ErrorHandler handler) {
    int nreturned;
    XImage *bgImg = NULL;
    XVisualInfo * visInfo = XGetVisualInfo(display, 0, NULL, &nreturned);
    if ((visInfo->depth >= 15) && (visInfo->c_class == DirectColor || visInfo->c_class == TrueColor)) {
        int drawableX = static_cast<int>(rc.left);
        int drawableY = static_cast<int>(rc.top);
        int drawableWidth = static_cast<int>(rc.right - rc.left);
        int drawableHeight = static_cast<int>(rc.bottom - rc.top);
	    /*
	     * Pull the current background from the display to blend with
	     */

	    bgImg = XGetImage(display, pixmap /*Tk_WindowId(tkwin)*/, drawableX, drawableY,
		    (unsigned int)drawableWidth, (unsigned int)drawableHeight, AllPlanes, ZPixmap);
    }
    return bgImg;
}

void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
      ColourDesired outline, int alphaOutline, int flags) {
#if USE_SOLID_INDICATORS
    if (cornerSize)
        RoundedRectangle(rc, fill, fill);
    else
        FillRectangle(rc, fill);
#else
int drawableX = static_cast<int>(rc.left);
int drawableY = static_cast<int>(rc.top);
int width = static_cast<int>(rc.right - rc.left);
int height = static_cast<int>(rc.bottom - rc.top);

    /*
     * Create an error handler to suppress the case where the input was
     * not properly constrained, which can cause an X error. [Bug 979239]
     */

    Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, (ClientData) NULL);

    XImage *bgImg = GetXImage(rc, handler);
    if (bgImg) {
        int x, y;
        unsigned char *p;
        size_t desiredSize = 4*width*height;

        if (RGBAPixMapSize < desiredSize) {
            RGBAPixMap = (unsigned char*)realloc(RGBAPixMap, desiredSize);
            RGBAPixMapSize = desiredSize;
        }
        // build RGBA rectangle
        p = RGBAPixMap;
        for (y = 0; y < height; ++y) {
            for (x = 0; x < width; ++x) {
                if ((x==0) || (x==width-1) || (y == 0) || (y == height-1)) {
                    // boarder pixel
                    p[0] = outline.GetRed();
                    p[1] = outline.GetGreen();
                    p[2] = outline.GetBlue();
                    p[3] = alphaOutline;
                } else {
                    p[0] = fill.GetRed();
                    p[1] = fill.GetGreen();
                    p[2] = fill.GetBlue();
                    p[3] = alphaFill;
                }
                p += 4;
            }
        }
        if (cornerSize && (width > 4) && (height > 4)) {
            // round the corners of the rectangle by adjusting the alpha values
            p = RGBAPixMap;
            p[3] = 0; /* make top left two pixels transparent */
            p += 4;
            p[3] = 0;
            p += (4 * (width - 3)); /* now the top right two pixels */
            p[3] = 0;
            p += 4; 
            p[3] = 0;
            p += 4; /* now the first pixel on the left, one line down */
            p[3] = 0;
            p += 4; /* now the next pixel should be an outline pixel */
            p[0] = outline.GetRed();
            p[1] = outline.GetGreen();
            p[2] = outline.GetBlue();
            p[3] = alphaOutline;
            p += (4 * (width - 3)); /* then the 2nd from the right pixel, one line down */
            p[0] = outline.GetRed();
            p[1] = outline.GetGreen();
            p[2] = outline.GetBlue();
            p[3] = alphaOutline;
            p += 4; 
            p[3] = 0;
            p += 4 + (4 * (height - 4) * width); /* then the left pixel, two from the bottom */
            p[3] = 0;
            p += 4; 
            p[0] = outline.GetRed();
            p[1] = outline.GetGreen();
            p[2] = outline.GetBlue();
            p[3] = alphaOutline;
            p += (4 * (width - 3));
            p[0] = outline.GetRed();
            p[1] = outline.GetGreen();
            p[2] = outline.GetBlue();
            p[3] = alphaOutline;
            p += 4; 
            p[3] = 0;
            p += 4;
            p[3] = 0;
            p += 4;
            p[3] = 0;
            p += (4 * (width - 3));
            p[3] = 0;
            p += 4;
            p[3] = 0;
        }
        ImgBlendComplexAlpha(bgImg, RGBAPixMap, 0, 0, width,  height);
        TkPutImage(NULL, 0, display, pixmap/*Tk_WindowId(tkwin)*/, gc, bgImg, 0, 0, drawableX, drawableY, 
              (unsigned int)width, (unsigned int)height);
        XDestroyImage(bgImg);
    }
    Tk_DeleteErrorHandler(handler);
#endif
}

#ifndef __WIN32__
#define GetRValue(rgb)	(UCHAR(((rgb) & red_mask) >> red_shift))
#define GetGValue(rgb)	(UCHAR(((rgb) & green_mask) >> green_shift))
#define GetBValue(rgb)	(UCHAR(((rgb) & blue_mask) >> blue_shift))
#define RGB(r, g, b)	((unsigned)( \
	(UCHAR(r) << red_shift)   | \
	(UCHAR(g) << green_shift) | \
	(UCHAR(b) << blue_shift)  ))
#define RGB15(r, g, b)	((unsigned)( \
	(((r) * red_mask / 255)   & red_mask)   | \
	(((g) * green_mask / 255) & green_mask) | \
	(((b) * blue_mask / 255)  & blue_mask)  ))
#endif /* !__WIN32__ */

void SurfaceImpl::ImgBlendComplexAlpha(
    XImage *bgImg,                    /* Background image to draw on. */
    const unsigned char *pixelsImage, /* Image instance to draw. NULL means color fill */
    int xOffset, int yOffset,         /* X & Y offset into image instance to
                                       * draw. */
    int width, int height)            /* Width & height of image to draw. */
{
    int x, y, line;
    unsigned long pixel;
    unsigned char r, g, b, alpha, unalpha;
    const unsigned char *masterPtr = NULL;
    const unsigned char *alphaAr = pixelsImage;

    /*
     * This blending is an integer version of the Source-Over compositing rule
     * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH
     * 1984) that has been hard-coded (for speed) to work with targetting a
     * solid surface.
     *
     * The 'unalpha' field must be 255-alpha; it is separated out to encourage
     * more efficient compilation.
     */

#define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \
	((bgPix * unalpha + imgPix * alpha) / 255)

    /*
     * We have to get the mask and shift info from the visual on non-Win32 so
     * that the macros Get*Value(), RGB() and RGB15() work correctly. This
     * might be cached for better performance.
     */

#ifndef __WIN32__
    unsigned long red_mask, green_mask, blue_mask;
    unsigned long red_shift, green_shift, blue_shift;
    int depth;
    Colormap colormap;
    Visual *visual = Tk_GetVisual(interp, tkwin, "default", &depth, &colormap);

    red_mask = visual->red_mask;
    green_mask = visual->green_mask;
    blue_mask = visual->blue_mask;
    red_shift = 0;
    green_shift = 0;
    blue_shift = 0;
    while ((0x0001 & (red_mask >> red_shift)) == 0) {
	red_shift++;
    }
    while ((0x0001 & (green_mask >> green_shift)) == 0) {
	green_shift++;
    }
    while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
	blue_shift++;
    }
#endif /* !__WIN32__ */

    /*
     * Only UNIX requires the special case for <24bpp. It varies with 3 extra
     * shifts and uses RGB15. The 24+bpp version could also then be further
     * optimized.
     */

#if !(defined(__WIN32__) || defined(MAC_OSX_TK))
    if (bgImg->depth < 24) {
	unsigned char red_mlen, green_mlen, blue_mlen;

	red_mlen = 8 - CountBits(red_mask >> red_shift);
	green_mlen = 8 - CountBits(green_mask >> green_shift);
	blue_mlen = 8 - CountBits(blue_mask >> blue_shift);
	for (y = 0; y < height; y++) {
	    line = (y + yOffset) * width;
	    for (x = 0; x < width; x++) {

        /* if we're merging images, get the RGBA value for the current pixel */
        masterPtr = alphaAr + ((line + x + xOffset) * 4);
        alpha = masterPtr[3];

		/*
		 * Ignore pixels that are fully transparent
		 */

		if (alpha) {
		    /*
		     * We could perhaps be more efficient than XGetPixel for
		     * 24 and 32 bit displays, but this seems "fast enough".
		     */

            r = masterPtr[0];
            g = masterPtr[1];
            b = masterPtr[2];

            if (alpha != 255) {
                /*
                 * Only blend pixels that have some transparency
                 */
                unsigned char ra, ga, ba;

                pixel = XGetPixel(bgImg, x, y);
                ra = GetRValue(pixel) << red_mlen;
                ga = GetGValue(pixel) << green_mlen;
                ba = GetBValue(pixel) << blue_mlen;
                unalpha = 255 - alpha;	/* Calculate once. */
                r = ALPHA_BLEND(ra, r, alpha, unalpha);
                g = ALPHA_BLEND(ga, g, alpha, unalpha);
                b = ALPHA_BLEND(ba, b, alpha, unalpha);
            }
		    XPutPixel(bgImg, x, y, RGB15(r, g, b));
		}
	    }
	}
	return;
    }
#endif /* !__WIN32__ && !MAC_OSX_TK */
    for (y = 0; y < height; y++) {
	line = (y + yOffset) * width;
	for (x = 0; x < width; x++) {
        /* if we're merging images, get the RGBA value for the current pixel */
        masterPtr = alphaAr + ((line + x + xOffset) * 4);
        alpha = masterPtr[3];

	    /*
	     * Ignore pixels that are fully transparent
	     */

	    if (alpha) {
		/*
		 * We could perhaps be more efficient than XGetPixel for 24
		 * and 32 bit displays, but this seems "fast enough".
		 */

        r = masterPtr[0];
        g = masterPtr[1];
        b = masterPtr[2];
		if (alpha != 255) {
		    /*
		     * Only blend pixels that have some transparency
		     */
		    unsigned char ra, ga, ba;

		    pixel = XGetPixel(bgImg, x, y);
		    ra = GetRValue(pixel);
		    ga = GetGValue(pixel);
		    ba = GetBValue(pixel);
		    unalpha = 255 - alpha;	/* Calculate once. */
		    r = ALPHA_BLEND(ra, r, alpha, unalpha);
		    g = ALPHA_BLEND(ga, g, alpha, unalpha);
		    b = ALPHA_BLEND(ba, b, alpha, unalpha);
		}
		XPutPixel(bgImg, x, y, RGB(r, g, b));
	    }
	}
    }
#undef ALPHA_BLEND
}

void SurfaceImpl::DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) {
    int drawableX = static_cast<int>(rc.left);
    int drawableY = static_cast<int>(rc.top);

    /*
     * If there's no pixmap, it means that an error occurred while creating
     * the image instance so it can't be displayed.
     */

    if (pixelsImage == NULL) {
        fprintf(stderr, "pixelsImage = %p\n", pixelsImage);
        return;
    }

	/*
	 * Create an error handler to suppress the case where the input was
	 * not properly constrained, which can cause an X error. [Bug 979239]
	 */

	Tk_ErrorHandler handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL,
		(ClientData) NULL);

	/*
	 * Pull the current background from the display to blend with
	 */

	XImage *bgImg = GetXImage(rc, handler);
	if (bgImg != NULL) {
	    ImgBlendComplexAlpha(bgImg, pixelsImage, 0, 0, width, height);

	    /*
	     * Color info is unimportant as we only do this operation for depth >=
	     * 15.
	     */
        TkPutImage(NULL, 0, display, pixmap/*Tk_WindowId(tkwin)*/, gc, 
                  bgImg, 0, 0, drawableX, drawableY, 
                  (unsigned int)width, (unsigned int)height);
	    XDestroyImage(bgImg);
    }
	Tk_DeleteErrorHandler(handler);
}

void SurfaceImpl::Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) {

   static int full_circle = 64 * 360;
   PenColour(back);
   XFillArc(display, pixmap, gc,
      static_cast<int>(rc.left + 1), static_cast<int>(rc.top + 1),
      static_cast<int>(rc.right - rc.left - 2), static_cast<int>(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,
      static_cast<int>(rc.left), static_cast<int>(rc.top),
      static_cast<int>(rc.right - rc.left - 1), static_cast<int>(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,static_cast<int>(rc.left), static_cast<int>(rc.top),static_cast<int>(rc.right - rc.left), static_cast<int>(rc.bottom - rc.top),static_cast<int>(rc.left), static_cast<int>(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,static_cast<int>(from.x), static_cast<int>(from.y),static_cast<int>(rc.right - rc.left), static_cast<int>(rc.bottom - rc.top), static_cast<int>(rc.left), static_cast<int>(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, static_cast<int>(rc.left), static_cast<int>(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;
      XYPOSITION totalWidth = 0.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.0;
      }
   }
}

XYPOSITION SurfaceImpl::WidthText(Scintilla::Font &font_, const char *s, int len) {
	if (font_.GetID()) {
            return (XYPOSITION)Tk_TextWidth(PFont(font_)->tkfont, s, len);
	} else {
		return 10.0;
	}
}

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.0;
   }
   Tk_FontMetrics fm;
   Tk_GetFontMetrics(PFont(font_)->tkfont, &fm);
   return (XYPOSITION)fm.ascent;
}

XYPOSITION SurfaceImpl::Descent(Scintilla::Font &font_) {
	if (!(font_.GetID()))
		return 1.0;
   Tk_FontMetrics fm;
   Tk_GetFontMetrics(PFont(font_)->tkfont, &fm);
   return (XYPOSITION)fm.descent;
}

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

XYPOSITION SurfaceImpl::ExternalLeading(Scintilla::Font &) {
   return 0.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.
 *
 *----------------------------------------------------------------------
 */

static Tcl_PackageInitProc *
sTclpFindSymbol(
    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

#ifdef  __linux

#include "dlfcn.h"

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

static Tcl_PackageInitProc *
sTclpFindSymbol(
    Tcl_Interp *interp,		/* Place to put error messages. */
    Tcl_LoadHandle loadHandle,	/* Value from TcpDlopen(). */
    CONST char *symbol)		/* Symbol to look up. */
{
    CONST char *native;
    Tcl_DString newName, ds;
    VOID *handle = (VOID*)loadHandle;
    Tcl_PackageInitProc *proc;

    /*
     * Some platforms still add an underscore to the beginning of symbol
     * names. If we can't find a name without an underscore, try again with
     * the underscore.
     */

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
    proc = (Tcl_PackageInitProc *) dlsym(handle,	/* INTL: Native. */
	    native);
    if (proc == NULL) {
	Tcl_DStringInit(&newName);
	Tcl_DStringAppend(&newName, "_", 1);
	native = Tcl_DStringAppend(&newName, native, -1);
	proc = (Tcl_PackageInitProc *) dlsym(handle,	/* INTL: Native. */
		native);
	Tcl_DStringFree(&newName);
    }
    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*) sTclpFindSymbol(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() {}

static Tcl_HashTable *fontTable = NULL;

void Font::Create(const FontParameters &fp) {
Tcl_HashEntry *hPtr = NULL;
int isNew;

//fprintf(stderr,"Font::Create ((%p))--> %s / %f / %d / italic=%d\n",(void *)this,fp.faceName,fp.size,fp.weight,fp.italic);

    if (fontTable == NULL) {
        // cache fonts to improve performance
        fontTable = new Tcl_HashTable;
        Tcl_InitHashTable(fontTable, TCL_STRING_KEYS);
    }

//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);
   }

   // Use hash table of previously created font descriptions as Tcl_Obj*
   // so we can realize a performance boost in Tk_AllocFontFromObj which
   // caches information in the Tcl_Obj.
   hPtr = Tcl_CreateHashEntry(fontTable, Tcl_GetString(objPtr), &isNew);
   FontHandle *p;
   if (isNew) {
      Tk_Font tkf = Tk_GetFont(Tk_Interp(_curr_tkwin),_curr_tkwin, Tcl_GetString(objPtr));
      p = new FontHandle(tkf);
      Tcl_SetHashValue(hPtr, new FontHandleMgr(p));
   } else {
      FontHandleMgr *mgrp = (FontHandleMgr *)Tcl_GetHashValue(hPtr);   // reuse existing object
      p = mgrp->GetHandle();
   }

   fid = new FontHandleMgr(p);
}

void Font::Release() {
   if (fid) {
      delete reinterpret_cast<FontHandleMgr *>(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       = static_cast<int>(rc.left);
    e.xexpose.y       = static_cast<int>(rc.top);
    e.xexpose.width   = static_cast<int>(rc.right - rc.left);
    e.xexpose.height  = static_cast<int>(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

Changes to tk/README.

41
42
43
44
45
46
47

48
49
50
51
52
53
54
..
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

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









>







 







<







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
72
73
74
75
76
77
78

79
80
81
82
83
84
85

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.h
ScintillaTK.cxx
sciwrappers.cxx
sciwrappers.h
scintilla-ext.cxx
scintilla-ext.h
scintilla-cmd.cxx
scintilla-cmd.h
................................................................................
=================
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.


src/
    Editor.cxx - Force number conversion via casts.
    XPM.h    - Support 1-4 character color indexes.
    XPM.cxx    This allows more colorful marker images.


Deleted 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/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 "ScintillaTk.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 ScintillaTk.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 ScintillaTk.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/ScintillaTk.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
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ScintillaTK.h - 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.

#ifndef SCINTILLATKWIDGET
#define SCINTILLATKWIDGET

#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

Changes to tk/configure.

1
2
3
4
5
6
7
8
9
10
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
...
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
....
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
.....
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
.....
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for ScintillaTk 0.26.
#
# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##
................................................................................
# This variable seems obsolete.  It should probably be removed, and
# only ac_max_sed_lines should be used.
: ${ac_max_here_lines=38}

# Identity of this package.
PACKAGE_NAME='ScintillaTk'
PACKAGE_TARNAME='scintillatk'
PACKAGE_VERSION='0.26'
PACKAGE_STRING='ScintillaTk 0.26'
PACKAGE_BUGREPORT=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
................................................................................
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures ScintillaTk 0.26 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.
................................................................................

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then
  case $ac_init_help in
     short | recursive ) echo "Configuration of ScintillaTk 0.26:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-threads        build with threads
................................................................................
    cd $ac_popdir
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF
ScintillaTk configure 0.26
generated by GNU Autoconf 2.59

Copyright (C) 2003 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
fi
exec 5>config.log
cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by ScintillaTk $as_me 0.26, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  $ $0 $@

_ACEOF
{
cat <<_ASUNAME
................................................................................
# 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.
#-----------------------------------------------------------------------


    vars="PlatTK.cxx ScintillaTK.cxx sciwrappers.cxx scintilla-cmd.cxx scintilla-ext.cxx"
    for i in $vars; do
	case $i in
	    \$*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;
................................................................................
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

This file was extended by ScintillaTk $as_me 0.26, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@
................................................................................
$config_files

Report bugs to <bug-autoconf@gnu.org>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
ScintillaTk config.status 0.26
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=$srcdir


|







 







|
|







 







|







 







|







 







|













|







 







|







 







|







 







|







1
2
3
4
5
6
7
8
9
10
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
...
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
....
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
.....
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
.....
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for ScintillaTk 0.29.
#
# Copyright (C) 2003 Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## --------------------- ##
## M4sh Initialization.  ##
## --------------------- ##
................................................................................
# This variable seems obsolete.  It should probably be removed, and
# only ac_max_sed_lines should be used.
: ${ac_max_here_lines=38}

# Identity of this package.
PACKAGE_NAME='ScintillaTk'
PACKAGE_TARNAME='scintillatk'
PACKAGE_VERSION='0.29'
PACKAGE_STRING='ScintillaTk 0.29'
PACKAGE_BUGREPORT=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
................................................................................
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures ScintillaTk 0.29 to adapt to many kinds of systems.

Usage: $0 [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.
................................................................................

  cat <<\_ACEOF
_ACEOF
fi

if test -n "$ac_init_help"; then
  case $ac_init_help in
     short | recursive ) echo "Configuration of ScintillaTk 0.29:";;
   esac
  cat <<\_ACEOF

Optional Features:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --enable-threads        build with threads
................................................................................
    cd $ac_popdir
  done
fi

test -n "$ac_init_help" && exit 0
if $ac_init_version; then
  cat <<\_ACEOF
ScintillaTk configure 0.29
generated by GNU Autoconf 2.59

Copyright (C) 2003 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit 0
fi
exec 5>config.log
cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.

It was created by ScintillaTk $as_me 0.29, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  $ $0 $@

_ACEOF
{
cat <<_ASUNAME
................................................................................
# 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.
#-----------------------------------------------------------------------


    vars="PlatTk.cxx ScintillaTk.cxx sciwrappers.cxx scintilla-cmd.cxx scintilla-ext.cxx"
    for i in $vars; do
	case $i in
	    \$*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;
................................................................................
  echo
  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
} >&5
cat >&5 <<_CSEOF

This file was extended by ScintillaTk $as_me 0.29, which was
generated by GNU Autoconf 2.59.  Invocation command line was

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@
................................................................................
$config_files

Report bugs to <bug-autoconf@gnu.org>."
_ACEOF

cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
ScintillaTk config.status 0.29
configured by $0, generated by GNU Autoconf 2.59,
  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

Copyright (C) 2003 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
srcdir=$srcdir

Changes to tk/configure.in.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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.
#--------------------------------------------------------------------

................................................................................
# 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])







|







 







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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.29])

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

................................................................................
# 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])

Changes to tk/doc/demos/ypedit.tcl.

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	}
   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 --







|


|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	}
   while { ! [ eof $infile ] } {
      gets $infile line
      $textw insert end $line
      $textw insert end "\n"
   }

	$textw tag configure pink -annotation -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 -annotation -bold 1 -background #4444ff -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 --

Added tk/pkgIndex.tcl.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
# Tcl package index file - handcrafted

# NOTE: keep version string in sync with the line
#       containing Tcl_PkgProvide in widget.cxx

package ifneeded ScintillaTk 0.1 "\
   load [file join $dir libscintilla[info sharedlibextension]];\
   source [file join $dir widget-bindings.tcl]"

Changes to tk/scintilla-cmd.cxx.

4
5
6
7
8
9
10











11
12
13



14
15
16
17
18
19
20
..
28
29
30
31
32
33
34

35
36
37
38
39





40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56
57











58
59
60
61
62
63
64
...
147
148
149
150
151
152
153



154
155
156
157
158
159
160
...
452
453
454
455
456
457
458
459
460
461
462
463
464















































































































































































































































































































465
466
467
468
469
470
471
...
477
478
479
480
481
482
483











































484
485
486
487
488
489
490
491
492
493

494
495
496
497
498
499
500
...
535
536
537
538
539
540
541

542
543
544
545
546
547
548



549
550
551
552
553
554
555
...
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
...
637
638
639
640
641
642
643

644
645
646
647
648
649
650
...
783
784
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
...
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
....
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
....
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
....
1318
1319
1320
1321
1322
1323
1324
1325

1326
1327
1328
1329
1330
1331
1332
1333
....
1405
1406
1407
1408
1409
1410
1411

1412
1413
1414
1415
1416
1417
1418
1419
....
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
....
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
....
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
....
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
....
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
....
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
....
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
....
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
....
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828

2829
2830
2831
2832
2833
2834
2835
2836
....
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
....
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
....
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
....
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
....
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
....
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
....
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
....
5734
5735
5736
5737
5738
5739
5740



















5741
5742
5743
5744
5745
5746
5747
....
5750
5751
5752
5753
5754
5755
5756


5757
5758
5759
5760
5761
5762
5763
....
5941
5942
5943
5944
5945
5946
5947












5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
....
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
....
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
....
6102
6103
6104
6105
6106
6107
6108

6109
6110
6111
6112
6113
6114
6115
....
6163
6164
6165
6166
6167
6168
6169

6170
6171
6172
6173
6174
6175
6176
....
6366
6367
6368
6369
6370
6371
6372



6373
6374
6375


6376
6377
6378
6379
6380
6381
6382
....
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
....
6473
6474
6475
6476
6477
6478
6479

6480
6481
6482
6483
6484
6485


6486
6487
6488




6489
6490
6491
6492
6493
6494
6495
....
6610
6611
6612
6613
6614
6615
6616

6617
6618
6619
6620
6621
6622
6623
....
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
....
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
....
7055
7056
7057
7058
7059
7060
7061










































7062
7063
7064
7065
7066
7067
7068
....
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
....
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
....
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
....
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
....
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
....
9513
9514
9515
9516
9517
9518
9519



9520
9521
9522
9523
9524
9525
9526
9527
....
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547






9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
....
9561
9562
9563
9564
9565
9566
9567




9568
9569

9570
9571
9572
9573
9574
9575
9576
....
9632
9633
9634
9635
9636
9637
9638




9639
9640
9641
9642
9643
9644
9645
....
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
....
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
....
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
....
9787
9788
9789
9790
9791
9792
9793


9794
9795
9796

9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
....
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867



9868
9869
9870
9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916

9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942













9943















9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958

9959
9960
9961
9962
9963
9964
9965
9966
9967
9968
9969
9970
9971
9972
9973


9974
9975
9976
9977
9978
9979




9980
9981
9982
9983
9984
9985
9986
9987


9988

9989
9990
9991
9992
9993

9994
9995
9996
9997
9998
9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036

10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
.....
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121




10122
10123

10124
10125
10126
10127
10128
10129
10130
10131



10132
10133














































10134
10135

10136



10137
10138
10139
10140
10141
10142
10143
.....
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
.....
10221
10222
10223
10224
10225
10226
10227



















10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239

10240

10241


10242


10243


10244


10245


10246


10247

10248
10249
10250
10251
10252
10253









10254
10255
10256
10257
10258
10259










10260



10261
10262





10263





10264
10265
10266
10267
10268
10269






10270






10271
10272
10273
10274




10275



10276



10277
10278
10279

10280
10281
10282
10283





10284
10285
10286
10287
10288
10289
10290
.....
10318
10319
10320
10321
10322
10323
10324







10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357


10358
10359
10360
10361
10362
10363
10364
10365
10366
10367
10368
.....
10369
10370
10371
10372
10373
10374
10375



10376
10377
10378
10379
10380
10381
10382
10383
10384



10385
10386
10387
10388
10389
10390



10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
.....
10440
10441
10442
10443
10444
10445
10446


10447
10448
10449
10450
10451
10452
10453

10454
10455
10456

10457
10458



10459
10460


10461
10462
10463
10464
10465
10466
10467
.....
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
.....
10586
10587
10588
10589
10590
10591
10592


10593
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606














10607




10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618





10619
10620
10621
10622
10623
10624
10625
.....
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
.....
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
.....
10733
10734
10735
10736
10737
10738
10739
10740
10741

10742
10743
10744
10745
10746
10747
10748
.....
10753
10754
10755
10756
10757
10758
10759


10760
10761
10762
10763
10764
10765
10766
.....
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
.....
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104
11105






11106
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
.....
11422
11423
11424
11425
11426
11427
11428
11429

11430
11431
11432
11433
11434
11435
11436
.....
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520

11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533

11534
11535
11536
11537
11538

11539



11540
11541

11542
11543
11544
11545
11546

11547
11548






11549
11550


11551
11552
11553

11554
11555

11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
.....
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
.....
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
.....
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860
11861
.....
12153
12154
12155
12156
12157
12158
12159
12160





























































































































































































































12161
//# open-source text editor
//#
//# NOTE: DUE TO TECHNICAL CHALLENGES WITH MANAGING THE SCINTILLA
//#       DRAWING, WE DO __NOT__ SUPPORT A BORDER OR HIGHLIGHT
//#       RECTANGLE AS PART OF THIS NEW WIDGET.
//#
//#####################################################################











// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.





#include <assert.h>
#include <tcl.h>
#include <tk.h>
#include <tkInt.h> // for access to "region" features

#ifdef _WIN32
................................................................................
#endif
#endif

#include "sciwrappers.h"
#include "scintilla-ext.h"
#include "scintilla-cmd.h"


#include <vector>

#ifndef F_OK
#define F_OK 0
#endif






#ifdef DEBUG
static void _DBG(const char *format, ...) {
   char buffer[2000];
   va_list pArguments;
   va_start(pArguments, format);
   vsprintf(buffer, format, pArguments);
   va_end(pArguments);
   fprintf(stderr, "%s", buffer);
}
#else
static void _DBG(const char *, ...) {}
#endif

Tcl_Interp *scintilla_interp = NULL;


// create our namespace
namespace TkSci {












//--------------------------------------------------------------------------
// local convenience macros
#define SSM(m, w, l) scintilla_send_message(sciwidgetPtr->editor, m, w, l)

// set color based on 0-255 values for RGB
#define _RGB_(r,g,b) r | (g << 8) | (b << 16)
................................................................................
            "5", -1, Tk_Offset(SciWidget, borderWidth), 0, 0, TK_SCI_LINE_GEOMETRY
      },
      {TK_OPTION_CURSOR,  "-busycursor", "cursor", "Cursor",
            "watch", -1, Tk_Offset(SciWidget, busycursor), TK_OPTION_NULL_OK, 0, OPT_CURSOR
      },
      {TK_OPTION_CURSOR,  "-cursor", "cursor", "Cursor",
            "xterm", -1, Tk_Offset(SciWidget, cursor), TK_OPTION_NULL_OK, 0, OPT_CURSOR



      },
      {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, 
            NULL, 0, -1, 0, (ClientData)"-foreground", 0
      },
      {TK_OPTION_STRING_TABLE, "-foldstyle", "foldstyle", "FoldStyle",
            "boxtree", -1, Tk_Offset(SciWidget, foldstyle), 0, (ClientData) foldStrings, OPT_FOLDM
      },
................................................................................
static void SciWidgetDestroy     (ClientData clientData);
static void SciWidgetGeometry    (SciWidget *);
static void SciWidgetBindProc    (ClientData clientData, XEvent *eventPtr);
static void SciWidgetEventProc   (ClientData clientData, XEvent *eventPtr);
static int  SciWidgetInstanceCmd (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

//--- others
static int      GetPosition(SciWidget *, CONST char *, int *, bool);
static Tcl_Obj* GetTextRange(SciWidget *, int, int, bool);
static void     ExtractText(SciWidget *, Tcl_Obj *, int, int);
static void     SortTags(int numTags, TagData **tagArrayPtr);
static int      TagSortProc(const void *first, const void *second);


















































































































































































































































































































/***********************************************************
 * Scintillatk_Init is called when the package is loaded.
 ***********************************************************/
#define SCI_VERSION  PACKAGE_VERSION
#define SCI_VER_DATE PACKAGE_DATE
................................................................................

   Tcl_CreateObjCommand(interp, "scintilla", SciWidgetCmd, (ClientData)NULL, SciWidgetDestroy);

   Tcl_PkgProvide(interp, "ScintillaTk", SCI_VERSION);
   scintilla_interp = interp;
   return TCL_OK;
}












































static int
SciWidgetCmd(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   SciWidget *sciwidgetPtr;
   Tk_Window tkwin;


   tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), NULL);
   if (tkwin == NULL) {
      return TCL_ERROR;
   }
   /*
    * Set resource class.
................................................................................
   sciwidgetPtr->readonly    = false;
   sciwidgetPtr->language    = NULL;
   sciwidgetPtr->langType    = SCLEX_NULL; // defined in include/SciLexer.h
   sciwidgetPtr->foldstyle   = foldBoxTree;
   sciwidgetPtr->busycursor  = None;
   sciwidgetPtr->cursor      = None;
   sciwidgetPtr->blinkcaret  = NULL;

   sciwidgetPtr->linesAddedCmd  = NULL;
   sciwidgetPtr->marginWidthCmd = NULL;
   sciwidgetPtr->moveUpdateCmd  = NULL;
   sciwidgetPtr->xScrollCmd     = NULL;
   sciwidgetPtr->yScrollCmd     = NULL;
   sciwidgetPtr->yscrollDelta = 0;
   sciwidgetPtr->styleBits = 5; // default is 5, may change when language changes



   sciwidgetPtr->added_data = new SciWidgetLinesAdded;
   sciwidgetPtr->marginMgr  = new MarginMgr(sciwidgetPtr);
   sciwidgetPtr->tagMgr     = new TagMgr(sciwidgetPtr);
   sciwidgetPtr->markerMgr  = new MarkerMgr(sciwidgetPtr);
   sciwidgetPtr->markMgr    = new MarkMgr(sciwidgetPtr);
   sciwidgetPtr->bindingTable = NULL;

................................................................................
   //       OF TEXT WHEN A NON-ZERO PADDING WAS USED ON THE RIGHT SIDE. SO WE WILL
   //       LELAVE IT UP TO THE CLIENT WINDOW TO PROVIDE RHS PADDING.
   sci_set_padding(SCIOBJ(sciwidgetPtr), 4, 0);

   // turn off display of the extra carets which by default are
   // drawn at the edge of each "sub region" of the rectangle
   sci_cmd(SCIOBJ(sciwidgetPtr), SCI_SETADDITIONALCARETSVISIBLE, 0);




   // Register a handler for when the window is exposed or resized.
   //
   Tk_CreateEventHandler(sciwidgetPtr->tkwin,
      ExposureMask|StructureNotifyMask|FocusChangeMask,
      SciWidgetEventProc, (ClientData) sciwidgetPtr);

................................................................................
   // Register a handler for events that client could define bindings for
   Tk_CreateEventHandler(sciwidgetPtr->tkwin,
       ButtonPressMask|ButtonReleaseMask|
       EnterWindowMask|LeaveWindowMask|
       PointerMotionMask|VirtualEventMask,
      SciWidgetBindProc, (ClientData) sciwidgetPtr);

//TODO: SciWidgetCmd >> use Tk_CreateSelHandler for support for selection changes


   // Create a Tcl command that operates on the widget.
   //
   sciwidgetPtr->widgetCmd =
      Tcl_CreateObjCommand(interp, Tk_PathName(sciwidgetPtr->tkwin),
         SciWidgetInstanceCmd,
         (ClientData) sciwidgetPtr,
         NULL);

   // Parse the command line arguments.
   //
   sciwidgetPtr->optionTable = Tk_CreateOptionTable(interp, optionSpecs);

   if (Tk_InitOptions(interp, (char *)sciwidgetPtr,
         sciwidgetPtr->optionTable, sciwidgetPtr->tkwin) != TCL_OK) {
................................................................................
   /*
    * This frees up colors and fonts and any allocated
    * storage associated with the widget attributes.
    */
   if (sciwidgetPtr->tkwin) {
	Tk_FreeConfigOptions((char *)sciwidgetPtr, sciwidgetPtr->optionTable, sciwidgetPtr->tkwin);
   }


   // other cleanup
   delete sciwidgetPtr->markerMgr;
   // marginMgr must be destroyed after markerMgr!
   delete sciwidgetPtr->marginMgr;
   delete sciwidgetPtr->markMgr;
   delete sciwidgetPtr->tagMgr;
................................................................................
         // stop here the "thumb" height will shrink, giving the user a
         // false sense of where in the document they are.
          keep_going = false;
      }
      SSM(SCI_SETFIRSTVISIBLELINE, topline, 0);
      if (!keep_going) return;

//using the following seems to screw up the repaint -- also, the DesignPad editor
//doesn't move the caret during a scrollbar drag, so not using it(for now) is ok

//SSM(SCI_MOVECARETINSIDEVIEW,0,0);

   } else {
      topline = SSM(SCI_GETFIRSTVISIBLELINE, 0,0);
   }
   // NOTE: This is same way that Tk's text widget does it(see
   // the GetYView function in tkTextDisp.c)
   char buf1[TCL_DOUBLE_SPACE+1];
................................................................................
      }
      case CMD_INSERT: {
         result = CmdInsert(clientData, interp, objc, objv);
         break;
      }
      case CMD_KEYWORDS: {
         int keywordSet;
         /* 1st argument is keyword number 0-9, followed by a string defining keyword set */
         /* objv[2] == keyword number */
         /* objv[3] == cmd list */
         if (objc != 4) {
            Tcl_WrongNumArgs(interp, 1, objv, "number keywords");
            return TCL_ERROR;
         }
         if (Tcl_GetIntFromObj(interp, objv[2], &keywordSet) != TCL_OK) {
            return TCL_ERROR;
         }






         SSM(SCI_SETKEYWORDS, keywordSet, (sptr_t)Tcl_GetString(objv[3]));








         break;
      }
      case CMD_LOADLEXER: {
         result = CmdLoadLexer(clientData, interp, objc, objv);
         break;
      }
      case CMD_MARGIN: {
................................................................................
      }
      case CMD_MARKER: {
         result = sciwidgetPtr->markerMgr->InstanceCmd(objc, objv);
         break;
      }
      case CMD_PROPERTY: {
         /* 1st argument is property name if 2nd argument exists, set the property; otherwise return the property */
         if ((objc != 3) && (objc != 4)) {
            Tcl_WrongNumArgs(interp, 1, objv, "property ?value?");
            return TCL_ERROR;
         }
         if (objc == 4) {
            SSM(SCI_SETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),(sptr_t)Tcl_GetString(objv[3]));
         } else {

            int len = SSM(SCI_GETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),0);
            if (len > 0) {
                char *buf = new char[len+1];
                len = SSM(SCI_GETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),(sptr_t)buf);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, len));
                delete[] buf;
            }





         }
         break;
      }
      case CMD_SEARCH: {
         result = CmdSearch(clientData, interp, objc, objv);
         break;
      }
................................................................................
 */
static int ExpandTabs(
   ClientData clientData,
   char      **_str)
{
   // We do Tab substitutions now since Scintilla doesn't
   // handle this for annotation strings
   char *str = *_str;
   size_t slen = strlen(str);
   int ntabs = 0;

   for (size_t i=0; i < slen; i++) if (str[i] == '\t') ntabs++;

   if (ntabs == 0) return 0;



   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   int tw = sciwidgetPtr->tabwidth; // current tab width


   int newlen = (slen - ntabs) + (ntabs * tw) + 1;
   char *buf = (char *) Tcl_Alloc(newlen);
   buf[newlen-1] = '\0';

   int offset = 0;
   for (size_t i=0; i < slen; i++) {

      if (str[i] != '\t') {
         strncpy(buf+offset, str+i, 1);

         offset++;
      } else {

         for (int j=0; j < tw; j++) {
            strncpy(buf+offset+j, " ", 1);
         }
         offset += tw;
      }
   }

   *_str = buf;
   return ntabs;
}


/*
 *----------------------------------------------------------------------
................................................................................
            int ntabs = ExpandTabs(clientData, &str);

            sci_cmd(sciobj, SCI_ANNOTATIONSETTEXT,  line, (sptr_t)str);
            if (ntabs)
               Tcl_Free(str);

            // if we have a valid tag, use it to set the style
            if (tag) {

               sci_cmd(sciobj, SCI_ANNOTATIONSETSTYLE, line, tag->StyleID());

               // as per Neil H. on 6/26/2012, the lack of support for the
               // following setting for attribute styles is a "limitation"
               //SSM(SCI_STYLESETEOLFILLED, tag->StyleID(), 0);
            }
            return TCL_OK;
         }
................................................................................
 */
static int CmdBbox(
    ClientData     clientData,
    Tcl_Interp    *interp,
    int            objc,
    Tcl_Obj *CONST objv[])
{

    int pos, endpos, x, y, width, line, line_ht, r_edge;
    char *index_str;

    if (objc != 3) {
        Tcl_WrongNumArgs(interp, 2, objv, "index");
        return TCL_ERROR;
    }
    SciWidget *sciwidgetPtr = (SciWidget *)clientData;
................................................................................
        width = (r_edge - x);
        if (width < 0) width = 0;
    } else if (x > r_edge) {
        // not at end of line, but outside visible area
        width = 0; //<< same as Tk Text widget behavior
    } else {
        char buf[2];
        int sid = sci_cmd(sciobj, SCI_GETSTYLEAT, pos);
        buf[0]  = sci_cmd(sciobj, SCI_GETCHARAT, pos);
        buf[1]  = '\0';
        width = sci_cmd(sciobj, SCI_TEXTWIDTH, sid, (sptr_t)buf);
    }
    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
................................................................................
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str, *op;
   int slen;
   int pos1 = -1;
   int pos2 = -1;

   if (objc != 5) {
      Tcl_WrongNumArgs(interp, 2, objv, "index1 op index2");
      return TCL_ERROR;
   }
   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   
................................................................................
static int CmdCount(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str, *option;
   int pos1 = -1;
   int pos2 = -1;
   int i = 0, found = 0, value = 0;
   Tcl_Obj *objPtr = NULL;

   if (objc < 4) {
      Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 index2");
      return TCL_ERROR;
   }
................................................................................
static int CmdDelete(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str;
   int pos1 = -1;
   int pos2 = -1;

   if (objc < 3) {
      Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2? ...?");
      return TCL_ERROR;
   }
   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   if (sciwidgetPtr->state == STATE_NORMAL) {
................................................................................
    if (i >= objc) {
        Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 ?index2?");
        return TCL_ERROR;
    }

    SciWidget *sciwidgetPtr = (SciWidget *)clientData;
    ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);
    int pos1 = -1;
    int pos2 = -1;
    char *index_str = Tcl_GetString(objv[i++]);
    if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
        goto error;
    }
    if (i < objc) {
        index_str = Tcl_GetString(objv[i++]);
        if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
................................................................................
   }
   // At this point, the value of "i" will be an argument
   // which should correspond with an index

   for (; i < objc; i += 2) {
      index_str = Tcl_GetString(objv[i]);

      int pos1 = -1;
      int pos2 = -1;
      if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
         goto error;
      }
      if (pos1 == -1) goto done; // index is valid, but not within document

      if (i+1 == objc) {
         // just a single index, either alone or as a single index
................................................................................
            SSM(SCI_GETTEXTRANGE,0,(sptr_t)&tr);
            //printf(">>>> FOUND (%d -> %d) <%s>\n",beg,end,tr.lpstrText);
            delete tr.lpstrText;
#endif
         }
      }
   } else {
      int pos = -1;
      if (GetPosition(sciwidgetPtr, ix, &pos, false) == TCL_OK) {
         if (pos == -1) {
             // index was a valid format, but couldn't be found
             goto done;
         }
         PosToIndex(interp, obj, pos);
         goto done;
................................................................................
            int new_ln = (plus ? (start_ln + num) : (start_ln - num));
            if (new_ln > sci_get_line_count(obj)) {
               // beyond last line, so use offset to end of document
               *offset = (sci_get_length(obj) - start_pos);
               return TCL_OK;
            }
            if (new_ln < 0) {
               *offset = start_pos;
               return TCL_OK;
            }
            // ok, so we know we'll land on a valid line. check that it
            // has a column to match the starting position, and if not
            // then use its end of line
            int endcol = sci_get_line_length(obj, new_ln);
            endcol--; // ignore eol char
................................................................................
 *    None.
 *
 *---------------------------------------------------------------------------
 */
static int GetPosition(
   SciWidget  *sciwidgetPtr,
   CONST char *index_str,
   int        *posPtr,
   bool        visible)
{
    char *cp, *endp;

    int offset, curr_pos, pos, line;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    if (index_str[0] == '@') {
        //----------------------
        //---  @X,Y
        //----------------------
        int x, y;
................................................................................

   if (sciwidgetPtr->state == STATE_NORMAL) {

      char *index_str = Tcl_GetString(objv[2]);
      char *to_add    = Tcl_GetString(objv[3]);

      // get the position where we'll do the add
      int pos;
      if (GetPosition(sciwidgetPtr, index_str, &pos, false) != TCL_OK) {
         return TCL_ERROR;
      }
      sci_add_text(obj, pos, to_add);
   }
   return TCL_OK;
}
................................................................................
   };

   // Parse the switch options
   int i, argsLeft, found;
   bool back = false;
   char *pattern, *index_str;
   Tcl_Obj *count_var = NULL;
   int pos1 = -1;
   int pos2 = -1;
   int flags = SCFIND_MATCHCASE; // default search flags

   for (i=2; i < objc; i++) {
      int index;

      if (Tcl_GetString(objv[i])[0] != '-') break;

................................................................................

   /*
	* Find the optional end location, similarly.
	*/

   if (toPtr != NULL) {
		SciWidget *sciwidgetPtr = (SciWidget *)searchSpecPtr->clientData;
		int posTo, posFrom;

		if (GetPosition(sciwidgetPtr, Tcl_GetString(toPtr), &posTo, false) != TCL_OK) {
			 return BadIndex(interp, Tcl_GetString(toPtr));
		}

		if (GetPosition(sciwidgetPtr, Tcl_GetString(fromPtr), &posFrom, false) != TCL_OK) {
			 return BadIndex(interp, Tcl_GetString(fromPtr));
................................................................................
    Tcl_Interp *interp,         /* For error messages. */
    Tcl_Obj *objPtr,            /* Contains a textual index like "1.2" */
    SearchSpec *searchSpecPtr,  /* Contains other search parameters. */
    int *linePosPtr,            /* For returning the line number. */
    int *offsetPosPtr)          /* For returning the text offset in the
                                 * line. */
{
   int pos1;
   int line;
   SciWidget *sciwidgetPtr = (SciWidget *)searchSpecPtr->clientData;
   ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

   if (GetPosition(sciwidgetPtr, Tcl_GetString(objPtr), &pos1, false) != TCL_OK) {
      return BadIndex(interp, Tcl_GetString(objPtr));
   }
................................................................................
   bool force_center = false;
   if (objc == 4) {
      char *arg = Tcl_GetString(objv[3]);
      if ((arg[0] == '-') && (strcmp(arg, "-center") == 0)) {
         force_center = true;
      }
   }
   int pos = -1;
   if (GetPosition(sciwidgetPtr, index_str, &pos, false) == TCL_OK) {
      if (pos == -1) {
         // assume index was specified beyond end of doc
         pos = sci_get_length(obj);
      }
      // if the widget isn't mapped yet, there's no point in continuing
      if ( ! Tk_IsMapped(sciwidgetPtr->tkwin)) {
          return TCL_OK;
      }
      // find out the top and bottom visible lines
      int topline  = sci_cmd(obj, SCI_GETFIRSTVISIBLELINE);

      int vislines = sci_cmd(obj, SCI_LINESONSCREEN);









      int botline  = topline + vislines;
      int midline  = topline + (vislines / 2);

      // get the line containing the target
      int line = sci_get_line(obj, pos);

      // get the last line
................................................................................

/****************************************************************
// Func: SciWidgetUpdateLang
// Desc: 
*****************************************************************/
static int
SciWidgetUpdateLang(Tcl_Interp *interp, SciWidget *sciwidgetPtr) {
    int newtype;

    if (!sciwidgetPtr->language) return TCL_OK;

    if( strcmp(sciwidgetPtr->language,"none") == 0) {
        newtype = SCLEX_NULL;
        SSM(SCI_SETLEXER, newtype, 0);
    } else {
................................................................................
        newtype =  SSM(SCI_GETLEXER,0,0);
        if (newtype == SCLEX_NULL) {
            Tcl_AppendResult(interp, "bad language name: ", sciwidgetPtr->language, (char*)NULL);
            return TCL_ERROR;
        }
    }
    if ((sciwidgetPtr->langType != SCLEX_NULL) && (sciwidgetPtr->langType != newtype)) {
        //
        // Only need to get style data cleared if we know any exists.
        // This check helps us avoid clearing away custom styles unintentionally
        //

        sciwidgetPtr->tagMgr->SaveRestore(true);
        SSM(SCI_CLEARDOCUMENTSTYLE, 0,0);
        SSM(SCI_STYLECLEARALL,0,0); //<<<SEEMS WE NEED THIS SO "BOLD"ing WILL WORK ???

        sciwidgetPtr->tagMgr->SaveRestore(false);

    }
    sciwidgetPtr->langType = newtype;

    // Not all of the lexers support this property, but the majority do
    SSM(SCI_SETPROPERTY, (uptr_t)"fold",         (sptr_t)"1");
    SSM(SCI_SETPROPERTY, (uptr_t)"fold.comment", (sptr_t)"1"); // notepad++ allows this








   return TCL_OK;
}

static void
SciWidgetCheckFoldMargin(SciWidget *sciwidgetPtr) {

   if (sciwidgetPtr->foldstyle < 0 || sciwidgetPtr->foldstyle >= foldMAX) {
      sciwidgetPtr->foldstyle = foldBoxTree; // force to valid value
................................................................................
    // over the text area (or we didn't get x/y)
    if (sci->cursor == None) {
        Tk_UndefineCursor(tkwin);
    } else {
        Tk_DefineCursor(tkwin, sci->cursor);
    }
}




















/****************************************************************
// Func: SciWidgetConfigure
// Desc: 
*****************************************************************/
static int
SciWidgetConfigure(
................................................................................
   int            objc,
   Tcl_Obj *CONST objv[])
{
   Tk_SavedOptions savedOptions;
   int mask = 0;
   // check if this is the first time doing this
   bool firsttime = false;


   if (!(sciwidgetPtr->flags & INIT_CFG_DONE)) {
      sciwidgetPtr->flags |= INIT_CFG_DONE;
      firsttime = true;
   }

   /*
    * Tk_SetOptions does all the work of parsing the
................................................................................
       // to some small value since the Scintilla behavior is to increase
       // the value whenever it encounters a line which is longer.
       sci_cmd(sciobj, SCI_SETHSCROLLBAR, 1);
       sci_cmd(sciobj, SCI_SETSCROLLWIDTH, 100);
       sci_cmd(sciobj, SCI_SETSCROLLWIDTHTRACKING, 1);
   }
   SciWidgetGeometry(sciwidgetPtr);













   /*
    * Set up a call to display ourself.
    */
   if ((sciwidgetPtr->tkwin != NULL) &&
      Tk_IsMapped(sciwidgetPtr->tkwin) &&
      !(sciwidgetPtr->flags & REDRAW_PENDING)) {

      Tk_DoWhenIdle(SciWidgetDisplay, (ClientData) sciwidgetPtr);
      sciwidgetPtr->flags |= REDRAW_PENDING;
   }
   Tk_FreeSavedOptions(&savedOptions);

   return TCL_OK;
}
................................................................................
/****************************************************************
// Func: SciWidgetEventProc
// Desc: 
*****************************************************************/
static void
SciWidgetEventProc(ClientData clientData, XEvent *eventPtr)
{
static int cache = 0;

   int redraw = 0;
   char buf[32];

   SciWidget *sciwidgetPtr = (SciWidget *) clientData;

   if (0) {
     fprintf(stderr, "[XEVENT] wave_EventProc: %s (type=%s (%d))\n", 
................................................................................
      break;

	  case Expose: {
         XExposeEvent e = eventPtr->xexpose;
//printf("EXPOSED: +%02d+%02dx%03dx%03d  COUNT=%d\n", e.x,e.y,e.width,e.height,e.count);
         if ((sciwidgetPtr->flags & REDRAW_EXPOSE)) {
		    int max_right, max_bottom;
			cache++;

            max_right  = Platform::Maximum((sciwidgetPtr->expose_x + sciwidgetPtr->expose_w), (e.x + e.width));
            max_bottom = Platform::Maximum((sciwidgetPtr->expose_y + sciwidgetPtr->expose_h), (e.y + e.height));

            sciwidgetPtr->expose_x = Platform::Minimum(sciwidgetPtr->expose_x, e.x);
            sciwidgetPtr->expose_y = Platform::Minimum(sciwidgetPtr->expose_y, e.y);
            sciwidgetPtr->expose_w = max_right - sciwidgetPtr->expose_x;
................................................................................
          */
         sciwidgetPtr->tkwin = NULL;

         if (sciwidgetPtr->flags & REDRAW_PENDING) {
            Tk_CancelIdleCall(SciWidgetDisplay, (ClientData) sciwidgetPtr);
            sciwidgetPtr->flags &= ~REDRAW_PENDING;
         }

         /*
          * This results in a call to SciWidgetDestroy.
          */
         Tcl_EventuallyFree((ClientData) sciwidgetPtr, (Tcl_FreeProc *)SciWidgetDestroy);
		 break;
      
	 case FocusIn :
................................................................................
		 break;
   }
   

   if (redraw) {
      if ((sciwidgetPtr->tkwin != NULL) && !(sciwidgetPtr->flags & REDRAW_PENDING)) {
         // schedule a call to the display routine

		 Tk_DoWhenIdle(SciWidgetDisplay, (ClientData) sciwidgetPtr);
         sciwidgetPtr->flags |= REDRAW_PENDING;
      }
   }
}

/*
................................................................................
/****************************************************************
// Func: SciWidgetDisplay
// Desc: 
*****************************************************************/
void SciWidgetDisplay(ClientData clientData)
{
   PRectangle rc;



   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   Tk_Window tkwin = sciwidgetPtr->tkwin;
   rc = PRectangle(0, 0, Tk_Width(tkwin), Tk_Height(tkwin)); 



#if 0
printf("#############################################\n");
printf("SciWidgetDisplay w/ FLAGS = ");
if (sciwidgetPtr->flags & REDRAW_PENDING) printf("|REDRAW_PENDING");
if (sciwidgetPtr->flags & REDRAW_YSCROLL) printf("|REDRAW_YSCROLL");
if (sciwidgetPtr->flags & REDRAW_EXPOSE)  printf("|REDRAW_EXPOSE");
................................................................................
         XGCValues gcValues;
         gcValues.graphics_exposures = True;
         sciwidgetPtr->copyGC = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
      }
	  /* test to see if the scroll region is less than the window hieght
	   * if it isn't, nosense in blitting as its all new text
	   */

      if (diff > 0 && diff < Tk_Height(tkwin)) {
















         // shift pixels UP

         XCopyArea(
            display, draw, draw, sciwidgetPtr->copyGC,
            0, diff,
            Tk_Width(tkwin), Tk_Height(tkwin) - diff,
            0, 0
         );






		 rc = PRectangle(0,Tk_Height(tkwin) - diff + 1,
                         Tk_Width(tkwin), Tk_Height(tkwin));

	  }
      
      if (diff < 0 && abs(diff) < Tk_Height(tkwin)) {














          // shift pixels DOWN
         XCopyArea(
            display, draw, draw, sciwidgetPtr->copyGC,
            0, 0,
            Tk_Width(tkwin), Tk_Height(tkwin) + diff,
            0, -diff
         );






 		 rc = PRectangle(0,0,
                         Tk_Width(tkwin), abs(diff));

      }	  

   }
   sciwidgetPtr->flags &= ~(REDRAW_PENDING|REDRAW_YSCROLL);
 
   if (sciwidgetPtr->flags & REDRAW_EXPOSE) {
      /*
	   * This is a work around for a scintilla bug.  If an expose occurs and the expose is entirerly over the 
	   * the margin (ie not text area exposed) Editor.cxx paint repaints the margin into the off screen pixmap.
................................................................................
	   */
	  int margin = sciwidgetPtr->marginMgr->Width() + 5;
	  if ((sciwidgetPtr->expose_x + sciwidgetPtr->expose_w) < margin) { 
			sciwidgetPtr->expose_w = margin;
	  }
	  /* end of work around */


	  rc = PRectangle(
         sciwidgetPtr->expose_x,
         sciwidgetPtr->expose_y,
        (sciwidgetPtr->expose_x + sciwidgetPtr->expose_w),
         (sciwidgetPtr->expose_y + sciwidgetPtr->expose_h)
      );


//printf("REDRAW_EXPOSE: +%02d+%02dx%03dx%03d\n", sciwidgetPtr->expose_x, sciwidgetPtr->expose_y, sciwidgetPtr->expose_w, sciwidgetPtr->expose_h);
      sciwidgetPtr->flags &= ~REDRAW_EXPOSE;
   } 




   uptr_t rc_ptr = reinterpret_cast<uptr_t>(&rc);
   scintilla_send_message(sciwidgetPtr->editor, SCI_TKMSG_PAINT, rc_ptr, 0);
}

/////////////////////////////////////////////////////////////////////////////////
// Handle message notifications from Scintilla code
//
................................................................................
   }
}
//### DTOR ###
MarginData::~MarginData() {

   // clean up objects used for margin options
   Tk_FreeConfigOptions((char *)mopts, optionTable, mgr->tkwin);

   Tcl_Free((char *)mopts);
}

//==========================================================================
int MarginData::Configure(int objc, Tcl_Obj *CONST objv[]) {

   Tk_SavedOptions savedOptions;
................................................................................
   // create the margin objects, default all to zero width; also disable
   // click handling by default until client explicitly enables it
   for (int i=0; i < MAXM; i++) {
      margins[i] = new MarginData(this, i, 0);
      sci_set_margin_width(SCIOBJ(w), i, 0);
      sci_enable_margin_click(SCIOBJ(w), i, false);
   }
   // We want to keep our custom(client-definable) margin style
   // IDs separate from the lexers and other Scintilla defined styles.
   // NOTE: The margin style has no affect on the default line-number
   // margin(ie the one managaged by Scintilla). That margin will still
   // use the STYLE_LINENUMBER style.
   //
   // NOTE: As of the 3.2.5 Scintilla release, a new mechanism was introduced for
   //       client code to manage use of style IDs. In the Scintilla documentation
   //       it is _RECOMMENDED_ that client code first call SCI_ALLOCATEEXTENDEDSTYLES
   //       to obtain the offset value to use. However, this requires that the client
   //       specify exactly how many style IDs they want available for use.
//TODO: switch to use SCI_ALLOCATEEXTENDEDSTYLES mechanism

   sci_cmd(SCIOBJ(w), SCI_MARGINSETSTYLEOFFSET, STYLE_MAX);
}
//### DTOR ###
MarginMgr::~MarginMgr() {

   // clean up the margin objects
   for (int i=0; i < MAXM; i++) {
      delete margins[i];
................................................................................
         break;
      }
      case CMD_COUNT: {
         Tcl_SetObjResult(interp, Tcl_NewIntObj(MAXM));
         break;
      }
      case CMD_DUMP: {
#if 0
         Tcl_Obj *buf = Tcl_NewStringObj("Margin DUMP:\n", -1);
         for (int i=0; i < MAXM; i++) {
            MarginData *m = margins[i];
            if (m->GetType() != SYMBOL && m->GetType() != FOLD)
            Tcl_AppendPrintfToObj(buf, 
               "%d - WIDTH= %2d/%2d, CURSOR= %-10s, TYPE= %-10s, MASK=      <n/a>, ALIAS= %-12s, CLICKCMD= %s\n",
               i,
               m->GetVisibleWidth(), 
               m->GetWidth(), 
               m->GetCursorStr(),
               m->GetTypeStr(),
               m->GetAlias()? m->GetAlias() : "<null>",
               m->GetClickCmd()? m->GetClickCmd() : "<null>"
            );
            else {
               // Need to use sprintf because Tcl_AppendPrintfToObj doesn't do the
               // hex formatting correctly
               char buf2[1024*10];
               sprintf(buf2, "%d - WIDTH= %2d/%2d, CURSOR= %-10s, TYPE= %-10s, MASK= 0x%08X, ALIAS= %-12s, CLICKCMD= %s\n",
                  i,
                  m->GetVisibleWidth(), 
                  m->GetWidth(), 
                  m->GetCursorStr(),
                  m->GetTypeStr(),
                  sci_get_margin_mask(SCIOBJ(sciwidgetPtr),i),
                  m->GetAlias()? m->GetAlias() : "<null>",
                  m->GetClickCmd()? m->GetClickCmd() : "<null>"
               );
               Tcl_AppendToObj(buf, buf2, -1);
            }
         }
         Tcl_SetObjResult(interp, buf);
#else
         result = CmdDump(objc, objv);
         break;
#endif
         break;
      }
      case CMD_FILLNUMS: {
         result = CmdFillNums(objc, objv);
         break;
      }
      case CMD_HIDE: {
................................................................................
      result = m->Configure(objc-4, objv+4);
   }
   return result;
}

//==========================================================================
int MarginMgr::CmdDump(int objc, Tcl_Obj *CONST objv[]) {










































    if (objc < 6) {
        Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 ?index2?");
        return TCL_ERROR;
    }

    // get selected margin
    int id;
................................................................................
         Tcl_AppendToObj(objbuf, ", ", -1);
      Tcl_AppendToObj(objbuf, MarginTypeNames[i], -1);
   }
   _reportError(Tcl_GetString(objbuf));
   return TCL_ERROR;
}


/////////////////////////////////////////////////////////////////////////////////
// Tag configuration options
//
static const char *IndicatorTypeNames[] = {
    "none", "plain", "squiggle", "tt", "diagonal", "strike",
    "hidden", "box", "roundbox", "squarebox", "dash", "dots", 
    "squigglelow", "dotbox", NULL
};

#define TOPT_BG         1
#define TOPT_FG         1 << 1
#define TOPT_UNDERLINE  1 << 2
#define TOPT_BOLD       1 << 3
#define TOPT_ITALIC     1 << 4
#define TOPT_INDIC_TYPE 1 << 5



static Tk_OptionSpec tagOptionSpecs[] = {
   {TK_OPTION_COLOR,  "-background", NULL, NULL,
         NULL, -1, Tk_Offset(TagData, bgColor), TK_OPTION_NULL_OK, 0, TOPT_BG
   },
   {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0},

   {TK_OPTION_BOOLEAN, "-bold", NULL, NULL,
         "0", -1, Tk_Offset(TagData, bold), 0, 0, TOPT_BOLD
   },




   {TK_OPTION_COLOR,  "-foreground", NULL, NULL,
         NULL, -1, Tk_Offset(TagData, fgColor), TK_OPTION_NULL_OK, 0, TOPT_FG
   },
   {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-foreground", 0},

   {TK_OPTION_STRING_TABLE, "-indicatortype", NULL, NULL,
	(char*)IndicatorTypeNames[indicNONE], -1, Tk_Offset(TagData, indicType), 0, (ClientData)IndicatorTypeNames, TOPT_INDIC_TYPE
   },






   {TK_OPTION_BOOLEAN, "-italic", NULL, NULL,
         "0", -1, Tk_Offset(TagData, italic), 0, 0, TOPT_ITALIC
   },
   {TK_OPTION_BOOLEAN, "-underline", NULL, NULL,
         "0", -1, Tk_Offset(TagData, underline), 0, 0, TOPT_UNDERLINE
   },
   {TK_OPTION_END}
};
















































































































































































































































/////////////////////////////////////////////////////////////////////////////////
// Implementation of TagMgr class
//
/////////////////////////////////////////////////////////////////////////////////

//### CTOR ###
................................................................................
   tkwin(w->tkwin),
   selTag(0),
   marginTag(0),
   numTags(0),
   numCurTags(0),
   curTagArrayPtr(0)
{
   // create the hash table
   Tcl_InitHashTable(&tagTable, TCL_STRING_KEYS);
   freeIndic = 0xfffffff0; // first eight indicators are preallocated by Scinilla, 8-31 are free


















































    freeTextStyles.reset(); /* clear all bits */
    /* mark pre-allocated text styles */
    freeTextStyles.set(0); /* zero is the default, for unset style */
    freeTextStyles.set(32);
    freeTextStyles.set(33);
    freeTextStyles.set(34);
    freeTextStyles.set(35);
    freeTextStyles.set(36);
    freeTextStyles.set(37);
    freeTextStyles.set(38);
    freeTextStyles.set(39);



    freeMarginStyles.reset(); /* clear all bits */
    freeMarginStyles.set(0); /* zero is the default, for unset style */

   // create "special" built-in tags
   _createTag(TT_TEXT, TAG_SEL);
   _createTag(TT_MARG, TAG_MARGIN);


    pickEvent.type = LeaveNotify; // match initialization done in Tk Text widget code

}

//### DTOR ###
TagMgr::~TagMgr() {

   Tcl_HashEntry *hPtr;
   Tcl_HashSearch search;
   TagData       *tagPtr;

   // first iterate through the objects in the hash table...
   for (hPtr = Tcl_FirstHashEntry(&tagTable, &search);
        hPtr != NULL; 
        hPtr = Tcl_NextHashEntry(&search)) {
      tagPtr = (TagData *) Tcl_GetHashValue(hPtr);

      _deleteTag(tagPtr, true/*ok to destroy built-in tags*/);
   }

   // then delete the has table itself
   Tcl_DeleteHashTable(&tagTable);

}

/*
 *--------------------------------------------------------------
 *
 * PickCurrent --
 *
................................................................................
                    }
                    Tcl_DeleteHashEntry(hPtr);
                }
            }
        }
        if (mask & 6) {
            // done with user-defined tags, dump lexer-related styles next
            int full_sid = sci_cmd(sciobj, SCI_GETSTYLEAT, i);
            // full_sid may have indicator bits encoded within, strip them appart
            if (full_sid) {
                char sbuf[10];
                int sid = SID2STYLE(sciwidgetPtr, full_sid);
                int indicator = SID2INDICATOR(sciwidgetPtr, full_sid);
                if (sid) {
                    if (last_sid && (last_sid != sid)) {
................................................................................
            Tcl_WrongNumArgs(interp, 3, objv, "tagName option");
            return TCL_ERROR;
         }
         TagData *tagPtr = FindTag(Tcl_GetString(objv[3]));
         if (tagPtr == NULL) {
            return TCL_ERROR;
         }
         Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *)tagPtr,
            tagPtr->optionTable, objv[4], tkwin);
         if (objPtr == NULL) {
            return TCL_ERROR;
         }
         Tcl_SetObjResult(interp, objPtr);
         break;
      }
................................................................................
//
// This function will associate a previously defined tag with a specified
// range of text, or if a tag doesn't already exist it will create a new
// one (this matches the Tk Text widget behavior).
//
int TagMgr::CmdAdd(int objc, Tcl_Obj *CONST objv[]) {

   TagData *tagPtr;
   char *index_str, *tagName;
   int pos1 = -1;
   int pos2 = -1;


   if (objc < 5) {
      Tcl_WrongNumArgs(interp, 3, objv,
         //ix: 3    4       5        6
         "tagName index1 ?index2 -rectangle|-addsel? ?index1 index2 ...?");
      return TCL_ERROR;
   }
   tagName = Tcl_GetString(objv[3]);
   // first check if it's an existing tag...
   if ((tagPtr = FindTag(tagName)) == NULL) {
       // If not, let's mimic the Tk Text behavior where a tag will get 
       // created. And since we can only apply tags which are indicators,
       // that's the type we'll use.
       //
       Tcl_ResetResult(interp);
       int isNewTag;
       tagPtr = _createTag(TT_INDIC|TT_TEXT, tagName, &isNewTag);
       if (tagPtr == NULL) {
           return TCL_ERROR;
       }
       // Note that in order to support existing code that may have been converted
       // from use with the Tk Text widget, we default the indicator type to be a
       // a solid filled rectangle. An example usage would be:
       //    $widget tag add my_tag 2.5 2.10
       //    #...other code...
       //    $widget tag configure my_tag -background yellow
       //
       tagPtr->indicType = indicSquareBox;
       _configIndicator(tagPtr);
   }
   bool rect = false;
   bool addsel = false;


   // check for -rectangle or -addsel option
   if (objc == 7) {
      char *s = Tcl_GetString(objv[6]);
      if (s && *s == '-') {
         if (!strncmp(s, "-rect",4)) {
            rect = true;
         } else if (!strcmp(s, "-addsel")) {
            addsel = true;
         }
      }
   }
   if (rect || addsel || (objc < 7)) {
      // simple case: either one or two indices
      index_str = Tcl_GetString(objv[4]);



      if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
         goto error;
      }
      if (pos1 == -1) goto done; // index is valid, but not within document
      if (rect || addsel || objc == 6) {




         index_str = Tcl_GetString(objv[5]);



         if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
            goto error;
         }
         if (pos2 == -1) goto done;
      } else {
         pos2 = pos1+1; // just tag one character
      }


   } else {
//TODO: TagMgr::CmdAdd >> support more than two indices...
      Tcl_ResetResult(interp);
      Tcl_AppendResult(interp, "more than two indices is not supported", NULL);
      return TCL_ERROR;
   }
   // NOTE: The Tk Text widget is defined so that (pos1 > pos2) is a no-op. However
   //       for the case of selection we need to ignore this condition so that we
   //       can support a client requesting that the insertion point to be located
   //       at the start of the selection range instead of the default behavior
   //       which would place it at the end. We allow clients to do this by
   //       specifying the selection range indices in reverse order.
   if ((pos1 > pos2) && (tagPtr != selTag)) {
      // according to the Tk documenation this is a no-op
   } else {
      ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
      if (tagPtr == selTag) {
         //-----------------
         //--- SELECTION ---
         //-----------------
         if (rect) {
            sci_cmd(obj, SCI_SETRECTANGULARSELECTIONANCHOR, pos1);
            sci_cmd(obj, SCI_SETRECTANGULARSELECTIONCARET,  pos2);
         } else {
            sci_select(obj, pos1, pos2, addsel);



         }
         FireSelectionVirtual(); // indicate a change occurred

      } else {
          if (IsIndicator(tagPtr)) {
              //-----------------
              //--- INDICATOR ---
              //-----------------
              sci_cmd(obj, SCI_SETINDICATORCURRENT, tagPtr->IndicID());
              sci_cmd(obj, SCI_INDICATORFILLRANGE, pos1, (pos2-pos1));
          } else {
             /* set style for selected positions */
             sci_cmd(obj, SCI_STARTSTYLING, pos1, STYLEMASK(sciwidgetPtr));
             sci_cmd(obj, SCI_SETSTYLING, (pos2-pos1), tagPtr->StyleID());

          }
      }
   }
 done:
   return TCL_OK;
 error:
   return BadIndex(interp, index_str);
}

//==========================================================================
// Implements the TAG BIND sub-command
//
// This function manages the interface between client binding definitions
// for a tag and setting up the widget to respond to those events
................................................................................
      Tcl_WrongNumArgs(interp, 3, objv,
         "tagName ?-margin? ?option? ?value? ?option value ...?");
      return TCL_ERROR;
   }
   // check for -margin option
   bool typeGiven = false;
   if (objc >= 5) {



      if (strcmp("-margin", Tcl_GetString(objv[4])) == 0) {
         typeGiven = true;
         tt = TT_MARG;
      }
   }
   // This is kind of a hack, but we need to know when calling _createTag
   // if this is for an indicator since the identifiers for styles are
   // different than those for indicators
................................................................................
           tt |= TT_INDIC;
           if (tt & TT_MARG) {
              Tcl_AppendResult(interp, "Indicator tags not supported in margins", NULL);
              return TCL_ERROR;
           }
       }
   }
   // either return an existing tag or create a new one
   tagPtr = _createTag(tt, Tcl_GetString(objv[3]), &isNewTag);
   if (tagPtr == NULL) {
      return TCL_ERROR;
   }

   if ( (typeGiven && (objc <= 6)) || (!typeGiven && (objc <= 5)) ) {
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // just return config info
      bool all = ( (typeGiven && (objc == 6)) || (!typeGiven && (objc == 5)) );
      int all_ix = 0;






      if (all) {
         all_ix = typeGiven ? 5 : 4;
      }
      Tcl_Obj *objPtr = Tk_GetOptionInfo(
         interp, (char *) tagPtr,
         tagPtr->optionTable,
         (all ? objv[all_ix] : NULL), tkwin);

      if (objPtr == NULL) {
         return TCL_ERROR;
      }
      Tcl_SetObjResult(interp, objPtr);
................................................................................
   } else {
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // modify the config data
      Tk_SavedOptions savedOptions;
      int mask = 0;
      int adj = (typeGiven ? 5 : 4);





      if (Tk_SetOptions(interp, (char *)tagPtr, tagPtr->optionTable,
            objc-adj, objv+adj, tkwin, &savedOptions, &mask) != TCL_OK) {

         return TCL_ERROR;
      }
      ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);

      if (tagPtr == selTag) {
         //-----------------
         //--- SELECTION ---
................................................................................

      if (mask & TOPT_BOLD) {
         sci_cmd(sciobj, SCI_STYLESETBOLD, sid, tagPtr->Bold());
         if ((tagPtr == marginTag) && (sid != STYLE_LINENUMBER)) {
            sci_cmd(sciobj, SCI_STYLESETBOLD, STYLE_LINENUMBER, tagPtr->Bold());
         }
      }




      if (mask & TOPT_ITALIC) {
         sci_cmd(sciobj, SCI_STYLESETITALIC, sid, tagPtr->Italic());
         if ((tagPtr == marginTag) && (sid != STYLE_LINENUMBER)) {
            sci_cmd(sciobj, SCI_STYLESETITALIC, STYLE_LINENUMBER, tagPtr->Italic());
         }
      }
      if (mask & TOPT_UNDERLINE) {
................................................................................
}

//==========================================================================
// Implements the TAG DELETE sub-command
//
int TagMgr::CmdDelete(int objc, Tcl_Obj *CONST objv[]) {

   Tcl_HashEntry *hPtr;
   TagData *tagPtr;

   if (objc < 4) {
      Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?");
      return TCL_ERROR;
   }
   for (int i=3; i < objc; i++) {
      const char *name = Tcl_GetString(objv[i]);
      if (IS_SEL(name)) continue;    // 'sel' tag cannot be deleted by user
      if (IS_MARGIN(name)) continue; // 'margin' tag cannot be deleted by user

      hPtr = Tcl_FindHashEntry(&tagTable, name);
      if (hPtr == NULL) continue;

      tagPtr = (TagData *)Tcl_GetHashValue(hPtr);

      // now delete the tag itself
      _deleteTag(tagPtr);

      // and finally remove it from the hash table
      Tcl_DeleteHashEntry(hPtr);
   }
   return TCL_OK;
}

//==========================================================================
// Implements the TAG NAMES sub-command
//
................................................................................
                Tcl_SetObjResult(interp, tmp);
            }
        }
    } else {
        // show only the tags at the specified location
        char *index_str = Tcl_GetString(objv[3]);
        char *tagName = (objc == 5 ? Tcl_GetString(objv[4]) : NULL);
        int pos = -1;
        if (GetPosition(sciwidgetPtr, index_str, &pos, false) != TCL_OK) {
            return BadIndex(interp, index_str);
        }
        for (hPtr = Tcl_FirstHashEntry(&tagTable, &search);
             hPtr != NULL; 
             hPtr = Tcl_NextHashEntry(&search)) {
            tagPtr = (TagData *) Tcl_GetHashValue(hPtr);
................................................................................

//==========================================================================
// Implements the TAG NEXTRANGE/PREVRANGE sub-commands
//
int TagMgr::CmdNPRange(int objc, Tcl_Obj *CONST objv[], bool next) {

    char *index_str;
    int pos1, pos2, tmp;
    TagData *tagPtr;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    Tcl_Obj *indices = Tcl_NewListObj(0, NULL);

    if ((objc != 5) && (objc != 6)) {
        Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
        return TCL_ERROR;
................................................................................
            goto error;
        }
        if (pos2 == -1) goto done;
        if (pos1 == pos2) goto done; // no-op
    } else {
        pos2 = (next ? sci_get_length(obj) : 0);
    }


    // for code simplicity, we interpret the two indices to
    // represent the start and then the end of the target range.
    if (pos2 < pos1) {

        tmp  = pos1;
        pos1 = pos2;
        pos2 = tmp;
    }

    if (tagPtr == selTag) {
        //-----------------
        //--- SELECTION ---
        //-----------------
        if (sci_has_selection(obj)) {
            // need to handle both single and multiple selections
            int nsels = sci_cmd(obj,SCI_GETSELECTIONS);
            int dir = next ? 1 : -1;
................................................................................
                    PosToIndex(interp, obj, beg, indices);
                    PosToIndex(interp, obj, end, indices);
                    break;
                }
            }
            Tcl_SetObjResult(interp, indices);
        }
    } else if (IsIndicator(tagPtr)) {
        //-----------------
        //--- INDICATOR ---
        //-----------------
        int id = tagPtr->IndicID();
        int dir = next ? 1 : -1;
        int len = sci_get_length(obj);
        int first = next ? 0 : (len - 1);

        for (int i = first; ; i += dir) {
            // loop termination check...
            if (next  && i >= len) break;
            if (!next && i < 0)    break;

            int beg = sci_cmd(obj, SCI_INDICATORSTART, id, i);
            int end = sci_cmd(obj, SCI_INDICATOREND,   id, beg + 1);

            // check if the indicator exists at all within the document
            if ((beg == end) && (beg == 0)) break;
            i = (next ? end : beg);

            // use the following call to know how to interpret the positions
            // we get from the above two calls; we want to verify that the
            // target indicator exists at the starting position.
            int mask = sci_cmd(obj, SCI_INDICATORALLONFOR, beg);

            if (mask & (1 << id)) {

                if (((beg >= pos1) && (beg < pos2)) || 
                    ((end >= pos1) && (end < pos2))) {

                    PosToIndex(interp, obj, beg, indices);
                    PosToIndex(interp, obj, end, indices);
                    break; // only looking for a single match
                }
            }
        }



        Tcl_SetObjResult(interp, indices);
    } else {
//TODO: TagMgr::CmdNPRange >> Support non-selection/non-indicator tags
    }
 done:
    return TCL_OK;
 error:
    return BadIndex(interp, index_str);
}

//==========================================================================
// Implements the TAG RANGES sub-command
//
int TagMgr::CmdRanges(int objc, Tcl_Obj *CONST objv[]) {

   TagData *tagPtr;
   ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

   if (objc != 4) {
      Tcl_WrongNumArgs(interp, 3, objv, "tagName");
      return TCL_ERROR;
   }
   tagPtr = FindTag(Tcl_GetString(objv[3]));
   if (tagPtr == NULL) {
       return TCL_ERROR;
   }
   Tcl_Obj *indices = Tcl_NewListObj(0, NULL);
   if (tagPtr == selTag) {
       //-----------------
       //--- SELECTION ---
       //-----------------
       if (sci_has_selection(obj)) {
           int nsels = sci_cmd(obj,SCI_GETSELECTIONS);
           // need to handle both single and multiple selections
           for (int i=0; i < nsels; i++) {
               int pos1 = sci_cmd(obj, SCI_GETSELECTIONNSTART, i);
               int pos2 = sci_cmd(obj, SCI_GETSELECTIONNEND, i);
               if (pos1 == pos2) continue;
               PosToIndex(interp, obj, pos1, indices);
               PosToIndex(interp, obj, pos2, indices);
           }
           Tcl_SetObjResult(interp, indices);
       }
   } else if (IsIndicator(tagPtr)) {
       //-----------------
       //--- INDICATOR ---
       //-----------------
       int id = tagPtr->IndicID();
       for (int i=0; i < sci_get_length(obj); i++) {

           int beg = sci_cmd(obj, SCI_INDICATORSTART, id, i);
           int end = sci_cmd(obj, SCI_INDICATOREND,   id, beg);

           // check if the indicator exists at all within the document
           if ((beg == end) && (beg == 0)) break;
           i = end;

           // use the following call to know how to interpret the positions
           // we get from the above two calls; we want to verify that the
           // target indicator exists at the starting position.
           int mask = sci_cmd(obj, SCI_INDICATORALLONFOR, beg);

           if (mask & (1 << id)) {
               PosToIndex(interp, obj, beg, indices);
               PosToIndex(interp, obj, end, indices);
           } else {
               // when the indicator doesn't exist at the "beg" position
               // then we want the next search to begin at the "end"
               // position; so we need to decrement "i" since the next
               // iteration of the "for" loop will increment it first.
               i--;
           }
       }
       Tcl_SetObjResult(interp, indices);
   } else {
//TODO: TagMgr::CmdRanges >> Support non-selection/non-indicator tags













   }















   return TCL_OK;
}

//==========================================================================
// Implements the TAG REMOVE sub-command
//
// This function will remove the styling for a previously defined tag 
// from a specified range of text
//
int TagMgr::CmdRemove(int objc, Tcl_Obj *CONST objv[]) {

   TagData *tagPtr;
   char *index_str;
   int pos1 = -1;
   int pos2 = -1;


   if (objc < 5) {
      Tcl_WrongNumArgs(interp, 3, objv,
         "tagName index1 ?index2 index1 index2 ...?");
      return TCL_ERROR;
   }
   // check if the tag exists
   tagPtr = FindTag(Tcl_GetString(objv[3]));
   if (tagPtr == NULL) {
       // Tk Text widget doesn't issue an error for this, so we won't either
       Tcl_ResetResult(interp);
       return TCL_OK;
   }
   if (objc < 7) {
      // simple case: either one or two indices


      index_str = Tcl_GetString(objv[4]);
      if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
         goto error;
      }
      if (pos1 == -1) goto done; // index is valid, but not within document
      if (objc == 6) {




         index_str = Tcl_GetString(objv[5]);
         if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
            goto error;
         }
         if (pos2 == -1) goto done;
         if (pos1 == pos2) goto done; // no-op
      } else {
         pos2 = pos1+1; // just one character


      }

   } else {
//TODO: TagMgr::CmdRemove >> support more than two indices...
      Tcl_ResetResult(interp);
      Tcl_AppendResult(interp, "more than two indices is not supported", NULL);
      return TCL_ERROR;

   }

   if ((pos1 > pos2) && (tagPtr != selTag)) {
      // according to the Tk documenation this is a no-op
   } else {
      ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
      if (tagPtr == selTag) {
         //-----------------
         //--- SELECTION ---
         //-----------------
         int sel_beg = sci_cmd(obj, SCI_GETSELECTIONSTART);
         int sel_end = sci_cmd(obj, SCI_GETSELECTIONEND);
         if (sel_beg == sel_end) {
            // there is no selection
            goto done;
         }
         // check if the range to be removed overlaps with current selection
         if ((pos2 < sel_beg) || (pos1 > sel_end)) {
            // no overlap
            goto done;
         }
         if (pos1 <= sel_beg && pos2 >= sel_end) {
            //CASE 1: range completely overlaps selection - remove it all
            sci_cmd(obj, SCI_SETEMPTYSELECTION, sci_get_current_pos(obj));
         } else {
            if (pos2 <= sel_end) {
               //CASE 2: range overlaps selection start
               sci_cmd(obj, SCI_SETSELECTIONSTART, pos2);
            }
            if (pos1 >= sel_beg) {
               //CASE 3: range overlaps selection start
               sci_cmd(obj, SCI_SETSELECTIONEND, pos1);
            }
         }
         FireSelectionVirtual(); // indicate a change occurred
      } else {
          if (IsIndicator(tagPtr)) {
              //-----------------
              //--- INDICATOR ---
              //-----------------
              sci_cmd(obj, SCI_SETINDICATORCURRENT, tagPtr->IndicID());
              sci_cmd(obj, SCI_INDICATORCLEARRANGE, pos1, (pos2-pos1));
              goto done;

          }
//TODO: TagMgr::CmdRemove >> handle non-selection tags
      }
   }
 done:
   return TCL_OK;
 error:
   return BadIndex(interp, index_str);
}


................................................................................
    e.xany.window                = Tk_WindowId(tkwin);
    e.xany.display               = Tk_Display(tkwin);
    ((XVirtualEvent *) &e)->name = Tk_GetUid("Selection");
    Tk_HandleEvent(&e);
}

//==========================================================================
// Called in preparation for a clearing of style data to allow saving
// styles that we really don't want undone by the STYLECLEARALL command
//
void TagMgr::SaveRestore(bool save) {

   static ColourDesired marginBG;
   static ColourDesired marginFG;





   ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
   if (save) {

      // save bg/fg for line number style because doing SCI_STYLECLEARALL
      // will reset it to the Scintilla default
      marginBG = ColourDesired(sci_cmd(obj, SCI_STYLEGETBACK, STYLE_LINENUMBER));
      marginFG = ColourDesired(sci_cmd(obj, SCI_STYLEGETFORE, STYLE_LINENUMBER));

   } else {
      // when we restore, we not only restore the built-in line number style
      // but also the one used by the custom "margin" tag



      sci_cmd(obj, SCI_STYLESETBACK, STYLE_LINENUMBER,     marginBG.AsLong());
      sci_cmd(obj, SCI_STYLESETFORE, STYLE_LINENUMBER,     marginFG.AsLong());














































      sci_cmd(obj, SCI_STYLESETBACK, marginTag->StyleID(), marginBG.AsLong());
      sci_cmd(obj, SCI_STYLESETFORE, marginTag->StyleID(), marginFG.AsLong());

   }



}

//==========================================================================
// Update the background/foreground colors for the margin tag
//
void TagMgr::UpdateMarginColor(bool bg, bool fg) {

................................................................................

   ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);
   int sid = marginTag->StyleID();
   XColor *c;

   if (bg) {
      // keep the tag in sync w/ toplevel config option
      c = marginTag->bgColor = sciwidgetPtr->marginBg;

      sci_set_style_bg(sciobj, sid, c);
      if (sid != STYLE_LINENUMBER)
         sci_set_style_bg(sciobj, STYLE_LINENUMBER, c);
   }
   if (fg) {
      c = marginTag->fgColor = sciwidgetPtr->marginFg;

      sci_set_style_fg(sciobj, sid, c);
      if (sid != STYLE_LINENUMBER)
         sci_set_style_fg(sciobj, STYLE_LINENUMBER, c);
   }
   // now we need to iterate through all of the margin tags and check for
   // ones that have no explicit bg/fg values; for these we'll update them
................................................................................
    Tcl_ListObjAppendElement(interp, tmp, Tcl_NewStringObj(sciwidgetPtr->tagMgr->GetMarginTag()->name, -1));
    return tmp;
}

//---------------------------------------------------------
// Private functions
//---------------------------------------------------------




















//==========================================================================
// This handles configuration the indicator style info for a tag
int TagMgr::_configIndicator(TagData *tagPtr, int mask) {

    // sanity check
    if (!IsIndicator(tagPtr)) return TCL_ERROR;

    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    // assign the indicator style
    switch (tagPtr->IndicType()) {

        case indicNONE: break; // make compiler happy

        case indicPlain       : _setIndicStyle(tagPtr, INDIC_PLAIN); break;


        case indicSquiggle    : _setIndicStyle(tagPtr, INDIC_SQUIGGLE); break;


        case indicTt          : _setIndicStyle(tagPtr, INDIC_TT); break;


        case indicDiag        : _setIndicStyle(tagPtr, INDIC_DIAGONAL); break;


        case indicStrike      : _setIndicStyle(tagPtr, INDIC_STRIKE); break;


        case indicHidden      : _setIndicStyle(tagPtr, INDIC_HIDDEN); break;


        case indicBox         : _setIndicStyle(tagPtr, INDIC_BOX); break;

        case indicRoundBox    : _setIndicStyle(tagPtr, INDIC_ROUNDBOX); break;
        case indicSquareBox   : _setIndicStyle(tagPtr, INDIC_STRAIGHTBOX); break;
        case indicDash        : _setIndicStyle(tagPtr, INDIC_DASH); break;
        case indicDots        : _setIndicStyle(tagPtr, INDIC_DOTS); break;
        case indicSquiggleLow : _setIndicStyle(tagPtr, INDIC_SQUIGGLELOW); break;
        case indicDotBox      : _setIndicStyle(tagPtr, INDIC_DOTBOX); break;









    }
    // now assign colors
    if (tagPtr->FG()) {
        sci_cmd(obj, SCI_INDICSETFORE, tagPtr->IndicID(), _XRGB_(tagPtr->FG()));
    }
    if (tagPtr->BG()) {










        sci_cmd(obj, SCI_INDICSETALPHA, tagPtr->IndicID(), _XRGB_(tagPtr->BG()));




        switch (tagPtr->IndicType()) {





            case indicRoundBox:





            case indicSquareBox:
                // A background color would go with indicators that use translucent filling.
                // Since we currently don't support that (see SurfaceImpl::AlphaRectangle),
                // we "fake" the interior filling by using solid rectangles that are drawn
                // under the text - which is why the next call is made.
                //






                sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);







                // The call to AlphaRectangle from the indicator code will pass in
                // the foreground for the fill!!
                sci_cmd(obj, SCI_INDICSETFORE , tagPtr->IndicID(), _XRGB_(tagPtr->BG()));




            default: break;



        }



    }
    return TCL_OK;
}

void TagMgr::_setIndicStyle(TagData *tagPtr, int id) {

    sci_cmd(SCIOBJ(sciwidgetPtr), SCI_INDICSETSTYLE, tagPtr->IndicID(), id);
}






//==========================================================================
// Creates a new tag or returns one matching the specfied name
//
TagData *TagMgr::_createTag(int ttMask, const char *tagname, int *newTag) {

   TagData *tagPtr;
................................................................................
         if (newTag != NULL) *newTag = 0;
         return marginTag; // return the one we already have
      } else if (newTag) *newTag = 1;

      name = TAG_MARGIN;

   } else {







      // if not, create(if needed) in the hash table
      hPtr = Tcl_CreateHashEntry(&tagTable, tagname, &isNew);
      if (newTag) *newTag = isNew;
      // Make sure we have either a text or margin tag, but not both
      assert((ttMask&(TT_MARG|TT_TEXT)) && ((ttMask&(TT_MARG|TT_TEXT)) != (TT_MARG|TT_TEXT)));
      if (!isNew) {
         tagPtr = (TagData *)Tcl_GetHashValue(hPtr);
         // make sure tag type is the same
        if (((TT_MARG|TT_TEXT)&tagPtr->tagType) != ((TT_MARG|TT_TEXT)&ttMask)) {
            Tcl_AppendResult(interp,
                "The \"", tagname, "\" tag can only be defined for the margin or text area, not both\n", (char *)NULL);
            return NULL;
        }
         return (TagData *)Tcl_GetHashValue(hPtr);
      }
      name = Tcl_GetHashKey(&tagTable, hPtr);
   }
   // No existing entry, so create a new one
   tagPtr = (TagData *) Tcl_Alloc(sizeof(TagData));
   tagPtr->name        = name;
   tagPtr->style_id    = -1;
   tagPtr->bgColor     = NULL;
   tagPtr->fgColor     = NULL;
   tagPtr->bold        = 0;
   tagPtr->italic      = 0;
   tagPtr->underline   = 0;
   tagPtr->tagType     = ttMask;
   tagPtr->indicType   = indicNONE;
   tagPtr->indic_id    = INDIC_PLAIN;
   tagPtr->optionTable = Tk_CreateOptionTable(interp, tagOptionSpecs);

   if (Tk_InitOptions(interp, (char *)tagPtr, tagPtr->optionTable, tkwin) != TCL_OK) {
      _deleteTag(tagPtr);


      fprintf(stderr, "ERROR in Tk_InitOptions: %s\n", Tcl_GetStringResult(interp));
      return NULL;
   }
   numTags++;

   if (IS_SEL(tagname)) {
      selTag = tagPtr;
      // set style info
      ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
      if (selTag->BG()) sci_cmd(obj, SCI_SETSELBACK, 1, _XRGB_(selTag->BG()));
      if (selTag->FG()) sci_cmd(obj, SCI_SETSELFORE, 1, _XRGB_(selTag->FG()));
................................................................................

   } else if (IS_MARGIN(tagname)) {
      marginTag = tagPtr;
      // assign it a Scintilla style id
      int id;
      if (_nextStyleID(&id, ttMask) != TCL_OK) {
          _deleteTag(tagPtr);



          return NULL;
      }
      tagPtr->style_id = id;
   } else {
      // assign it a Scintilla id
      int id;
      if (ttMask & TT_INDIC) {
          if (_nextIndicID(&id) != TCL_OK) {
              _deleteTag(tagPtr);



              return NULL;
          }
          tagPtr->indic_id = id;
      } else {
          if (_nextStyleID(&id, ttMask) != TCL_OK) {
              _deleteTag(tagPtr);



              return NULL;
          }
          tagPtr->style_id = id;
      }
      // store in hash table
      Tcl_SetHashValue(hPtr, tagPtr);
   }
   return tagPtr;
}

//==========================================================================
// Delete a tag, either by its name or its object pointer
//
void TagMgr::_deleteTag(const char *tagname) {
   TagData *tagPtr;
   tagPtr = FindTag(tagname);
   if (tagPtr == NULL) return;

   _deleteTag(tagPtr);
}

void TagMgr::_deleteTag(TagData *tagPtr, bool force) {

   if (tagPtr == NULL) return;

   // do cleanup of the options data
   Tk_FreeConfigOptions((char *)tagPtr, tagPtr->optionTable, tkwin);

   // destroy the tag (possibly)
   bool is_special = ((tagPtr == selTag) || (tagPtr == marginTag));

   // see if we need to remove the tag's definitions in the text area.
   // NOTE: DO NOT DO DURING DESTRUCTION (I've seen strange crashes
   // in client applications due to that)
   if (!is_special && IsIndicator(tagPtr) && !force) {
       ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
       int pos1 = 0;
       int pos2 = sci_get_length(obj);
       sci_cmd(obj, SCI_SETINDICATORCURRENT, tagPtr->IndicID());
       sci_cmd(obj, SCI_INDICATORCLEARRANGE, pos1, (pos2-pos1));
   }

   if (!is_special || force) {
       //
       // Make sure this tag isn't referenced from the 'current' tag array.
       //
       for (int i = 0; i < numCurTags; i++) {
           if (curTagArrayPtr[i] == tagPtr) {
               for (; i < numCurTags-1; i++) {
................................................................................
                   curTagArrayPtr[i] = curTagArrayPtr[i+1];
               }
               curTagArrayPtr[numCurTags-1] = NULL;
               numCurTags--;
               break;
           }
       }


       if (IsIndicator(tagPtr)) {
           if ((tagPtr->indic_id >= INDIC_CONTAINER) && (tagPtr->indic_id <= INDIC_MAX)) {
              // indicator is now "free"
              freeIndic |= (1 << tagPtr->IndicID());
           }
       } else {
           if (tagPtr->Type() & TT_TEXT) {

              freeTextStyles.set(tagPtr->StyleID(), 0);
           }
           if (tagPtr->Type() & TT_MARG) {

              freeMarginStyles.set(tagPtr->StyleID() - STYLE_MAX, 0);
           }



       }
       Tcl_Free((char *)tagPtr);


       if (tagPtr == selTag) {
           selTag = NULL;
       } else if (tagPtr == marginTag) {
           marginTag = NULL;
       }
       numTags--;
   }
................................................................................
// Return the next available Scintilla indicator id. This routine is
// responsible for managing a free-list so that IDs can be reused.
//
int TagMgr::_nextIndicID(int *idPtr) {
    int i;
    if (!idPtr) return TCL_ERROR;

    // find first bit in freeIndic, no need to check first 8
    for (i = INDIC_CONTAINER; i <= INDIC_MAX; ++i) {
        int bitmask = 1 << i;
        if (freeIndic & bitmask) {
            freeIndic &= ~bitmask;
            *idPtr = i;
            return TCL_OK;
        }
    }
    // if all indicators allocated, report error
    if (i > INDIC_MAX) {
        char buf[33];
................................................................................
}

//==========================================================================
// Return the next available Scintilla style id. This routine is responsible
// for managing a free-list so that IDs can be reused.
//
int TagMgr::_nextStyleID(int *idPtr, int ttMask) {



    if (!idPtr) return TCL_ERROR;

    if (ttMask & TT_TEXT) {
        /* text style */
        for (int id = 0; id < 255; id++) {
            if (!freeTextStyles.test(id)) {
                /* found free style, mark it as allocated */
                freeTextStyles.set(id, 1);
                *idPtr = id;
                return TCL_OK;
            }
        }
    } else {














        /* margin style */




        for (int id = 0; id < 255; id++) {
            if (!freeMarginStyles.test(id)) {
                /* found free style, mark it as allocated */
                freeMarginStyles.set(id, 1);
                *idPtr = id + STYLE_MAX;
                return TCL_OK;
            }
        }
    }

    /* unable to find style, return error */





    return TCL_ERROR;
}

//==========================================================================
void TagMgr::_dump(TagData *tagPtr) {

   if (tagPtr == NULL) {
................................................................................


// define IDs for options we either need to error check or respond to
#define MKOPT_BG   1
#define MKOPT_FG   1 << 1
#define MKOPT_TYPE 1 << 2
#define MKOPT_IMG  1 << 3
#define MKOPT_XPM  1 << 4

// define configuration options
static Tk_OptionSpec markerOptionSpecs[] = {
   {TK_OPTION_COLOR,  "-background", NULL, NULL,
         "white", -1, Tk_Offset(MarkerOptions, bgColor), TK_OPTION_NULL_OK, 0, MKOPT_BG
   },
   {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0},
................................................................................

   {TK_OPTION_STRING,  "-image", NULL, NULL,
         "", -1, Tk_Offset(MarkerOptions, imgName), 0, 0, MKOPT_IMG
   },
   {TK_OPTION_STRING_TABLE, "-type", NULL, NULL,
	     (char*)MarkerTypeNames[MK_CIRCLE], -1, Tk_Offset(MarkerOptions, type), 0, (ClientData)MarkerTypeNames, MKOPT_TYPE
   },
   {TK_OPTION_STRING,  "-xpm", NULL, NULL,
         "", -1, Tk_Offset(MarkerOptions, xpmData), 0, 0, MKOPT_XPM
   },
   {TK_OPTION_END}
};
//### CTOR ###
MarkerData::MarkerData(MarkerMgr *mgr) :
   name(0),
   id(-1),
   handle(-1),
................................................................................

   // must initialize all pointer/token values as per the Tk doc page:
   //    "...is responsible for storing NULL or None in all pointer 
   //    and token fields before invoking Tk_InitOptions."
   mopts->bgColor = NULL;
   mopts->fgColor = NULL;
   mopts->imgName = NULL;
   mopts->xpmData = NULL;
   mopts->type    = None;


   optionTable = Tk_CreateOptionTable(mgr->interp, markerOptionSpecs);

   if (Tk_InitOptions(mgr->interp, (char *)mopts, optionTable, mgr->tkwin) != TCL_OK) {
      fprintf(stderr, "ERROR in Tk_InitOptions: %s\n", Tcl_GetStringResult(mgr->interp));
   } else {
      // map the user-specified type to the Scintilla ID
................................................................................
MarkerData::~MarkerData() {
    if (cloned_from) {
        // update parent marker to let it know it just lost a clone
        cloned_from->cloned_n--;
    }
    // clean up objects used for marker options
    Tk_FreeConfigOptions((char *)mopts, optionTable, mgr->tkwin);


    Tcl_Free((char *)mopts);
}

//==========================================================================
// This will assign the Scintilla marker ID corresponding to the
// user-visible type name
//
................................................................................
            n, objv_arr, mgr->tkwin, NULL, NULL) != TCL_OK) {
        // uh oh...
    }
    Tcl_Free((char *)objv_arr);

    ScintillaObject *sci = SCIOBJ(mgr->sciwidgetPtr);

    if (src->typeID == SC_MARK_PIXMAP) {
        typeID = SC_MARK_PIXMAP;

        sci_cmd(sci, SCI_MARKERDEFINEPIXMAP, id, (sptr_t)mopts->xpmData);
    } else {
        sci_cmd(sci, SCI_MARKERDEFINE, id, typeID);
        if (mopts->bgColor) {
            sci_cmd(sci, SCI_MARKERSETBACK, id, _XRGB_(mopts->bgColor));
        }
        if (mopts->fgColor) {
            sci_cmd(sci, SCI_MARKERSETFORE, id, _XRGB_(mopts->fgColor));
................................................................................
            // get rid of the marker we had to create
            _deleteMarker(mPtr);
         }
         return TCL_ERROR;
      }
      // do some error checking...

      if ((mask & MKOPT_IMG) && (mask & MKOPT_XPM)) {
         Tk_RestoreSavedOptions(&savedOptions);
         if (isNew) _deleteMarker(mPtr);
         Tcl_AppendResult(interp, "the -image and -xpm options are mutually exclusive", (char *)NULL);
         return TCL_ERROR;
      }
      if ((mask & MKOPT_TYPE) && ((mask & MKOPT_IMG) || (mask & MKOPT_XPM))) {
         Tk_RestoreSavedOptions(&savedOptions);
         if (isNew) _deleteMarker(mPtr);
         Tcl_AppendResult(interp, "cannot use -type option with either -image or -xpm", (char *)NULL);
         return TCL_ERROR;
      }
      ScintillaObject *sci = SCIOBJ(sciwidgetPtr);
      bool do_define = true;

      if ((mask & MKOPT_IMG) || (mask & MKOPT_XPM)) {
         // verify the image is legal






         if (_validateImage(mPtr, (mask & MKOPT_XPM)) != TCL_OK) {
            Tk_RestoreSavedOptions(&savedOptions);
            if (isNew) _deleteMarker(mPtr);
            return TCL_ERROR;
         }
         // it's valid
         // NOTE: we (currently) don't do any checks on the data (it's assumed good)
         mPtr->typeID = SC_MARK_PIXMAP;
         sci_cmd(sci, SCI_MARKERDEFINEPIXMAP, mPtr->id, (sptr_t)mPtr->mopts->xpmData);
         do_define = false;
      }
      if (mask & MKOPT_TYPE) {
         mPtr->UpdateType();
      }

      // now let Scintilla know about it
................................................................................
      return NULL;
   }
   // look up the name in the hash table
   hPtr = Tcl_CreateHashEntry(&markerTable, markerName, &isNewMarker);
   if (isNew) *isNew = isNewMarker;
   if (!isNewMarker) {
      // Found it!
      return (MarkerData *)Tcl_GetHashValue(hPtr);

   }
   // No match, so create a new marker -- VERIFY WE CAN!!
   int id = _getNextId();
   if (id == -1) {
      Tcl_DeleteHashEntry(hPtr);
      Tcl_AppendResult(interp,
         "new marker could not be created: too many markers already exist", (char *)NULL);
................................................................................

//==========================================================================
// Validate image information being requested for use as a marker
//

// need a callback defined if we want to use Tk_GetImage
static void
_imgCallbackProc(ClientData cd, int x, int y, int w, int h, int imgW, int imgH) {}

int MarkerMgr::_validateImage(MarkerData *mPtr, bool check_xpm) {


   if (check_xpm) {
      // simplest check is to see if caller actually gave us a path
      // to an XPM file instead of the data
      Tcl_Obj *path = Tcl_NewStringObj( mPtr->mopts->xpmData,-1);
      int stat;
      Tcl_IncrRefCount(path);
      if (Tcl_FSAccess(path, F_OK) == 0) {
          Tcl_AppendResult(interp,
                "XPM image data invalid: option specified is a file pathname(",
              mPtr->mopts->xpmData, ")", (char *)NULL);
          stat = TCL_ERROR;
      } else {
          stat = TCL_OK;

      }
      Tcl_DecrRefCount(path);
      return stat;
   }
   // assumed to be an existing Tk image name ... verify it

   const char *imageName = mPtr->mopts->imgName;




   if (Tk_GetImage(interp, tkwin, imageName, _imgCallbackProc,0) == NULL) {

      return TCL_ERROR;
   }
   // we know the image exists, let's check its data

   Tcl_Obj *cmd = Tcl_ObjPrintf("%s data -format xpm", imageName);


   if (Tcl_Eval(interp, Tcl_GetString(cmd)) != TCL_OK) {






      return TCL_ERROR;
   }


   // at this point we should have the XPM char array data stored in the Tcl result.
   // store it with the marker
   //

   // *** NEED TO MANUALLY CALL Tcl_Alloc TO MAKE SURE THE
   // *** MEMORY ALLOCATION IS DONE FOR THE -XPM OPTION.

   Tcl_Obj *result = Tcl_GetObjResult(interp);
   char *xpm_data  = Tcl_GetStringFromObj(result, NULL);
   int slen        = strlen(xpm_data);
   char *buf       = Tcl_Alloc (slen+1);
   strcpy(buf, xpm_data);
   mPtr->mopts->xpmData = buf; // this will get free'd in the destructor

   Tcl_ResetResult(interp);
   return TCL_OK;
}


//==========================================================================
void MarkerMgr::_dump(MarkerData *mPtr) {

................................................................................

   fprintf(stderr, "NAME   : %s\n", mPtr->name);
   fprintf(stderr, "ID     : %d\n", mPtr->id);
   fprintf(stderr, "HNDL   : %d\n", mPtr->handle);
   fprintf(stderr, "TYPE   : %s\n", MarkerTypeNames[mPtr->mopts->type]);
   if (mopts->imgName)
   fprintf(stderr, "IMAGE  : %s\n", mopts->imgName);
   if (mopts->xpmData) {
      // get a reasonable subset of the XPM content for display
      Tcl_DString dstr;
      Tcl_DStringInit(&dstr);
      Tcl_DStringAppend(&dstr, mopts->xpmData, -1);
      Tcl_DStringSetLength(&dstr, 100);
      Tcl_DStringAppend(&dstr, "\n...", -1);
      fprintf(stderr, "XPM    : %s\n", Tcl_DStringValue(&dstr));
   }
   fprintf(stderr, "S-TYPE : %d\n", mPtr->typeID);
   if (mopts->fgColor == NULL)
   fprintf(stderr, "FG     : <null>\n");
   else
   fprintf(stderr, "FG     : %d,%d,%d\n", mopts->fgColor->red,mopts->fgColor->green,mopts->fgColor->blue);
   if (mopts->bgColor == NULL)
   fprintf(stderr, "BG     : <null>\n");
................................................................................
        case CMD_PREV: {
            if (objc != 4) {
                Tcl_WrongNumArgs(interp, 3, objv, "index");
                return TCL_ERROR;
            }
            bool fwd = ((enum optionIds)index == CMD_NEXT);
            char *index_str = Tcl_GetString(objv[3]);
            int start_pos;
            if ((markPtr = FindMark(index_str)) != NULL) {
                if (fwd) {
                    start_pos = markPtr->pos + 1; // start AFTER the mark
                } else {
                    start_pos = markPtr->pos - 1; // start BEFORE the mark
                }
            } else {
................................................................................
// Implements the MARK SET sub-command
//
int MarkMgr::CmdSet(int objc, Tcl_Obj *CONST objv[]) {

    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    MarkData *markPtr;
    char *name, *index_str;
    int pos;
    
    if (objc != 5) {
        Tcl_WrongNumArgs(interp, 3, objv, "markName index");
        return TCL_ERROR;
    }
    name      = Tcl_GetString(objv[3]);
    index_str = Tcl_GetString(objv[4]);
................................................................................
        return;
    }
    fprintf(stderr, "POINTER: %p\n", (void *)mPtr);
    fprintf(stderr, "NAME   : %s\n", mPtr->name);
    fprintf(stderr, "POS    : %d\n", mPtr->pos);
    fprintf(stderr, "GRAVITY: %s\n", mPtr->gravityLeft ? "Left" : "Right");
}






























































































































































































































}//--- end of namespace TkSci







>
>
>
>
>
>
>
>
>
>
>



>
>
>







 







>





>
>
>
>
>











|


|
>
|
<
|
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







 







|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>







 







>






|
>
>
>







 







>
>
>







 







|
>







|







 







>







 







|
|
>
|







 







|

|
|
|





>
>
>
>
>
>
|
>
>
>
>
>
>
>
>







 







|
|
|
|
|
|
|
>







>
>
>
>
>







 







|
<

>
|


>
>



<
>
|

|
<
|
<
>
|
<
>
|
|
>
|
|
|
|
|

>







 







|
>
|







 







>
|







 







|







 







|
|







 







|
|







 







|
|







 







|
|







 







|
|







 







|







 







|







 







|



>
|







 







|







 







|
|







 







|







 







|







 







|











>
|
>
>
>
>
>
>
>
>
>







 







|







 







|
|
|
<
>
|
|
|
>
|
>







>
>
>
>
>
>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>







|







 







<
<







 







<







 







>







 







>







 







>
>
>



>
>







 







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

|




>
>
>
>
>
>
|

>



>
>
>
>
>
>
>
>
>
>
>
>
>
>


|




>
>
>
>
>
>
|

>
|
>







 







>
|
|
|
|
|
|
>
>



>
>
>
>







 







>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<






|


|
|
|
|
|
|
>
>



|




|

>
>
>
>

|




|

>
>
>
>
>
>

|


|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
>
>


|
<
<
<

>
|
>


<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







 







|







 







|







 







|
|
|
|
>

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<

>
|
|
|
|
<
<
<
<
<
<
<
<
<
|
>
>
>
|
|
|
|
<
>
>
>
>
|
>
>
>
|
|
|
|
|
|
|
<
>
|
|
<
<
<
|
<
<
<
<
<
<
|
|
|
|
|
|
|
|
<
<
<
<
|
>
>
>
|
|
>
|
<
<
<
<
<
<
<
<
<
<
>
|
|
|
<
|

|







 







>
>
>
|







 







<
<
<
<
<






>
>
>
>
>
>




|







 







>
>
>
>
|

>







 







>
>
>
>







 







<
<
<






<
<
<
<
<
<
<
<
<
|
<
<
<







 







|







 







|







 







>
>
|
|
|
>
|
|
|
|
<
<







 







|
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>

<
<












|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|

|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|









<
|
|
|
|
>

|
|
|
|
|
|
|
|
|
|
|
|
<
<
>
>
|
|
|
|
|
<
>
>
>
>
|
|
|
|
|
<
<
<
>
>
|
>
|
<
<
<
<
>
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
>
|
<
|
|







 







|
|
<
<

|
|
<
>
>
>
>
|
<
>
|
|
|
|

<
|
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>







 







|






|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|








>
|
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
|
<
|
<
<
<
>
>
>
>
>
>
>
>
>
|
<
<
<
|
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
<
>
>
>
>
>
|
>
>
>
>
>
|
<
<
<
<
<
>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
>
>
>
>
|
>
>
>
|
>
>
>



>




>
>
>
>
>







 







>
>
>
>
>
>
>



|
|



|

|







|
<
<
<
<
<
<
<
<
<
<
<

|

>
>



<







 







>
>
>









>
>
>






>
>
>











|

<
<
<
<
<
<
<






|




<
<
<
<
<
<
<
<
<
<
<







 







>
>



|



>
|


>
|

>
>
>
|
<
>
>







 







|


|
|







 







>
>




|
|







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>




|





|
>
>
>
>
>







 







<







 







<
<
<







 







|

>







 







>
>







 







|
|
|
|







 







<
<
<
<
<
<
|


|





|

>
>
>
>
>
>
|




<
<
<
<







 







|
>







 







|
|
|
<
>
|
|
|
|
<
<
<
<
<
|
<
<
<
>
|
<
<
|
<
>

>
>
>

<
>


<

<
>

<
>
>
>
>
>
>
|

>
>
|
|
<
>
|
<
>
|
|
|
|
<
<

<







 







<
<
<
<
<
<
<
<
<







 







|







 







|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
42
43
44
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
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
...
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
...
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
...
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
...
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
....
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
....
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
....
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
....
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
....
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
....
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
....
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
....
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
....
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
....
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
....
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
....
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
....
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
....
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
....
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
....
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
....
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
....
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
....
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
....
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
....
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
....
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
....
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
....
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
....
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
....
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
....
6479
6480
6481
6482
6483
6484
6485


6486
6487
6488
6489
6490
6491
6492
....
6528
6529
6530
6531
6532
6533
6534

6535
6536
6537
6538
6539
6540
6541
....
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
....
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
....
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
....
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
....
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
....
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
....
7225
7226
7227
7228
7229
7230
7231














7232
7233
7234
7235
7236
7237
7238
....
7375
7376
7377
7378
7379
7380
7381


































7382


7383
7384
7385
7386
7387
7388
7389
....
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
....
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
....
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
....
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
.....
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
.....
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133


10134
10135
10136
10137
10138
10139









10140
10141
10142
10143
10144
10145
10146
10147

10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162

10163
10164
10165



10166






10167
10168
10169
10170
10171
10172
10173
10174




10175
10176
10177
10178
10179
10180
10181
10182










10183
10184
10185
10186

10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
.....
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
.....
10316
10317
10318
10319
10320
10321
10322





10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
.....
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361
10362
10363
10364
10365
10366
10367
10368
.....
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
.....
10449
10450
10451
10452
10453
10454
10455



10456
10457
10458
10459
10460
10461









10462



10463
10464
10465
10466
10467
10468
10469
.....
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
.....
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
.....
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584


10585
10586
10587
10588
10589
10590
10591
.....
10606
10607
10608
10609
10610
10611
10612
10613
10614









10615

























10616
10617
10618
10619


10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691

10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730

10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748


10749
10750
10751
10752
10753
10754
10755

10756
10757
10758
10759
10760
10761
10762
10763
10764



10765
10766
10767
10768
10769




10770
10771

10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802
10803
10804
10805







10806
10807

10808
10809
10810
10811
10812
10813
10814
10815
10816
.....
10876
10877
10878
10879
10880
10881
10882
10883
10884


10885
10886
10887

10888
10889
10890
10891
10892

10893
10894
10895
10896
10897
10898

10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
.....
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
.....
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104

11105



11106
11107
11108
11109
11110
11111
11112
11113
11114
11115



11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132

11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144





11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158



11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190
.....
11218
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250











11251
11252
11253
11254
11255
11256
11257
11258

11259
11260
11261
11262
11263
11264
11265
.....
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309







11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320











11321
11322
11323
11324
11325
11326
11327
.....
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354

11355
11356
11357
11358
11359
11360
11361
11362
11363
.....
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
.....
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
.....
11610
11611
11612
11613
11614
11615
11616

11617
11618
11619
11620
11621
11622
11623
.....
11629
11630
11631
11632
11633
11634
11635



11636
11637
11638
11639
11640
11641
11642
.....
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
.....
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
.....
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758
.....
12002
12003
12004
12005
12006
12007
12008






12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030




12031
12032
12033
12034
12035
12036
12037
.....
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
.....
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436

12437
12438
12439
12440
12441





12442



12443
12444


12445

12446
12447
12448
12449
12450
12451

12452
12453
12454

12455

12456
12457

12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469

12470
12471

12472
12473
12474
12475
12476


12477

12478
12479
12480
12481
12482
12483
12484
.....
12507
12508
12509
12510
12511
12512
12513









12514
12515
12516
12517
12518
12519
12520
.....
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
.....
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765
12766
.....
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
13167
13168
13169
13170
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267
13268
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
//# open-source text editor
//#
//# NOTE: DUE TO TECHNICAL CHALLENGES WITH MANAGING THE SCINTILLA
//#       DRAWING, WE DO __NOT__ SUPPORT A BORDER OR HIGHLIGHT
//#       RECTANGLE AS PART OF THIS NEW WIDGET.
//#
//#####################################################################
//
// Portions copied from tkText.c --
//
// Copyright (c) 1992-1994 The Regents of the University of California.
// Copyright (c) 1994-1996 Sun Microsystems, Inc.
// Copyright (c) 1999 by Scriptics Corporation.
//
// See the file "license.terms" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
///
//
// Copyright (c) 2013 Mentor Graphics Corporation
// The license.terms file describes the conditions under which this software may be distributed.

//#define DEBUG_TAGLOCATIONS
#define CHECK_TAGLOCATIONS
//#define ENABLE_TAG_PRIORITIES

#include <assert.h>
#include <tcl.h>
#include <tk.h>
#include <tkInt.h> // for access to "region" features

#ifdef _WIN32
................................................................................
#endif
#endif

#include "sciwrappers.h"
#include "scintilla-ext.h"
#include "scintilla-cmd.h"

#include <algorithm>
#include <vector>

#ifndef F_OK
#define F_OK 0
#endif

Tcl_Interp *scintilla_interp = NULL;

// create our namespace
namespace TkSci {

#ifdef DEBUG
static void _DBG(const char *format, ...) {
   char buffer[2000];
   va_list pArguments;
   va_start(pArguments, format);
   vsprintf(buffer, format, pArguments);
   va_end(pArguments);
   fprintf(stderr, "%s", buffer);
}
#else
#define _DBG(a)
#endif

#ifdef CHECK_TAGLOCATIONS
static void checkLocations(std::vector<TagLocation*> &locations)
{

sptr_t lastloc = (sptr_t)-1;
TagLocation *tp;
    for (std::vector<TagLocation*>::iterator it = locations.begin(); it != locations.end(); ++it) {
        tp = *it;
        assert(tp->startpos() > lastloc);
        assert(tp->startpos() <= tp->endpos());
        lastloc = tp->endpos();
    }
}
#else
#define checkLocations(arg) /*nothing*/
#endif

//--------------------------------------------------------------------------
// local convenience macros
#define SSM(m, w, l) scintilla_send_message(sciwidgetPtr->editor, m, w, l)

// set color based on 0-255 values for RGB
#define _RGB_(r,g,b) r | (g << 8) | (b << 16)
................................................................................
            "5", -1, Tk_Offset(SciWidget, borderWidth), 0, 0, TK_SCI_LINE_GEOMETRY
      },
      {TK_OPTION_CURSOR,  "-busycursor", "cursor", "Cursor",
            "watch", -1, Tk_Offset(SciWidget, busycursor), TK_OPTION_NULL_OK, 0, OPT_CURSOR
      },
      {TK_OPTION_CURSOR,  "-cursor", "cursor", "Cursor",
            "xterm", -1, Tk_Offset(SciWidget, cursor), TK_OPTION_NULL_OK, 0, OPT_CURSOR
      },
      {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection",
          "1", -1, Tk_Offset(SciWidget, exportSelection), 0,0,0
      },
      {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, 
            NULL, 0, -1, 0, (ClientData)"-foreground", 0
      },
      {TK_OPTION_STRING_TABLE, "-foldstyle", "foldstyle", "FoldStyle",
            "boxtree", -1, Tk_Offset(SciWidget, foldstyle), 0, (ClientData) foldStrings, OPT_FOLDM
      },
................................................................................
static void SciWidgetDestroy     (ClientData clientData);
static void SciWidgetGeometry    (SciWidget *);
static void SciWidgetBindProc    (ClientData clientData, XEvent *eventPtr);
static void SciWidgetEventProc   (ClientData clientData, XEvent *eventPtr);
static int  SciWidgetInstanceCmd (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);

//--- others
static int      GetPosition(SciWidget *, CONST char *, sptr_t *, bool);
static Tcl_Obj* GetTextRange(SciWidget *, int, int, bool);
static void     ExtractText(SciWidget *, Tcl_Obj *, int, int);
static void     SortTags(int numTags, TagData **tagArrayPtr);
static int      TagSortProc(const void *first, const void *second);

// search tag locations for range start to end. If add is true, create location(s) and return the first one
// return iterator through it_p that can be used to retrieve additional locations for range via nextLocation calls. 
// If add is false, then only create tags if start-end does not span existing set of tags, return NULL if none found
typedef enum {
    SEARCH_ADD, // searching for an add operation, locations may be created to represent start/end points
    SEARCH_REM, // searching for a remove operation, locations may be split to represent start/end points but new locations will not be added
    SEARCH_IDX  // searching for an index operation, no locations will be created or split
} SearchType;

static void dumpLocations(const char* ident, std::vector<TagLocation*> &tagLocations)
{
    fprintf(stderr,"%s\n", ident);
    int count = 0;
    for (std::vector<TagLocation*>::iterator it = tagLocations.begin(); it != tagLocations.end(); ++it) {
        TagLocation *t_p = *it;
        fprintf(stderr,"   %d %p range %ld-%ld\n", count++, (void*)t_p, t_p->startpos(), t_p->endpos());
    }
}

static TagLocation *nextLocation(std::vector<TagLocation*> &tagLocations, sptr_t start, sptr_t end, std::vector<TagLocation*>::iterator *it_p)
{
    // Iterator pointed to by it_p was returned by searchLocations and/or this routine, client can use this
    // routine to step through TagLocations until the end position is reached
    TagLocation *t_p;

    if ((*it_p) >= tagLocations.end())
        return NULL;
    ++(*it_p);  // advance iterator to next tag location
    if ((*it_p) < tagLocations.end()) {
        t_p = *(*it_p);
        if ((t_p->startpos() >= start) && (t_p->endpos() <= end)) {
            return t_p;
        }
    }
    return NULL;
}

static TagLocation *adjustLocations(const char* ident, std::vector<TagLocation*> &tagLocations, SearchType type, sptr_t start, sptr_t end, long *idx_p)
{
long idx = *idx_p;
std::vector<TagLocation*>::iterator tmp_it = tagLocations.begin() + idx;
TagLocation *t_p = *tmp_it;
TagLocation *newLoc;

    assert(tmp_it >= tagLocations.begin() && tmp_it <= tagLocations.end());
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"adjustLocations start %ld end %ld idx %d tp %p %ld-%ld\n", start, end, idx, t_p, t_p->startpos(), t_p->endpos());
#endif
    if (t_p->startpos() > start) {
        // we've hit a "hole" in the allocated locations.  If add is
        // true, add a missing location, otherwise adjust start
        // position.
        if (type == SEARCH_ADD) {
            sptr_t endpos;
            if (end < t_p->startpos() - 1)
                endpos = end;
            else
                endpos = t_p->startpos() -1;
            newLoc = new TagLocation(NULL, start, endpos);
            tagLocations.insert(tmp_it, newLoc);
            *idx_p = *idx_p + 1;
            ++tmp_it;
            ++idx;
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"adjustLocations1, index %d current location %ld-%ld adding location %p %ld-%ld\n", *idx_p, t_p->startpos(), t_p->endpos(), newLoc, newLoc->startpos(), newLoc->endpos());
            dumpLocations(ident, tagLocations);
#endif
            checkLocations(tagLocations);
            if (endpos < end) {
                adjustLocations(ident, tagLocations, type, newLoc->endpos() + 1, end, &idx);
            }
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"adjustLocations1.5 returning %p\n", newLoc);
#endif
            return newLoc;
        } else {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"adjustLocations2, adjusting start to %ld\n", t_p->startpos());
#endif
            if (t_p->startpos() >= end)
                return t_p;
            start = t_p->startpos();
        }
    }

#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"adjustLocations2.5 start %ld end %ld idx %d tp %p %ld-%ld\n", start, end, idx, t_p, t_p->startpos(), t_p->endpos());
#endif
    if (type != SEARCH_IDX) {
        // adjust existing tag locations so that locations begin/end
        // exactly on start/end locations iterator points to location
        // containing start location. The value of add determines if
        // new locations are created (we're adding tags so new
        // locations should be added as opposed to removing tags were
        // we don't creat locations for non-existant tags)
        
        // case 1: tmp_it points to location that starts before start,
        //         break location in two such that the first part ends
        //         right before start. Then recurse and process rest.
        if (t_p->startpos() < start) {
#ifdef DEBUG_TAGLOCATIONS
            sptr_t oldStart = t_p->startpos();
#endif
            // split the existing location so it ends where the desired range begins
            newLoc = new TagLocation(t_p, start-1);   // create new tag location, intialize it's tags and start position from old
            // replace the old locaton with the new
            *tmp_it = newLoc;
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"adjustLocations3, start 0x%d changing location %p %ld-%ld to %p %ld-%ld\n", start, t_p, oldStart, t_p->endpos(), newLoc, newLoc->startpos(), newLoc->endpos());
            dumpLocations(ident, tagLocations);
#endif
            checkLocations(tagLocations);
            t_p->setStartPos(start);
            ++tmp_it;  // advance iterator to next location in table and insert adjusted location
            tagLocations.insert(tmp_it, t_p);
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"adjustLocations4, adding location %p %ld-%ld\n", t_p, t_p->startpos(), t_p->endpos());
            dumpLocations(ident, tagLocations);
#endif
            checkLocations(tagLocations);
            // pass index of location containing start position
            *idx_p = *idx_p + 1;
            // use copy of index for recursion to prevent update
            idx = *idx_p;
            // recurse to handle rest
            t_p = adjustLocations(ident, tagLocations, type, start, end, &idx);
        } else {
            // case 2: t_p->startpos() == start, location ends before end position
            assert(t_p->startpos() == start);
            idx = *idx_p + 1;
            if (t_p->endpos() < end) {
                if (idx < tagLocations.size()) {
                    // recurse to handle rest
                    adjustLocations(ident, tagLocations, type, t_p->endpos() + 1, end, &idx);
                } else if (type == SEARCH_ADD) {
                    t_p = new TagLocation(NULL, t_p->endpos() + 1, end);
                    tagLocations.push_back(t_p);
#ifdef DEBUG_TAGLOCATIONS
                    fprintf(stderr,"adjustLocations5, adding location %p %ld-%ld\n", t_p, t_p->startpos(), t_p->endpos());
                    dumpLocations(ident, tagLocations);
#endif
                    checkLocations(tagLocations);
                }
            } else if (t_p->endpos() > end) {
                // case 3: t_p->startpos() == start, location ends
                //         after end position, break location in two
                //         such that the first part ends at end, then
                //         insert new location that spans the rest of
                //         the original location
                newLoc = new TagLocation(t_p, end);   // create new tag location, intialize it's tags and start position from old
                // replace the old locaton with the new
                *tmp_it = newLoc;
#ifdef DEBUG_TAGLOCATIONS
                fprintf(stderr,"adjustLocations6, changing idx %d %ld-%ld to %ld-%ld\n", tmp_it - tagLocations.begin(), t_p->startpos(), t_p->endpos(), newLoc->startpos(), newLoc->endpos());
                dumpLocations(ident, tagLocations);
#endif
                checkLocations(tagLocations);
                t_p->setStartPos(end+1);
                if (tmp_it < tagLocations.end()) {
                    ++tmp_it;  // advance iterator to next location in table and insert adjusted location
                    tagLocations.insert(tmp_it, t_p);
                } else {
                    tagLocations.push_back(t_p);
                }
#ifdef DEBUG_TAGLOCATIONS
                fprintf(stderr,"adjustLocations7, adding location %p %ld-%ld\n", t_p, t_p->startpos(), t_p->endpos());
                dumpLocations(ident, tagLocations);
#endif
                checkLocations(tagLocations);
                t_p = newLoc;   // return pointer to location containing startpos
            } else {
                // case 4: location is exact match, nothing needs to be done
            }
        }
    }
    return t_p;
}

static TagLocation *searchLocations(const char* ident, std::vector<TagLocation*> &tagLocations, SearchType type, sptr_t start, sptr_t end, std::vector<TagLocation*>::iterator *it_p)
{
TagLocation *t_p;
long low = 0, mid = 0;
long high = tagLocations.size() - 1;
std::vector<TagLocation*>::iterator tmp_it;

    // do binary search of tagLocations, note the start/end of a location may overlap that of desired location, return
    // first location that contains the start position; it may need to be broken up, return iterator that can be used by
    // the sister method, nextLocation(sptr_t start, sptr_t end, std::vector<TagLocation*>::iterator *it_p)
    // The iterator should point to the entry for the returned TagLocation pointer, or tagLocations.end() if returning NULL.
    if (tagLocations.size() > 0) {
        while (high >= low) {
            mid = low+((high-low)>>1);
            t_p = tagLocations[mid];
            if (t_p->endpos() < start) {
                // location too low, search upper half
                low = mid + 1;
            } else if (t_p->startpos() > start) {
                // location too high, search bottom half
                high = mid - 1;
            } else {
#ifdef DEBUG_TAGLOCATIONS
                fprintf(stderr,"type %d found tag span %d-%d for search %d-%d\n", type, t_p->startpos(), t_p->endpos(), start, end);
#endif
                if ((type != SEARCH_IDX) && ((t_p->startpos() != start) || (t_p->endpos() != end))) {
                    t_p = adjustLocations(ident, tagLocations, type, start, end, &mid);
#ifdef DEBUG_TAGLOCATIONS
                    dumpLocations(ident, tagLocations);
                    fprintf(stderr,"   1returning %p, setting iterator to element %d, size %ld\n", t_p, mid, tagLocations.size());
#endif
                    checkLocations(tagLocations);
                }
                *it_p = tagLocations.begin() + mid;
                return t_p;
            }
        }
    }
    tmp_it = tagLocations.begin() + mid;
    // advance iterator to first location that follows new location
    while (tmp_it < tagLocations.end()) {
        TagLocation *newLoc = *tmp_it;
        if (newLoc->endpos() < start) {
            ++tmp_it;
            ++mid;
        } else
            break;
    }
    // unable to find location containing start, if we're doing search-only, return failure with iterator at proper insertion point
    if (type == SEARCH_IDX) {
        if (tmp_it < tagLocations.end()) {
            TagLocation *newLoc = *tmp_it;
            *it_p = tmp_it;
            if (newLoc->startpos() >= start && newLoc->endpos() <= end) {
#ifdef DEBUG_TAGLOCATIONS
                fprintf(stderr,"found tag span %ld-%ld\n", newLoc->startpos(), newLoc->endpos());
#endif
                return newLoc;
            } else {
                return NULL;
            }
        } else {
            *it_p = tagLocations.end();
            return NULL;
        }
    }
    // couldn't find location containing start, create one being mindful that there may be locations in table
    // overlapping locations before the end locations
    if (tmp_it < tagLocations.end()) {
        TagLocation *newLoc = *tmp_it;
        long tmp_idx;
        if (newLoc->startpos() <= end) {
            // use a copy of mid so that adjustLocations does not alter mid value
            tmp_idx = mid;
            if (type == SEARCH_ADD) {
                // create new location to cover area from start to existing location
                t_p = new TagLocation(NULL, start, newLoc->startpos() - 1);
                tagLocations.insert(tmp_it, t_p);
#ifdef DEBUG_TAGLOCATIONS
                fprintf(stderr,"search1: adding location %ld-%ld ahead of existing location %p %ld-%ld\n", t_p->startpos(), t_p->endpos(), newLoc, newLoc->startpos(), newLoc->endpos());
                dumpLocations(ident, tagLocations);
#endif
                checkLocations(tagLocations);
                ++tmp_idx;
            } else {
                t_p = newLoc;
            }
            adjustLocations(ident, tagLocations, type, newLoc->startpos(), end, &tmp_idx);
#ifdef DEBUG_TAGLOCATIONS
            dumpLocations(ident, tagLocations);
            fprintf(stderr,"   2returning %p, setting iterator to element %d\n", t_p, mid);
#endif
            checkLocations(tagLocations);
            // inserting may have reallocated vector, re-init iterator to be sure it's valid
            *it_p = tagLocations.begin() + mid;
            return t_p;
        } else if (type == SEARCH_ADD) {
            t_p = new TagLocation(NULL, start, end);
            tagLocations.insert(tmp_it, t_p);
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"search2: unable to find location %ld-%ld, creating one\n", start, end);
            dumpLocations(ident, tagLocations);
            fprintf(stderr,"   3returning %p, setting iterator to element %d\n", t_p, mid);
#endif
            checkLocations(tagLocations);
            *it_p = tagLocations.begin() + mid;
            return t_p;
        }
    } else if (type == SEARCH_ADD) {
        // simple case, no existing locations overlap any portion of new range
        t_p = new TagLocation(NULL, start, end);
        tagLocations.push_back(t_p);
        mid = tagLocations.end() - tagLocations.begin() - 1;
#ifdef DEBUG_TAGLOCATIONS
        fprintf(stderr,"search3: unable to find location %ld-%ld, creating one\n", start, end);
        dumpLocations(ident, tagLocations);
        fprintf(stderr,"   returning %p, setting iterator to element %d\n", t_p, mid);
#endif
        checkLocations(tagLocations);
        *it_p = tagLocations.begin() + mid;
        return t_p;
    }
    *it_p = tagLocations.end();
    return NULL;
}


/***********************************************************
 * Scintillatk_Init is called when the package is loaded.
 ***********************************************************/
#define SCI_VERSION  PACKAGE_VERSION
#define SCI_VER_DATE PACKAGE_DATE
................................................................................

   Tcl_CreateObjCommand(interp, "scintilla", SciWidgetCmd, (ClientData)NULL, SciWidgetDestroy);

   Tcl_PkgProvide(interp, "ScintillaTk", SCI_VERSION);
   scintilla_interp = interp;
   return TCL_OK;
}

static void SciWidgetDeleteCmd(void *data)
{
SciWidget *sciwidgetPtr = (SciWidget *)data;

    if (!(sciwidgetPtr->flags & DESTROYED)) {
        sciwidgetPtr->flags |= DESTROYED;
        Tk_DestroyWindow(sciwidgetPtr->tkwin);
    }
}

/* ScintillaFetchSelection 
 *   Called by Tk when the selection is requested by someone. It
 *   returns part or all of the selectionin a buffer provided by
 *   caller. 
 *
 * Results:
 *    The return value is the number of non-NULL bytes stored in
 *    buffer. Buffer is filled with NULL-terminated string containing
 *    part or all of selection, as specified by offset and maxBytes. 
 */
static int ScintillaFetchSelection(ClientData clientData, int offset, char* buffer, int maxBytes)
{
    SciWidget *sciwidgetPtr = (SciWidget*)clientData;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    if (!sciwidgetPtr->exportSelection)
        return -1;  // we're not exporting selections to others.
    int sel_beg = sci_cmd(obj, SCI_GETSELECTIONSTART);
    int sel_end = sci_cmd(obj, SCI_GETSELECTIONEND);
    if (sel_beg != sel_end) {
        Sci_TextRange tr;

        sel_beg += offset;
        if ((sel_end - sel_beg) > maxBytes)
            sel_end = sel_beg + maxBytes;
        tr.chrg.cpMin = sel_beg;
        tr.chrg.cpMax = sel_end;
        tr.lpstrText = buffer;
        SSM(SCI_GETTEXTRANGE, 0, (sptr_t)&tr);
        return (sel_end - sel_beg);
    }
    return 0;
}

static int
SciWidgetCmd(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   SciWidget *sciwidgetPtr;
   Tk_Window tkwin;
   int i;

   tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), NULL);
   if (tkwin == NULL) {
      return TCL_ERROR;
   }
   /*
    * Set resource class.
................................................................................
   sciwidgetPtr->readonly    = false;
   sciwidgetPtr->language    = NULL;
   sciwidgetPtr->langType    = SCLEX_NULL; // defined in include/SciLexer.h
   sciwidgetPtr->foldstyle   = foldBoxTree;
   sciwidgetPtr->busycursor  = None;
   sciwidgetPtr->cursor      = None;
   sciwidgetPtr->blinkcaret  = NULL;
   sciwidgetPtr->exportSelection = true;
   sciwidgetPtr->linesAddedCmd  = NULL;
   sciwidgetPtr->marginWidthCmd = NULL;
   sciwidgetPtr->moveUpdateCmd  = NULL;
   sciwidgetPtr->xScrollCmd     = NULL;
   sciwidgetPtr->yScrollCmd     = NULL;
   sciwidgetPtr->yscrollDelta = 0;
   sciwidgetPtr->styleBits = 8; // maximum is 8, value may change with different parsers
   for (i = 0; i < KEYWORDSET_MAX; ++i) {
      sciwidgetPtr->keywords[i] = NULL;
   }
   sciwidgetPtr->added_data = new SciWidgetLinesAdded;
   sciwidgetPtr->marginMgr  = new MarginMgr(sciwidgetPtr);
   sciwidgetPtr->tagMgr     = new TagMgr(sciwidgetPtr);
   sciwidgetPtr->markerMgr  = new MarkerMgr(sciwidgetPtr);
   sciwidgetPtr->markMgr    = new MarkMgr(sciwidgetPtr);
   sciwidgetPtr->bindingTable = NULL;

................................................................................
   //       OF TEXT WHEN A NON-ZERO PADDING WAS USED ON THE RIGHT SIDE. SO WE WILL
   //       LELAVE IT UP TO THE CLIENT WINDOW TO PROVIDE RHS PADDING.
   sci_set_padding(SCIOBJ(sciwidgetPtr), 4, 0);

   // turn off display of the extra carets which by default are
   // drawn at the edge of each "sub region" of the rectangle
   sci_cmd(SCIOBJ(sciwidgetPtr), SCI_SETADDITIONALCARETSVISIBLE, 0);

   // Set number of style bits to maximum supported, lexers may change this when they are loaded
   sci_cmd(SCIOBJ(sciwidgetPtr), SCI_SETSTYLEBITS, 8);

   // Register a handler for when the window is exposed or resized.
   //
   Tk_CreateEventHandler(sciwidgetPtr->tkwin,
      ExposureMask|StructureNotifyMask|FocusChangeMask,
      SciWidgetEventProc, (ClientData) sciwidgetPtr);

................................................................................
   // Register a handler for events that client could define bindings for
   Tk_CreateEventHandler(sciwidgetPtr->tkwin,
       ButtonPressMask|ButtonReleaseMask|
       EnterWindowMask|LeaveWindowMask|
       PointerMotionMask|VirtualEventMask,
      SciWidgetBindProc, (ClientData) sciwidgetPtr);

   // Register selection handler when other windows want our selection
   Tk_CreateSelHandler(sciwidgetPtr->tkwin, XA_PRIMARY, XA_STRING, ScintillaFetchSelection, (ClientData) sciwidgetPtr, XA_STRING);

   // Create a Tcl command that operates on the widget.
   //
   sciwidgetPtr->widgetCmd =
      Tcl_CreateObjCommand(interp, Tk_PathName(sciwidgetPtr->tkwin),
         SciWidgetInstanceCmd,
         (ClientData) sciwidgetPtr,
         SciWidgetDeleteCmd);

   // Parse the command line arguments.
   //
   sciwidgetPtr->optionTable = Tk_CreateOptionTable(interp, optionSpecs);

   if (Tk_InitOptions(interp, (char *)sciwidgetPtr,
         sciwidgetPtr->optionTable, sciwidgetPtr->tkwin) != TCL_OK) {
................................................................................
   /*
    * This frees up colors and fonts and any allocated
    * storage associated with the widget attributes.
    */
   if (sciwidgetPtr->tkwin) {
	Tk_FreeConfigOptions((char *)sciwidgetPtr, sciwidgetPtr->optionTable, sciwidgetPtr->tkwin);
   }
   Tk_DeleteOptionTable(sciwidgetPtr->optionTable);

   // other cleanup
   delete sciwidgetPtr->markerMgr;
   // marginMgr must be destroyed after markerMgr!
   delete sciwidgetPtr->marginMgr;
   delete sciwidgetPtr->markMgr;
   delete sciwidgetPtr->tagMgr;
................................................................................
         // stop here the "thumb" height will shrink, giving the user a
         // false sense of where in the document they are.
          keep_going = false;
      }
      SSM(SCI_SETFIRSTVISIBLELINE, topline, 0);
      if (!keep_going) return;

      // Using the following seems to screw up the repaint -- also,
      // other editors don't move the caret during a scrollbar drag,
      // so not using it(for now) is ok 
      //SSM(SCI_MOVECARETINSIDEVIEW,0,0);

   } else {
      topline = SSM(SCI_GETFIRSTVISIBLELINE, 0,0);
   }
   // NOTE: This is same way that Tk's text widget does it(see
   // the GetYView function in tkTextDisp.c)
   char buf1[TCL_DOUBLE_SPACE+1];
................................................................................
      }
      case CMD_INSERT: {
         result = CmdInsert(clientData, interp, objc, objv);
         break;
      }
      case CMD_KEYWORDS: {
         int keywordSet;
         /* 1st argument is keyword number 0-8, followed by a string defining keyword set */
         /* objv[2] == keyword number */
         /* objv[3] == cmd list (optional) */
         if ((objc != 3) && (objc != 4)) {
            Tcl_WrongNumArgs(interp, 1, objv, "number [keywords]");
            return TCL_ERROR;
         }
         if (Tcl_GetIntFromObj(interp, objv[2], &keywordSet) != TCL_OK) {
            return TCL_ERROR;
         }
         if (objc == 4) {
            if (sciwidgetPtr->keywords[keywordSet]) {
                Tcl_DecrRefCount(sciwidgetPtr->keywords[keywordSet]);
            }
            sciwidgetPtr->keywords[keywordSet] = objv[3];
            Tcl_IncrRefCount(sciwidgetPtr->keywords[keywordSet]);
            SSM(SCI_SETKEYWORDS, keywordSet, (sptr_t)Tcl_GetString(objv[3]));
         } else {
            // return keyword set
            if (sciwidgetPtr->keywords[keywordSet]) {
                Tcl_SetObjResult(interp, sciwidgetPtr->keywords[keywordSet]);
            } else {
                Tcl_ResetResult(interp);
            }
         }
         break;
      }
      case CMD_LOADLEXER: {
         result = CmdLoadLexer(clientData, interp, objc, objv);
         break;
      }
      case CMD_MARGIN: {
................................................................................
      }
      case CMD_MARKER: {
         result = sciwidgetPtr->markerMgr->InstanceCmd(objc, objv);
         break;
      }
      case CMD_PROPERTY: {
         /* 1st argument is property name if 2nd argument exists, set the property; otherwise return the property */
         if (objc == 2) {
             char *names;
             int len = SSM(SCI_PROPERTYNAMES, 0, 0);
             names = new char[len+1];
             len = SSM(SCI_PROPERTYNAMES, 0, (sptr_t)names);
             Tcl_SetObjResult(interp, Tcl_NewStringObj(names, len));
             delete[] names;
         } else if (objc == 3) {
            int len = SSM(SCI_GETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),0);
            if (len > 0) {
                char *buf = new char[len+1];
                len = SSM(SCI_GETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),(sptr_t)buf);
                Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, len));
                delete[] buf;
            }
         } else if (objc == 4) {
            SSM(SCI_SETPROPERTY,(uptr_t)Tcl_GetString(objv[2]),(sptr_t)Tcl_GetString(objv[3]));
         } else {
            Tcl_WrongNumArgs(interp, 1, objv, "property ?value?");
            return TCL_ERROR;
         }
         break;
      }
      case CMD_SEARCH: {
         result = CmdSearch(clientData, interp, objc, objv);
         break;
      }
................................................................................
 */
static int ExpandTabs(
   ClientData clientData,
   char      **_str)
{
   // We do Tab substitutions now since Scintilla doesn't
   // handle this for annotation strings
   char *src = *_str;

   int ntabs = 0;
   int col;
   while (*src != '\0') if (*src++ == '\t') ntabs++;

   if (ntabs == 0) return 0;

   src = *_str;

   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   int tw = sciwidgetPtr->tabwidth; // current tab width

   if (tw <= 0) return 0;
   int newlen = (strlen(src) - ntabs) + (ntabs * tw) + 1;
   char *buf = (char *) Tcl_Alloc(newlen);
   char *dst = buf; 

   col = 0;

   while (*src != '\0') {
       if (*src != '\t') {

           *dst++ = *src++;
           col++;
       } else {
           int tabstop = col + tw - (col % tw);
           for (; col < tabstop; col++) {
               *dst++ = ' '; 
           }
           src++;
       }
   }
   *dst++ = '\0';
   *_str = buf;
   return ntabs;
}


/*
 *----------------------------------------------------------------------
................................................................................
            int ntabs = ExpandTabs(clientData, &str);

            sci_cmd(sciobj, SCI_ANNOTATIONSETTEXT,  line, (sptr_t)str);
            if (ntabs)
               Tcl_Free(str);

            // if we have a valid tag, use it to set the style
            int offset = sci_cmd(sciobj, SCI_ANNOTATIONGETSTYLEOFFSET);
            if (tag && (tag->Type() & TT_ANNO)) {
               sci_cmd(sciobj, SCI_ANNOTATIONSETSTYLE, line, tag->StyleID() - offset);

               // as per Neil H. on 6/26/2012, the lack of support for the
               // following setting for attribute styles is a "limitation"
               //SSM(SCI_STYLESETEOLFILLED, tag->StyleID(), 0);
            }
            return TCL_OK;
         }
................................................................................
 */
static int CmdBbox(
    ClientData     clientData,
    Tcl_Interp    *interp,
    int            objc,
    Tcl_Obj *CONST objv[])
{
    sptr_t pos, endpos;
    int x, y, width, line, line_ht, r_edge;
    char *index_str;

    if (objc != 3) {
        Tcl_WrongNumArgs(interp, 2, objv, "index");
        return TCL_ERROR;
    }
    SciWidget *sciwidgetPtr = (SciWidget *)clientData;
................................................................................
        width = (r_edge - x);
        if (width < 0) width = 0;
    } else if (x > r_edge) {
        // not at end of line, but outside visible area
        width = 0; //<< same as Tk Text widget behavior
    } else {
        char buf[2];
        unsigned char sid = sci_cmd(sciobj, SCI_GETSTYLEAT, pos);
        buf[0]  = sci_cmd(sciobj, SCI_GETCHARAT, pos);
        buf[1]  = '\0';
        width = sci_cmd(sciobj, SCI_TEXTWIDTH, sid, (sptr_t)buf);
    }
    Tcl_Obj *listObj = Tcl_NewListObj(0, NULL);

    Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x));
................................................................................
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str, *op;
   int slen;
   sptr_t pos1 = -1;
   sptr_t pos2 = -1;

   if (objc != 5) {
      Tcl_WrongNumArgs(interp, 2, objv, "index1 op index2");
      return TCL_ERROR;
   }
   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   
................................................................................
static int CmdCount(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str, *option;
   sptr_t pos1 = -1;
   sptr_t pos2 = -1;
   int i = 0, found = 0, value = 0;
   Tcl_Obj *objPtr = NULL;

   if (objc < 4) {
      Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 index2");
      return TCL_ERROR;
   }
................................................................................
static int CmdDelete(
   ClientData     clientData,
   Tcl_Interp    *interp,
   int            objc,
   Tcl_Obj *CONST objv[])
{
   char *index_str;
   sptr_t pos1 = -1;
   sptr_t pos2 = -1;

   if (objc < 3) {
      Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2? ...?");
      return TCL_ERROR;
   }
   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   if (sciwidgetPtr->state == STATE_NORMAL) {
................................................................................
    if (i >= objc) {
        Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 ?index2?");
        return TCL_ERROR;
    }

    SciWidget *sciwidgetPtr = (SciWidget *)clientData;
    ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);
    sptr_t pos1 = -1;
    sptr_t pos2 = -1;
    char *index_str = Tcl_GetString(objv[i++]);
    if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
        goto error;
    }
    if (i < objc) {
        index_str = Tcl_GetString(objv[i++]);
        if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
................................................................................
   }
   // At this point, the value of "i" will be an argument
   // which should correspond with an index

   for (; i < objc; i += 2) {
      index_str = Tcl_GetString(objv[i]);

      sptr_t pos1 = -1;
      sptr_t pos2 = -1;
      if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
         goto error;
      }
      if (pos1 == -1) goto done; // index is valid, but not within document

      if (i+1 == objc) {
         // just a single index, either alone or as a single index
................................................................................
            SSM(SCI_GETTEXTRANGE,0,(sptr_t)&tr);
            //printf(">>>> FOUND (%d -> %d) <%s>\n",beg,end,tr.lpstrText);
            delete tr.lpstrText;
#endif
         }
      }
   } else {
      sptr_t pos = -1;
      if (GetPosition(sciwidgetPtr, ix, &pos, false) == TCL_OK) {
         if (pos == -1) {
             // index was a valid format, but couldn't be found
             goto done;
         }
         PosToIndex(interp, obj, pos);
         goto done;
................................................................................
            int new_ln = (plus ? (start_ln + num) : (start_ln - num));
            if (new_ln > sci_get_line_count(obj)) {
               // beyond last line, so use offset to end of document
               *offset = (sci_get_length(obj) - start_pos);
               return TCL_OK;
            }
            if (new_ln < 0) {
              *offset = (plus ? start_pos : -start_pos);
               return TCL_OK;
            }
            // ok, so we know we'll land on a valid line. check that it
            // has a column to match the starting position, and if not
            // then use its end of line
            int endcol = sci_get_line_length(obj, new_ln);
            endcol--; // ignore eol char
................................................................................
 *    None.
 *
 *---------------------------------------------------------------------------
 */
static int GetPosition(
   SciWidget  *sciwidgetPtr,
   CONST char *index_str,
   sptr_t     *posPtr,
   bool        visible)
{
    char *cp, *endp;
    sptr_t pos, curr_pos;
    int offset, line;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    if (index_str[0] == '@') {
        //----------------------
        //---  @X,Y
        //----------------------
        int x, y;
................................................................................

   if (sciwidgetPtr->state == STATE_NORMAL) {

      char *index_str = Tcl_GetString(objv[2]);
      char *to_add    = Tcl_GetString(objv[3]);

      // get the position where we'll do the add
      sptr_t pos;
      if (GetPosition(sciwidgetPtr, index_str, &pos, false) != TCL_OK) {
         return TCL_ERROR;
      }
      sci_add_text(obj, pos, to_add);
   }
   return TCL_OK;
}
................................................................................
   };

   // Parse the switch options
   int i, argsLeft, found;
   bool back = false;
   char *pattern, *index_str;
   Tcl_Obj *count_var = NULL;
   sptr_t pos1 = -1;
   sptr_t pos2 = -1;
   int flags = SCFIND_MATCHCASE; // default search flags

   for (i=2; i < objc; i++) {
      int index;

      if (Tcl_GetString(objv[i])[0] != '-') break;

................................................................................

   /*
	* Find the optional end location, similarly.
	*/

   if (toPtr != NULL) {
		SciWidget *sciwidgetPtr = (SciWidget *)searchSpecPtr->clientData;
		sptr_t posTo, posFrom;

		if (GetPosition(sciwidgetPtr, Tcl_GetString(toPtr), &posTo, false) != TCL_OK) {
			 return BadIndex(interp, Tcl_GetString(toPtr));
		}

		if (GetPosition(sciwidgetPtr, Tcl_GetString(fromPtr), &posFrom, false) != TCL_OK) {
			 return BadIndex(interp, Tcl_GetString(fromPtr));
................................................................................
    Tcl_Interp *interp,         /* For error messages. */
    Tcl_Obj *objPtr,            /* Contains a textual index like "1.2" */
    SearchSpec *searchSpecPtr,  /* Contains other search parameters. */
    int *linePosPtr,            /* For returning the line number. */
    int *offsetPosPtr)          /* For returning the text offset in the
                                 * line. */
{
   sptr_t pos1;
   int line;
   SciWidget *sciwidgetPtr = (SciWidget *)searchSpecPtr->clientData;
   ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

   if (GetPosition(sciwidgetPtr, Tcl_GetString(objPtr), &pos1, false) != TCL_OK) {
      return BadIndex(interp, Tcl_GetString(objPtr));
   }
................................................................................
   bool force_center = false;
   if (objc == 4) {
      char *arg = Tcl_GetString(objv[3]);
      if ((arg[0] == '-') && (strcmp(arg, "-center") == 0)) {
         force_center = true;
      }
   }
   sptr_t pos = -1;
   if (GetPosition(sciwidgetPtr, index_str, &pos, false) == TCL_OK) {
      if (pos == -1) {
         // assume index was specified beyond end of doc
         pos = sci_get_length(obj);
      }
      // if the widget isn't mapped yet, there's no point in continuing
      if ( ! Tk_IsMapped(sciwidgetPtr->tkwin)) {
          return TCL_OK;
      }
      // find out the top and bottom visible lines
      int topline  = sci_cmd(obj, SCI_GETFIRSTVISIBLELINE);
      // You can't use SCI_LINESONSCREEN because the returned value includes any annotation lines, not just document lines
      //int vislines = sci_cmd(obj, SCI_LINESONSCREEN);
      int x = 0;
      int y = Tk_Height(sciwidgetPtr->tkwin);
      int marginwidth = sciwidgetPtr->marginMgr->Width();
      marginwidth += SSM(SCI_GETMARGINLEFT,0,0); // internal text area padding
      if (x < marginwidth) {
         x = marginwidth;
      }
      int pos2  = sci_get_pos_from_xy(obj, x, y);
      int vislines = sci_get_line(obj, pos2) - topline;
      int botline  = topline + vislines;
      int midline  = topline + (vislines / 2);

      // get the line containing the target
      int line = sci_get_line(obj, pos);

      // get the last line
................................................................................

/****************************************************************
// Func: SciWidgetUpdateLang
// Desc: 
*****************************************************************/
static int
SciWidgetUpdateLang(Tcl_Interp *interp, SciWidget *sciwidgetPtr) {
    int newtype, i;

    if (!sciwidgetPtr->language) return TCL_OK;

    if( strcmp(sciwidgetPtr->language,"none") == 0) {
        newtype = SCLEX_NULL;
        SSM(SCI_SETLEXER, newtype, 0);
    } else {
................................................................................
        newtype =  SSM(SCI_GETLEXER,0,0);
        if (newtype == SCLEX_NULL) {
            Tcl_AppendResult(interp, "bad language name: ", sciwidgetPtr->language, (char*)NULL);
            return TCL_ERROR;
        }
    }
    if ((sciwidgetPtr->langType != SCLEX_NULL) && (sciwidgetPtr->langType != newtype)) {
        // determine style bits used by new lexer before reallocating styles for existant tags
        if (newtype == SCLEX_NULL) {
            // set number of style bits to maximum

            SSM(SCI_SETSTYLEBITS, 8, 0);
            sciwidgetPtr->styleBits = 8;
        } else {
            sciwidgetPtr->styleBits = SSM(SCI_GETSTYLEBITSNEEDED, 0, 0);
        }
        if (sciwidgetPtr->tagMgr->Reset(interp, newtype) != TCL_OK)
            return TCL_ERROR;
    }
    sciwidgetPtr->langType = newtype;

    // Not all of the lexers support this property, but the majority do
    SSM(SCI_SETPROPERTY, (uptr_t)"fold",         (sptr_t)"1");
    SSM(SCI_SETPROPERTY, (uptr_t)"fold.comment", (sptr_t)"1"); // notepad++ allows this

    // clear out any saved keywords for previous lexer
    for (i = 0; i < KEYWORDSET_MAX; ++i) {
        if (sciwidgetPtr->keywords[i]) {
           Tcl_DecrRefCount(sciwidgetPtr->keywords[i]);
            sciwidgetPtr->keywords[i] = NULL;
        }
    }
    return TCL_OK;
}

static void
SciWidgetCheckFoldMargin(SciWidget *sciwidgetPtr) {

   if (sciwidgetPtr->foldstyle < 0 || sciwidgetPtr->foldstyle >= foldMAX) {
      sciwidgetPtr->foldstyle = foldBoxTree; // force to valid value
................................................................................
    // over the text area (or we didn't get x/y)
    if (sci->cursor == None) {
        Tk_UndefineCursor(tkwin);
    } else {
        Tk_DefineCursor(tkwin, sci->cursor);
    }
}

/****************************************************************
// Func: ScintillaLostSelection
// Desc: Called by Tk when selection is grabbed away from a Scintilla widget.
*****************************************************************/
static void ScintillaLostSelection(ClientData clientData)
{
    SciWidget *sciwidgetPtr = (SciWidget*)clientData;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    if (!sciwidgetPtr->exportSelection)
        return;
    int sel_beg = sci_cmd(obj, SCI_GETSELECTIONSTART);
    int sel_end = sci_cmd(obj, SCI_GETSELECTIONEND);
    if (sel_beg != sel_end) {
        sci_cmd(obj, SCI_SETEMPTYSELECTION, sci_get_current_pos(obj));
        sciwidgetPtr->tagMgr->FireSelectionVirtual(); // signal selection changed.
    }
    sciwidgetPtr->flags &= ~GOT_SELECTION;
}

/****************************************************************
// Func: SciWidgetConfigure
// Desc: 
*****************************************************************/
static int
SciWidgetConfigure(
................................................................................
   int            objc,
   Tcl_Obj *CONST objv[])
{
   Tk_SavedOptions savedOptions;
   int mask = 0;
   // check if this is the first time doing this
   bool firsttime = false;
   bool oldExport = sciwidgetPtr->exportSelection;

   if (!(sciwidgetPtr->flags & INIT_CFG_DONE)) {
      sciwidgetPtr->flags |= INIT_CFG_DONE;
      firsttime = true;
   }

   /*
    * Tk_SetOptions does all the work of parsing the
................................................................................
       // to some small value since the Scintilla behavior is to increase
       // the value whenever it encounters a line which is longer.
       sci_cmd(sciobj, SCI_SETHSCROLLBAR, 1);
       sci_cmd(sciobj, SCI_SETSCROLLWIDTH, 100);
       sci_cmd(sciobj, SCI_SETSCROLLWIDTHTRACKING, 1);
   }
   SciWidgetGeometry(sciwidgetPtr);

   if (sciwidgetPtr->exportSelection && !oldExport) {
      /* If we've turned on exporting selection and there are selected characters,
       * claim the global selection.
       */
      int sel_beg = sci_cmd(sciobj, SCI_GETSELECTIONSTART);
      int sel_end = sci_cmd(sciobj, SCI_GETSELECTIONEND);
      if (sel_beg != sel_end) {
         Tk_OwnSelection(sciwidgetPtr->tkwin, XA_PRIMARY, ScintillaLostSelection, sciwidgetPtr);
         sciwidgetPtr->flags |= GOT_SELECTION;
      }
   }

   /*
    * Set up a call to display ourself.
    */
   if ((sciwidgetPtr->tkwin != NULL) &&
      Tk_IsMapped(sciwidgetPtr->tkwin) &&
      !(sciwidgetPtr->flags & REDRAW_PENDING)) {
	  Tk_CancelIdleCall(SciWidgetDisplay, (ClientData) sciwidgetPtr);
      Tk_DoWhenIdle(SciWidgetDisplay, (ClientData) sciwidgetPtr);
      sciwidgetPtr->flags |= REDRAW_PENDING;
   }
   Tk_FreeSavedOptions(&savedOptions);

   return TCL_OK;
}
................................................................................
/****************************************************************
// Func: SciWidgetEventProc
// Desc: 
*****************************************************************/
static void
SciWidgetEventProc(ClientData clientData, XEvent *eventPtr)
{


   int redraw = 0;
   char buf[32];

   SciWidget *sciwidgetPtr = (SciWidget *) clientData;

   if (0) {
     fprintf(stderr, "[XEVENT] wave_EventProc: %s (type=%s (%d))\n", 
................................................................................
      break;

	  case Expose: {
         XExposeEvent e = eventPtr->xexpose;
//printf("EXPOSED: +%02d+%02dx%03dx%03d  COUNT=%d\n", e.x,e.y,e.width,e.height,e.count);
         if ((sciwidgetPtr->flags & REDRAW_EXPOSE)) {
		    int max_right, max_bottom;


            max_right  = Platform::Maximum((sciwidgetPtr->expose_x + sciwidgetPtr->expose_w), (e.x + e.width));
            max_bottom = Platform::Maximum((sciwidgetPtr->expose_y + sciwidgetPtr->expose_h), (e.y + e.height));

            sciwidgetPtr->expose_x = Platform::Minimum(sciwidgetPtr->expose_x, e.x);
            sciwidgetPtr->expose_y = Platform::Minimum(sciwidgetPtr->expose_y, e.y);
            sciwidgetPtr->expose_w = max_right - sciwidgetPtr->expose_x;
................................................................................
          */
         sciwidgetPtr->tkwin = NULL;

         if (sciwidgetPtr->flags & REDRAW_PENDING) {
            Tk_CancelIdleCall(SciWidgetDisplay, (ClientData) sciwidgetPtr);
            sciwidgetPtr->flags &= ~REDRAW_PENDING;
         }
         sciwidgetPtr->flags |= DESTROYED;
         /*
          * This results in a call to SciWidgetDestroy.
          */
         Tcl_EventuallyFree((ClientData) sciwidgetPtr, (Tcl_FreeProc *)SciWidgetDestroy);
		 break;
      
	 case FocusIn :
................................................................................
		 break;
   }
   

   if (redraw) {
      if ((sciwidgetPtr->tkwin != NULL) && !(sciwidgetPtr->flags & REDRAW_PENDING)) {
         // schedule a call to the display routine
		 Tk_CancelIdleCall(SciWidgetDisplay, (ClientData) sciwidgetPtr);
		 Tk_DoWhenIdle(SciWidgetDisplay, (ClientData) sciwidgetPtr);
         sciwidgetPtr->flags |= REDRAW_PENDING;
      }
   }
}

/*
................................................................................
/****************************************************************
// Func: SciWidgetDisplay
// Desc: 
*****************************************************************/
void SciWidgetDisplay(ClientData clientData)
{
   PRectangle rc;
   PRectangle cursor_rc;
   int efficient_blt = 0;
   ScintillaObject *sciobj;
   SciWidget *sciwidgetPtr = (SciWidget *)clientData;
   Tk_Window tkwin = sciwidgetPtr->tkwin;
   rc = PRectangle(0, 0, Tk_Width(tkwin), Tk_Height(tkwin)); 
   sciobj = SCIOBJ(sciwidgetPtr);
   cursor_rc = PRectangle(0,0,0,0);

#if 0
printf("#############################################\n");
printf("SciWidgetDisplay w/ FLAGS = ");
if (sciwidgetPtr->flags & REDRAW_PENDING) printf("|REDRAW_PENDING");
if (sciwidgetPtr->flags & REDRAW_YSCROLL) printf("|REDRAW_YSCROLL");
if (sciwidgetPtr->flags & REDRAW_EXPOSE)  printf("|REDRAW_EXPOSE");
................................................................................
         XGCValues gcValues;
         gcValues.graphics_exposures = True;
         sciwidgetPtr->copyGC = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
      }
	  /* test to see if the scroll region is less than the window hieght
	   * if it isn't, nosense in blitting as its all new text
	   */
	  if (sciwidgetPtr->mainPixmap && sciwidgetPtr->copyGC) {
	   if (diff > 0 && diff < Tk_Height(tkwin)) {
	     /* if the cursor is blinking, we need to determine if it's rectangle also needs to be invalidated and redrawn */
	     
		if ( sciwidgetPtr->blinkcaret) {
			int cursorpos, currentline, firstline,lines;
			cursorpos = sci_cmd(sciobj, SCI_GETCURRENTPOS);
			firstline = sci_cmd(sciobj, SCI_GETFIRSTVISIBLELINE);
			lines = sci_cmd(sciobj, SCI_LINESONSCREEN);
			currentline = sci_cmd(sciobj, SCI_LINEFROMPOSITION,cursorpos);
			if (currentline > firstline && currentline <= (firstline + lines)) { 
				int y, height;				
				y = sci_cmd(sciobj, SCI_POINTYFROMPOSITION,0,cursorpos);
				height = sci_cmd(sciobj, SCI_TEXTHEIGHT,currentline);
				if ((y + height - diff) > 0)
                   cursor_rc = PRectangle(0,y- diff,Tk_Width(tkwin),y + height - diff);
			}
		}
         // shift pixels UP

         XCopyArea(
            display, sciwidgetPtr->mainPixmap, sciwidgetPtr->mainPixmap, sciwidgetPtr->copyGC,
            0, diff,
            Tk_Width(tkwin), Tk_Height(tkwin) - diff,
            0, 0
         );
         XCopyArea(
            display, sciwidgetPtr->mainPixmap, draw, sciwidgetPtr->copyGC,
            0, 0,
            Tk_Width(tkwin), Tk_Height(tkwin),
            0, 0
         );
		 rc = PRectangle(0,Tk_Height(tkwin) - diff ,
                         Tk_Width(tkwin), Tk_Height(tkwin));
		 efficient_blt = 1;
	  }
      
      if (diff < 0 && abs(diff) < Tk_Height(tkwin)) {
	     /* if the cursor is blinking, we need to determine if it's rectangle also needs to be invalidated and redrawn */
         if ( sciwidgetPtr->blinkcaret) {
			int cursorpos, currentline, firstline,lines;
			cursorpos = sci_cmd(sciobj, SCI_GETCURRENTPOS);
			firstline = sci_cmd(sciobj, SCI_GETFIRSTVISIBLELINE);
			lines = sci_cmd(sciobj, SCI_LINESONSCREEN);
			currentline = sci_cmd(sciobj, SCI_LINEFROMPOSITION,cursorpos);
			if (currentline >= firstline && currentline < (firstline + lines)) { 
				int y, height;
				y = sci_cmd(sciobj, SCI_POINTYFROMPOSITION,0,cursorpos);
				height = sci_cmd(sciobj, SCI_TEXTHEIGHT,currentline);
                cursor_rc = PRectangle(0,y+ abs(diff),Tk_Width(tkwin),y + height + abs(diff));
			}
		 }
          // shift pixels DOWN
         XCopyArea(
            display, sciwidgetPtr->mainPixmap, sciwidgetPtr->mainPixmap, sciwidgetPtr->copyGC,
            0, 0,
            Tk_Width(tkwin), Tk_Height(tkwin) + diff,
            0, -diff
         );
          XCopyArea(
            display, sciwidgetPtr->mainPixmap, draw, sciwidgetPtr->copyGC,
            0, 0,
            Tk_Width(tkwin), Tk_Height(tkwin),
            0, 0
         );
		 rc = PRectangle(0,0,
                         Tk_Width(tkwin), abs(diff));
 		 efficient_blt = 1;
      }	
    }
   }
   sciwidgetPtr->flags &= ~(REDRAW_PENDING|REDRAW_YSCROLL);
 
   if (sciwidgetPtr->flags & REDRAW_EXPOSE) {
      /*
	   * This is a work around for a scintilla bug.  If an expose occurs and the expose is entirerly over the 
	   * the margin (ie not text area exposed) Editor.cxx paint repaints the margin into the off screen pixmap.
................................................................................
	   */
	  int margin = sciwidgetPtr->marginMgr->Width() + 5;
	  if ((sciwidgetPtr->expose_x + sciwidgetPtr->expose_w) < margin) { 
			sciwidgetPtr->expose_w = margin;
	  }
	  /* end of work around */

	  if ( !efficient_blt  ) {
		  rc = PRectangle(
			sciwidgetPtr->expose_x,
			sciwidgetPtr->expose_y,
			(sciwidgetPtr->expose_x + sciwidgetPtr->expose_w),
			(sciwidgetPtr->expose_y + sciwidgetPtr->expose_h)
		);
	  }

//printf("REDRAW_EXPOSE: +%02d+%02dx%03dx%03d\n", sciwidgetPtr->expose_x, sciwidgetPtr->expose_y, sciwidgetPtr->expose_w, sciwidgetPtr->expose_h);
      sciwidgetPtr->flags &= ~REDRAW_EXPOSE;
   } 
   if ((efficient_blt) && (cursor_rc.Width() > 0)) {
	  	uptr_t cursor_rc_ptr = reinterpret_cast<uptr_t>(&cursor_rc);
	    scintilla_send_message(sciwidgetPtr->editor, SCI_TKMSG_PAINT, cursor_rc_ptr, 0);
   }
   uptr_t rc_ptr = reinterpret_cast<uptr_t>(&rc);
   scintilla_send_message(sciwidgetPtr->editor, SCI_TKMSG_PAINT, rc_ptr, 0);
}

/////////////////////////////////////////////////////////////////////////////////
// Handle message notifications from Scintilla code
//
................................................................................
   }
}
//### DTOR ###
MarginData::~MarginData() {

   // clean up objects used for margin options
   Tk_FreeConfigOptions((char *)mopts, optionTable, mgr->tkwin);
   Tk_DeleteOptionTable(optionTable);
   Tcl_Free((char *)mopts);
}

//==========================================================================
int MarginData::Configure(int objc, Tcl_Obj *CONST objv[]) {

   Tk_SavedOptions savedOptions;
................................................................................
   // create the margin objects, default all to zero width; also disable
   // click handling by default until client explicitly enables it
   for (int i=0; i < MAXM; i++) {
      margins[i] = new MarginData(this, i, 0);
      sci_set_margin_width(SCIOBJ(w), i, 0);
      sci_enable_margin_click(SCIOBJ(w), i, false);
   }














}
//### DTOR ###
MarginMgr::~MarginMgr() {

   // clean up the margin objects
   for (int i=0; i < MAXM; i++) {
      delete margins[i];
................................................................................
         break;
      }
      case CMD_COUNT: {
         Tcl_SetObjResult(interp, Tcl_NewIntObj(MAXM));
         break;
      }
      case CMD_DUMP: {


































         result = CmdDump(objc, objv);


         break;
      }
      case CMD_FILLNUMS: {
         result = CmdFillNums(objc, objv);
         break;
      }
      case CMD_HIDE: {
................................................................................
      result = m->Configure(objc-4, objv+4);
   }
   return result;
}

//==========================================================================
int MarginMgr::CmdDump(int objc, Tcl_Obj *CONST objv[]) {
    if (objc < 4) {
        Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 ?index2?");
        return TCL_ERROR;
    }

    // check to see if user wants internal dump style
    if (!strcmp(Tcl_GetString(objv[3]), "-internals")) {
        Tcl_Obj *buf = Tcl_NewStringObj("Margin DUMP:\n", -1);
        for (int i=0; i < MAXM; i++) {
            MarginData *m = margins[i];
            if (m->GetType() != SYMBOL && m->GetType() != FOLD)
                Tcl_AppendPrintfToObj(buf, 
                    "%d - WIDTH= %2d/%2d, CURSOR= %-10s, TYPE= %-10s, MASK=      <n/a>, ALIAS= %-12s, CLICKCMD= %s\n",
                    i,
                    m->GetVisibleWidth(), 
                    m->GetWidth(), 
                    m->GetCursorStr(),
                    m->GetTypeStr(),
                    m->GetAlias()? m->GetAlias() : "<null>",
                    m->GetClickCmd()? m->GetClickCmd() : "<null>"
                );
            else {
                // Need to use sprintf because Tcl_AppendPrintfToObj doesn't do the
                // hex formatting correctly
                char buf2[1024*10];
                sprintf(buf2, "%d - WIDTH= %2d/%2d, CURSOR= %-10s, TYPE= %-10s, MASK= 0x%08X, ALIAS= %-12s, CLICKCMD= %s\n",
                    i,
                    m->GetVisibleWidth(), 
                    m->GetWidth(), 
                    m->GetCursorStr(),
                    m->GetTypeStr(),
                    sci_get_margin_mask(SCIOBJ(sciwidgetPtr),i),
                    m->GetAlias()? m->GetAlias() : "<null>",
                    m->GetClickCmd()? m->GetClickCmd() : "<null>"
                );
                Tcl_AppendToObj(buf, buf2, -1);
            }
        }
        Tcl_SetObjResult(interp, buf);
        return TCL_OK;
    }

    if (objc < 6) {
        Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 ?index2?");
        return TCL_ERROR;
    }

    // get selected margin
    int id;
................................................................................
         Tcl_AppendToObj(objbuf, ", ", -1);
      Tcl_AppendToObj(objbuf, MarginTypeNames[i], -1);
   }
   _reportError(Tcl_GetString(objbuf));
   return TCL_ERROR;
}


/////////////////////////////////////////////////////////////////////////////////
// Tag configuration options
//
static const char *IndicatorTypeNames[] = {
    "none", "plain", "squiggle", "tt", "diagonal", "strike",
    "hidden", "box", "roundbox", "squarebox", "dash", "dots", 
    "squigglelow", "dotbox", "squigglepixmap", NULL
};

#define TOPT_BG          1
#define TOPT_FG          1 << 1
#define TOPT_UNDERLINE   1 << 2
#define TOPT_BOLD        1 << 3
#define TOPT_ITALIC      1 << 4
#define TOPT_INDIC_TYPE  1 << 5
#define TOPT_INDIC_ALPHA 1 << 6
#define TOPT_EOLFILLED   1 << 7

static Tk_OptionSpec tagOptionSpecs[] = {
   {TK_OPTION_COLOR,  "-background", NULL, NULL,
         NULL, -1, Tk_Offset(TagDataOptions, bgColor), TK_OPTION_NULL_OK, 0, TOPT_BG
   },
   {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0},

   {TK_OPTION_BOOLEAN, "-bold", NULL, NULL,
         "0", -1, Tk_Offset(TagDataOptions, bold), 0, 0, TOPT_BOLD
   },
    // default for eolfilled is 1 (on) to be consistent with the Tk text widget
   {TK_OPTION_BOOLEAN, "-eolfilled", NULL, NULL,
         "1", -1, Tk_Offset(StyleOptions, eolfilled), 0, 0, TOPT_EOLFILLED
   },
   {TK_OPTION_COLOR,  "-foreground", NULL, NULL,
         NULL, -1, Tk_Offset(TagDataOptions, fgColor), TK_OPTION_NULL_OK, 0, TOPT_FG
   },
   {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-foreground", 0},

   {TK_OPTION_STRING_TABLE, "-indicatortype", NULL, NULL,
	(char*)IndicatorTypeNames[indicNONE], -1, Tk_Offset(TagDataOptions, indicType), 0, (ClientData)IndicatorTypeNames, TOPT_INDIC_TYPE
   },
   {TK_OPTION_INT,     "-alpha", "alpha", "Alpha",
         "-1", -1, Tk_Offset(TagDataOptions, alpha), 0, 0, 0
   },
   {TK_OPTION_INT,     "-alphab", "alphab", "AlphaB",
         "-1", -1, Tk_Offset(TagDataOptions, alphab), 0, 0, 0
   },
   {TK_OPTION_BOOLEAN, "-italic", NULL, NULL,
         "0", -1, Tk_Offset(TagDataOptions, italic), 0, 0, TOPT_ITALIC
   },
   {TK_OPTION_BOOLEAN, "-underline", NULL, NULL,
         "0", -1, Tk_Offset(TagDataOptions, underline), 0, 0, TOPT_UNDERLINE
   },
   {TK_OPTION_END}
};


TagData::TagData(Tcl_Interp *interp, const char* n, int ttMask, int _priority)
{
    name        = new char[strlen(n)+1];
    strcpy(name, n);
    style_id    = -1;
    indic_id    = INDIC_PLAIN;
    tagType     = ttMask;
    options.bgColor     = NULL;
    options.fgColor     = NULL;
    options.bold        = 0;
    options.eolfilled   = 1;    // default is on to be consistent with Tk text widget
    options.italic      = 0;
    options.underline   = 0;
    options.indicType   = indicNONE;
    options.alpha       = -1;
    options.alphab      = -1;
    optionTable = Tk_CreateOptionTable(interp, tagOptionSpecs);
    // establish tag priority
    priority = _priority;
    flags = FLAG_NONE;
}

TagData::~TagData()
{
    delete [] name;
    Tk_DeleteOptionTable(optionTable);
}

void TagData::RegisterLocation(TagLocation *tl_p)
{
std::vector<TagLocation*>::iterator it;

#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"RegisterLocation %p %ld-%ld to tag %s\n", tl_p, tl_p->startpos(), tl_p->endpos(), Name());
    dumpLocations("TagData Locations", tagLocations);
#endif
    TagLocation *found_p = searchLocations("TagData Locations", tagLocations, SEARCH_IDX, tl_p->startpos(), tl_p->endpos(), &it);
    if (!found_p) {
        tagLocations.insert(it, tl_p);
#ifdef DEBUG_TAGLOCATIONS
        fprintf(stderr,"RegisterLocation added %p %ld-%ld to tag %s\n", tl_p, tl_p->startpos(), tl_p->endpos(), Name());
        dumpLocations("TagData Locations", tagLocations);
#endif
        checkLocations(tagLocations);
    }
}

void TagData::UnregisterLocation(TagLocation *tl_p)
{
std::vector<TagLocation*>::iterator it;

    // if we're in the process of deleting this tag, don't update the tagLocations vector or TagData::DeleteTag will have
    // invalid iterator issues
    if (flags & FLAG_DELETING)
        return;

#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"UnregisterLocation %p %ld-%ld from tag %s\n", tl_p, tl_p->startpos(), tl_p->endpos(), Name());
    dumpLocations("TagData Locations", tagLocations);
#endif
    // search tag location vector for desired tag
    TagLocation *found_p = searchLocations("TagData Locations", tagLocations, SEARCH_IDX, tl_p->startpos(), tl_p->endpos(), &it);
    if (found_p && found_p == tl_p) {
        // remove location from vector
        tagLocations.erase(it);
#ifdef DEBUG_TAGLOCATIONS
        fprintf(stderr,"UnregisterLocation erased %p %ld-%ld from tag %s\n", tl_p, tl_p->startpos(), tl_p->endpos(), Name());
        dumpLocations("TagData Locations", tagLocations);
#endif
    }
}

// implements tag nextrange command
void TagData::NextRange(Tcl_Interp *interp, ScintillaObject *obj, sptr_t pos1, sptr_t pos2, Tcl_Obj* indices)
{
std::vector<TagLocation*>::iterator it;
    // search tag location vector for desired tag
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"NextRange %ld-%ld tag %s\n", pos1, pos2, Name());
    dumpLocations("TagData Locations", tagLocations);
#endif
    TagLocation *found_p = searchLocations("TagData Locations", tagLocations, SEARCH_IDX, pos1, pos2, &it);
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"search %ld-%ld returned %p %ld-%ld\n", pos1, pos2, found_p, found_p?found_p->startpos():-1, found_p?found_p->endpos():-1);
    dumpLocations("TagData Locations", tagLocations);
#endif
    if (found_p) {
        sptr_t start = found_p->startpos();
        sptr_t end = found_p->endpos();
        // found location may begin before pos1, if so, go to the next location
        if ((start < pos1) && (++it < tagLocations.end())) {
            found_p = *it;
            if (found_p->startpos() > pos2) {
                return;
            }
            start = found_p->startpos();
            end = found_p->endpos();
        }
        // check following locations, if contiguous with previous, table may be fragmented due to tag add/remove operations
        while (++it < tagLocations.end()) {
            found_p = *it;
            if (found_p->startpos() != end+1)
                break;
            end = found_p->endpos();
        }
        PosToIndex(interp, obj, start, indices);
        PosToIndex(interp, obj, end+1, indices);
    }
}

// implements tag prevrange command
void TagData::PrevRange(Tcl_Interp *interp, ScintillaObject *obj, sptr_t pos1, sptr_t pos2, Tcl_Obj* indices)
{
std::vector<TagLocation*>::iterator it;
    // search tag location vector for desired tag
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"PrevRange %ld-%ld tag %s\n", pos1, pos2, Name());
    dumpLocations("TagData Locations", tagLocations);
#endif
    TagLocation *found_p = searchLocations("TagData Locations", tagLocations, SEARCH_IDX, pos1-1, pos1-1, &it);
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"search %ld-%ld returned %p %ld-%ld\n", pos1, pos1, found_p, found_p?found_p->startpos():-1, found_p?found_p->endpos():-1);
    dumpLocations("TagData Locations", tagLocations);
#endif
    if (found_p) {
        sptr_t start = found_p->startpos();
        sptr_t end = found_p->endpos();

        // found a location that began before pos1, make sure it does not begin before pos2
        // check previous locations, if contiguous, table may be fragmented due to tag add/remove operations
        if (start < pos2) {
            // tag starts too low
            return;
        }
        while (--it >= tagLocations.begin()) {
            found_p = *it;
            if  (found_p->endpos() != start-1) {
                break;
            }
            if (found_p->startpos() < pos2) {
                // tag starts too low
                return;
            }
            start = found_p->startpos();
        }
        PosToIndex(interp, obj, start, indices);
        PosToIndex(interp, obj, end+1, indices);
    }
}

// implements tag ranges command
void TagData::Ranges(Tcl_Interp *interp, ScintillaObject *obj, Tcl_Obj* indices)
{
sptr_t start = -1, end = -1;
    // generate start/end ranges for tag, adjacent Locations may have the same tag applied due to fragmentation caused by add/remove tag operations
    // concatenate adjacent locations if needed to span the full length of a tag range
    for (std::vector<TagLocation*>::iterator it = tagLocations.begin(); it != tagLocations.end(); ++it) {
        TagLocation *t_p = *it;
        if (start == -1) {
            start = t_p->startpos();
            end = t_p->endpos();
        } else if (end == t_p->endpos() - 1) {
            // logically concatenate locations
            end = t_p->endpos();
        } else {
            PosToIndex(interp, obj, start, indices);
            PosToIndex(interp, obj, end, indices);
            start = -1;
        }
    }
    // flush out last range
    if (start != -1) {
        PosToIndex(interp, obj, start, indices);
        PosToIndex(interp, obj, end, indices);
    }
}

void TagData::RemoveTag(TagMgr *mgr, sptr_t start, sptr_t end)
{
std::vector<TagLocation*>::iterator it;

    // see if tag is applied within start and end, remove it. If removed and display needs update, do so.
    // If this was the last tag on a location, notify TagMgr to remove the location.

    // search tag location vector for desired tag
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"RemoveTag %ld-%ld tag %s\n", start, end, Name());
    dumpLocations("TagData Locations", tagLocations);
#endif
    TagLocation *tl_p = searchLocations("TagData Locations", tagLocations, SEARCH_IDX, start, end, &it);
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"search %ld-%ld returned %p %ld-%ld\n", start, end, tl_p, tl_p?tl_p->startpos():-1, tl_p?tl_p->endpos():-1);
    dumpLocations("TagData Locations", tagLocations);
#endif
    while (tl_p) {
        TagData *newTd = tl_p->UnregisterTag(this);
        // if we're in the process of deleting this tag, don't update the tagLocations vector or TagData::DeleteTag will have
        // invalid iterator issues
        if (!(flags & FLAG_DELETING))
            tagLocations.erase(it);
        if (newTd) {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr, "   applying style for %s from %ld to %ld\n", newTd->name, tl_p->startpos(), tl_p->endpos());
#endif
            if (this->Type() & TT_INDIC) {
                // if we're replacing an indicator you have to remove the old value because they aren't mutually exclusive
                mgr->RemoveStyle(this, start, end);
            }
            mgr->ApplyStyle(newTd, tl_p->startpos(), tl_p->endpos());
        } else  if (tl_p->empty()) {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"      no more tags for location, setting to default\n");
#endif
            // remove all style, the tag location is empty, remove tag location too
            mgr->RemoveStyle(this, start, end);
            mgr->RemoveLocation(tl_p);
        }
        tl_p = nextLocation(tagLocations, start, end, &it);
    }
}

void TagData::DumpLocations()
{
char buf[2048];
    sprintf(buf, "%s TagData Locations:", Name());
    dumpLocations(buf, tagLocations);
}

void TagData::DeleteTag(TagMgr *mgr)
{
    flags |= FLAG_DELETING;
    // remove tag from tag manager's location list
    for (std::vector<TagLocation*>::iterator it = tagLocations.begin(); it != tagLocations.end(); ++it) {
        TagLocation *t_p = *it;
        mgr->RemoveTag(this, t_p->startpos(), t_p->endpos());
    }
}

/////////////////////////////////////////////////////////////////////////////////
// Implementation of TagMgr class
//
/////////////////////////////////////////////////////////////////////////////////

//### CTOR ###
................................................................................
   tkwin(w->tkwin),
   selTag(0),
   marginTag(0),
   numTags(0),
   numCurTags(0),
   curTagArrayPtr(0)
{
    // create the hash table
    Tcl_InitHashTable(&tagTable, TCL_STRING_KEYS);


    resetFreeIndicators();
    resetFreeTextStyles();
    resetFreeMarginStyles();
    resetFreeAnnotationStyles();

    pickEvent.type = LeaveNotify; // match initialization done in Tk Text widget code

    // allocate tag space for margins and annotations, maximum of 256 each
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    marginStyleOffset = sci_cmd(obj, SCI_ALLOCATEEXTENDEDSTYLES, 256, 0);
    sci_cmd(SCIOBJ(w), SCI_MARGINSETSTYLEOFFSET, marginStyleOffset);
    annotationStyleOffset = sci_cmd(obj, SCI_ALLOCATEEXTENDEDSTYLES, 256, 0);
    sci_cmd(SCIOBJ(w), SCI_ANNOTATIONSETSTYLEOFFSET, annotationStyleOffset);

    // create "special" built-in tags
    _createTag(TT_TEXT, TAG_SEL);
    _createTag(TT_MARG, TAG_MARGIN);
}

//### DTOR ###
TagMgr::~TagMgr() {

    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    TagData       *tagPtr;

    // first iterate through the objects in the hash table...
    for (hPtr = Tcl_FirstHashEntry(&tagTable, &search);
            hPtr != NULL; 
            hPtr = Tcl_NextHashEntry(&search)) {
        tagPtr = (TagData *) Tcl_GetHashValue(hPtr);

        _deleteTag(tagPtr, true/*ok to destroy built-in tags*/);
    }

    // then delete the has table itself
    Tcl_DeleteHashTable(&tagTable);

    // delete tagLocation vector
    for (std::vector<TagLocation*>::iterator it = tagLocations.begin(); it != tagLocations.end(); ++it) {
        delete *it;
    }

    // free tag space for margins and annotations
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    sci_cmd(obj, SCI_RELEASEALLEXTENDEDSTYLES, 0, 0);
}

void TagMgr::resetFreeTextStyles() {
    freeTextStyles.reset(); /* clear all bits */
    /* mark pre-allocated text styles */
    freeTextStyles.set(0); /* zero is the default, for unset style */
    freeTextStyles.set(32);
    freeTextStyles.set(33);
    freeTextStyles.set(34);
    freeTextStyles.set(35);
    freeTextStyles.set(36);
    freeTextStyles.set(37);
    freeTextStyles.set(38);
    freeTextStyles.set(39);
}

void TagMgr::resetFreeMarginStyles() {
    freeMarginStyles.reset(); /* clear all bits */
    freeMarginStyles.set(0); /* zero is the default, for unset style */
}




void TagMgr::resetFreeAnnotationStyles() {
    freeAnnotationStyles.reset(); /* clear all bits */
    freeAnnotationStyles.set(0); /* zero is the default, for unset style */
}


void TagMgr::resetFreeIndicators() {
















   freeIndicators = 0xfffffff0; // first eight indicators are preallocated by Scinilla, 8-31 are free
}

/*
 *--------------------------------------------------------------
 *
 * PickCurrent --
 *
................................................................................
                    }
                    Tcl_DeleteHashEntry(hPtr);
                }
            }
        }
        if (mask & 6) {
            // done with user-defined tags, dump lexer-related styles next
            unsigned char full_sid = sci_cmd(sciobj, SCI_GETSTYLEAT, i);
            // full_sid may have indicator bits encoded within, strip them appart
            if (full_sid) {
                char sbuf[10];
                int sid = SID2STYLE(sciwidgetPtr, full_sid);
                int indicator = SID2INDICATOR(sciwidgetPtr, full_sid);
                if (sid) {
                    if (last_sid && (last_sid != sid)) {
................................................................................
            Tcl_WrongNumArgs(interp, 3, objv, "tagName option");
            return TCL_ERROR;
         }
         TagData *tagPtr = FindTag(Tcl_GetString(objv[3]));
         if (tagPtr == NULL) {
            return TCL_ERROR;
         }
         Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *)&tagPtr->options,
            tagPtr->optionTable, objv[4], tkwin);
         if (objPtr == NULL) {
            return TCL_ERROR;
         }
         Tcl_SetObjResult(interp, objPtr);
         break;
      }
................................................................................
//
// This function will associate a previously defined tag with a specified
// range of text, or if a tag doesn't already exist it will create a new
// one (this matches the Tk Text widget behavior).
//
int TagMgr::CmdAdd(int objc, Tcl_Obj *CONST objv[]) {

TagData *tagPtr;
char *index_str, *tagName;
sptr_t pos1 = -1;
sptr_t pos2 = -1;
int i;

    if (objc < 5) {
        Tcl_WrongNumArgs(interp, 3, objv,
            //ix: 3    4       5      6
            "tagName index1 ?index2 ?index1 index2 ...?");
        return TCL_ERROR;
    }
    tagName = Tcl_GetString(objv[3]);
    // first check if it's an existing tag...
    if ((tagPtr = FindTag(tagName)) == NULL) {
        // If not, let's mimic the Tk Text behavior where a tag will get 
        // created. And since we can only apply tags which are indicators,
        // that's the type we'll use.
        //
        Tcl_ResetResult(interp);
        int isNewTag;
        tagPtr = _createTag(TT_INDIC|TT_TEXT, tagName, &isNewTag);
        if (tagPtr == NULL) {
            return TCL_ERROR;
        }
        // Note that in order to support existing code that may have been converted
        // from use with the Tk Text widget, we default the indicator type to be a
        // a solid filled rectangle. An example usage would be:
        //    $widget tag add my_tag 2.5 2.10
        //    #...other code...
        //    $widget tag configure my_tag -background yellow
        //
        tagPtr->options.indicType = indicSquareBox;
        _configIndicator(tagPtr);
    }



#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"Tag %s, applying from ", tagPtr->name);
#endif
    for (i = 4; i < objc; ++i) {
        // decode first location









        index_str = Tcl_GetString(objv[i++]);
#ifdef DEBUG_TAGLOCATIONS
        fprintf(stderr,"%s to ", index_str);
#endif
        if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
            goto error;
        }
        if (pos1 == -1) {

            // position outside of document, ignore it
            continue;
        }
        if (i < objc) {
            index_str = Tcl_GetString(objv[i]);
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"%s\n", index_str);
#endif
            if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
                goto error;
            }
            if (pos2 == -1) {
                // position outside of document, ignore it
                continue;
            }

            --pos2; // character range ends at character before second index
        } else {
            pos2 = pos1;    // just tag one character



        }






        if ((pos1 > pos2) && (tagPtr != selTag)) {
            // according to the Tk documenation this is a no-op
        } else {
            ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
            if (tagPtr == selTag) {
                //-----------------
                //--- SELECTION ---
                //-----------------




                sci_select(obj, pos1, pos2+1, 0);
                if (!(sciwidgetPtr->flags & GOT_SELECTION)) {
                    Tk_OwnSelection(sciwidgetPtr->tkwin, XA_PRIMARY, ScintillaLostSelection, sciwidgetPtr);
                    sciwidgetPtr->flags |= GOT_SELECTION;
                }
                FireSelectionVirtual(); // indicate a change occurred
                // no need to register selection locations
            } else {










                ApplyTag(tagPtr, pos1, pos2);
            }
        }
    }

    return TCL_OK;
 error:
    return BadIndex(interp, index_str);
}

//==========================================================================
// Implements the TAG BIND sub-command
//
// This function manages the interface between client binding definitions
// for a tag and setting up the widget to respond to those events
................................................................................
      Tcl_WrongNumArgs(interp, 3, objv,
         "tagName ?-margin? ?option? ?value? ?option value ...?");
      return TCL_ERROR;
   }
   // check for -margin option
   bool typeGiven = false;
   if (objc >= 5) {
      if (strcmp("-annotation", Tcl_GetString(objv[4])) == 0) {
         typeGiven = true;
         tt = TT_ANNO;
      } else if (strcmp("-margin", Tcl_GetString(objv[4])) == 0) {
         typeGiven = true;
         tt = TT_MARG;
      }
   }
   // This is kind of a hack, but we need to know when calling _createTag
   // if this is for an indicator since the identifiers for styles are
   // different than those for indicators
................................................................................
           tt |= TT_INDIC;
           if (tt & TT_MARG) {
              Tcl_AppendResult(interp, "Indicator tags not supported in margins", NULL);
              return TCL_ERROR;
           }
       }
   }






   if ( (typeGiven && (objc <= 6)) || (!typeGiven && (objc <= 5)) ) {
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // just return config info
      bool all = ( (typeGiven && (objc == 6)) || (!typeGiven && (objc == 5)) );
      int all_ix = 0;

      // look up tag, it's an error if tag does not exist
      tagPtr = FindTag(Tcl_GetString(objv[3]));
      if (tagPtr == NULL) {
          return TCL_ERROR;
      }
      if (all) {
         all_ix = typeGiven ? 5 : 4;
      }
      Tcl_Obj *objPtr = Tk_GetOptionInfo(
         interp, (char *) &tagPtr->options,
         tagPtr->optionTable,
         (all ? objv[all_ix] : NULL), tkwin);

      if (objPtr == NULL) {
         return TCL_ERROR;
      }
      Tcl_SetObjResult(interp, objPtr);
................................................................................
   } else {
      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      // modify the config data
      Tk_SavedOptions savedOptions;
      int mask = 0;
      int adj = (typeGiven ? 5 : 4);

      tagPtr = _createTag(tt, Tcl_GetString(objv[3]), &isNewTag);
      if (tagPtr == NULL) {
          return TCL_ERROR;
      }
      if (Tk_SetOptions(interp, (char *)&tagPtr->options, tagPtr->optionTable,
            objc-adj, objv+adj, tkwin, &savedOptions, &mask) != TCL_OK) {
         deleteTag(Tcl_GetString(objv[3]));
         return TCL_ERROR;
      }
      ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);

      if (tagPtr == selTag) {
         //-----------------
         //--- SELECTION ---
................................................................................

      if (mask & TOPT_BOLD) {
         sci_cmd(sciobj, SCI_STYLESETBOLD, sid, tagPtr->Bold());
         if ((tagPtr == marginTag) && (sid != STYLE_LINENUMBER)) {
            sci_cmd(sciobj, SCI_STYLESETBOLD, STYLE_LINENUMBER, tagPtr->Bold());
         }
      }
      if (tagPtr->EolFilled()) {
         sci_cmd(sciobj, SCI_STYLESETEOLFILLED, sid, tagPtr->EolFilled());
         // EolFilled is not supported in margins
      }
      if (mask & TOPT_ITALIC) {
         sci_cmd(sciobj, SCI_STYLESETITALIC, sid, tagPtr->Italic());
         if ((tagPtr == marginTag) && (sid != STYLE_LINENUMBER)) {
            sci_cmd(sciobj, SCI_STYLESETITALIC, STYLE_LINENUMBER, tagPtr->Italic());
         }
      }
      if (mask & TOPT_UNDERLINE) {
................................................................................
}

//==========================================================================
// Implements the TAG DELETE sub-command
//
int TagMgr::CmdDelete(int objc, Tcl_Obj *CONST objv[]) {




   if (objc < 4) {
      Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?");
      return TCL_ERROR;
   }
   for (int i=3; i < objc; i++) {
      const char *name = Tcl_GetString(objv[i]);









      deleteTag(name);



   }
   return TCL_OK;
}

//==========================================================================
// Implements the TAG NAMES sub-command
//
................................................................................
                Tcl_SetObjResult(interp, tmp);
            }
        }
    } else {
        // show only the tags at the specified location
        char *index_str = Tcl_GetString(objv[3]);
        char *tagName = (objc == 5 ? Tcl_GetString(objv[4]) : NULL);
        sptr_t pos = -1;
        if (GetPosition(sciwidgetPtr, index_str, &pos, false) != TCL_OK) {
            return BadIndex(interp, index_str);
        }
        for (hPtr = Tcl_FirstHashEntry(&tagTable, &search);
             hPtr != NULL; 
             hPtr = Tcl_NextHashEntry(&search)) {
            tagPtr = (TagData *) Tcl_GetHashValue(hPtr);
................................................................................

//==========================================================================
// Implements the TAG NEXTRANGE/PREVRANGE sub-commands
//
int TagMgr::CmdNPRange(int objc, Tcl_Obj *CONST objv[], bool next) {

    char *index_str;
    sptr_t pos1, pos2;
    TagData *tagPtr;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    Tcl_Obj *indices = Tcl_NewListObj(0, NULL);

    if ((objc != 5) && (objc != 6)) {
        Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
        return TCL_ERROR;
................................................................................
            goto error;
        }
        if (pos2 == -1) goto done;
        if (pos1 == pos2) goto done; // no-op
    } else {
        pos2 = (next ? sci_get_length(obj) : 0);
    }

    if (tagPtr == selTag) {
        // for code simplicity, we interpret the two indices to
        // represent the start and then the end of the target range.
        if (pos2 < pos1) {
            sptr_t tmp;
            tmp  = pos1;
            pos1 = pos2;
            pos2 = tmp;
        }


        //-----------------
        //--- SELECTION ---
        //-----------------
        if (sci_has_selection(obj)) {
            // need to handle both single and multiple selections
            int nsels = sci_cmd(obj,SCI_GETSELECTIONS);
            int dir = next ? 1 : -1;
................................................................................
                    PosToIndex(interp, obj, beg, indices);
                    PosToIndex(interp, obj, end, indices);
                    break;
                }
            }
            Tcl_SetObjResult(interp, indices);
        }
    } else {
        // search registered locations for tag









        if (next)

























            tagPtr->NextRange(interp, obj, pos1, pos2, indices);
        else
            tagPtr->PrevRange(interp, obj, pos1, pos2, indices);
        Tcl_SetObjResult(interp, indices);


    }
 done:
    return TCL_OK;
 error:
    return BadIndex(interp, index_str);
}

//==========================================================================
// Implements the TAG RANGES sub-command
//
int TagMgr::CmdRanges(int objc, Tcl_Obj *CONST objv[]) {

    TagData *tagPtr;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    if (objc != 4) {
        Tcl_WrongNumArgs(interp, 3, objv, "tagName");
        return TCL_ERROR;
    }
    tagPtr = FindTag(Tcl_GetString(objv[3]));
    if (tagPtr == NULL) {
        return TCL_ERROR;
    }
    Tcl_Obj *indices = Tcl_NewListObj(0, NULL);
    if (tagPtr == selTag) {
        //-----------------
        //--- SELECTION ---
        //-----------------
        if (sci_has_selection(obj)) {
            int nsels = sci_cmd(obj,SCI_GETSELECTIONS);
            // need to handle both single and multiple selections
            for (int i=0; i < nsels; i++) {
                int pos1 = sci_cmd(obj, SCI_GETSELECTIONNSTART, i);
                int pos2 = sci_cmd(obj, SCI_GETSELECTIONNEND, i);
                if (pos1 == pos2) continue;
                PosToIndex(interp, obj, pos1, indices);
                PosToIndex(interp, obj, pos2, indices);
            }
            Tcl_SetObjResult(interp, indices);
        }
    } else if (IsIndicator(tagPtr)) {
        //-----------------
        //--- INDICATOR ---
        //-----------------
        int id = tagPtr->IndicID();
        int len = sci_get_length(obj);
        for (int i=0; i < len; i++) {
            int beg = sci_cmd(obj, SCI_INDICATORSTART, id, i);
            int end = sci_cmd(obj, SCI_INDICATOREND,   id, beg);

            // check if the indicator exists at all within the document
            if ((beg == end) && (beg == 0)) break;
            i = end;

            // use the following call to know how to interpret the positions
            // we get from the above two calls; we want to verify that the
            // target indicator exists at the starting position.
            int mask = sci_cmd(obj, SCI_INDICATORALLONFOR, beg);

            if (mask & (1 << id)) {
                PosToIndex(interp, obj, beg, indices);
                PosToIndex(interp, obj, end, indices);
            } else {
                // when the indicator doesn't exist at the "beg" position
                // then we want the next search to begin at the "end"
                // position; so we need to decrement "i" since the next
                // iteration of the "for" loop will increment it first.
                i--;
            }
        }
        Tcl_SetObjResult(interp, indices);
    } else {

        //-----------------
        //--- STYLE ---
        //-----------------
        int i, id = tagPtr->StyleID();
        int beg = -1;
        int len = sci_get_length(obj);
        for (i=0; i < len; i++) {
            unsigned char style = sci_cmd(obj, SCI_GETSTYLEAT, i);
            if (style == id) {
                if (beg == -1) {
                    /* remember begining position */
                    beg = i;
                    PosToIndex(interp, obj, beg, indices);
                }
            } else {
                /* style is not what we looked for, see if we recorded a begining location */
                if (beg != -1) {
                    /* note end of style range */
                    PosToIndex(interp, obj, i, indices);
                    beg = -1;
                }
            }
        }
        if (beg != -1) {
            /* note end of style range */
            PosToIndex(interp, obj, i, indices);
        }
        Tcl_SetObjResult(interp, indices);
    }
    return TCL_OK;
}

//==========================================================================
// Implements the TAG REMOVE sub-command
//
// This function will remove the styling for a previously defined tag 
// from a specified range of text
//
int TagMgr::CmdRemove(int objc, Tcl_Obj *CONST objv[]) {

TagData *tagPtr;
char *index_str;
sptr_t pos1 = -1;
sptr_t pos2 = -1;
int i;

    if (objc < 5) {
        Tcl_WrongNumArgs(interp, 3, objv,
            "tagName index1 ?index2 index1 index2 ...?");
        return TCL_ERROR;
    }
    // check if the tag exists
    tagPtr = FindTag(Tcl_GetString(objv[3]));
    if (tagPtr == NULL) {
        // Tk Text widget doesn't issue an error for this, so we won't either
        Tcl_ResetResult(interp);
        return TCL_OK;
    }


    for (i = 4; i < objc; ++i) {
        // decode first location
        index_str = Tcl_GetString(objv[i++]);
        if (GetPosition(sciwidgetPtr, index_str, &pos1, false) != TCL_OK) {
            goto error;
        }
        if (pos1 == -1) {

            // position outside of document, ignore it
            continue;
        }
        if (i < objc) {
            index_str = Tcl_GetString(objv[i]);
            if (GetPosition(sciwidgetPtr, index_str, &pos2, false) != TCL_OK) {
                goto error;
            }
            if (pos2 == -1) {



                // position outside of document, ignore it
                continue;
            }
            --pos2; // character range ends at character before second index
        } else {




            pos2 = pos1;    // just process one character
        }

        if ((pos1 > pos2) && (tagPtr != selTag)) {
            // according to the Tk documenation this is a no-op
        } else {
            ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
            if (tagPtr == selTag) {
                //-----------------
                //--- SELECTION ---
                //-----------------
                int sel_beg = sci_cmd(obj, SCI_GETSELECTIONSTART);
                int sel_end = sci_cmd(obj, SCI_GETSELECTIONEND);
                if (sel_beg == sel_end) {
                    // there is no selection
                    goto done;
                }
                // check if the range to be removed overlaps with current selection
                if ((pos2 < sel_beg) || (pos1 > sel_end)) {
                    // no overlap
                    goto done;
                }
                if (pos1 <= sel_beg && pos2 >= sel_end) {
                    //CASE 1: range completely overlaps selection - remove it all
                    sci_cmd(obj, SCI_SETEMPTYSELECTION, sci_get_current_pos(obj));
                } else {
                    if (pos2 <= sel_end) {
                        //CASE 2: range overlaps selection start
                        sci_cmd(obj, SCI_SETSELECTIONSTART, pos2);
                    }
                    if (pos1 >= sel_beg) {
                        //CASE 3: range overlaps selection start
                        sci_cmd(obj, SCI_SETSELECTIONEND, pos1);
                    }
                }
                FireSelectionVirtual(); // indicate a change occurred
            } else {







                RemoveTag(tagPtr, pos1, pos2);
            }

        }
    }
 done:
   return TCL_OK;
 error:
   return BadIndex(interp, index_str);
}


................................................................................
    e.xany.window                = Tk_WindowId(tkwin);
    e.xany.display               = Tk_Display(tkwin);
    ((XVirtualEvent *) &e)->name = Tk_GetUid("Selection");
    Tk_HandleEvent(&e);
}

//==========================================================================
// Called when language set in widget and we need to reset all styles/indicators/tags
int TagMgr::Reset(Tcl_Interp *interp, int langType) {



    ColourDesired marginBG;
    ColourDesired marginFG;

    int type;
    TagData *tagPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);


    // save bg/fg for default line number style because doing SCI_STYLECLEARALL
    // will reset it to the Scintilla default
    marginBG = ColourDesired(sci_cmd(obj, SCI_STYLEGETBACK, STYLE_LINENUMBER));
    marginFG = ColourDesired(sci_cmd(obj, SCI_STYLEGETFORE, STYLE_LINENUMBER));


    // clear all styling information
    SSM(SCI_CLEARDOCUMENTSTYLE, 0,0);
    SSM(SCI_STYLECLEARALL,0,0);

    // restore default line number style
    sci_cmd(obj, SCI_STYLESETBACK, STYLE_LINENUMBER,     marginBG.AsLong());
    sci_cmd(obj, SCI_STYLESETFORE, STYLE_LINENUMBER,     marginFG.AsLong());

    // re-allocate styles/indicators/tags
    for (hPtr = Tcl_FirstHashEntry(&tagTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
        tagPtr = (TagData *) Tcl_GetHashValue(hPtr);
        type = tagPtr->Type();
        // indicators are unaffected by lexer change, only styles
        if (!IsIndicator(tagPtr)) {
            int sid = tagPtr->StyleID();
            if (tagPtr == selTag) {
                /* selection tag is special, you can only set foreground/background color */
                XColor *c = tagPtr->BG();
                if (c) {
                    sci_cmd(obj, SCI_SETSELBACK, 1, _XRGB_(c));
                } else {
                    sci_cmd(obj, SCI_SETSELBACK, 0, 0); // reset to using default
                }
                c = tagPtr->FG();
                if (c) {
                    sci_cmd(obj, SCI_SETSELFORE, 1, _XRGB_(c));
                } else {
                    sci_cmd(obj, SCI_SETSELFORE, 0, 0); // reset to using default
                }
                continue;
            } else if (tagPtr == marginTag) {
                /* margin tag is special, config value should already be set in widget */
                UpdateMarginColor(true, false);
                UpdateMarginColor(false, true);
                if (sid != STYLE_LINENUMBER) {
                    sci_cmd(obj, SCI_STYLESETBOLD, STYLE_LINENUMBER, tagPtr->Bold());
                    sci_cmd(obj, SCI_STYLESETITALIC, STYLE_LINENUMBER, tagPtr->Italic());
                    sci_cmd(obj, SCI_STYLESETUNDERLINE, STYLE_LINENUMBER, tagPtr->Underline());
                }
            } else {
                if ((tagPtr->Type() & TT_TEXT) && (langType != SCLEX_NULL)) {
                    /* setting language to something other than "none" */
                    Tcl_AppendResult(interp, "Tag \"", tagPtr->Name(), "\" invalid when language other than \"none\"", (char *)NULL);
                    return TCL_ERROR;
                }
                XColor *c = tagPtr->BG();
                if (c) {
                    sci_set_style_bg(obj, sid, c);
                }
                c = tagPtr->FG();
                if (c) {
                    sci_set_style_fg(obj, sid, c);
                }
                sci_cmd(obj, SCI_STYLESETBOLD, sid, tagPtr->Bold());
                sci_cmd(obj, SCI_STYLESETITALIC, sid, tagPtr->Italic());
                sci_cmd(obj, SCI_STYLESETUNDERLINE, sid, tagPtr->Underline());
            }
        }
    }
    return TCL_OK;
}

//==========================================================================
// Update the background/foreground colors for the margin tag
//
void TagMgr::UpdateMarginColor(bool bg, bool fg) {

................................................................................

   ScintillaObject *sciobj = SCIOBJ(sciwidgetPtr);
   int sid = marginTag->StyleID();
   XColor *c;

   if (bg) {
      // keep the tag in sync w/ toplevel config option
      c = marginTag->options.bgColor = sciwidgetPtr->marginBg;

      sci_set_style_bg(sciobj, sid, c);
      if (sid != STYLE_LINENUMBER)
         sci_set_style_bg(sciobj, STYLE_LINENUMBER, c);
   }
   if (fg) {
      c = marginTag->options.fgColor = sciwidgetPtr->marginFg;

      sci_set_style_fg(sciobj, sid, c);
      if (sid != STYLE_LINENUMBER)
         sci_set_style_fg(sciobj, STYLE_LINENUMBER, c);
   }
   // now we need to iterate through all of the margin tags and check for
   // ones that have no explicit bg/fg values; for these we'll update them
................................................................................
    Tcl_ListObjAppendElement(interp, tmp, Tcl_NewStringObj(sciwidgetPtr->tagMgr->GetMarginTag()->name, -1));
    return tmp;
}

//---------------------------------------------------------
// Private functions
//---------------------------------------------------------

void TagMgr::deleteTag(const char* name) {
Tcl_HashEntry *hPtr;
TagData *tagPtr;

    if (IS_SEL(name)) return;    // 'sel' tag cannot be deleted by user
    if (IS_MARGIN(name)) return; // 'margin' tag cannot be deleted by user

    hPtr = Tcl_FindHashEntry(&tagTable, name);
    if (hPtr == NULL) return;

    tagPtr = (TagData *)Tcl_GetHashValue(hPtr);

    // now delete the tag itself
    _deleteTag(tagPtr);

    // and finally remove it from the hash table
    Tcl_DeleteHashEntry(hPtr);
}

//==========================================================================
// This handles configuration the indicator style info for a tag
int TagMgr::_configIndicator(TagData *tagPtr) {

    // sanity check
    if (!IsIndicator(tagPtr)) return TCL_ERROR;

    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    // assign the indicator style
    switch (tagPtr->IndicType()) {
        case indicNONE:
            break; // make compiler happy
        case indicPlain:
            _setIndicStyle(tagPtr, INDIC_PLAIN);
            break;
        case indicSquiggle:
            _setIndicStyle(tagPtr, INDIC_SQUIGGLE);
            break;
        case indicTt:
            _setIndicStyle(tagPtr, INDIC_TT);
            break;
        case indicDiag:
            _setIndicStyle(tagPtr, INDIC_DIAGONAL);
            break;
        case indicStrike:
            _setIndicStyle(tagPtr, INDIC_STRIKE);
            break;
        case indicHidden:
            _setIndicStyle(tagPtr, INDIC_HIDDEN);
            break;
        case indicBox:
            _setIndicStyle(tagPtr, INDIC_BOX);
            break;
        case indicRoundBox:

            _setIndicStyle(tagPtr, INDIC_ROUNDBOX);



#if USE_SOLID_INDICATORS
            // solid indicators, display under text so text isn't obscured
            sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
#else
            if (tagPtr->Alpha() != -1) {
                sci_cmd(obj, SCI_INDICSETALPHA, tagPtr->IndicID(), tagPtr->Alpha());
                if (tagPtr->Alpha() >= SC_ALPHA_OPAQUE) {
                    // need this, otherwise text will be obscured by opaqueness!
                    sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
                }



            }
            if (tagPtr->AlphaB() != -1)
                sci_cmd(obj, SCI_INDICSETOUTLINEALPHA, tagPtr->IndicID(), tagPtr->AlphaB());
#endif
            break;
        case indicSquareBox:
            _setIndicStyle(tagPtr, INDIC_STRAIGHTBOX);
#if USE_SOLID_INDICATORS
            // solid indicators, display under text so text isn't obscured
            sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
#else
            if (tagPtr->Alpha() != -1) {
                sci_cmd(obj, SCI_INDICSETALPHA, tagPtr->IndicID(), tagPtr->Alpha());
                if (tagPtr->Alpha() >= SC_ALPHA_OPAQUE) {
                    // need this, otherwise text will be obscured by opaqueness!
                    sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
                }

            }
            if (tagPtr->AlphaB() != -1)
                sci_cmd(obj, SCI_INDICSETOUTLINEALPHA, tagPtr->IndicID(), tagPtr->AlphaB());
#endif
            break;
        case indicDash:
            _setIndicStyle(tagPtr, INDIC_DASH);
            break;
        case indicDots:
            _setIndicStyle(tagPtr, INDIC_DOTS);
            break;
        case indicSquiggleLow:





            _setIndicStyle(tagPtr, INDIC_SQUIGGLELOW);
            break;
        case indicDotBox:
            _setIndicStyle(tagPtr, INDIC_DOTBOX);
#if USE_SOLID_INDICATORS
            // solid indicators, display under text so text isn't obscured
            sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
#else
            if (tagPtr->Alpha() != -1) {
                sci_cmd(obj, SCI_INDICSETALPHA, tagPtr->IndicID(), tagPtr->Alpha());
                if (tagPtr->Alpha() >= SC_ALPHA_OPAQUE) {
                    // need this, otherwise text will be obscured by opaqueness!
                    sci_cmd(obj, SCI_INDICSETUNDER, tagPtr->IndicID(), 1);
                }



            }
            if (tagPtr->AlphaB() != -1)
                sci_cmd(obj, SCI_INDICSETOUTLINEALPHA, tagPtr->IndicID(), tagPtr->AlphaB());
#endif
            break;
        case indicSquigglePixMap:
            _setIndicStyle(tagPtr, INDIC_SQUIGGLEPIXMAP);
            break;
    }
    // now assign colors
    if (tagPtr->FG()) {
        sci_cmd(obj, SCI_INDICSETFORE, tagPtr->IndicID(), _XRGB_(tagPtr->FG()));
    }
    return TCL_OK;
}

void TagMgr::_setIndicStyle(TagData *tagPtr, int id) {

    sci_cmd(SCIOBJ(sciwidgetPtr), SCI_INDICSETSTYLE, tagPtr->IndicID(), id);
}

static int spin = 1;
extern "C" void stopme() {
    while (spin);
}

//==========================================================================
// Creates a new tag or returns one matching the specfied name
//
TagData *TagMgr::_createTag(int ttMask, const char *tagname, int *newTag) {

   TagData *tagPtr;
................................................................................
         if (newTag != NULL) *newTag = 0;
         return marginTag; // return the one we already have
      } else if (newTag) *newTag = 1;

      name = TAG_MARGIN;

   } else {
      if (((ttMask & TT_TEXT|TT_INDIC) == TT_TEXT) && (sciwidgetPtr->langType != SCLEX_NULL)) {
          // you can't define a text tag when there's a lexer styling the text because the style tag will conflict with the lexer
          // indicators are ok
          Tcl_AppendResult(interp,
                "The \"", tagname, "\" tag can only be defined in the text area when language is \"none\"", (char *)NULL);
            return NULL;
      }
      // if not, create(if needed) in the hash table
      hPtr = Tcl_CreateHashEntry(&tagTable, tagname, &isNew);
      if (newTag) *newTag = isNew;
      // Make sure we have either an annotation, text or margin tag
      assert(((ttMask&(TT_MARG|TT_TEXT|TT_ANNO)) == TT_ANNO) || ((ttMask&(TT_MARG|TT_TEXT|TT_ANNO)) == TT_MARG) || ((ttMask&(TT_MARG|TT_TEXT|TT_ANNO)) == TT_TEXT));
      if (!isNew) {
         tagPtr = (TagData *)Tcl_GetHashValue(hPtr);
         // make sure tag type is the same
        if (((TT_MARG|TT_TEXT|TT_ANNO)&tagPtr->tagType) != ((TT_MARG|TT_TEXT|TT_ANNO)&ttMask)) {
            Tcl_AppendResult(interp,
                "The \"", tagname, "\" tag can only be defined for the annotation, margin, or text area, not more than one", (char *)NULL);
            return NULL;
        }
         return (TagData *)Tcl_GetHashValue(hPtr);
      }
      name = Tcl_GetHashKey(&tagTable, hPtr);
   }
   // No existing entry, so create a new one
   tagPtr = new TagData(interp, tagname, ttMask, numTags++);












   if (Tk_InitOptions(interp, (char *)&tagPtr->options, tagPtr->optionTable, tkwin) != TCL_OK) {
      _deleteTag(tagPtr);
      if (isNew)
        Tcl_DeleteHashEntry(hPtr);
      fprintf(stderr, "ERROR in Tk_InitOptions: %s\n", Tcl_GetStringResult(interp));
      return NULL;
   }


   if (IS_SEL(tagname)) {
      selTag = tagPtr;
      // set style info
      ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
      if (selTag->BG()) sci_cmd(obj, SCI_SETSELBACK, 1, _XRGB_(selTag->BG()));
      if (selTag->FG()) sci_cmd(obj, SCI_SETSELFORE, 1, _XRGB_(selTag->FG()));
................................................................................

   } else if (IS_MARGIN(tagname)) {
      marginTag = tagPtr;
      // assign it a Scintilla style id
      int id;
      if (_nextStyleID(&id, ttMask) != TCL_OK) {
          _deleteTag(tagPtr);
          if (isNew)
             Tcl_DeleteHashEntry(hPtr);
          Tcl_AppendResult(interp, "\nUnable to create tag ", tagname, (char*) NULL);
          return NULL;
      }
      tagPtr->style_id = id;
   } else {
      // assign it a Scintilla id
      int id;
      if (ttMask & TT_INDIC) {
          if (_nextIndicID(&id) != TCL_OK) {
              _deleteTag(tagPtr);
              if (isNew)
                 Tcl_DeleteHashEntry(hPtr);
              Tcl_AppendResult(interp, "\nUnable to create tag ", tagname, (char*) NULL);
              return NULL;
          }
          tagPtr->indic_id = id;
      } else {
          if (_nextStyleID(&id, ttMask) != TCL_OK) {
              _deleteTag(tagPtr);
              if (isNew)
                 Tcl_DeleteHashEntry(hPtr);
              Tcl_AppendResult(interp, "\nUnable to create tag ", tagname, (char*) NULL);
              return NULL;
          }
          tagPtr->style_id = id;
      }
      // store in hash table
      Tcl_SetHashValue(hPtr, tagPtr);
   }
   return tagPtr;
}

//==========================================================================
// Delete a tag
//








void TagMgr::_deleteTag(TagData *tagPtr, bool force) {

   if (tagPtr == NULL) return;

   // do cleanup of the options data
   Tk_FreeConfigOptions((char *)&tagPtr->options, tagPtr->optionTable, tkwin);

   // destroy the tag (possibly)
   bool is_special = ((tagPtr == selTag) || (tagPtr == marginTag));












   if (!is_special || force) {
       //
       // Make sure this tag isn't referenced from the 'current' tag array.
       //
       for (int i = 0; i < numCurTags; i++) {
           if (curTagArrayPtr[i] == tagPtr) {
               for (; i < numCurTags-1; i++) {
................................................................................
                   curTagArrayPtr[i] = curTagArrayPtr[i+1];
               }
               curTagArrayPtr[numCurTags-1] = NULL;
               numCurTags--;
               break;
           }
       }
       // remove tag from TagLocations, remove Location if no other tags associated with it
       tagPtr->DeleteTag(this);
       if (IsIndicator(tagPtr)) {
           if ((tagPtr->indic_id >= INDIC_CONTAINER) && (tagPtr->indic_id <= INDIC_MAX)) {
              // indicator is now "free"
              freeIndicators |= (1 << tagPtr->IndicID());
           }
       } else {
           if (tagPtr->Type() & TT_TEXT) {
              if (tagPtr->StyleID() > 0)
                 freeTextStyles.set(tagPtr->StyleID(), 0);
           }
           if (tagPtr->Type() & TT_MARG) {
              if (tagPtr->StyleID() > 0)
                 freeMarginStyles.set(tagPtr->StyleID() - GetMarginStyleOffset(), 0);
           }
           if (tagPtr->Type() & TT_ANNO) {
              if (tagPtr->StyleID() > 0)
                 freeAnnotationStyles.set(tagPtr->StyleID() - GetAnnotationStyleOffset(), 0);
           }

       }
       delete tagPtr;
       if (tagPtr == selTag) {
           selTag = NULL;
       } else if (tagPtr == marginTag) {
           marginTag = NULL;
       }
       numTags--;
   }
................................................................................
// Return the next available Scintilla indicator id. This routine is
// responsible for managing a free-list so that IDs can be reused.
//
int TagMgr::_nextIndicID(int *idPtr) {
    int i;
    if (!idPtr) return TCL_ERROR;

    // find first bit in freeIndicators, no need to check first 8
    for (i = INDIC_CONTAINER; i <= INDIC_MAX; ++i) {
        int bitmask = 1 << i;
        if (freeIndicators & bitmask) {
            freeIndicators &= ~bitmask;
            *idPtr = i;
            return TCL_OK;
        }
    }
    // if all indicators allocated, report error
    if (i > INDIC_MAX) {
        char buf[33];
................................................................................
}

//==========================================================================
// Return the next available Scintilla style id. This routine is responsible
// for managing a free-list so that IDs can be reused.
//
int TagMgr::_nextStyleID(int *idPtr, int ttMask) {
int max = (1 << sciwidgetPtr->styleBits) - 1;
char *type = "text";

    if (!idPtr) return TCL_ERROR;

    if (ttMask & TT_TEXT) {
        /* text style, allocate from max down to avoid lexer collisions */
        for (int id = max; id > 0; id--) {
            if (!freeTextStyles.test(id)) {
                /* found free style, mark it as allocated */
                freeTextStyles.set(id, 1);
                *idPtr = id;
                return TCL_OK;
            }
        }
    } else if (ttMask & TT_ANNO) {
        /* annotation style, this can be allocated starting at 0 because
         * the style ids won't collide with styles allocated by lexers
         */
        max = 255;
        type = "annotation";
        for (int id = 0; id < 255; id++) {
            if (!freeAnnotationStyles.test(id)) {
                /* found free style, mark it as allocated */
                freeAnnotationStyles.set(id, 1);
                *idPtr = id + GetAnnotationStyleOffset();
                return TCL_OK;
            }
        }
    } else if (ttMask & TT_MARG) {
        /* margin style, this can be allocated starting at 0 because
         * the style ids won't collide with styles allocated by lexers
         */
        max = 255;
        type = "margin";
        for (int id = 0; id < 255; id++) {
            if (!freeMarginStyles.test(id)) {
                /* found free style, mark it as allocated */
                freeMarginStyles.set(id, 1);
                *idPtr = id + GetMarginStyleOffset();
                return TCL_OK;
            }
        }
    }

    /* unable to allocate style, return error */
    {
    char buf[33];
        sprintf(buf,"%d", max);
        Tcl_AppendResult(interp, "cannot allocate new ", type, " ID: max number of styles(", buf, ") exceeded", (char *)NULL);
    }
    return TCL_ERROR;
}

//==========================================================================
void TagMgr::_dump(TagData *tagPtr) {

   if (tagPtr == NULL) {
................................................................................


// define IDs for options we either need to error check or respond to
#define MKOPT_BG   1
#define MKOPT_FG   1 << 1
#define MKOPT_TYPE 1 << 2
#define MKOPT_IMG  1 << 3


// define configuration options
static Tk_OptionSpec markerOptionSpecs[] = {
   {TK_OPTION_COLOR,  "-background", NULL, NULL,
         "white", -1, Tk_Offset(MarkerOptions, bgColor), TK_OPTION_NULL_OK, 0, MKOPT_BG
   },
   {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0},
................................................................................

   {TK_OPTION_STRING,  "-image", NULL, NULL,
         "", -1, Tk_Offset(MarkerOptions, imgName), 0, 0, MKOPT_IMG
   },
   {TK_OPTION_STRING_TABLE, "-type", NULL, NULL,
	     (char*)MarkerTypeNames[MK_CIRCLE], -1, Tk_Offset(MarkerOptions, type), 0, (ClientData)MarkerTypeNames, MKOPT_TYPE
   },



   {TK_OPTION_END}
};
//### CTOR ###
MarkerData::MarkerData(MarkerMgr *mgr) :
   name(0),
   id(-1),
   handle(-1),
................................................................................

   // must initialize all pointer/token values as per the Tk doc page:
   //    "...is responsible for storing NULL or None in all pointer 
   //    and token fields before invoking Tk_InitOptions."
   mopts->bgColor = NULL;
   mopts->fgColor = NULL;
   mopts->imgName = NULL;
   mopts->img = NULL;
   mopts->type    = None;
   mopts->pixels = NULL;

   optionTable = Tk_CreateOptionTable(mgr->interp, markerOptionSpecs);

   if (Tk_InitOptions(mgr->interp, (char *)mopts, optionTable, mgr->tkwin) != TCL_OK) {
      fprintf(stderr, "ERROR in Tk_InitOptions: %s\n", Tcl_GetStringResult(mgr->interp));
   } else {
      // map the user-specified type to the Scintilla ID
................................................................................
MarkerData::~MarkerData() {
    if (cloned_from) {
        // update parent marker to let it know it just lost a clone
        cloned_from->cloned_n--;
    }
    // clean up objects used for marker options
    Tk_FreeConfigOptions((char *)mopts, optionTable, mgr->tkwin);
    Tk_DeleteOptionTable(optionTable);
    if (mopts->img) Tk_FreeImage(mopts->img);
    Tcl_Free((char *)mopts);
}

//==========================================================================
// This will assign the Scintilla marker ID corresponding to the
// user-visible type name
//
................................................................................
            n, objv_arr, mgr->tkwin, NULL, NULL) != TCL_OK) {
        // uh oh...
    }
    Tcl_Free((char *)objv_arr);

    ScintillaObject *sci = SCIOBJ(mgr->sciwidgetPtr);

    if (src->typeID == SC_MARK_RGBAIMAGE) {
        typeID = SC_MARK_RGBAIMAGE;
        
        sci_cmd(sci, SCI_MARKERDEFINERGBAIMAGE, id, (sptr_t)mopts->pixels);
    } else {
        sci_cmd(sci, SCI_MARKERDEFINE, id, typeID);
        if (mopts->bgColor) {
            sci_cmd(sci, SCI_MARKERSETBACK, id, _XRGB_(mopts->bgColor));
        }
        if (mopts->fgColor) {
            sci_cmd(sci, SCI_MARKERSETFORE, id, _XRGB_(mopts->fgColor));
................................................................................
            // get rid of the marker we had to create
            _deleteMarker(mPtr);
         }
         return TCL_ERROR;
      }
      // do some error checking...







      if ((mask & MKOPT_TYPE) && ((mask & MKOPT_IMG))) {
         Tk_RestoreSavedOptions(&savedOptions);
         if (isNew) _deleteMarker(mPtr);
         Tcl_AppendResult(interp, "cannot use -type option with -image", (char *)NULL);
         return TCL_ERROR;
      }
      ScintillaObject *sci = SCIOBJ(sciwidgetPtr);
      bool do_define = true;

      if (mask & MKOPT_IMG) {
         // verify the image is legal
         if (!isNew) {
             // if marker already existed and had an image associated with it, free old image
             if (mPtr->mopts->img) {
                 Tk_FreeImage(mPtr->mopts->img);
             }
         }
         if (_validateImage(mPtr) != TCL_OK) {
            Tk_RestoreSavedOptions(&savedOptions);
            if (isNew) _deleteMarker(mPtr);
            return TCL_ERROR;
         }




         do_define = false;
      }
      if (mask & MKOPT_TYPE) {
         mPtr->UpdateType();
      }

      // now let Scintilla know about it
................................................................................
      return NULL;
   }
   // look up the name in the hash table
   hPtr = Tcl_CreateHashEntry(&markerTable, markerName, &isNewMarker);
   if (isNew) *isNew = isNewMarker;
   if (!isNewMarker) {
      // Found it!
      mPtr = (MarkerData *)Tcl_GetHashValue(hPtr);
      return mPtr;
   }
   // No match, so create a new marker -- VERIFY WE CAN!!
   int id = _getNextId();
   if (id == -1) {
      Tcl_DeleteHashEntry(hPtr);
      Tcl_AppendResult(interp,
         "new marker could not be created: too many markers already exist", (char *)NULL);
................................................................................

//==========================================================================
// Validate image information being requested for use as a marker
//

// need a callback defined if we want to use Tk_GetImage
static void
_imgCallbackProc(ClientData cd, int x, int y, int w, int h, int imgW, int imgH) 
{
    MarkerData *mPtr = (MarkerData*)cd;

    fprintf(stderr,"_imgCallbackProc(%p, x=%d, y=%d, w=%d, h=%d, imgW=%d, imgH=%d)\n"
            "imageName=%s\n", 
            (void*)cd, x, y, w, h, imgW, imgH, mPtr->mopts->imgName);
    if (mPtr->mopts->img) Tk_FreeImage(mPtr->mopts->img);
    mPtr->mopts->img = NULL;





    mPtr->mopts->pixels = NULL;



    mPtr->mgr->_validateImage(mPtr);
}




int MarkerMgr::_validateImage(MarkerData *mPtr) {
   const char *imageName = mPtr->mopts->imgName;
   Tk_Image tk_image = Tk_GetImage(interp, tkwin, imageName, _imgCallbackProc, (ClientData)mPtr);
   Tk_PhotoHandle photo = Tk_FindPhoto(interp, imageName);
   Tk_PhotoImageBlock photo_block;


   if (tk_image == NULL || photo == NULL) {
      return TCL_ERROR;
   }



   Tk_PhotoGetImage(photo, &photo_block);


   //fprintf(stderr,"pixelPtr=%p pixelSize=%d w=%d h=%d pitch=%d\n", 
   //        photo_block.pixelPtr, photo_block.pixelSize, 
   //        photo_block.width, photo_block.height, photo_block.pitch);
   if (photo_block.pixelSize != 4) {
       Tcl_SetResult(interp, "Unsupported photo image: pixelSize!=4\n", TCL_STATIC);
       Tk_FreeImage(tk_image);
       return TCL_ERROR;
   }

   mPtr->mopts->img = tk_image;
   mPtr->mopts->pixels = photo_block.pixelPtr;
   ScintillaObject *sci = SCIOBJ(sciwidgetPtr);

   sci_cmd(sci, SCI_RGBAIMAGESETWIDTH, photo_block.width);
   sci_cmd(sci, SCI_RGBAIMAGESETHEIGHT, photo_block.height);


   mPtr->typeID = SC_MARK_RGBAIMAGE;
   //fprintf(stderr, "sci_cmd(sci, SCI_MARKERDEFINERGBAIMAGE, %d, %p);\n", 
   //        mPtr->id, mPtr->mopts->pixels);
   sci_cmd(sci, SCI_MARKERDEFINERGBAIMAGE, mPtr->id, (sptr_t)mPtr->mopts->pixels);




   return TCL_OK;
}


//==========================================================================
void MarkerMgr::_dump(MarkerData *mPtr) {

................................................................................

   fprintf(stderr, "NAME   : %s\n", mPtr->name);
   fprintf(stderr, "ID     : %d\n", mPtr->id);
   fprintf(stderr, "HNDL   : %d\n", mPtr->handle);
   fprintf(stderr, "TYPE   : %s\n", MarkerTypeNames[mPtr->mopts->type]);
   if (mopts->imgName)
   fprintf(stderr, "IMAGE  : %s\n", mopts->imgName);









   fprintf(stderr, "S-TYPE : %d\n", mPtr->typeID);
   if (mopts->fgColor == NULL)
   fprintf(stderr, "FG     : <null>\n");
   else
   fprintf(stderr, "FG     : %d,%d,%d\n", mopts->fgColor->red,mopts->fgColor->green,mopts->fgColor->blue);
   if (mopts->bgColor == NULL)
   fprintf(stderr, "BG     : <null>\n");
................................................................................
        case CMD_PREV: {
            if (objc != 4) {
                Tcl_WrongNumArgs(interp, 3, objv, "index");
                return TCL_ERROR;
            }
            bool fwd = ((enum optionIds)index == CMD_NEXT);
            char *index_str = Tcl_GetString(objv[3]);
            sptr_t start_pos;
            if ((markPtr = FindMark(index_str)) != NULL) {
                if (fwd) {
                    start_pos = markPtr->pos + 1; // start AFTER the mark
                } else {
                    start_pos = markPtr->pos - 1; // start BEFORE the mark
                }
            } else {
................................................................................
// Implements the MARK SET sub-command
//
int MarkMgr::CmdSet(int objc, Tcl_Obj *CONST objv[]) {

    ScintillaObject *obj = SCIOBJ(sciwidgetPtr);
    MarkData *markPtr;
    char *name, *index_str;
    sptr_t pos;
    
    if (objc != 5) {
        Tcl_WrongNumArgs(interp, 3, objv, "markName index");
        return TCL_ERROR;
    }
    name      = Tcl_GetString(objv[3]);
    index_str = Tcl_GetString(objv[4]);
................................................................................
        return;
    }
    fprintf(stderr, "POINTER: %p\n", (void *)mPtr);
    fprintf(stderr, "NAME   : %s\n", mPtr->name);
    fprintf(stderr, "POS    : %d\n", mPtr->pos);
    fprintf(stderr, "GRAVITY: %s\n", mPtr->gravityLeft ? "Left" : "Right");
}

TagLocation::TagLocation(TagData *td, sptr_t start, sptr_t end)
{
    if (td) {
        tags.push_back(td);
    }
    location.startpos = start;
    location.endpos = end;
}

TagLocation::TagLocation(TagLocation *other, sptr_t end)
{
unsigned long i;

    tags.assign(other->tags.begin(), other->tags.end());
    location.startpos = other->startpos();
    location.endpos = end;
    for (i = 0; i < tags.size(); ++i) {
        tags[i]->UnregisterLocation(other); // location is about to change value, unregister it with the tag
        tags[i]->RegisterLocation(this);    // register new location with tag
    }
}

TagLocation::~TagLocation()
{
}

void TagLocation::setStartPos(sptr_t start)
{
unsigned long i;

    // remove registration of this location with tag & re-add it because it's location has been modified
    for (i = 0; i < tags.size(); ++i) {
        tags[i]->UnregisterLocation(this);    // unregister current location value
    }
    location.startpos = start;
    for (i = 0; i < tags.size(); ++i) {
        tags[i]->RegisterLocation(this);    // register new location value
    }
}

void TagLocation::setEndPos(sptr_t end)
{
unsigned long i;

    // remove registration of this location with tag & re-add it because it's location has been modified
    for (i = 0; i < tags.size(); ++i) {
        tags[i]->UnregisterLocation(this);    // unregister current location value
    }
    location.endpos = end;
    for (i = 0; i < tags.size(); ++i) {
        tags[i]->RegisterLocation(this);    // register new location value
    }
}

// Associate tag with location, return nonzero if new tag is highest priority and display update needed
int TagLocation::RegisterTag(TagData *td)
{
unsigned long i;
int highestPriority = -1;

    // the list of tags should be small, search tag vector and add data if not already in it
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"RegisterTag %p %ld-%ld tag %s\n", this, startpos(), endpos(), td->Name());
#endif
    for (i = 0; i < tags.size(); ++i) {
        if (tags[i]->priority > highestPriority)
            highestPriority = tags[i]->priority;
        if (tags[i] == td) {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"   RegisterTag %p %ld-%ld tag %s already registered\n", this, startpos(), endpos(), td->Name());
#endif
            td->RegisterLocation(this);
#ifdef ENABLE_TAG_PRIORITIES
            return 0;
#else
            return 1;
#endif
        }
    }
    tags.push_back(td);
    // notify tag of new location
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"   RegisterTag %p %ld-%ld tag %s registering location with tag\n", this, startpos(), endpos(), td->Name());
#endif
    td->RegisterLocation(this);
#ifdef ENABLE_TAG_PRIORITIES
    if (td->priority > highestPriority)
        return 1;
    else
        return 0;
#else
    return 1;
#endif
}

TagData *TagLocation::UnregisterTag(TagData *td)
{
int highestPriority = -1;
std::vector<TagData*>::iterator highest_it = tags.end();
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"UnregisterTag %s, priority %d\n", td->Name(), td->priority);
#endif
    for (std::vector<TagData*>::iterator it = tags.begin(); it != tags.end();) {
        if (*it == td) {
            // remove this tag from list
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"UnregisterTag, erasing %s from tags array\n", td->Name());
#endif
            it = tags.erase(it);
        } else {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr,"UT tag %s priority %d highestPriority %d\n", (*it)->Name(), (*it)->priority, highestPriority);
#endif
            if ((*it)->priority > highestPriority) {
                highestPriority = (*it)->priority;
                highest_it = it;
            }
            ++it;
        }
    }
    if (highestPriority != -1) {
        // we removed the highest priority tag, return the next highest
#ifdef DEBUG_TAGLOCATIONS
        fprintf(stderr,"UnregisterTag, returning %p %s\n", (void*) (*highest_it), (*highest_it)->Name());
#endif
        return *highest_it;
    }
    // either we removed the last tag or we removed a tag that doesn't affect styling
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"UnregisterTag, returning NULL\n");
#endif
    return NULL;
}

void TagLocation::dumpTags()
{
    fprintf(stderr,"TagLocation %ld-%ld tags:\n", startpos(), endpos());
    for (std::vector<TagData*>::iterator it = tags.begin(); it != tags.end();) {
        fprintf(stderr,"   %s\n", (*it)->Name());
        ++it;
    }
}

void TagMgr::RemoveStyle(TagData *td, sptr_t startpos, sptr_t endpos)
{
ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    // Called when tag removed from location and there's no lower priority tag to take it's place
    if (IsIndicator(td)) {
        //-----------------
        //--- INDICATOR ---
        //-----------------
        sci_cmd(obj, SCI_SETINDICATORCURRENT, td->IndicID());
        sci_cmd(obj, SCI_INDICATORCLEARRANGE, startpos, (endpos-startpos+1));
    } else {
        /* set style for selected positions */
        sci_cmd(obj, SCI_STARTSTYLING, startpos, STYLEMASK(sciwidgetPtr));
        sci_cmd(obj, SCI_SETSTYLING, (endpos-startpos+1), STYLE_DEFAULT);
    }
}

void TagMgr::ApplyStyle(TagData *td, sptr_t startpos, sptr_t endpos)
{
ScintillaObject *obj = SCIOBJ(sciwidgetPtr);

    // new tag was higher priority than previously applied tag, add styling for new tag to document
    if (IsIndicator(td)) {
        //-----------------
        //--- INDICATOR ---
        //-----------------
        sci_cmd(obj, SCI_SETINDICATORCURRENT, td->IndicID());
        sci_cmd(obj, SCI_INDICATORFILLRANGE, startpos, (endpos-startpos+1));
    } else {
        /* set style for selected positions */
        sci_cmd(obj, SCI_STARTSTYLING, startpos, STYLEMASK(sciwidgetPtr));
        sci_cmd(obj, SCI_SETSTYLING, (endpos-startpos+1), td->StyleID());
    }
}

void TagMgr::ApplyTag(TagData *td, sptr_t startpos, sptr_t endpos)
{
    // search location map to see if Location already registered
    std::vector<TagLocation*>::iterator it;
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"AppyTag: Tag %s, type 0x%x Searching for location %ld-%ld\n", td->name, td->Type(), startpos, endpos);
#endif
    TagLocation *tl_p = searchLocations("TagMgr Locations", tagLocations, SEARCH_ADD, startpos, endpos, &it);
#ifdef DEBUG_TAGLOCATIONS
    fprintf(stderr,"AppyTag: Searching returned %p\n", tl_p);
#endif
    while (tl_p) {
        if (tl_p->RegisterTag(td)) {
#ifdef DEBUG_TAGLOCATIONS
            fprintf(stderr, "   applying style for %s from %ld to %ld\n", td->name, tl_p->startpos(), tl_p->endpos());
#endif
            ApplyStyle(td, tl_p->startpos(), tl_p->endpos());
        }
#ifdef DEBUG_TAGLOCATIONS
        else {
            fprintf(stderr, "   not applying style for lower-priority tag %s from %ld to %ld\n", td->name, tl_p->startpos(), tl_p->endpos());
        }
#endif
        tl_p = nextLocation(tagLocations, startpos, endpos, &it);
    }
}

void TagMgr::RemoveLocation(TagLocation *tl_p)
{
    std::vector<TagLocation*>::iterator it;
    TagLocation *tl_p2 = searchLocations("TagMgr Locations", tagLocations, SEARCH_IDX, tl_p->startpos(), tl_p->endpos(), &it);
    assert(tl_p == tl_p2);  // we better find it!
    // remove location from vector
    tagLocations.erase(it);
}

void TagMgr::RemoveTag(TagData *td, sptr_t startpos, sptr_t endpos)
{
    // Notify the tag to remove itself and notify TagMgr if last tag removed from location
    td->RemoveTag(this, startpos, endpos);
}

}//--- end of namespace TkSci

Changes to tk/scintilla-cmd.h.

12
13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
..
51
52
53
54
55
56
57

58
59
60
61
62
63
64
...
107
108
109
110
111
112
113

114
115
116
117
118
119
120
...
126
127
128
129
130
131
132

133
134
135
136
137
138
139
...
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
...
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
...
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
...
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

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

................................................................................
#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;
................................................................................
   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;
................................................................................
   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;
................................................................................

////////////////////////////////////////////////////////////////////
// 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[]);
................................................................................
   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);

................................................................................
      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:
................................................................................
   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;







|

>







 







>







 







>







 







>







 







>
|






|
|
|
|
|
|
|
|
|
|
|
|
>
|


>
>
>
>
>

<
>
>
>
>

<
<
<



>


<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>

|
>
|
|
|
|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>





>







 







|



|



>
>


|

<







 







>
>
>
>
>
>







|
|
|
>

>
>







>
>
>
>
>
>
>
>
>











>

<
>







 







|



>
>








<







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
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
...
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
...
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
...
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

#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 "ScintillaTk.h"
#include <bitset>
#include <vector>

#include "Platform.h" // for access to PRectangle
using namespace Scintilla;

// create a namespace for ourselves
namespace TkSci {

................................................................................
#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
#define GOT_SELECTION  0x200

// 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;
................................................................................
   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;
   bool        exportSelection; // controls if selection is X global selection

   /* callback commands */
   char       *linesAddedCmd;
   char       *marginWidthCmd;
   char       *moveUpdateCmd;
   char       *yScrollCmd;
   char       *xScrollCmd;
................................................................................
   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
   Tcl_Obj   *keywords[KEYWORDSET_MAX];

   /* data used for expose repaints */
   int expose_x;
   int expose_y;
   int expose_w;
   int expose_h;
} SciWidget;
................................................................................

////////////////////////////////////////////////////////////////////
// Tag management

typedef enum {
    TT_TEXT  = 1,
    TT_MARG  = 2,
    TT_ANNO  = 4,
    TT_INDIC = 8
} 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
    indicSquigglePixMap // dotted rectangle around text - uses transparent interior
} IndicTypeID;

// Structure defining a tag location
typedef struct {
    sptr_t startpos;   // position within document where tag begins
    sptr_t endpos;     // position within document where tag ends
} Location;


class TagLocation;
class TagMgr;

// options for TagData, in struct so Tk_Offset can be used to set options
typedef struct {



    XColor        *fgColor;    // foreground color of text
    XColor        *bgColor;    // background color of text
    int            bold;       // boolean to indicate if text is bold
    int            eolfilled;  // boolean to indicate if background color of last character in line extends to right margin
    int            italic   ;  // boolean to indicate if text is italicized
    int            underline;  // boolean to indicate if text is underlined

    IndicTypeID    indicType;  // indicator type (if any)
    int            alpha;      // alpha value to be used for transparent indicators
    int            alphab;     // alpha value to be used for the boarder of transparent indicators
} TagDataOptions;

// data structure to hold configuration options used by each tag
class TagData {
    typedef enum {
        FLAG_NONE = 0,
        FLAG_DELETING = 1
    } TagDataFlags;
public:
    char    *name;             // symbolic name of the tag
    int            tagType;    // mask intended to identify the owning area (text or margin)
    int            style_id;   // Scintilla style id
    int            indic_id;   // Scintilla id used for indicators
    TagDataOptions options;
    Tk_OptionTable optionTable;// table to hold config options

    std::vector<TagLocation*> tagLocations; // sorted array of locations where tag applied, we don't "own" TagLocation* pointers, don't delete them!
    int            priority;   // priority relative to other tags when more than one tag applied to same text
    int            flags;      // flags

    TagData(Tcl_Interp *interp, const char* n, int ttMask, int _priority);
    ~TagData();

    const char *Name()      { return name; }
    int Bold()              { return options.bold; }
    int EolFilled()         { return options.eolfilled; }
    int Italic()            { return options.italic; }
    int Underline()         { return options.underline; }
    XColor *BG()            { return options.bgColor; }
    XColor *FG()            { return options.fgColor; }
    int StyleID()           { return style_id; }
    int IndicID()           { return indic_id; }
    int Type()              { return tagType; }
    IndicTypeID IndicType() { return options.indicType; }
    int Alpha()             { return options.alpha; }
    int AlphaB()            { return options.alphab; }
    void RegisterLocation(TagLocation* t_p);
    void UnregisterLocation(TagLocation* t_p);
    void NextRange(Tcl_Interp *interp, ScintillaObject *obj, sptr_t pos1, sptr_t pos2, Tcl_Obj* indices);
    void PrevRange(Tcl_Interp *interp, ScintillaObject *obj, sptr_t pos1, sptr_t pos2, Tcl_Obj* indices);
    void Ranges(Tcl_Interp *interp, ScintillaObject *obj, Tcl_Obj* indices);
    void RemoveTag(TagMgr *mgr, sptr_t startpos, sptr_t endpos);
    void DumpLocations();
    void DeleteTag(TagMgr *mgr);
};

class TagLocation {
    Location location;
    std::vector<TagData*> tags; // list of tags at location, we don't "own" TagData* pointers, don't delete them!
public:
    TagLocation(TagData *tag, sptr_t start, sptr_t end);
    TagLocation(TagLocation *, sptr_t end);
    ~TagLocation();
    // associate tag with location, return 1 if tag's priority is higher than previous high and display needs update
    int RegisterTag(TagData *td);
    // disassociate tag with location, return new highest priority tag if display needs update (td was highest priority)
    TagData *UnregisterTag(TagData *td);
    void setStartPos(sptr_t start);
    void setEndPos(sptr_t end);
    sptr_t startpos()   { return location.startpos; }
    sptr_t endpos()   { return location.endpos; }
    bool empty()   { return tags.empty(); }
    void dumpTags();
};

//-------------------------------------
// CLASS TagMgr
//-------------------------------------
class TagMgr {
    friend class TagData;
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[]);
................................................................................
   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 *);
   int       Reset(Tcl_Interp *interp, int langType);
   void      UpdateMarginColor(bool bg, bool fg);
   TagData  *ValidateForMargin(const char *tagname);
   bool IsIndicator(TagData *tagPtr) {
       return (tagPtr->Type() & TT_INDIC);
   }
   // return list of all margin tags
   Tcl_Obj *GetMarginTags(Tcl_Interp *interp);
   int       GetMarginStyleOffset() { return marginStyleOffset; }
   int       GetAnnotationStyleOffset() { return annotationStyleOffset; }

private:
   int       _configIndicator(TagData *);
   TagData  *_createTag(int ttMask, const char *tagname, int *newTag = NULL);

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

................................................................................
      return (strcmp(tagname, TAG_SEL) == 0);
   }
   const char *TAG_MARGIN;
   bool IS_MARGIN(const char *tagname) {
      return (strcmp(tagname, TAG_MARGIN) == 0);
   }

   void resetFreeTextStyles();
   void resetFreeMarginStyles();
   void resetFreeAnnotationStyles();
   void resetFreeIndicators();
   void deleteTag(const char* name);

   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           freeIndicators; // bit mask of available indicators (max 32)
   std::bitset<256>  freeTextStyles;
   std::bitset<256>  freeMarginStyles;
   std::bitset<256>  freeAnnotationStyles;
   int           numTags;     // total number of defined tags
   int           annotationStyleOffset;
   int           marginStyleOffset;

   // 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. */

    // tag location management for fast lookup of tag by position
    std::vector<TagLocation*> tagLocations; // sorted array of tag locations

    void ApplyStyle(TagData *td, sptr_t startpos, sptr_t endpos);
    void RemoveStyle(TagData *td, sptr_t startpos, sptr_t endpos);
    void ApplyTag(TagData *td, sptr_t startpos, sptr_t endpos);
    void RemoveTag(TagData *td, sptr_t startpos, sptr_t endpos);
    void RemoveLocation(TagLocation *tl_p);
};


////////////////////////////////////////////////////////////////////
// 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
   Tk_Image img;    //(Tk_Image) image handle
   int     type;    //(STRING_TABLE) index of marker type in MarkerTypeNames

    const unsigned char *pixels;
} MarkerOptions;

//-------------------------------------
// CLASS MarkerData
//-------------------------------------
class MarkerData {
public:
................................................................................
   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 *name);
   MarkerData *FindMarker(int marker_id);
   MarkerData *FindMarker(int marginID, const char *, bool ok_to_clone = true);
   int         GetMaxId();

   int         _validateImage(MarkerData *);

private:
   MarkerData *_cloneOp(CloneOpId, MarkerData *);
   MarkerData *_cloneMarker(const char *, MarkerData *);
   MarkerData *_createMarker(const char *, int *);
   void        _deleteMarker(MarkerData *);
   void        _deleteMarkerImpl(MarkerData *);
   int         _getNextId();


   // for testing purposes
   void _dump  (MarkerData *mPtr = NULL);
   void _dumpIt(MarkerData *mPtr);

   Tcl_HashTable  markerTable;
   int            ids;

Changes to tk/scintilla-ext.cxx.

46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65
//==================================================
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.
//==================================================







>





|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//==================================================
void UpdateForScroll(ClientData d) {

   SciWidget *sciw = (SciWidget *)d;

   if ( !(sciw->flags & REDRAW_PENDING) ) {
//printf("ScrollText -- QUEUING DISPLAY\n");
	 Tk_CancelIdleCall(SciWidgetDisplay, (ClientData) d);
     Tk_DoWhenIdle(SciWidgetDisplay, d);

   } else {
//printf("ScrollText -- SKIPPING REDRAW...\n");
   }
   sciw->flags |= 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.
//==================================================

Changes to tk/scintilla-ext.h.

10
11
12
13
14
15
16






17
18
19
20
21
22
23
#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 {







>
>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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

// The description for indicators says that roundbox, squarebox, and dotbox are transparent overlay of text, this is
// expensive to do. Better performance is achieved with solid color fill under the text at the expense of loosing the
// darker outline effect and partial obscuring of the text. If you want transparent overlays for indicators, change the
// value of the following definition to 0 (zero).
#define USE_SOLID_INDICATORS 1

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

// create out namespace
namespace TkSciExt {

Changes to tk/scintillatk.tcl.

1





2
3
4
5
6
7
8
..
14
15
16
17
18
19
20































21
22
23
24
25
26
27
..
56
57
58
59
60
61
62








63
64
65
66
67
68
69
...
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
...
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
# 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] == ""} {
................................................................................
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
................................................................................
    # 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
................................................................................
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
................................................................................

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

>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>

>

>
>
>
|
>





<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>













|
|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
..
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
...
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
...
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
# ScintillaTK class bindings
#
# Copyright (c) 2013 Mentor Graphics Corporation
# The license.terms file describes the conditions under which this software 
# may be distributed.
#

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] == ""} {
................................................................................
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}
    }
}

bind Scintilla <Shift-1> {
    if {[%W margin index @%x,%y] == ""} {
        tk::TextResetAnchor %W @%x,%y
        set tk::Priv(selectMode) char
        tk::TextSelectTo %W %x %y
        catch {%W mark set insert sel.first}
    }
}

bind Scintilla <Double-Shift-1>  {
    if {[%W margin index @%x,%y] == ""} {
        set tk::Priv(selectMode) word
        tk::TextSelectTo %W %x %y 1
        catch {%W mark set insert sel.first}
    }
}

bind Scintilla <Triple-Shift-1>  {
    if {[%W margin index @%x,%y] == ""} {
        set tk::Priv(selectMode) line
        tk::TextSelectTo %W %x %y
        catch {%W mark set insert sel.first}
    }
}

bind Scintilla <Control-1> {
    if {[%W margin index @%x,%y] == ""} {
        catch {%W mark set insert @%x,%y}
    }
}

# Mimic some of the button bindings from Tk Text widget
set btns {
    1
    B1-Motion
    B1-Enter
    B1-Leave
................................................................................
    # selection be displayed even for state disabled text widgets.
    if {$::tcl_platform(platform) eq "windows" \
            || [$w cget -state] ne "disabled"} {
        focus $w
    }
}

# Like TextButton1, we change the logic checking the state
bind Scintilla <Tab> {
    if {[%W cget -state] ne "disabled"} {
        ::tk::ScintillaInsert %W \t
        focus %W
        break
    }
}

# 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
................................................................................
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 the key bindings from Tk Text widget
set keys {
    Control-a
    Control-b
    Control-backslash
    Control-d
    Control-Down
    Control-e
    Control-f
    Control-h
    Control-i
    Control-k
    Control-Left
    Control-n
    Control-Next
    Control-o
    Control-p
    Control-Prior
    Control-Right
    Control-Shift-End
    Control-Shift-Home
    Control-Shift-space
    Control-Shift-Tab
    Control-slash
    Control-t
    Control-v
    Control-Up
    Control-Tab
    Control-space
    Meta-b
    Meta-d
    Meta-f
    Meta-less
    Meta-greater
    Meta-backspace
    Meta-delete
    Next
    Prior
    Select
    Shift-Prior
    Shift-Next
    Shift-Control-Left
    Shift-Control-Right
    Shift-Control-Up
    Shift-Control-Down
    Shift-Down
    Shift-End
    Shift-Home
    Shift-Left
    Shift-Right
    Shift-Tab
    Shift-Up
    Shift-Select
}    
foreach e $keys {
    bind Scintilla <$e> [bind Text <$e>]
}









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

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

bind Scintilla <Insert> {
    catch {::tk::ScintillaInsert %W [::tk::GetSelection %W PRIMARY]}
}

bind Scintilla <KeyPress> {
   ::tk::ScintillaInsert %W %A
}

# 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 <<Redo>> {
    catch { %W edit redo }
}

bind Scintilla <<Undo>> {
    catch { %W edit undo }
}

# MOUSE WHEEL
bind Scintilla <Button-4> {
   %W yview scroll -5 units
}
bind Scintilla <Button-5> {

Added tk/scitk_make.patch.

































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
==== //dvt/mti/prod/src/scintilla/tk/Makefile.in#4 - /home/bgriffin/dev/devm2_backup/prod/src/scintilla/tk/Makefile.in ====
***************
*** 32,42 ****
  # 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@
--- 32,48 ----
  # It is not important to specify the directory, as long as it is the
  # $(srcdir) or in the generic, win or unix subdirectory.
  #========================================================================
+ VPATH=$(srcdir):$(srcdir)/../lexers:$(srcdir)/../src
+ LEXSRCS = $(notdir $(wildcard $(srcdir)/../lexers/Lex*.cxx))
+ LEXOBJS = $(addsuffix .$(OBJEXT),$(basename $(LEXSRCS)))
+ 
+ OTHERSRCS = $(notdir $(wildcard $(srcdir)/../src/*.cxx) $(wildcard $(srcdir)/../lexlib/*.cxx))
+ OTHEROBJS = $(addsuffix .$(OBJEXT),$(basename $(OTHERSRCS)))
+ SRCS = $(notdir $(wildcard $(srcdir)/*.cxx))
+ SRCOBJS = $(addsuffix .$(OBJEXT),$(basename $(SRCS)))
  
  PKG_SOURCES	= @PKG_SOURCES@ 
! PKG_OBJECTS	= $(OTHEROBJS)  @PKG_OBJECTS@ $(LEXOBJS) 
  
  PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
  PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
***************
*** 289,295 ****
  valgrindshell: binaries libraries
  	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
  
! depend:
  
  #========================================================================
  # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
--- 295,304 ----
  valgrindshell: binaries libraries
  	$(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
  
! $(warning "OTHERSRCS=$(OTHERSRCS)")
! 
! depend: $(SRCS) $(LEXSRCS) $(OTHERSRCS)
! 	makedepend -f- -- $(CFLAGS) $(INCLUDES) -- $^ >.depends
  
  #========================================================================
  # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
***************
*** 388,394 ****
  
  clean:
  	-test -z "$(BINARIES)" || rm -f $(BINARIES)
! 	-rm -f *.$(OBJEXT) core *.core
  	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
  
  distclean: clean
--- 397,403 ----
  
  clean:
  	-test -z "$(BINARIES)" || rm -f $(BINARIES)
! 	-rm -f *.$(OBJEXT) core *.core .depend
  	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
  
  distclean: clean
***************
*** 483,485 ****
--- 492,499 ----
  # 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:
+ 
+ 
+ ifeq (.depend,$(wildcard .depend))
+ include .depend
+ endif

Changes to tk/sciwrappers.cxx.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
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
...
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
...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
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
...
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
//#############################################################################

//=============================================================================
// 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
................................................................................
 }

//=============================================================================
// 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;
   }
................................................................................
}

//=============================================================================
// 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--;

................................................................................
//=============================================================================
// 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)
................................................................................

//=============================================================================
// 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;
................................................................................
//#############################################################################

//=============================================================================
// 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
//
................................................................................
}

//=============================================================================
// 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
//
................................................................................
//=============================================================================
// 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
//
................................................................................
//=============================================================================
// 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
//
................................................................................
}

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







|




|







 







|







 







|







 







|
|







 







|







 







|











|







 







|











|









|







 







|







 







|











|

>
>
>
>

|

|







 







|









|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
...
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
...
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
...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
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
...
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
//#############################################################################

//=============================================================================
// sci_add_text
//
// Add new text at the specified document position
//-----------------------------------------------------------------------------
void sci_add_text(ScintillaObject *sci, sptr_t 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.
    sptr_t 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
................................................................................
 }

//=============================================================================
// sci_delete_text
//
// Deletes text between two positions
//-----------------------------------------------------------------------------
void sci_delete_text(ScintillaObject *sci, sptr_t pos1, sptr_t pos2)
{
   if (pos1 == pos2) return;
   if (pos1 > pos2) {
      int tmp = pos2;
      pos2 = pos1;
      pos1 = tmp;
   }
................................................................................
}

//=============================================================================
// sci_goto_pos
//
// Change current position and scroll(if needed) to see it
//-----------------------------------------------------------------------------
void sci_goto_pos(ScintillaObject *sci, sptr_t 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--;

................................................................................
//=============================================================================
// sci_has_selection
//
// Return whether any text is selected
//-----------------------------------------------------------------------------
bool sci_has_selection(ScintillaObject *sci)
{
    sptr_t pos1 = SSM(sci, SCI_GETSELECTIONSTART, 0, 0);
    sptr_t pos2 = SSM(sci, SCI_GETSELECTIONEND, 0, 0);
    return (pos1 != pos2);
}

//=============================================================================
// sci_redo
//-----------------------------------------------------------------------------
void sci_redo(ScintillaObject *sci)
................................................................................

//=============================================================================
// 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, sptr_t pos1, sptr_t 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;
................................................................................
//#############################################################################

//=============================================================================
// sci_get_column
//
// Return the column position from a document position
//-----------------------------------------------------------------------------
int sci_get_column(ScintillaObject *sci, sptr_t 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)
//-----------------------------------------------------------------------------
sptr_t sci_get_current_pos(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETCURRENTPOS, 0, 0);
}

//=============================================================================
// sci_get_foldlevel
//
................................................................................
}

//=============================================================================
// sci_get_length
//
// Return the number of characters in the document
//-----------------------------------------------------------------------------
sptr_t 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
//-----------------------------------------------------------------------------
sptr_t sci_get_line(ScintillaObject *sci, sptr_t pos)
{
   return SSM(sci, SCI_LINEFROMPOSITION, pos, 0);
}

//=============================================================================
// sci_get_line_count
//
// Return the number of lines in the document
//-----------------------------------------------------------------------------
sptr_t sci_get_line_count(ScintillaObject *sci)
{
   return SSM(sci, SCI_GETLINECOUNT, 0, 0);
}

//=============================================================================
// sci_get_line_length
//
................................................................................
//=============================================================================
// sci_get_lineend_pos
//
// Return the document position for a line
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
sptr_t sci_get_lineend_pos(ScintillaObject *sci, int line)
{
   return SSM(sci, SCI_GETLINEENDPOSITION, line, 0);
}

//=============================================================================
// sci_get_margin_mask
//
................................................................................
//=============================================================================
// sci_get_pos
//
// Return document position for specified line number
//
// NOTE: LINE NUMBER IS 0-BASED
//-----------------------------------------------------------------------------
sptr_t 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.
//-----------------------------------------------------------------------------
sptr_t sci_get_pos_from_xy(ScintillaObject *sci, int x, int y, bool close)
{
    // in order to match the behavior of Tk's Text widget, we want to
    // ask for the character position at x/y; otherwise, what we will
    // get from Scintilla is the inter-character position.

    if (close)
        return SSM(sci, SCI_CHARPOSITIONFROMPOINTCLOSE, x, y);

    return SSM(sci, SCI_CHARPOSITIONFROMPOINT, x, y);
}

//=============================================================================
// sci_get_text_height
//
// Return the height(in pixels) of the specified line
//
................................................................................
}

//=============================================================================
// sci_get_x_from_pos
//
// Return the screen X location corresponding to a document position
//-----------------------------------------------------------------------------
int sci_get_x_from_pos(ScintillaObject *sci, sptr_t 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, sptr_t pos)
{
    return SSM(sci, SCI_POINTYFROMPOSITION, 0/*unused*/, pos);
}

//=============================================================================
// sci_get_zoom
//

Changes to tk/sciwrappers.h.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 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);







|










|
|

|



|







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 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 "ScintillaTk.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, sptr_t pos, const char *s);
void sci_delete_text        (ScintillaObject *sci, sptr_t pos1, sptr_t pos2);
void sci_enable_margin_click(ScintillaObject *sci, int m, bool enable);
void sci_goto_pos           (ScintillaObject *sci, sptr_t pos);
bool sci_has_selection      (ScintillaObject *sci);
void sci_redo               (ScintillaObject *sci);
void sci_reset_undo_history (ScintillaObject *sci);
void sci_select             (ScintillaObject *sci, sptr_t pos1, sptr_t 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, sptr_t pos);
sptr_t sci_get_current_pos    (ScintillaObject *sci);
int    sci_get_foldlevel      (ScintillaObject *sci, int line);
int    sci_get_is_modified    (ScintillaObject *sci);
sptr_t sci_get_length         (ScintillaObject *sci);
sptr_t sci_get_line           (ScintillaObject *sci, sptr_t pos);
sptr_t sci_get_line_count     (ScintillaObject *sci);
int    sci_get_line_length    (ScintillaObject *sci, int line);
int    sci_get_line_markers   (ScintillaObject *sci, int line);
sptr_t 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);
sptr_t sci_get_pos            (ScintillaObject *sci, int line);
sptr_t 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, sptr_t pos);
int    sci_get_y_from_pos     (ScintillaObject *sci, sptr_t 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);

Added tk/test/pointer.gif.

cannot compute difference between binary files

Added tk/test/pointer.png.

cannot compute difference between binary files

Added tk/test/pointer.xpm.



































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* 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        ",
"                ",
"                "};

Added tk/test/rainbow.gif.

cannot compute difference between binary files

Added tk/test/rainbow.xpm.





















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
/* 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    "};

Added tk/test/rightarrow.gif.

cannot compute difference between binary files

Added tk/test/rightarrow.xpm.































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
/* 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.          ",
"                                ",
"                                ",
"                                "};

Changes to tk/test/widget-test.tcl.

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27
..
48
49
50
51
52
53
54


55
56
57
58
59
60
61
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
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

# 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} {
................................................................................
$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
................................................................................
}

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}
................................................................................
"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
}







|
>







 







>
>







 







|







 







<
<
|
|

|
|
<

<
<
<
<
<
<
>
|









13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
489
490
491
492
493
494
495


496
497
498
499
500

501






502
503
504
505
506
507
508
509
510
511
512

# load the shared library
set SUFFIX ""
if {[info exists ::env(WINDIR)] && [info exists ::tcl_platform(debug)]} {
    set SUFFIX "g"
}

# load the shared library, assumes test being run in build directory
set auto_path [linsert auto_path 0 [file normalize [glob ./usr/lib/ScintillaTk*]]]
package require ScintillaTk

##################
# TEST
##################
set curr_loc ""
proc moveupdate {args} {
................................................................................
$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

$sci configure -marginbackground red

# configure appearance
$sci tag config exec -margin -fg red


# configure the margins we want
$sci margin config 0 -type text      -alias cov1
................................................................................
}

set lang "none"

if {[llength $argv] > 0} {
	set f [lindex $argv 0]
} else {
set EX ../../src/tk
set f $EX/PlatTK.cxx
}

if {$DO_LANG} {
switch [::file extension $f] {
   .tcl                 {$sci config -lang tcl}
   .sv - .svh - .v      {$sci config -lang verilog}
................................................................................
"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} {


    set img1 [image create photo -file $EX/test/pointer.gif]
	$sci marker configure pointer -image $img1

	set img2 [image create photo -file $EX/test/rightarrow.gif]
	$sci marker configure rightarrow -image $img2








	set img3 [image create photo -file $EX/test/rainbow.gif]
    $sci marker configure rainbow -image $img3

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

Changes to tk/test/widget-text-test.tcl.

61
62
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
		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







|
|

>
>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
		foreach c [winfo children .] {
			destroy $c
		}
	}
}


# load the shared library, assumes test being run in build directory
set auto_path [linsert auto_path 0 [file normalize [glob ./usr/lib/ScintillaTk*]]]
package require ScintillaTk
# If you want to run the test with the text widget, comment out the previous two lines and uncomment the following line
#interp alias {} scintilla {} text

scintilla .t
pack .t

catch {destroy .t2}
scintilla .t2
set i 0