[geany/geany] 3996ae: Update Scintilla to version 3.5.3

Colomban Wendling git-noreply at xxxxx
Tue Jan 20 14:56:38 UTC 2015


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Tue, 20 Jan 2015 14:56:38 UTC
Commit:      3996ae9268bc433c4b3c73c0c422fd6e75053dee
             https://github.com/geany/geany/commit/3996ae9268bc433c4b3c73c0c422fd6e75053dee

Log Message:
-----------
Update Scintilla to version 3.5.3

Closes [bugs:#1041].


Modified Paths:
--------------
    data/filetypes.verilog
    scintilla/gtk/ScintillaGTK.cxx
    scintilla/include/Platform.h
    scintilla/include/SciLexer.h
    scintilla/include/Scintilla.iface
    scintilla/lexers/LexBash.cxx
    scintilla/lexers/LexCPP.cxx
    scintilla/lexers/LexVerilog.cxx
    scintilla/lexlib/LexAccessor.h
    scintilla/lexlib/WordList.cxx
    scintilla/scintilla_changes.patch
    scintilla/src/Document.cxx
    scintilla/src/Editor.cxx
    scintilla/src/Editor.h
    scintilla/src/MarginView.cxx
    scintilla/src/ScintillaBase.cxx
    scintilla/src/UniConversion.cxx
    scintilla/src/UniConversion.h
    scintilla/version.txt
    src/highlightingmappings.h

Modified: data/filetypes.verilog
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -15,12 +15,18 @@ operator=operator
 identifier=identifier_1
 stringeol=string_eol
 userword=type
+comment_word=comment_doc_keyword
+input=keyword_4
+output=keyword_4
+inout=keyword_4
+port_connect=keyword_4
 
 [keywords]
 # all items must be in one line
 word=always and assign attribute begin buf bufif0 bufif1 case casex casez cmos deassign default defparam disable edge else end endattribute endcase endfunction endmodule endprimitive endspecify endtable endtask event for force forever fork function highz0 highz1 if ifnone initial join medium module large macromodule nand negedge nmos nor not notif0 notif1 or parameter pmos posedge primitive pull0 pull1 pulldown pullup rcmos realtime release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared signed small specify specparam strength strong0 strong1 supply0 supply1 table task tran tranif0 tranif1 tri tri0 tri1 triand trior trireg unsigned vectored wait wand weak0 weak1 while wor xnor xor @
 word2=$display $write $fdisplay $fwrite $strobe $fstrobe $monitor $fmonitor $time $realtime $finish $stop $setup $hold $width $setuphold $readmemb $readmemh $sreadmemb $sreadmemh $getpattern $history $save $restart $incsave $shm_open $shm_probe $shm_close $scale $showscopes $showvars
 word3=real integer time reg wire input output inout
+docComment=
 
 [settings]
 # default extension used when saving files


Modified: scintilla/gtk/ScintillaGTK.cxx
395 lines changed, 263 insertions(+), 132 deletions(-)
===================================================================
@@ -89,6 +89,11 @@
 #define IS_WIDGET_VISIBLE(w) (GTK_WIDGET_VISIBLE(w))
 #endif
 
+#define SC_INDICATOR_INPUT INDIC_IME
+#define SC_INDICATOR_TARGET INDIC_IME+1
+#define SC_INDICATOR_CONVERTED INDIC_IME+2
+#define SC_INDICATOR_UNKNOWN INDIC_IME_MAX
+
 static GdkWindow *WindowFromWidget(GtkWidget *w) {
 #if GTK_CHECK_VERSION(3,0,0)
 	return gtk_widget_get_window(w);
@@ -291,18 +296,26 @@ class ScintillaGTK : public ScintillaBase {
 	gboolean ExposePreeditThis(GtkWidget *widget, GdkEventExpose *ose);
 	static gboolean ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, ScintillaGTK *sciThis);
 #endif
+
+	bool KoreanIME();
 	void CommitThis(char *str);
 	static void Commit(GtkIMContext *context, char *str, ScintillaGTK *sciThis);
-	void PreeditChangedThis();
+	void PreeditChangedInlineThis();
+	void PreeditChangedWindowedThis();
 	static void PreeditChanged(GtkIMContext *context, ScintillaGTK *sciThis);
-
-	bool KoreanIME();
+	void MoveImeCarets(int pos);
+	void DrawImeIndicator(int indicator, int len);
+	void GetImeUnderlines(PangoAttrList *attrs, bool *normalInput);
+	void GetImeBackgrounds(PangoAttrList *attrs, bool *targetInput);
+	void SetCandidateWindowPos();
 
 	static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void*);
 	static void RealizeText(GtkWidget *widget, void*);
 	static void Destroy(GObject *object);
 	static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
 	                              guint time);
+	static void ClipboardReceived(GtkClipboard *clipboard, GtkSelectionData *selection_data, 
+	                              gpointer data);
 	static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
 	                         guint info, guint time);
 	static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
@@ -638,12 +651,20 @@ class PreEditString {
 	gchar *str;
 	gint cursor_pos;
 	PangoAttrList *attrs;
+	gboolean validUTF8;
+	glong uniStrLen;
+	gunichar *uniStr;
+	PangoScript pscript;
 
 	PreEditString(GtkIMContext *im_context) {
 		gtk_im_context_get_preedit_string(im_context, &str, &attrs, &cursor_pos);
+		validUTF8 = g_utf8_validate(str, strlen(str), NULL);
+		uniStr = g_utf8_to_ucs4_fast(str, strlen(str), &uniStrLen);
+		pscript = pango_script_for_unichar(uniStr[0]);
 	}
 	~PreEditString() {
 		g_free(str);
+		g_free(uniStr);
 		pango_attr_list_unref(attrs);
 	}
 };
@@ -869,6 +890,10 @@ void ScintillaGTK::Initialise() {
 		timers[tr].reason = tr;
 		timers[tr].scintilla = this;
 	}
+	vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff));
+	vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff));
+	vs.indicators[SC_INDICATOR_CONVERTED] = Indicator(INDIC_COMPOSITIONTHICK, ColourDesired(0, 0, 0xff));
+	vs.indicators[SC_INDICATOR_TARGET] = Indicator(INDIC_STRAIGHTBOX, ColourDesired(0, 0, 0xff));
 }
 
 void ScintillaGTK::Finalise() {
@@ -1462,10 +1487,18 @@ void ScintillaGTK::Copy() {
 	}
 }
 
+void ScintillaGTK::ClipboardReceived(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) {
+	ScintillaGTK *sciThis = static_cast<ScintillaGTK *>(data);
+	sciThis->ReceivedSelection(selection_data);
+}
+
 void ScintillaGTK::Paste() {
 	atomSought = atomUTF8;
-	gtk_selection_convert(GTK_WIDGET(PWidget(wMain)),
-	                      atomClipboard, atomSought, GDK_CURRENT_TIME);
+	GtkClipboard *clipBoard =
+		gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
+	if (clipBoard == NULL)
+		return;
+	gtk_clipboard_request_contents(clipBoard, atomSought, ClipboardReceived, this);
 }
 
 void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {
@@ -2323,64 +2356,128 @@ gboolean ScintillaGTK::ExposePreedit(GtkWidget *widget, GdkEventExpose *ose, Sci
 #endif
 
 bool ScintillaGTK::KoreanIME() {
-	// Warn : for KoreanIME use only.
-	if (pdoc->TentativeActive()) {
-		return true;
-	}
-
-	bool koreanIME = false;
-	PreEditString utfval(im_context);
+	PreEditString preeditStr(im_context);
+	PangoLanguage *pLang = pango_language_from_string("ko-KR"); // RFC-3066
+	bool koreanIme = pango_language_includes_script(pLang,  preeditStr.pscript);
+	return koreanIme;
+}
 
-	// Only need to check if the first preedit char is Korean.
-	// The rest will be handled in TentativeActive()
-	// which can handle backspace and CJK commons and so forth.
+void ScintillaGTK::MoveImeCarets(int pos) {
+	// Move carets relatively by bytes
+	for (size_t r=0; r<sel.Count(); r++) {
+		int positionInsert = sel.Range(r).Start().Position();
+		sel.Range(r).caret.SetPosition(positionInsert + pos);
+		sel.Range(r).anchor.SetPosition(positionInsert + pos);
+	}
+}
 
-	if (strlen(utfval.str) == 3) {  // One hangul char has 3byte.
-		int unicode = UnicodeFromUTF8(reinterpret_cast<unsigned char *>(utfval.str));
-		// Korean character ranges which are used for the first preedit chars.
-		// http://www.programminginkorean.com/programming/hangul-in-unicode/
-		bool HangulJamo = (0x1100 <= unicode && unicode <= 0x11FF);
-		bool HangulCompatibleJamo = (0x3130 <= unicode && unicode <= 0x318F);
-		bool HangulJamoExtendedA = (0xA960 <= unicode && unicode <= 0xA97F);
-		bool HangulJamoExtendedB = (0xD7B0 <= unicode && unicode <= 0xD7FF);
-		bool HangulSyllable = (0xAC00 <= unicode && unicode <= 0xD7A3);
-		koreanIME = (HangulJamo | HangulCompatibleJamo  | HangulSyllable
-					| HangulJamoExtendedA | HangulJamoExtendedB);
+void ScintillaGTK::DrawImeIndicator(int indicator, int len) {
+	// Emulate the visual style of IME characters with indicators.
+	// Draw an indicator on the character before caret by the character bytes of len
+	// so it should be called after addCharUTF().
+	// It does not affect caret positions.
+	if (indicator < 8 || indicator > INDIC_MAX) {
+		return;
+	}
+	pdoc->decorations.SetCurrentIndicator(indicator);
+	for (size_t r=0; r<sel.Count(); r++) {
+		int positionInsert = sel.Range(r).Start().Position();
+		pdoc->DecorationFillRange(positionInsert - len, 1, len);
+	}
+}
+
+void ScintillaGTK::GetImeUnderlines(PangoAttrList *attrs, bool *normalInput) {
+	// Whether single underlines attribute is or not
+	// attr position is counted by the number of UTF-8 bytes
+	PangoAttrIterator *iterunderline = pango_attr_list_get_iterator(attrs);
+	if (iterunderline) {
+		do {
+			PangoAttribute  *attrunderline = pango_attr_iterator_get(iterunderline, PANGO_ATTR_UNDERLINE);
+			if (attrunderline) {
+				glong start = attrunderline->start_index;
+				glong end = attrunderline->end_index;
+				PangoUnderline uline = (PangoUnderline)((PangoAttrInt *)attrunderline)->value;
+				for (glong i=start; i < end; ++i) {
+					switch (uline) {
+					case PANGO_UNDERLINE_NONE:
+						normalInput[i] = false;
+						break;
+					case PANGO_UNDERLINE_SINGLE: // normal input
+						normalInput[i] = true;
+						break;
+					case PANGO_UNDERLINE_DOUBLE:
+					case PANGO_UNDERLINE_LOW:
+					case PANGO_UNDERLINE_ERROR:
+						break;
+					}
+				}
+			}
+		} while (pango_attr_iterator_next(iterunderline));
+		pango_attr_iterator_destroy(iterunderline);
+	}
+}
+
+void ScintillaGTK::GetImeBackgrounds(PangoAttrList *attrs, bool *targetInput) {
+	// Whether background color attribue is or not
+	// attr position is measured in UTF-8 bytes
+	PangoAttrIterator *itercolor = pango_attr_list_get_iterator(attrs);
+	if (itercolor) {
+		do {
+			PangoAttribute  *backcolor = pango_attr_iterator_get(itercolor, PANGO_ATTR_BACKGROUND);
+			if (backcolor) {
+				glong start = backcolor->start_index;
+				glong end =  backcolor->end_index;
+				for (glong i=start; i < end; ++i) {
+					targetInput[i] = true;  // target converted
+				}
+			}
+		} while (pango_attr_iterator_next(itercolor));
+		pango_attr_iterator_destroy(itercolor);
 	}
-	return koreanIME;
 }
 
-void ScintillaGTK::CommitThis(char *utfVal) {
+void ScintillaGTK::SetCandidateWindowPos() {
+	// Composition box accompanies candidate box.
+	Point pt = PointMainCaret();
+	GdkRectangle imeBox = {0}; // No need to set width
+	imeBox.x = pt.x;           // Only need positiion
+	imeBox.y = pt.y + vs.lineHeight; // underneath the first charater
+	gtk_im_context_set_cursor_location(im_context, &imeBox);
+}
+
+void ScintillaGTK::CommitThis(char *commitStr) {
 	try {
-		//~ fprintf(stderr, "Commit '%s'\n", utfVal);
+		//~ fprintf(stderr, "Commit '%s'\n", commitStr);
+		view.imeCaretBlockOverride = false;
+
 		if (pdoc->TentativeActive()) {
 			pdoc->TentativeUndo();
 		}
 
-		view.imeCaretBlockOverride = false;
+		const char *charSetSource = CharacterSetID();
 
-		if (IsUnicodeMode()) {
-			AddCharUTF(utfVal, strlen(utfVal));
-		} else {
-			const char *source = CharacterSetID();
-			if (*source) {
-				Converter conv(source, "UTF-8", true);
-				if (conv) {
-					char localeVal[maxLenInputIME * 2];
-					char *pin = utfVal;
-					size_t inLeft = strlen(utfVal);
-					char *pout = localeVal;
-					size_t outLeft = sizeof(localeVal);
-					size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
-					if (conversions != ((size_t)(-1))) {
-						*pout = '\0';
-						AddCharUTF(localeVal, strlen(localeVal));
-					} else {
-						fprintf(stderr, "Conversion failed '%s'\n", utfVal);
-					}
-				}
+		glong uniStrLen = 0;
+		gunichar *uniStr = g_utf8_to_ucs4_fast(commitStr, strlen(commitStr), &uniStrLen);
+		for (glong i = 0; i < uniStrLen; i++) {
+
+			gunichar uniChar[1] = {0};
+			uniChar[0] = uniStr[i];
+
+			glong oneCharLen = 0;
+			gchar *oneChar = g_ucs4_to_utf8(uniChar, 1, NULL, &oneCharLen, NULL);
+
+			if (IsUnicodeMode()) {
+				// Do nothing ;
+			} else {
+				std::string oneCharSTD = ConvertText(oneChar, oneCharLen, charSetSource, "UTF-8", true);
+				oneCharLen = oneCharSTD.copy(oneChar,oneCharSTD.length(), 0);
+				oneChar[oneCharLen] = '\0';
 			}
+
+			AddCharUTF(oneChar, oneCharLen);
+			g_free(oneChar);
 		}
+		g_free(uniStr);
 		ShowCaretAtCurrentPosition();
 	} catch (...) {
 		errorStatus = SC_STATUS_FAILURE;
@@ -2391,100 +2488,130 @@ void ScintillaGTK::Commit(GtkIMContext *, char  *str, ScintillaGTK *sciThis) {
 	sciThis->CommitThis(str);
 }
 
-void ScintillaGTK::PreeditChangedThis() {
+void ScintillaGTK::PreeditChangedInlineThis() {
+	// Copy & paste by johnsonj with a lot of helps of Neil
+	// Great thanks for my foreruners, jiniya and BLUEnLIVE
 	try {
-		if (KoreanIME()) {
-			// Copy & paste by johnsonj.
-			// Great thanks to
-			// jiniya from http://www.jiniya.net/tt/494  for DBCS input with AddCharUTF().
-			// BLUEnLIVE from http://zockr.tistory.com/1118 for UNDO and inOverstrike.
-			view.imeCaretBlockOverride = false; // If backspace.
-
-			if (pdoc->TentativeActive()) {
-				pdoc->TentativeUndo();
-			} else {
-				// No tentative undo means start of this composition so
-				// fill in any virtual spaces.
-				bool tmpOverstrike = inOverstrike;
-				inOverstrike = false;   // Not allowed to be deleted twice.
-				AddCharUTF("", 0);
-				inOverstrike = tmpOverstrike;
-			}
+		view.imeCaretBlockOverride = false; // If backspace.
 
-			PreEditString utfval(im_context);
+		if (pdoc->TentativeActive()) {
+			pdoc->TentativeUndo();
+		} else {
+			// No tentative undo means start of this composition so
+			// fill in any virtual spaces.
+			FillVirtualSpace();
+		}
 
-			if ((strlen(utfval.str) == 0) || strlen(utfval.str) > maxLenInputIME * 3) {
-				return; // Do not allow over 200 chars.
-			}
+		PreEditString preeditStr(im_context);
+		const char *charSetSource = CharacterSetID();
+
+		if (!preeditStr.validUTF8 || (charSetSource == NULL)) {
+			ShowCaretAtCurrentPosition();
+			return;
+		}
+
+		if (preeditStr.uniStrLen == 0 || preeditStr.uniStrLen > maxLenInputIME) {
+			//fprintf(stderr, "Do not allow over 200 chars: %i\n", preeditStr.uniStrLen);
+			ShowCaretAtCurrentPosition();
+			return;
+		}
+
+		pdoc->TentativeStart(); // TentativeActive() from now on
+
+		// Get preedit string attribues
+		bool normalInput[maxLenInputIME*3+1] = {false};
+		bool targetInput[maxLenInputIME*3+1] = {false};
+		GetImeUnderlines(preeditStr.attrs, normalInput);
+		GetImeBackgrounds(preeditStr.attrs, targetInput);
 
-			char localeVal[maxLenInputIME * 2];
-			char *hanval = (char *)"";
+		// Display preedit characters, one by one
+		glong imeCharPos[maxLenInputIME+1] = { 0 };
+		glong attrPos = -1; // Start at -1 to designate the last byte of one character.
+		glong charWidth = 0;
+
+		bool tmpRecordingMacro = recordingMacro;
+		recordingMacro = false;
+		for (glong i = 0; i < preeditStr.uniStrLen; i++) {
+
+			gunichar uniChar[1] = {0};
+			uniChar[0] = preeditStr.uniStr[i];
+
+			glong oneCharLen = 0;
+			gchar *oneChar = g_ucs4_to_utf8(uniChar, 1, NULL, &oneCharLen, NULL);
+
+			// Record attribute positions in UTF-8 bytes
+			attrPos += oneCharLen;
 
 			if (IsUnicodeMode()) {
-				hanval = utfval.str;
+				// Do nothing
 			} else {
-				const char *source = CharacterSetID();
-				if (*source) {
-					Converter conv(source, "UTF-8", true);
-					if (conv) {
-						char *pin = utfval.str;
-						size_t inLeft = strlen(utfval.str);
-						char *pout = localeVal;
-						size_t outLeft = sizeof(localeVal);
-						size_t conversions = conv.Convert(&pin, &inLeft, &pout, &outLeft);
-						if (conversions != ((size_t)(-1))) {
-							*pout = '\0';
-							hanval = localeVal;
-						} else {
-							fprintf(stderr, "Conversion failed '%s'\n", utfval.str);
-						}
-					}
-				}
+				std::string oneCharSTD = ConvertText(oneChar, oneCharLen, charSetSource, "UTF-8", true);
+				oneCharLen = oneCharSTD.copy(oneChar,oneCharSTD.length(), 0);
+				oneChar[oneCharLen] = '\0';
 			}
 
-			if (!pdoc->TentativeActive()) {
-				pdoc->TentativeStart();
-			}
+			// Record character positions in UTF-8 or DBCS bytes
 
-			bool tmpRecordingMacro = recordingMacro;
-			recordingMacro = false;
-			int hanlen = strlen(hanval);
-			AddCharUTF(hanval, hanlen);
-			recordingMacro = tmpRecordingMacro;
+			charWidth += oneCharLen;
+			imeCharPos[i+1] = charWidth;
 
-			// For block caret which means KoreanIME is in composition.
-			view.imeCaretBlockOverride = true;
-			for (size_t r = 0; r < sel.Count(); r++) {
-				int positionInsert = sel.Range(r).Start().Position();
-				sel.Range(r).caret.SetPosition(positionInsert - hanlen);
-				sel.Range(r).anchor.SetPosition(positionInsert - hanlen);
+			// Display one character
+			AddCharUTF(oneChar, oneCharLen);
+
+			// Draw an indicator on the character,
+			// Overlapping allowed
+			if (normalInput[attrPos]) {
+				DrawImeIndicator(SC_INDICATOR_INPUT, oneCharLen);
 			}
-		} else { // Original code follows  for other IMEs.
-			PreEditString pes(im_context);
-			if (strlen(pes.str) > 0) {
-				PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), pes.str);
-				pango_layout_set_attributes(layout, pes.attrs);
-
-				gint w, h;
-				pango_layout_get_pixel_size(layout, &w, &h);
-				g_object_unref(layout);
-
-				gint x, y;
-				gdk_window_get_origin(PWindow(wText), &x, &y);
-
-				Point pt = PointMainCaret();
-				if (pt.x < 0)
-					pt.x = 0;
-				if (pt.y < 0)
-					pt.y = 0;
-
-				gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
-				gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
-				gtk_widget_show(PWidget(wPreedit));
-				gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
-			} else {
-				gtk_widget_hide(PWidget(wPreedit));
+			if (targetInput[attrPos]) {
+				DrawImeIndicator(SC_INDICATOR_TARGET, oneCharLen);
 			}
+			g_free(oneChar);
+		}
+		recordingMacro = tmpRecordingMacro;
+
+		// Move caret to ime cursor position.
+		if (KoreanIME()) {
+			view.imeCaretBlockOverride = true;
+			MoveImeCarets( - (imeCharPos[preeditStr.uniStrLen]));
+
+		} else {
+			MoveImeCarets( - (imeCharPos[preeditStr.uniStrLen]) + imeCharPos[preeditStr.cursor_pos]);
+		}
+
+		SetCandidateWindowPos();
+		ShowCaretAtCurrentPosition();
+	} catch (...) {
+		errorStatus = SC_STATUS_FAILURE;
+	}
+}
+
+void ScintillaGTK::PreeditChangedWindowedThis() {
+	try {
+		PreEditString pes(im_context);
+		if (strlen(pes.str) > 0) {
+			PangoLayout *layout = gtk_widget_create_pango_layout(PWidget(wText), pes.str);
+			pango_layout_set_attributes(layout, pes.attrs);
+
+			gint w, h;
+			pango_layout_get_pixel_size(layout, &w, &h);
+			g_object_unref(layout);
+
+			gint x, y;
+			gdk_window_get_origin(PWindow(wText), &x, &y);
+
+			Point pt = PointMainCaret();
+			if (pt.x < 0)
+				pt.x = 0;
+			if (pt.y < 0)
+				pt.y = 0;
+
+			gtk_window_move(GTK_WINDOW(PWidget(wPreedit)), x + pt.x, y + pt.y);
+			gtk_window_resize(GTK_WINDOW(PWidget(wPreedit)), w, h);
+			gtk_widget_show(PWidget(wPreedit));
+			gtk_widget_queue_draw_area(PWidget(wPreeditDraw), 0, 0, w, h);
+		} else {
+			gtk_widget_hide(PWidget(wPreedit));
 		}
 	} catch (...) {
 		errorStatus = SC_STATUS_FAILURE;
@@ -2492,7 +2619,11 @@ void ScintillaGTK::PreeditChangedThis() {
 }
 
 void ScintillaGTK::PreeditChanged(GtkIMContext *, ScintillaGTK *sciThis) {
-	sciThis->PreeditChangedThis();
+	if (sciThis->imeInteraction == imeInline) {
+		sciThis->PreeditChangedInlineThis();
+	} else {
+		sciThis->PreeditChangedWindowedThis();
+	}
 }
 
 void ScintillaGTK::StyleSetText(GtkWidget *widget, GtkStyle *, void*) {


Modified: scintilla/include/Platform.h
5 lines changed, 5 insertions(+), 0 deletions(-)
===================================================================
@@ -144,6 +144,11 @@ class PRectangle {
 		return (pt.x >= left) && (pt.x <= right) &&
 			(pt.y >= top) && (pt.y <= bottom);
 	}
+	bool ContainsWholePixel(Point pt) const {
+		// Does the rectangle contain all of the pixel to left/below the point 
+		return (pt.x >= left) && ((pt.x+1) <= right) &&
+			(pt.y >= top) && ((pt.y+1) <= bottom);
+	}
 	bool Contains(PRectangle rc) const {
 		return (rc.left >= left) && (rc.right <= right) &&
 			(rc.top >= top) && (rc.bottom <= bottom);


Modified: scintilla/include/SciLexer.h
27 lines changed, 27 insertions(+), 0 deletions(-)
===================================================================
@@ -129,6 +129,9 @@
 #define SCLEX_DMIS 114
 #define SCLEX_REGISTRY 115
 #define SCLEX_BIBTEX 116
+#define SCLEX_SREC 117
+#define SCLEX_IHEX 118
+#define SCLEX_TEHEX 119
 #define SCLEX_AUTOMATIC 1000
 #define SCE_P_DEFAULT 0
 #define SCE_P_COMMENTLINE 1
@@ -898,6 +901,11 @@
 #define SCE_V_IDENTIFIER 11
 #define SCE_V_STRINGEOL 12
 #define SCE_V_USER 19
+#define SCE_V_COMMENT_WORD 20
+#define SCE_V_INPUT 21
+#define SCE_V_OUTPUT 22
+#define SCE_V_INOUT 23
+#define SCE_V_PORT_CONNECT 24
 #define SCE_KIX_DEFAULT 0
 #define SCE_KIX_COMMENT 1
 #define SCE_KIX_STRING1 2
@@ -1741,6 +1749,25 @@
 #define SCE_BIBTEX_PARAMETER 4
 #define SCE_BIBTEX_VALUE 5
 #define SCE_BIBTEX_COMMENT 6
+#define SCE_HEX_DEFAULT 0
+#define SCE_HEX_RECSTART 1
+#define SCE_HEX_RECTYPE 2
+#define SCE_HEX_RECTYPE_UNKNOWN 3
+#define SCE_HEX_BYTECOUNT 4
+#define SCE_HEX_BYTECOUNT_WRONG 5
+#define SCE_HEX_NOADDRESS 6
+#define SCE_HEX_DATAADDRESS 7
+#define SCE_HEX_RECCOUNT 8
+#define SCE_HEX_STARTADDRESS 9
+#define SCE_HEX_ADDRESSFIELD_UNKNOWN 10
+#define SCE_HEX_EXTENDEDADDRESS 11
+#define SCE_HEX_DATA_ODD 12
+#define SCE_HEX_DATA_EVEN 13
+#define SCE_HEX_DATA_UNKNOWN 14
+#define SCE_HEX_DATA_EMPTY 15
+#define SCE_HEX_CHECKSUM 16
+#define SCE_HEX_CHECKSUM_WRONG 17
+#define SCE_HEX_GARBAGE 18
 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */
 
 #endif


Modified: scintilla/include/Scintilla.iface
33 lines changed, 33 insertions(+), 0 deletions(-)
===================================================================
@@ -2719,6 +2719,9 @@ val SCLEX_AS=113
 val SCLEX_DMIS=114
 val SCLEX_REGISTRY=115
 val SCLEX_BIBTEX=116
+val SCLEX_SREC=117
+val SCLEX_IHEX=118
+val SCLEX_TEHEX=119
 
 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
 # value assigned in sequence from SCLEX_AUTOMATIC+1.
@@ -3599,6 +3602,11 @@ val SCE_V_OPERATOR=10
 val SCE_V_IDENTIFIER=11
 val SCE_V_STRINGEOL=12
 val SCE_V_USER=19
+val SCE_V_COMMENT_WORD=20
+val SCE_V_INPUT=21
+val SCE_V_OUTPUT=22
+val SCE_V_INOUT=23
+val SCE_V_PORT_CONNECT=24
 # Lexical states for SCLEX_KIX
 lex Kix=SCLEX_KIX SCE_KIX_
 val SCE_KIX_DEFAULT=0
@@ -4542,6 +4550,31 @@ val SCE_BIBTEX_KEY=3
 val SCE_BIBTEX_PARAMETER=4
 val SCE_BIBTEX_VALUE=5
 val SCE_BIBTEX_COMMENT=6
+# Lexical state for SCLEX_SREC
+lex Srec=SCLEX_SREC SCE_HEX_
+val SCE_HEX_DEFAULT=0
+val SCE_HEX_RECSTART=1
+val SCE_HEX_RECTYPE=2
+val SCE_HEX_RECTYPE_UNKNOWN=3
+val SCE_HEX_BYTECOUNT=4
+val SCE_HEX_BYTECOUNT_WRONG=5
+val SCE_HEX_NOADDRESS=6
+val SCE_HEX_DATAADDRESS=7
+val SCE_HEX_RECCOUNT=8
+val SCE_HEX_STARTADDRESS=9
+val SCE_HEX_ADDRESSFIELD_UNKNOWN=10
+val SCE_HEX_EXTENDEDADDRESS=11
+val SCE_HEX_DATA_ODD=12
+val SCE_HEX_DATA_EVEN=13
+val SCE_HEX_DATA_UNKNOWN=14
+val SCE_HEX_DATA_EMPTY=15
+val SCE_HEX_CHECKSUM=16
+val SCE_HEX_CHECKSUM_WRONG=17
+val SCE_HEX_GARBAGE=18
+# Lexical state for SCLEX_IHEX (shared with Srec)
+lex IHex=SCLEX_IHEX SCE_HEX_
+# Lexical state for SCLEX_TEHEX (shared with Srec)
+lex TEHex=SCLEX_TEHEX SCE_HEX_
 
 # Events
 


Modified: scintilla/lexers/LexBash.cxx
14 lines changed, 9 insertions(+), 5 deletions(-)
===================================================================
@@ -419,8 +419,6 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
 						sc.Forward();
 						HereDoc.Quoted = true;
 						HereDoc.State = 1;
-					} else if (!HereDoc.Indent && sc.chNext == '-') {	// <<- indent case
-						HereDoc.Indent = true;
 					} else if (setHereDoc.Contains(sc.chNext)) {
 						// an unquoted here-doc delimiter, no special handling
 						// TODO check what exactly bash considers part of the delim
@@ -469,7 +467,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
 				if (sc.atLineStart) {
 					sc.SetState(SCE_SH_HERE_Q);
 					int prefixws = 0;
-					while (IsASpace(sc.ch) && !sc.atLineEnd) {	// whitespace prefix
+					while (sc.ch == '\t' && !sc.atLineEnd) {	// tabulation prefix
 						sc.Forward();
 						prefixws++;
 					}
@@ -481,7 +479,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
 					char s[HERE_DELIM_MAX];
 					sc.GetCurrent(s, sizeof(s));
 					if (sc.LengthCurrent() == 0) {  // '' or "" delimiters
-						if (prefixws == 0 && HereDoc.Quoted && HereDoc.DelimiterLength == 0)
+						if ((prefixws == 0 || HereDoc.Indent) &&
+							HereDoc.Quoted && HereDoc.DelimiterLength == 0)
 							sc.SetState(SCE_SH_DEFAULT);
 						break;
 					}
@@ -672,7 +671,12 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
 			} else if (sc.Match('<', '<')) {
 				sc.SetState(SCE_SH_HERE_DELIM);
 				HereDoc.State = 0;
-				HereDoc.Indent = false;
+				if (sc.GetRelative(2) == '-') {	// <<- indent case
+					HereDoc.Indent = true;
+					sc.Forward();
+				} else {
+					HereDoc.Indent = false;
+				}
 			} else if (sc.ch == '-'	&&	// one-char file test operators
 					   setSingleCharOp.Contains(sc.chNext) &&
 					   !setWord.Contains(sc.GetRelative(2)) &&


Modified: scintilla/lexers/LexCPP.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1344,14 +1344,14 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
 			}
 		}
 		if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) {
-			if (ch == '{') {
+			if (ch == '{' || ch == '[') {
 				// Measure the minimum before a '{' to allow
 				// folding on "} else {"
 				if (levelMinCurrent > levelNext) {
 					levelMinCurrent = levelNext;
 				}
 				levelNext++;
-			} else if (ch == '}') {
+			} else if (ch == '}' || ch == ']') {
 				levelNext--;
 			}
 		}


Modified: scintilla/lexers/LexVerilog.cxx
876 lines changed, 733 insertions(+), 143 deletions(-)
===================================================================
@@ -13,6 +13,11 @@
 #include <assert.h>
 #include <ctype.h>
 
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+
 #include "ILexer.h"
 #include "Scintilla.h"
 #include "SciLexer.h"
@@ -24,10 +29,309 @@
 #include "CharacterSet.h"
 #include "LexerModule.h"
 
+#include "OptionSet.h"
+#include "SubStyles.h"
+
 #ifdef SCI_NAMESPACE
 using namespace Scintilla;
 #endif
 
+namespace {
+	// Use an unnamed namespace to protect the functions and classes from name conflicts
+
+struct PPDefinition {
+	int line;
+	std::string key;
+	std::string value;
+	bool isUndef;
+	std::string arguments;
+	PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") :
+		line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) {
+	}
+};
+
+class LinePPState {
+	int state;
+	int ifTaken;
+	int level;
+	bool ValidLevel() const {
+		return level >= 0 && level < 32;
+	}
+	int maskLevel() const {
+		return 1 << level;
+	}
+public:
+	LinePPState() : state(0), ifTaken(0), level(-1) {
+	}
+	bool IsInactive() const {
+		return state != 0;
+	}
+	bool CurrentIfTaken() const {
+		return (ifTaken & maskLevel()) != 0;
+	}
+	void StartSection(bool on) {
+		level++;
+		if (ValidLevel()) {
+			if (on) {
+				state &= ~maskLevel();
+				ifTaken |= maskLevel();
+			} else {
+				state |= maskLevel();
+				ifTaken &= ~maskLevel();
+			}
+		}
+	}
+	void EndSection() {
+		if (ValidLevel()) {
+			state &= ~maskLevel();
+			ifTaken &= ~maskLevel();
+		}
+		level--;
+	}
+	void InvertCurrentLevel() {
+		if (ValidLevel()) {
+			state ^= maskLevel();
+			ifTaken |= maskLevel();
+		}
+	}
+};
+
+// Hold the preprocessor state for each line seen.
+// Currently one entry per line but could become sparse with just one entry per preprocessor line.
+class PPStates {
+	std::vector<LinePPState> vlls;
+public:
+	LinePPState ForLine(int line) const {
+		if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) {
+			return vlls[line];
+		} else {
+			return LinePPState();
+		}
+	}
+	void Add(int line, LinePPState lls) {
+		vlls.resize(line+1);
+		vlls[line] = lls;
+	}
+};
+
+// Options used for LexerVerilog
+struct OptionsVerilog {
+	bool foldComment;
+	bool foldPreprocessor;
+	bool foldCompact;
+	bool foldAtElse;
+	bool foldAtModule;
+	bool trackPreprocessor;
+	bool updatePreprocessor;
+	bool portStyling;
+	bool allUppercaseDocKeyword;
+	OptionsVerilog() {
+		foldComment = false;
+		foldPreprocessor = false;
+		foldCompact = false;
+		foldAtElse = false;
+		foldAtModule = false;
+		// for backwards compatibility, preprocessor functionality is disabled by default
+		trackPreprocessor = false;
+		updatePreprocessor = false;
+		// for backwards compatibility, treat input/output/inout as regular keywords
+		portStyling = false;
+		// for backwards compatibility, don't treat all uppercase identifiers as documentation keywords
+		allUppercaseDocKeyword = false;
+	}
+};
+
+struct OptionSetVerilog : public OptionSet<OptionsVerilog> {
+	OptionSetVerilog() {
+		DefineProperty("fold.comment", &OptionsVerilog::foldComment,
+			"This option enables folding multi-line comments when using the Verilog lexer.");
+		DefineProperty("fold.preprocessor", &OptionsVerilog::foldPreprocessor,
+			"This option enables folding preprocessor directives when using the Verilog lexer.");
+		DefineProperty("fold.compact", &OptionsVerilog::foldCompact);
+		DefineProperty("fold.at.else", &OptionsVerilog::foldAtElse,
+			"This option enables folding on the else line of an if statement.");
+		DefineProperty("fold.verilog.flags", &OptionsVerilog::foldAtModule,
+			"This option enables folding module definitions. Typically source files "
+			"contain only one module definition so this option is somewhat useless.");
+		DefineProperty("lexer.verilog.track.preprocessor", &OptionsVerilog::trackPreprocessor,
+			"Set to 1 to interpret `if/`else/`endif to grey out code that is not active.");
+		DefineProperty("lexer.verilog.update.preprocessor", &OptionsVerilog::updatePreprocessor,
+			"Set to 1 to update preprocessor definitions when `define, `undef, or `undefineall found.");
+		DefineProperty("lexer.verilog.portstyling", &OptionsVerilog::portStyling,
+			"Set to 1 to style input, output, and inout ports differently from regular keywords.");
+		DefineProperty("lexer.verilog.allupperkeywords", &OptionsVerilog::allUppercaseDocKeyword,
+			"Set to 1 to style identifiers that are all uppercase as documentation keyword.");
+	}
+};
+
+const char styleSubable[] = {0};
+
+}
+
+class LexerVerilog : public ILexerWithSubStyles {
+	CharacterSet setWord;
+	WordList keywords;
+	WordList keywords2;
+	WordList keywords3;
+	WordList keywords4;
+	WordList keywords5;
+	WordList ppDefinitions;
+	PPStates vlls;
+	std::vector<PPDefinition> ppDefineHistory;
+	struct SymbolValue {
+		std::string value;
+		std::string arguments;
+		SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) {
+		}
+		SymbolValue &operator = (const std::string &value_) {
+			value = value_;
+			arguments.clear();
+			return *this;
+		}
+		bool IsMacro() const {
+			return !arguments.empty();
+		}
+	};
+	typedef std::map<std::string, SymbolValue> SymbolTable;
+	SymbolTable preprocessorDefinitionsStart;
+	OptionsVerilog options;
+	OptionSetVerilog osVerilog;
+	enum { activeFlag = 0x40 };
+	SubStyles subStyles;
+public:
+	LexerVerilog() :
+		setWord(CharacterSet::setAlphaNum, "._", 0x80, true),
+		subStyles(styleSubable, 0x80, 0x40, activeFlag) {
+		}
+	virtual ~LexerVerilog() {}
+	int SCI_METHOD Version() const {
+		return lvSubStyles;
+	}
+	void SCI_METHOD Release() {
+		delete this;
+	}
+	const char* SCI_METHOD PropertyNames() {
+		return osVerilog.PropertyNames();
+	}
+	int SCI_METHOD PropertyType(const char* name) {
+		return osVerilog.PropertyType(name);
+	}
+	const char* SCI_METHOD DescribeProperty(const char* name) {
+		return osVerilog.DescribeProperty(name);
+	}
+	int SCI_METHOD PropertySet(const char* key, const char* val) {
+	    return osVerilog.PropertySet(&options, key, val);
+	}
+	const char* SCI_METHOD DescribeWordListSets() {
+		return osVerilog.DescribeWordListSets();
+	}
+	int SCI_METHOD WordListSet(int n, const char* wl);
+	void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
+	void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
+	void* SCI_METHOD PrivateCall(int, void*) {
+		return 0;
+	}
+	int SCI_METHOD LineEndTypesSupported() {
+		return SC_LINE_END_TYPE_UNICODE;
+	}
+	int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
+		return subStyles.Allocate(styleBase, numberStyles);
+	}
+	int SCI_METHOD SubStylesStart(int styleBase) {
+		return subStyles.Start(styleBase);
+	}
+	int SCI_METHOD SubStylesLength(int styleBase) {
+		return subStyles.Length(styleBase);
+	}
+	int SCI_METHOD StyleFromSubStyle(int subStyle) {
+		int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
+		int active = subStyle & activeFlag;
+		return styleBase | active;
+	}
+	int SCI_METHOD PrimaryStyleFromStyle(int style) {
+		return MaskActive(style);
+ 	}
+	void SCI_METHOD FreeSubStyles() {
+		subStyles.Free();
+	}
+	void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
+		subStyles.SetIdentifiers(style, identifiers);
+	}
+	int SCI_METHOD DistanceToSecondaryStyles() {
+		return activeFlag;
+	}
+	const char * SCI_METHOD GetSubStyleBases() {
+		return styleSubable;
+	}
+	static ILexer* LexerFactoryVerilog() {
+		return new LexerVerilog();
+	}
+	static int MaskActive(int style) {
+		return style & ~activeFlag;
+	}
+	std::vector<std::string> Tokenize(const std::string &expr) const;
+};
+
+int SCI_METHOD LexerVerilog::WordListSet(int n, const char *wl) {
+	WordList *wordListN = 0;
+	switch (n) {
+	case 0:
+		wordListN = &keywords;
+		break;
+	case 1:
+		wordListN = &keywords2;
+		break;
+	case 2:
+		wordListN = &keywords3;
+		break;
+	case 3:
+		wordListN = &keywords4;
+		break;
+	case 4:
+		wordListN = &keywords5;
+		break;
+	case 5:
+		wordListN = &ppDefinitions;
+		break;
+	}
+	int firstModification = -1;
+	if (wordListN) {
+		WordList wlNew;
+		wlNew.Set(wl);
+		if (*wordListN != wlNew) {
+			wordListN->Set(wl);
+			firstModification = 0;
+			if (n == 5) {
+				// Rebuild preprocessorDefinitions
+				preprocessorDefinitionsStart.clear();
+				for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) {
+					const char *cpDefinition = ppDefinitions.WordAt(nDefinition);
+					const char *cpEquals = strchr(cpDefinition, '=');
+					if (cpEquals) {
+						std::string name(cpDefinition, cpEquals - cpDefinition);
+						std::string val(cpEquals+1);
+						size_t bracket = name.find('(');
+						size_t bracketEnd = name.find(')');
+						if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) {
+							// Macro
+							std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1);
+							name = name.substr(0, bracket);
+							preprocessorDefinitionsStart[name] = SymbolValue(val, args);
+						} else {
+							preprocessorDefinitionsStart[name] = val;
+						}
+					} else {
+						std::string name(cpDefinition);
+						std::string val("1");
+						preprocessorDefinitionsStart[name] = val;
+					}
+				}
+			}
+		}
+	}
+	return firstModification;
+}
+
 static inline bool IsAWordChar(const int ch) {
 	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$');
 }
@@ -36,116 +340,389 @@ static inline bool IsAWordStart(const int ch) {
 	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
 }
 
-static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
-                            Accessor &styler) {
+static inline bool AllUpperCase(const char *a) {
+	while (*a) {
+		if (*a >= 'a' && *a <= 'z') return false;
+		a++;
+	}
+	return true;
+}
 
-	WordList &keywords = *keywordlists[0];
-	WordList &keywords2 = *keywordlists[1];
-	WordList &keywords3 = *keywordlists[2];
-	WordList &keywords4 = *keywordlists[3];
+// Functor used to truncate history
+struct After {
+	int line;
+	explicit After(int line_) : line(line_) {}
+	bool operator()(PPDefinition &p) const {
+		return p.line > line;
+	}
+};
+
+static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) {
+	std::string restOfLine;
+	int i =0;
+	char ch = styler.SafeGetCharAt(start, '\n');
+	int endLine = styler.LineEnd(styler.GetLine(start));
+	while (((start+i) < endLine) && (ch != '\r')) {
+		char chNext = styler.SafeGetCharAt(start + i + 1, '\n');
+		if (ch == '/' && (chNext == '/' || chNext == '*'))
+			break;
+		if (allowSpace || (ch != ' '))
+			restOfLine += ch;
+		i++;
+		ch = chNext;
+	}
+	return restOfLine;
+}
+
+static bool IsSpaceOrTab(int ch) {
+	return ch == ' ' || ch == '\t';
+}
+
+void SCI_METHOD LexerVerilog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess)
+{
+	LexAccessor styler(pAccess);
+
+	const int kwOther=0, kwDot=0x100, kwInput=0x200, kwOutput=0x300, kwInout=0x400;
+	int lineState = kwOther;
+	bool continuationLine = false;
+
+	int curLine = styler.GetLine(startPos);
+	if (curLine > 0) lineState = styler.GetLineState(curLine - 1);
 
 	// Do not leak onto next line
 	if (initStyle == SCE_V_STRINGEOL)
 		initStyle = SCE_V_DEFAULT;
 
+	if ((MaskActive(initStyle) == SCE_V_PREPROCESSOR) ||
+			(MaskActive(initStyle) == SCE_V_COMMENTLINE) ||
+			(MaskActive(initStyle) == SCE_V_COMMENTLINEBANG)) {
+		// Set continuationLine if last character of previous line is '\'
+		if (curLine > 0) {
+			int endLinePrevious = styler.LineEnd(curLine - 1);
+			if (endLinePrevious > 0) {
+				continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
+			}
+		}
+	}
+
 	StyleContext sc(startPos, length, initStyle, styler);
+	LinePPState preproc = vlls.ForLine(curLine);
+
+	bool definitionsChanged = false;
+
+	// Truncate ppDefineHistory before current line
+
+	if (!options.updatePreprocessor)
+		ppDefineHistory.clear();
+
+	std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(curLine-1));
+	if (itInvalid != ppDefineHistory.end()) {
+		ppDefineHistory.erase(itInvalid, ppDefineHistory.end());
+		definitionsChanged = true;
+	}
+
+	SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart;
+	for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
+		if (itDef->isUndef)
+			preprocessorDefinitions.erase(itDef->key);
+		else
+			preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments);
+	}
+
+	int activitySet = preproc.IsInactive() ? activeFlag : 0;
+	int lineEndNext = styler.LineEnd(curLine);
 
 	for (; sc.More(); sc.Forward()) {
+		if (sc.atLineStart) {
+			if (sc.state == SCE_V_STRING) {
+				// Prevent SCE_V_STRINGEOL from leaking back to previous line
+				sc.SetState(SCE_V_STRING);
+			}
+			if ((MaskActive(sc.state) == SCE_V_PREPROCESSOR) && (!continuationLine)) {
+				sc.SetState(SCE_V_DEFAULT|activitySet);
+			}
+			if (preproc.IsInactive()) {
+				activitySet = activeFlag;
+				sc.SetState(sc.state | activitySet);
+			}
+		}
 
-		if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
-			// Prevent SCE_V_STRINGEOL from leaking back to previous line
-			sc.SetState(SCE_V_STRING);
+		if (sc.atLineEnd) {
+			curLine++;
+			lineEndNext = styler.LineEnd(curLine);
+			vlls.Add(curLine, preproc);
+			// Update the line state, so it can be seen by next line
+			styler.SetLineState(curLine, lineState);
 		}
 
 		// Handle line continuation generically.
 		if (sc.ch == '\\') {
-			if (sc.chNext == '\n' || sc.chNext == '\r') {
+			if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) {
+				curLine++;
+				lineEndNext = styler.LineEnd(curLine);
+				vlls.Add(curLine, preproc);
+				// Update the line state, so it can be seen by next line
+				styler.SetLineState(curLine, lineState);
 				sc.Forward();
 				if (sc.ch == '\r' && sc.chNext == '\n') {
+					// Even in UTF-8, \r and \n are separate
 					sc.Forward();
 				}
+				continuationLine = true;
+				sc.Forward();
 				continue;
 			}
 		}
 
-		// Determine if the current state should terminate.
-		if (sc.state == SCE_V_OPERATOR) {
-			sc.SetState(SCE_V_DEFAULT);
-		} else if (sc.state == SCE_V_NUMBER) {
-			if (!IsAWordChar(sc.ch)) {
-				sc.SetState(SCE_V_DEFAULT);
+		// for comment keyword
+		if (MaskActive(sc.state) == SCE_V_COMMENT_WORD && !IsAWordChar(sc.ch)) {
+			char s[100];
+			int state = lineState & 0xff;
+			sc.GetCurrent(s, sizeof(s));
+			if (keywords5.InList(s)) {
+				sc.ChangeState(SCE_V_COMMENT_WORD|activitySet);
+			} else {
+				sc.ChangeState(state|activitySet);
 			}
-		} else if (sc.state == SCE_V_IDENTIFIER) {
-			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
-				char s[100];
-                                sc.GetCurrent(s, sizeof(s));
-				if (keywords.InList(s)) {
-					sc.ChangeState(SCE_V_WORD);
-				} else if (keywords2.InList(s)) {
-					sc.ChangeState(SCE_V_WORD2);
-				} else if (keywords3.InList(s)) {
-					sc.ChangeState(SCE_V_WORD3);
-                                } else if (keywords4.InList(s)) {
-					sc.ChangeState(SCE_V_USER);
+			sc.SetState(state|activitySet);
+		}
+
+		const bool atLineEndBeforeSwitch = sc.atLineEnd;
+
+		// Determine if the current state should terminate.
+		switch (MaskActive(sc.state)) {
+			case SCE_V_OPERATOR:
+				sc.SetState(SCE_V_DEFAULT|activitySet);
+				break;
+			case SCE_V_NUMBER:
+				if (!(IsAWordChar(sc.ch) || (sc.ch == '?'))) {
+					sc.SetState(SCE_V_DEFAULT|activitySet);
 				}
-				sc.SetState(SCE_V_DEFAULT);
-			}
-		} else if (sc.state == SCE_V_PREPROCESSOR) {
-                        if (!IsAWordChar(sc.ch)) {
-                                sc.SetState(SCE_V_DEFAULT);
-                        }
-		} else if (sc.state == SCE_V_COMMENT) {
-			if (sc.Match('*', '/')) {
-				sc.Forward();
-				sc.ForwardSetState(SCE_V_DEFAULT);
-			}
-		} else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
-			if (sc.atLineStart) {
-				sc.SetState(SCE_V_DEFAULT);
-			}
-                } else if (sc.state == SCE_V_STRING) {
-			if (sc.ch == '\\') {
-				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+				break;
+			case SCE_V_IDENTIFIER:
+				if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+					char s[100];
+					lineState &= 0xff00;
+					sc.GetCurrent(s, sizeof(s));
+					if (options.portStyling && (strcmp(s, "input") == 0)) {
+						lineState = kwInput;
+						sc.ChangeState(SCE_V_INPUT|activitySet);
+					} else if (options.portStyling && (strcmp(s, "output") == 0)) {
+						lineState = kwOutput;
+						sc.ChangeState(SCE_V_OUTPUT|activitySet);
+					} else if (options.portStyling && (strcmp(s, "inout") == 0)) {
+						lineState = kwInout;
+						sc.ChangeState(SCE_V_INOUT|activitySet);
+					} else if (lineState == kwInput) {
+						sc.ChangeState(SCE_V_INPUT|activitySet);
+					} else if (lineState == kwOutput) {
+						sc.ChangeState(SCE_V_OUTPUT|activitySet);
+					} else if (lineState == kwInout) {
+						sc.ChangeState(SCE_V_INOUT|activitySet);
+					} else if (lineState == kwDot) {
+						lineState = kwOther;
+						if (options.portStyling)
+							sc.ChangeState(SCE_V_PORT_CONNECT|activitySet);
+					} else if (keywords.InList(s)) {
+						sc.ChangeState(SCE_V_WORD|activitySet);
+					} else if (keywords2.InList(s)) {
+						sc.ChangeState(SCE_V_WORD2|activitySet);
+					} else if (keywords3.InList(s)) {
+						sc.ChangeState(SCE_V_WORD3|activitySet);
+					} else if (keywords4.InList(s)) {
+						sc.ChangeState(SCE_V_USER|activitySet);
+					} else if (options.allUppercaseDocKeyword && AllUpperCase(s)) {
+						sc.ChangeState(SCE_V_USER|activitySet);
+					}
+					sc.SetState(SCE_V_DEFAULT|activitySet);
+				}
+				break;
+			case SCE_V_PREPROCESSOR:
+				if (!IsAWordChar(sc.ch) && !sc.atLineEnd) {
+					sc.SetState(SCE_V_DEFAULT|activitySet);
+				}
+				break;
+			case SCE_V_COMMENT:
+				if (sc.Match('*', '/')) {
 					sc.Forward();
+					sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+				} else if (IsAWordStart(sc.ch)) {
+					lineState = sc.state | (lineState & 0xff00);
+					sc.SetState(SCE_V_COMMENT_WORD|activitySet);
 				}
-			} else if (sc.ch == '\"') {
-				sc.ForwardSetState(SCE_V_DEFAULT);
-			} else if (sc.atLineEnd) {
-				sc.ChangeState(SCE_V_STRINGEOL);
-				sc.ForwardSetState(SCE_V_DEFAULT);
-			}
+				break;
+			case SCE_V_COMMENTLINE:
+			case SCE_V_COMMENTLINEBANG:
+				if (sc.atLineStart) {
+					sc.SetState(SCE_V_DEFAULT|activitySet);
+				} else if (IsAWordStart(sc.ch)) {
+					lineState = sc.state | (lineState & 0xff00);
+					sc.SetState(SCE_V_COMMENT_WORD|activitySet);
+				}
+				break;
+			case SCE_V_STRING:
+				if (sc.ch == '\\') {
+					if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+						sc.Forward();
+					}
+				} else if (sc.ch == '\"') {
+					sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+				} else if (sc.atLineEnd) {
+					sc.ChangeState(SCE_V_STRINGEOL|activitySet);
+					sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+				}
+				break;
+		}
+
+		if (sc.atLineEnd && !atLineEndBeforeSwitch) {
+			// State exit processing consumed characters up to end of line.
+			curLine++;
+			lineEndNext = styler.LineEnd(curLine);
+			vlls.Add(curLine, preproc);
+			// Update the line state, so it can be seen by next line
+			styler.SetLineState(curLine, lineState);
 		}
 
 		// Determine if a new state should be entered.
-		if (sc.state == SCE_V_DEFAULT) {
+		if (MaskActive(sc.state) == SCE_V_DEFAULT) {
 			if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
-				sc.SetState(SCE_V_NUMBER);
+				sc.SetState(SCE_V_NUMBER|activitySet);
 			} else if (IsAWordStart(sc.ch)) {
-				sc.SetState(SCE_V_IDENTIFIER);
+				sc.SetState(SCE_V_IDENTIFIER|activitySet);
 			} else if (sc.Match('/', '*')) {
-                                sc.SetState(SCE_V_COMMENT);
+				sc.SetState(SCE_V_COMMENT|activitySet);
 				sc.Forward();	// Eat the * so it isn't used for the end of the comment
 			} else if (sc.Match('/', '/')) {
 				if (sc.Match("//!"))	// Nice to have a different comment style
-					sc.SetState(SCE_V_COMMENTLINEBANG);
+					sc.SetState(SCE_V_COMMENTLINEBANG|activitySet);
 				else
-					sc.SetState(SCE_V_COMMENTLINE);
+					sc.SetState(SCE_V_COMMENTLINE|activitySet);
 			} else if (sc.ch == '\"') {
-				sc.SetState(SCE_V_STRING);
+				sc.SetState(SCE_V_STRING|activitySet);
 			} else if (sc.ch == '`') {
-				sc.SetState(SCE_V_PREPROCESSOR);
+				sc.SetState(SCE_V_PREPROCESSOR|activitySet);
 				// Skip whitespace between ` and preprocessor word
 				do {
 					sc.Forward();
 				} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
 				if (sc.atLineEnd) {
-					sc.SetState(SCE_V_DEFAULT);
+					sc.SetState(SCE_V_DEFAULT|activitySet);
+					styler.SetLineState(curLine, lineState);
+				} else {
+					if (options.trackPreprocessor) {
+						if (sc.Match("ifdef") || sc.Match("ifndef")) {
+							bool isIfDef = sc.Match("ifdef");
+							int i = isIfDef ? 5 : 6;
+							std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false);
+							bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
+							preproc.StartSection(isIfDef == foundDef);
+						} else if (sc.Match("else")) {
+							if (!preproc.CurrentIfTaken()) {
+								preproc.InvertCurrentLevel();
+								activitySet = preproc.IsInactive() ? activeFlag : 0;
+								if (!activitySet) {
+									sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+								}
+							} else if (!preproc.IsInactive()) {
+								preproc.InvertCurrentLevel();
+								activitySet = preproc.IsInactive() ? activeFlag : 0;
+								if (!activitySet) {
+									sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+								}
+							}
+						} else if (sc.Match("elsif")) {
+							// Ensure only one chosen out of `if .. `elsif .. `elsif .. `else .. `endif
+							if (!preproc.CurrentIfTaken()) {
+								// Similar to `ifdef
+								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
+								bool ifGood = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
+								if (ifGood) {
+									preproc.InvertCurrentLevel();
+									activitySet = preproc.IsInactive() ? activeFlag : 0;
+									if (!activitySet)
+										sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+								}
+							} else if (!preproc.IsInactive()) {
+								preproc.InvertCurrentLevel();
+								activitySet = preproc.IsInactive() ? activeFlag : 0;
+								if (!activitySet)
+									sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+							}
+						} else if (sc.Match("endif")) {
+							preproc.EndSection();
+							activitySet = preproc.IsInactive() ? activeFlag : 0;
+							sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+						} else if (sc.Match("define")) {
+							if (options.updatePreprocessor && !preproc.IsInactive()) {
+								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
+								size_t startName = 0;
+								while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName]))
+									startName++;
+								size_t endName = startName;
+								while ((endName < restOfLine.length()) && setWord.Contains(static_cast<unsigned char>(restOfLine[endName])))
+									endName++;
+								std::string key = restOfLine.substr(startName, endName-startName);
+								if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) {
+									// Macro
+									size_t endArgs = endName;
+									while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')'))
+										endArgs++;
+									std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1);
+									size_t startValue = endArgs+1;
+									while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue]))
+										startValue++;
+									std::string value;
+									if (startValue < restOfLine.length())
+										value = restOfLine.substr(startValue);
+									preprocessorDefinitions[key] = SymbolValue(value, args);
+									ppDefineHistory.push_back(PPDefinition(curLine, key, value, false, args));
+									definitionsChanged = true;
+								} else {
+									// Value
+									size_t startValue = endName;
+									while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue]))
+										startValue++;
+									std::string value = restOfLine.substr(startValue);
+									preprocessorDefinitions[key] = value;
+									ppDefineHistory.push_back(PPDefinition(curLine, key, value));
+									definitionsChanged = true;
+								}
+							}
+						} else if (sc.Match("undefineall")) {
+							if (options.updatePreprocessor && !preproc.IsInactive()) {
+								// remove all preprocessor definitions
+								std::map<std::string, SymbolValue>::iterator itDef;
+								for(itDef = preprocessorDefinitions.begin(); itDef != preprocessorDefinitions.end(); ++itDef) {
+									ppDefineHistory.push_back(PPDefinition(curLine, itDef->first, "", true));
+								}
+								preprocessorDefinitions.clear();
+								definitionsChanged = true;
+							}
+						} else if (sc.Match("undef")) {
+							if (options.updatePreprocessor && !preproc.IsInactive()) {
+								std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true);
+								std::vector<std::string> tokens = Tokenize(restOfLine);
+								std::string key;
+								if (tokens.size() >= 1) {
+									key = tokens[0];
+									preprocessorDefinitions.erase(key);
+									ppDefineHistory.push_back(PPDefinition(curLine, key, "", true));
+									definitionsChanged = true;
+								}
+							}
+						}
+					}
 				}
 			} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
-				sc.SetState(SCE_V_OPERATOR);
+				sc.SetState(SCE_V_OPERATOR|activitySet);
+				if (sc.ch == '.') lineState = kwDot;
+				if (sc.ch == ';') lineState = kwOther;
 			}
 		}
 	}
+	if (definitionsChanged) {
+		styler.ChangeLexerState(startPos, startPos + length);
+	}
 	sc.Complete();
 }
 
@@ -153,7 +730,7 @@ static bool IsStreamCommentStyle(int style) {
 	return style == SCE_V_COMMENT;
 }
 
-static bool IsCommentLine(int line, Accessor &styler) {
+static bool IsCommentLine(int line, LexAccessor &styler) {
 	int pos = styler.LineStart(line);
 	int eolPos = styler.LineStart(line + 1) - 1;
 	for (int i = pos; i < eolPos; i++) {
@@ -169,22 +746,13 @@ static bool IsCommentLine(int line, Accessor &styler) {
 	}
 	return false;
 }
+
 // Store both the current line's fold level and the next lines in the
 // level store to make it easy to pick up with each increment
 // and to make it possible to fiddle the current level for "} else {".
-static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
-                            Accessor &styler) {
-	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
-	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
-	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
-	bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
-        // Verilog specific folding options:
-        // fold_at_module -
-        //      Generally used methodology in verilog code is
-        //      one module per file, so folding at module definition is useless.
-        // fold_at_brace/parenthese -
-        //      Folding of long port lists can be convenient.
-	bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
+void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess)
+{
+	LexAccessor styler(pAccess);
 	bool foldAtBrace  = 1;
 	bool foldAtParenthese  = 1;
 
@@ -197,16 +765,16 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 	int levelMinCurrent = levelCurrent;
 	int levelNext = levelCurrent;
 	char chNext = styler[startPos];
-	int styleNext = styler.StyleAt(startPos);
-	int style = initStyle;
+	int styleNext = MaskActive(styler.StyleAt(startPos));
+	int style = MaskActive(initStyle);
 	for (unsigned int i = startPos; i < endPos; i++) {
 		char ch = chNext;
 		chNext = styler.SafeGetCharAt(i + 1);
 		int stylePrev = style;
 		style = styleNext;
-		styleNext = styler.StyleAt(i + 1);
+		styleNext = MaskActive(styler.StyleAt(i + 1));
 		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
-		if (foldComment && IsStreamCommentStyle(style)) {
+		if (options.foldComment && IsStreamCommentStyle(style)) {
 			if (!IsStreamCommentStyle(stylePrev)) {
 				levelNext++;
 			} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
@@ -214,7 +782,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 				levelNext--;
 			}
 		}
-		if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+		if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler))
 		{
 			if (!IsCommentLine(lineCurrent - 1, styler)
 			    && IsCommentLine(lineCurrent + 1, styler))
@@ -223,7 +791,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 			         && !IsCommentLine(lineCurrent+1, styler))
 				levelNext--;
 		}
-		if (foldComment && (style == SCE_V_COMMENTLINE)) {
+		if (options.foldComment && (style == SCE_V_COMMENTLINE)) {
 			if ((ch == '/') && (chNext == '/')) {
 				char chNext2 = styler.SafeGetCharAt(i + 2);
 				if (chNext2 == '{') {
@@ -233,7 +801,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 				}
 			}
 		}
-		if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
+		if (options.foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
 			if (ch == '`') {
 				unsigned int j = i + 1;
 				while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
@@ -246,71 +814,71 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 				}
 			}
 		}
-                if (style == SCE_V_OPERATOR) {
-                    if (foldAtParenthese) {
-			if (ch == '(') {
-				levelNext++;
-			} else if (ch == ')') {
-				levelNext--;
+		if (style == SCE_V_OPERATOR) {
+			if (foldAtParenthese) {
+				if (ch == '(') {
+					levelNext++;
+				} else if (ch == ')') {
+					levelNext--;
+				}
 			}
-                    }
 		}
-                if (style == SCE_V_OPERATOR) {
-                    if (foldAtBrace) {
-			if (ch == '{') {
+		if (style == SCE_V_OPERATOR) {
+			if (foldAtBrace) {
+				if (ch == '{') {
+					levelNext++;
+				} else if (ch == '}') {
+					levelNext--;
+				}
+			}
+		}
+		if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
+			unsigned int j = i;
+			if (styler.Match(j, "case") ||
+				styler.Match(j, "casex") ||
+				styler.Match(j, "casez") ||
+				styler.Match(j, "class") ||
+				styler.Match(j, "function") ||
+				styler.Match(j, "generate") ||
+				styler.Match(j, "covergroup") ||
+				styler.Match(j, "package") ||
+				styler.Match(j, "primitive") ||
+				styler.Match(j, "program") ||
+				styler.Match(j, "sequence") ||
+				styler.Match(j, "specify") ||
+				styler.Match(j, "table") ||
+				styler.Match(j, "task") ||
+				styler.Match(j, "fork") ||
+				(styler.Match(j, "module") && options.foldAtModule) ||
+				styler.Match(j, "begin")) {
 				levelNext++;
-			} else if (ch == '}') {
+			} else if (styler.Match(j, "endcase") ||
+				styler.Match(j, "endclass") ||
+				styler.Match(j, "endfunction") ||
+				styler.Match(j, "endgenerate") ||
+				styler.Match(j, "endgroup") ||
+				styler.Match(j, "endpackage") ||
+				styler.Match(j, "endprimitive") ||
+				styler.Match(j, "endprogram") ||
+				styler.Match(j, "endsequence") ||
+				styler.Match(j, "endspecify") ||
+				styler.Match(j, "endtable") ||
+				styler.Match(j, "endtask") ||
+				styler.Match(j, "join") ||
+				styler.Match(j, "join_any") ||
+				styler.Match(j, "join_none") ||
+				(styler.Match(j, "endmodule") && options.foldAtModule) ||
+				(styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j + 3)))) {
 				levelNext--;
 			}
-                    }
-		}
-                if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
-                        unsigned int j = i;
-                        if (styler.Match(j, "case") ||
-                            styler.Match(j, "casex") ||
-                            styler.Match(j, "casez") ||
-                            styler.Match(j, "class") ||
-                            styler.Match(j, "function") ||
-                            styler.Match(j, "generate") ||
-                            styler.Match(j, "covergroup") ||
-                            styler.Match(j, "package") ||
-                            styler.Match(j, "primitive") ||
-                            styler.Match(j, "program") ||
-                            styler.Match(j, "sequence") ||
-                            styler.Match(j, "specify") ||
-                            styler.Match(j, "table") ||
-                            styler.Match(j, "task") ||
-                            styler.Match(j, "fork") ||
-                            (styler.Match(j, "module") && foldAtModule) ||
-                            styler.Match(j, "begin")) {
-                                levelNext++;
-                        } else if (styler.Match(j, "endcase") ||
-                                   styler.Match(j, "endclass") ||
-                                   styler.Match(j, "endfunction") ||
-                                   styler.Match(j, "endgenerate") ||
-                                   styler.Match(j, "endgroup") ||
-                                   styler.Match(j, "endpackage") ||
-                                   styler.Match(j, "endprimitive") ||
-                                   styler.Match(j, "endprogram") ||
-                                   styler.Match(j, "endsequence") ||
-                                   styler.Match(j, "endspecify") ||
-                                   styler.Match(j, "endtable") ||
-                                   styler.Match(j, "endtask") ||
-                                   styler.Match(j, "join") ||
-                                   styler.Match(j, "join_any") ||
-                                   styler.Match(j, "join_none") ||
-                                   (styler.Match(j, "endmodule") && foldAtModule) ||
-                                   (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
-                                levelNext--;
-                        }
 		}
 		if (atEOL) {
 			int levelUse = levelCurrent;
-			if (foldAtElse) {
+			if (options.foldAtElse) {
 				levelUse = levelMinCurrent;
 			}
 			int lev = levelUse | levelNext << 16;
-			if (visibleChars == 0 && foldCompact)
+			if (visibleChars == 0 && options.foldCompact)
 				lev |= SC_FOLDLEVELWHITEFLAG;
 			if (levelUse < levelNext)
 				lev |= SC_FOLDLEVELHEADERFLAG;
@@ -327,9 +895,31 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
 	}
 }
 
-static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
-                       Accessor &styler) {
-	FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
+std::vector<std::string> LexerVerilog::Tokenize(const std::string &expr) const {
+	// Break into tokens
+	std::vector<std::string> tokens;
+	const char *cp = expr.c_str();
+	while (*cp) {
+		std::string word;
+		if (setWord.Contains(static_cast<unsigned char>(*cp))) {
+			// Identifiers and numbers
+			while (setWord.Contains(static_cast<unsigned char>(*cp))) {
+				word += *cp;
+				cp++;
+			}
+		} else if (IsSpaceOrTab(*cp)) {
+			while (IsSpaceOrTab(*cp)) {
+				cp++;
+			}
+			continue;
+		} else {
+			// Should handle strings, characters, and comments here
+			word += *cp;
+			cp++;
+		}
+		tokens.push_back(word);
+	}
+	return tokens;
 }
 
 static const char * const verilogWordLists[] = {
@@ -337,9 +927,9 @@ static const char * const verilogWordLists[] = {
             "Secondary keywords and identifiers",
             "System Tasks",
             "User defined tasks and identifiers",
-            "Unused",
+            "Documentation comment keywords",
+            "Preprocessor definitions",
             0,
         };
 
-
-LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);
+LexerModule lmVerilog(SCLEX_VERILOG, LexerVerilog::LexerFactoryVerilog, "verilog", verilogWordLists);


Modified: scintilla/lexlib/LexAccessor.h
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -58,6 +58,9 @@ class LexAccessor {
 		validLen(0),
 		startSeg(0), startPosStyling(0),
 		documentVersion(pAccess->Version()) {
+		// Prevent warnings by static analyzers about uninitialized buf and styleBuf.
+		buf[0] = 0;
+		styleBuf[0] = 0;
 		switch (codePage) {
 		case 65001:
 			encodingType = encUnicode;


Modified: scintilla/lexlib/WordList.cxx
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -69,6 +69,8 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa
 
 WordList::WordList(bool onlyLineEnds_) :
 	words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
+	// Prevent warnings by static analyzers about uninitialized starts.
+	starts[0] = -1;
 }
 
 WordList::~WordList() {


Modified: scintilla/scintilla_changes.patch
5 lines changed, 4 insertions(+), 1 deletions(-)
===================================================================
@@ -31,7 +31,7 @@ diff --git b/scintilla/src/Catalogue.cxx a/scintilla/src/Catalogue.cxx
 index 41d5d54..70ce3bc 100644
 --- scintilla/src/Catalogue.cxx
 +++ scintilla/src/Catalogue.cxx
-@@ -76,117 +76,49 @@ int Scintilla_LinkLexers() {
+@@ -76,120 +76,49 @@ int Scintilla_LinkLexers() {
  
  //++Autogenerated -- run scripts/LexGen.py to regenerate
  //**\(\tLINK_LEXER(\*);\n\)
@@ -82,6 +82,7 @@ index 41d5d54..70ce3bc 100644
 -	LINK_LEXER(lmGui4Cli);
  	LINK_LEXER(lmHaskell);
  	LINK_LEXER(lmHTML);
+-	LINK_LEXER(lmIHex);
 -	LINK_LEXER(lmInno);
 -	LINK_LEXER(lmKix);
 -	LINK_LEXER(lmKVIrc);
@@ -134,12 +135,14 @@ index 41d5d54..70ce3bc 100644
 -	LINK_LEXER(lmSpecman);
 -	LINK_LEXER(lmSpice);
  	LINK_LEXER(lmSQL);
+-	LINK_LEXER(lmSrec);
 -	LINK_LEXER(lmSTTXT);
 -	LINK_LEXER(lmTACL);
 -	LINK_LEXER(lmTADS3);
 -	LINK_LEXER(lmTAL);
  	LINK_LEXER(lmTCL);
 -	LINK_LEXER(lmTCMD);
+-	LINK_LEXER(lmTEHex);
 -	LINK_LEXER(lmTeX);
  	LINK_LEXER(lmTxt2tags);
 -	LINK_LEXER(lmVB);


Modified: scintilla/src/Document.cxx
18 lines changed, 3 insertions(+), 15 deletions(-)
===================================================================
@@ -37,6 +37,7 @@
 #include "Document.h"
 #include "RESearch.h"
 #include "UniConversion.h"
+#include "UnicodeFromUTF8.h"
 
 #ifdef SCI_NAMESPACE
 using namespace Scintilla;
@@ -766,19 +767,6 @@ bool Document::NextCharacter(int &pos, int moveDir) const {
 	}
 }
 
-static inline int UnicodeFromBytes(const unsigned char *us) {
-	if (us[0] < 0xC2) {
-		return us[0];
-	} else if (us[0] < 0xE0) {
-		return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
-	} else if (us[0] < 0xF0) {
-		return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
-	} else if (us[0] < 0xF5) {
-		return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
-	}
-	return us[0];
-}
-
 // Return -1  on out-of-bounds
 int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOffset) const {
 	int pos = positionStart;
@@ -819,7 +807,7 @@ int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const {
 					character =  0xDC80 + leadByte;
 				} else {
 					bytesInCharacter = utf8status & UTF8MaskWidth;
-					character = UnicodeFromBytes(charBytes);
+					character = UnicodeFromUTF8(charBytes);
 				}
 			}
 		} else {
@@ -1610,7 +1598,7 @@ Document::CharacterExtracted Document::ExtractCharacter(int position) const {
 		// Treat as invalid and use up just one byte
 		return CharacterExtracted(unicodeReplacementChar, 1);
 	} else {
-		return CharacterExtracted(UnicodeFromBytes(charBytes), utf8status & UTF8MaskWidth);
+		return CharacterExtracted(UnicodeFromUTF8(charBytes), utf8status & UTF8MaskWidth);
 	}
 }
 


Modified: scintilla/src/Editor.cxx
26 lines changed, 16 insertions(+), 10 deletions(-)
===================================================================
@@ -8,10 +8,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
-#include <math.h>
 #include <assert.h>
 #include <ctype.h>
 
+#include <cmath>
 #include <stdexcept>
 #include <string>
 #include <vector>
@@ -1333,7 +1333,9 @@ void Editor::ShowCaretAtCurrentPosition() {
 
 void Editor::DropCaret() {
 	caret.active = false;
-	FineTickerCancel(tickCaret);
+	if (FineTickerAvailable()) {
+		FineTickerCancel(tickCaret);
+	}
 	InvalidateCaret();
 }
 
@@ -1898,6 +1900,13 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) {
 	}
 }
 
+void Editor::FillVirtualSpace() {
+	const bool tmpOverstrike = inOverstrike;
+	inOverstrike = false;         // not allow to be deleted twice.
+	AddCharUTF("", 0);
+	inOverstrike = tmpOverstrike;
+}
+
 void Editor::InsertPaste(const char *text, int len) {
 	if (multiPasteMode == SC_MULTIPASTE_ONCE) {
 		SelectionPosition selStart = sel.Start();
@@ -3283,7 +3292,6 @@ int Editor::KeyCommand(unsigned int iMessage) {
 		break;
 	case SCI_EDITTOGGLEOVERTYPE:
 		inOverstrike = !inOverstrike;
-		DropCaret();
 		ShowCaretAtCurrentPosition();
 		ContainerNeedsUpdate(SC_UPDATE_CONTENT);
 		NotifyUpdateUI();
@@ -3779,9 +3787,9 @@ void Editor::GoToLine(int lineNo) {
 }
 
 static bool Close(Point pt1, Point pt2, Point threshold) {
-	if (abs(pt1.x - pt2.x) > threshold.x)
+	if (std::abs(pt1.x - pt2.x) > threshold.x)
 		return false;
-	if (abs(pt1.y - pt2.y) > threshold.y)
+	if (std::abs(pt1.y - pt2.y) > threshold.y)
 		return false;
 	return true;
 }
@@ -4000,7 +4008,7 @@ bool Editor::PointInSelMargin(Point pt) const {
 		PRectangle rcSelMargin = GetClientRectangle();
 		rcSelMargin.right = static_cast<XYPOSITION>(vs.textStart - vs.leftMarginWidth);
 		rcSelMargin.left = static_cast<XYPOSITION>(vs.textStart - vs.fixedColumnWidth);
-		return rcSelMargin.Contains(pt);
+		return rcSelMargin.ContainsWholePixel(pt);
 	} else {
 		return false;
 	}
@@ -4671,12 +4679,10 @@ void Editor::FineTickerCancel(TickReason) {
 void Editor::SetFocusState(bool focusState) {
 	hasFocus = focusState;
 	NotifyFocus(hasFocus);
-	if (hasFocus) {
-		ShowCaretAtCurrentPosition();
-	} else {
+	if (!hasFocus) {
 		CancelModes();
-		DropCaret();
 	}
+	ShowCaretAtCurrentPosition();
 }
 
 int Editor::PositionAfterArea(PRectangle rcArea) const {


Modified: scintilla/src/Editor.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -388,6 +388,7 @@ class Editor : public EditModel, public DocWatcher {
 	int InsertSpace(int position, unsigned int spaces);
 	void AddChar(char ch);
 	virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false);
+	void FillVirtualSpace();
 	void InsertPaste(const char *text, int len);
 	enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 };
 	void InsertPasteShape(const char *text, int len, PasteShape shape);


Modified: scintilla/src/MarginView.cxx
18 lines changed, 13 insertions(+), 5 deletions(-)
===================================================================
@@ -263,8 +263,10 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
 				PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed());
 				const int lineDoc = model.cs.DocFromDisplay(visibleLine);
 				PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
-				const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc);
-				const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc);
+				const int firstVisibleLine = model.cs.DisplayFromDoc(lineDoc);
+				const int lastVisibleLine = model.cs.DisplayLastFromDoc(lineDoc);
+				const bool firstSubLine = visibleLine == firstVisibleLine;
+				const bool lastSubLine = visibleLine == lastVisibleLine;
 
 				int marks = model.pdoc->GetMark(lineDoc);
 				if (!firstSubLine)
@@ -403,9 +405,9 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
 						}
 					}
 				} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
-					if (firstSubLine) {
-						const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
-						if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+					const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
+					if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+						if (firstSubLine) {
 							surface->FillRectangle(rcMarker,
 								vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
 							if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
@@ -414,6 +416,12 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
 							}
 							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker,
 								stMargin, 0, stMargin.length, drawAll);
+						} else {
+							// if we're displaying annotation lines, color the margin to match the associated document line
+							const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
+							if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
+								surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
+							}
 						}
 					}
 				}


Modified: scintilla/src/ScintillaBase.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -449,12 +449,12 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
 	PRectangle rcClient = GetClientRectangle();
 	int offset = vs.lineHeight + static_cast<int>(rc.Height());
 	// adjust so it displays above the text.
-	if (rc.bottom > rcClient.bottom) {
+	if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) {
 		rc.top -= offset;
 		rc.bottom -= offset;
 	}
 	// adjust so it displays below the text.
-	if (rc.top < rcClient.top) {
+	if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) {
 		rc.top += offset;
 		rc.bottom += offset;
 	}


Modified: scintilla/src/UniConversion.cxx
14 lines changed, 7 insertions(+), 7 deletions(-)
===================================================================
@@ -82,10 +82,10 @@ unsigned int UTF8CharLength(unsigned char ch) {
 	}
 }
 
-unsigned int UTF16Length(const char *s, unsigned int len) {
-	unsigned int ulen = 0;
-	unsigned int charLen;
-	for (unsigned int i=0; i<len;) {
+size_t UTF16Length(const char *s, size_t len) {
+	size_t ulen = 0;
+	size_t charLen;
+	for (size_t i = 0; i<len;) {
 		unsigned char ch = static_cast<unsigned char>(s[i]);
 		if (ch < 0x80) {
 			charLen = 1;
@@ -103,10 +103,10 @@ unsigned int UTF16Length(const char *s, unsigned int len) {
 	return ulen;
 }
 
-unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) {
-	unsigned int ui=0;
+size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) {
+	size_t ui = 0;
 	const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
-	unsigned int i=0;
+	size_t i = 0;
 	while ((i<len) && (ui<tlen)) {
 		unsigned char ch = us[i++];
 		if (ch < 0x80) {


Modified: scintilla/src/UniConversion.h
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -19,8 +19,8 @@ const int unicodeReplacementChar = 0xFFFD;
 unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
 void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
 unsigned int UTF8CharLength(unsigned char ch);
-unsigned int UTF16Length(const char *s, unsigned int len);
-unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);
+size_t UTF16Length(const char *s, size_t len);
+size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen);
 unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen);
 unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf);
 


Modified: scintilla/version.txt
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-352
+353


Modified: src/highlightingmappings.h
14 lines changed, 10 insertions(+), 4 deletions(-)
===================================================================
@@ -1563,13 +1563,19 @@ static const HLStyle highlighting_styles_VERILOG[] =
 	{ SCE_V_OPERATOR,			"operator",				FALSE },
 	{ SCE_V_IDENTIFIER,			"identifier",			FALSE },
 	{ SCE_V_STRINGEOL,			"stringeol",			FALSE },
-	{ SCE_V_USER,				"userword",				FALSE }
+	{ SCE_V_USER,				"userword",				FALSE },
+	{ SCE_V_COMMENT_WORD,		"comment_word",			FALSE },
+	{ SCE_V_INPUT,				"input",				FALSE },
+	{ SCE_V_OUTPUT,				"output",				FALSE },
+	{ SCE_V_INOUT,				"inout",				FALSE },
+	{ SCE_V_PORT_CONNECT,		"port_connect",			FALSE }
 };
 static const HLKeyword highlighting_keywords_VERILOG[] =
 {
-	{ 0, "word",	FALSE },
-	{ 1, "word2",	FALSE },
-	{ 2, "word3",	FALSE }
+	{ 0, "word",		FALSE },
+	{ 1, "word2",		FALSE },
+	{ 2, "word3",		FALSE },
+	{ 4, "docComment",	FALSE }
 };
 #define highlighting_properties_VERILOG		EMPTY_PROPERTIES
 



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list