diff options
author | nyamatongwe <devnull@localhost> | 2000-06-21 02:59:25 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2000-06-21 02:59:25 +0000 |
commit | 6d3878dca546f21822b087d70bea23db9437c0a9 (patch) | |
tree | dce2610a6c578021e13c36d3e4e2c9f4a2eb6dfc | |
parent | 507a9f0685923e0b06597f717daa3b362db1b6ef (diff) | |
download | scintilla-mirror-6d3878dca546f21822b087d70bea23db9437c0a9.tar.gz |
Added indentation guide API.
View whitespace has setting to only see outside indentation.
Indentation guide highlight.
-rw-r--r-- | include/Scintilla.h | 9 | ||||
-rw-r--r-- | include/Scintilla.iface | 28 | ||||
-rw-r--r-- | src/Editor.cxx | 138 | ||||
-rw-r--r-- | src/Editor.h | 11 | ||||
-rw-r--r-- | src/ScintillaBase.cxx | 2 | ||||
-rw-r--r-- | src/ViewStyle.cxx | 4 | ||||
-rw-r--r-- | src/ViewStyle.h | 4 | ||||
-rw-r--r-- | win32/PlatWin.cxx | 2 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 16 |
9 files changed, 165 insertions, 49 deletions
diff --git a/include/Scintilla.h b/include/Scintilla.h index 7e31d5db1..9f42fef0f 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -51,6 +51,10 @@ void Scintilla_RegisterClasses(HINSTANCE hInstance); #define SC_UNDOCOLLECT_NONE 0 #define SC_UNDOCOLLECT_AUTOSTART 1 +#define SCWS_INVISIBLE 0 +#define SCWS_VISIBLEALWAYS 1 +#define SCWS_VISIBLEAFTERINDENT 2 + #define SCI_GETVIEWWS SCI_START + 20 #define SCI_SETVIEWWS SCI_START + 21 #define SCI_GOTOLINE SCI_START + 24 @@ -120,6 +124,7 @@ void Scintilla_RegisterClasses(HINSTANCE hInstance); #define STYLE_BRACELIGHT 34 #define STYLE_BRACEBAD 35 #define STYLE_CONTROLCHAR 36 +#define STYLE_INDENTGUIDE 37 #define STYLE_MAX 127 #define SC_CHARSET_ANSI 0 @@ -217,6 +222,10 @@ void Scintilla_RegisterClasses(HINSTANCE hInstance); #define SCI_SETHSCROLLBAR SCI_START + 130 #define SCI_GETHSCROLLBAR SCI_START + 131 +#define SCI_SETINDENTATIONGUIDES SCI_START + 132 +#define SCI_GETINDENTATIONGUIDES SCI_START + 133 +#define SCI_SETHIGHLIGHTGUIDE SCI_START + 134 +#define SCI_GETHIGHLIGHTGUIDE SCI_START + 135 #define SCI_CALLTIPSHOW SCI_START + 200 #define SCI_CALLTIPCANCEL SCI_START + 201 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 8aac3fdc8..f3eec65df 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -108,11 +108,16 @@ fun int MarkerLineFromHandle=2017(int handle,) # Delete a marker. fun void MarkerDeleteHandle=2018(int handle,) +val SCWS_INVISIBLE=0 +val SCWS_VISIBLEALWAYS=1 +val SCWS_VISIBLEAFTERINDENT=2 + # Are white space characters currently visible? -get bool GetViewWS=2020(,) +# Returns one of SCWS_* constants. +get int GetViewWS=2020(,) -# Make white space characters visible or invisible. -set void SetViewWS=2021(bool viewWS,) +# Make white space characters invisible, always visible or visible outside indentation. +set void SetViewWS=2021(int viewWS,) # Set caret to start of a line and ensure it is visible. fun void GotoLine=2024(int line,) @@ -439,12 +444,25 @@ get position GetLineIndentPosition=2128(int line,) # Retrieve the column number of a position, taking tab width into account. get int GetColumn=2129(position pos,) -# Show or hide the horizontal scroll bar +# Show or hide the horizontal scroll bar. set void SetHScrollBar=2130(bool show,) -# Is the horizontal scroll bar visible. +# Is the horizontal scroll bar visible? get bool GetHScrollBar=2131(,) +# Show or hide indentation guides. +set void SetIndentationGuides=2132(bool show,) + +# Are the indentation guides visible? +get bool GetIndentationGuides=2133(,) + +# Set the highlighted indentation guide column. +# 0 = no highlighted guide. +set void SetHighlightGuide=2134(int column,) + +# Get the highlighted indentation guide column. +get int GetHighlightGuide=2135(,) + # Show a call tip containing a definition near position pos. fun void CallTipShow=2200(position pos, string definition) diff --git a/src/Editor.cxx b/src/Editor.cxx index 878baacff..8596eb8f9 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -81,7 +81,8 @@ Editor::Editor() { braces[0]=invalidPosition; braces[1]=invalidPosition; bracesMatchStyle = STYLE_BRACEBAD; - + highlightGuideColumn = 0; + edgeState = EDGE_NONE; theEdge = 0; @@ -119,6 +120,7 @@ void Editor::DropGraphics() { pixmapLine.Release(); pixmapSelMargin.Release(); pixmapSelPattern.Release(); + pixmapIndentGuide.Release(); } void Editor::InvalidateStyleData() { @@ -729,6 +731,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font; char styleByte = 0; int styleMask = pdoc->stylingBitsMask; + ll.xHighlightGuide = 0; for (int charInDoc = posLineStart; charInDoc < posLineEnd && numCharsInLine < LineLayout::maxLineLength - 1; charInDoc++) { @@ -778,7 +781,8 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll.numCharsInLine = numCharsInLine; } -void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout &ll) { +void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, + PRectangle rcLine, LineLayout &ll) { PRectangle rcSegment = rcLine; @@ -802,7 +806,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, marks = pdoc->GetMark(line) & vsDraw.maskInLine; } - bool inIndentation = true; + bool inIndentation = true; + int indentWidth = pdoc->indentInChars * vs.spaceWidth; + int posLineStart = pdoc->LineStart(line); int posLineEnd = pdoc->LineStart(line + 1); @@ -816,8 +822,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, int iDoc = i + posLineStart; // If there is the end of a style run for any reason if ((ll.styles[i] != ll.styles[i + 1]) || - IsControlCharacter(ll.chars[i]) || IsControlCharacter(ll.chars[i + 1]) || - ((selStart != selEnd) && ((iDoc + 1 == selStart) || (iDoc + 1 == selEnd))) || + IsControlCharacter(ll.chars[i]) || IsControlCharacter(ll.chars[i + 1]) || + ((selStart != selEnd) && ((iDoc + 1 == selStart) || (iDoc + 1 == selEnd))) || (i == (theEdge-1))) { int styleMain = ll.styles[i]; Colour textBack = vsDraw.styles[styleMain].back.allocated; @@ -840,22 +846,31 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, rcSegment.left = ll.positions[i] + xStart; rcSegment.right = ll.positions[i + 1] + xStart; surface->FillRectangle(rcSegment, textBack); - if (vsDraw.viewWhitespace) { - surface->PenColour(textFore); - if (inIndentation) { - if (ll.positions[i] > 0) { - surface->MoveTo(rcSegment.left + 1, rcSegment.top); - surface->LineTo(rcSegment.left + 1, rcSegment.bottom); - } - } else { - PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, - rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); - DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2); - } + if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) { + surface->PenColour(textFore); + } + if (inIndentation && vsDraw.viewIndentationGuides) { + for (int xIG = ll.positions[i] / indentWidth * indentWidth; xIG < ll.positions[i + 1]; xIG += indentWidth) { + if (xIG >= ll.positions[i] && xIG > 0) { + Point from(0, ((lineVisible & 1) && (vs.lineHeight & 1)) ? 1 : 0); + PRectangle rcCopyArea(xIG + xStart + 1, rcSegment.top, xIG + xStart + 2, rcSegment.bottom); + surface->Copy(rcCopyArea, from, (ll.xHighlightGuide == xIG) ? + pixmapIndentGuideHighlight : pixmapIndentGuide); + } + } + //if (ll.positions[i] > 0 && (ll.positions[i] % indentWidth == 0)) { + //} + } + if (vsDraw.viewWhitespace != wsInvisible) { + if (inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { + PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4, + rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent); + DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2); + } } // Manage control character display } else if (IsControlCharacter(ll.chars[i])) { - inIndentation = false; + inIndentation = false; const char *ctrlChar = ControlCharacterString(ll.chars[i]); rcSegment.left = ll.positions[i] + xStart; rcSegment.right = ll.positions[i + 1] + xStart; @@ -878,23 +893,38 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, textBack, textFore); // Manage normal display } else { - inIndentation = false; rcSegment.left = ll.positions[startseg] + xStart; rcSegment.right = ll.positions[i + 1] + xStart; // Only try to draw if really visible - enhances performance by not calling environment to // draw strings that are completely past the right side of the window. if (rcSegment.left <= rcLine.right) { surface->DrawText(rcSegment, textFont, - rcSegment.top + vsDraw.maxAscent, ll.chars + startseg, - i - startseg + 1, textFore, textBack); - if (vsDraw.viewWhitespace) { + rcSegment.top + vsDraw.maxAscent, ll.chars + startseg, + i - startseg + 1, textFore, textBack); + if (vsDraw.viewWhitespace != wsInvisible || + (inIndentation && vs.viewIndentationGuides)) { for (int cpos = 0; cpos <= i - startseg; cpos++) { if (ll.chars[cpos + startseg] == ' ') { - int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2; - PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0); - rcDot.right = rcDot.left + 1; - rcDot.bottom = rcDot.top + 1; - surface->FillRectangle(rcDot, textFore); + if (vsDraw.viewWhitespace != wsInvisible) { + if (inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { + int xmid = (ll.positions[cpos + startseg] + ll.positions[cpos + startseg + 1]) / 2; + PRectangle rcDot(xmid + xStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0); + rcDot.right = rcDot.left + 1; + rcDot.bottom = rcDot.top + 1; + surface->FillRectangle(rcDot, textFore); + } + } + if (inIndentation && vsDraw.viewIndentationGuides) { + int startSpace = ll.positions[cpos + startseg]; + if (startSpace > 0 && (startSpace % indentWidth == 0)) { + Point from(0, ((lineVisible & 1) && (vs.lineHeight & 1)) ? 1 : 0); + PRectangle rcCopyArea(startSpace + xStart + 1, rcSegment.top, startSpace + xStart + 2, rcSegment.bottom); + surface->Copy(rcCopyArea, from, (ll.xHighlightGuide == ll.positions[cpos + startseg]) ? + pixmapIndentGuideHighlight : pixmapIndentGuide); + } + } + } else { + inIndentation = false; } } } @@ -994,7 +1024,23 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { pixmapSelPattern.FillRectangle(rcPattern, vs.selbarlight.allocated); } } - + if (!pixmapIndentGuide.Initialised()) { + // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line + pixmapIndentGuide.InitPixMap(1, vs.lineHeight+1, surfaceWindow); + pixmapIndentGuideHighlight.InitPixMap(1, vs.lineHeight+1, surfaceWindow); + PRectangle rcIG(0, 0, 1, vs.lineHeight); + pixmapIndentGuide.FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated); + pixmapIndentGuide.PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated); + pixmapIndentGuideHighlight.FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); + pixmapIndentGuideHighlight.PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); + for (int stripe = 1; stripe < vs.lineHeight+1; stripe+=2) { + pixmapIndentGuide.MoveTo(0, stripe); + pixmapIndentGuide.LineTo(2, stripe); + pixmapIndentGuideHighlight.MoveTo(0, stripe); + pixmapIndentGuideHighlight.LineTo(2, stripe); + } + } + if (bufferedDraw) { if (!pixmapLine.Initialised()) { pixmapLine.InitPixMap(rcClient.Width(), rcClient.Height(), @@ -1096,10 +1142,14 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { if ((braces[1] >= posLineStart) && (braces[1] < posLineEnd)) ll.styles[braces[1] - posLineStart] = static_cast<char>(bracesMatchStyle); + if ((braces[0] >= posLineStart && braces[1] <= posLineEnd) || + (braces[1] >= posLineStart && braces[0] <= posLineEnd)) { + ll.xHighlightGuide = highlightGuideColumn * vs.spaceWidth; + } // Draw the line if (cs.GetVisible(line)) - DrawLine(surface, vs, line, xStart, rcLine, ll); + DrawLine(surface, vs, line, visibleLine, xStart, rcLine, ll); bool expanded = cs.GetExpanded(line); if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) { @@ -1293,7 +1343,7 @@ long Editor::FormatRange(bool draw, FORMATRANGE *pfr) { // Draw the line surface->FlushCachedState(); - DrawLine(surface, vsPrint, line, xStart, rcLine, ll); + DrawLine(surface, vsPrint, line, line, xStart, rcLine, ll); ypos += vsPrint.lineHeight; line++; @@ -2082,11 +2132,11 @@ int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt) { return KeyDefault(key, modifiers); } -void Editor::SetWhitespaceVisible(bool view) { - vs.viewWhitespace = view; +void Editor::SetWhitespaceVisible(int view) { + vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(view); } -bool Editor::GetWhitespaceVisible() { +int Editor::GetWhitespaceVisible() { return vs.viewWhitespace; } @@ -3318,10 +3368,10 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { return vs.viewWhitespace; case SCI_SETVIEWWS: - vs.viewWhitespace = wParam; + vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam); Redraw(); break; - + case SCI_GOTOLINE: GoToLine(wParam); break; @@ -3434,6 +3484,24 @@ LRESULT Editor::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { case SCI_GETHSCROLLBAR: return horizontalScrollBarVisible; + case SCI_SETINDENTATIONGUIDES: + vs.viewIndentationGuides = wParam; + Redraw(); + break; + + case SCI_GETINDENTATIONGUIDES: + return vs.viewIndentationGuides; + + case SCI_SETHIGHLIGHTGUIDE: + if (highlightGuideColumn != wParam) { + highlightGuideColumn = wParam; + Redraw(); + } + break; + + case SCI_GETHIGHLIGHTGUIDE: + return highlightGuideColumn; + case SCI_SETCODEPAGE: pdoc->dbcsCodePage = wParam; break; diff --git a/src/Editor.h b/src/Editor.h index 808a656be..73b0308c8 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -31,6 +31,8 @@ public: // Drawing is only performed for maxLineLength characters on each line. enum {maxLineLength = 4000}; int numCharsInLine; + int xHighlightGuide; + bool highlightColumn; char chars[maxLineLength]; char styles[maxLineLength]; char indicators[maxLineLength]; @@ -69,6 +71,8 @@ protected: // ScintillaBase subclass needs access to much of Editor Surface pixmapLine; Surface pixmapSelMargin; Surface pixmapSelPattern; + Surface pixmapIndentGuide; + Surface pixmapIndentGuideHighlight; // Intellimouse support - currently only implemented for Windows unsigned int ucWheelScrollLines; int cWheelDelta; //wheel delta from roll @@ -98,6 +102,7 @@ protected: // ScintillaBase subclass needs access to much of Editor bool needUpdateUI; Position braces[2]; int bracesMatchStyle; + int highlightGuideColumn; int edgeState; int theEdge; @@ -183,7 +188,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void PaintSelMargin(Surface *surface, PRectangle &rc); void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout &ll); - void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int xStart, + void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout &ll); void Paint(Surface *surfaceWindow, PRectangle rcArea); long FormatRange(bool draw, FORMATRANGE *pfr); @@ -241,8 +246,8 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual int KeyDefault(int /* key */, int /*modifiers*/); int KeyDown(int key, bool shift, bool ctrl, bool alt); - bool GetWhitespaceVisible(); - void SetWhitespaceVisible(bool view); + int GetWhitespaceVisible(); + void SetWhitespaceVisible(int view); void Indent(bool forwards); diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index 87b84f706..0f7d944fe 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -325,7 +325,7 @@ LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { break; case SCI_AUTOCSETSEPARATOR: - ac.SetSeparator(wParam); + ac.SetSeparator(static_cast<char>(wParam)); break; case SCI_AUTOCGETSEPARATOR: diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index 580ecc71f..fe2375018 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -83,6 +83,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) { fixedColumnWidth = source.fixedColumnWidth; zoomLevel = source.zoomLevel; viewWhitespace = source.viewWhitespace; + viewIndentationGuides = source.viewIndentationGuides; viewEOL = source.viewEOL; showMarkedLines = source.showMarkedLines; } @@ -142,7 +143,8 @@ void ViewStyle::Init() { maskInLine &= ~ms[margin].mask; } zoomLevel = 0; - viewWhitespace = false; + viewWhitespace = wsInvisible; + viewIndentationGuides = false; viewEOL = false; showMarkedLines = true; } diff --git a/src/ViewStyle.h b/src/ViewStyle.h index 4436e83ff..5660368ec 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -26,6 +26,7 @@ public: const char *Save(const char *name); }; +enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2}; class ViewStyle { public: FontNames fontNames; @@ -52,7 +53,8 @@ public: MarginStyle ms[margins]; int fixedColumnWidth; int zoomLevel; - bool viewWhitespace; + WhiteSpaceVisibility viewWhitespace; + bool viewIndentationGuides; bool viewEOL; bool showMarkedLines; ColourPair caretcolour; diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index a6dfb8dd6..48fe7f7b8 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -721,7 +721,7 @@ int Platform::Maximum(int a, int b) { return b; } -//#define TRACE +#define TRACE #ifdef TRACE void Platform::DebugPrintf(const char *format, ...) { diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 829b973fa..25af77f99 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -288,7 +288,12 @@ LRESULT ScintillaWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { break; case WM_PAINT: { - //CElapsed ce; ce.Begin(); + //CElapsed ce; ce.Begin(); + LARGE_INTEGER perfStart; + LARGE_INTEGER perfEnd; + LARGE_INTEGER performanceFreq; + QueryPerformanceFrequency(&performanceFreq); + QueryPerformanceCounter(&perfStart); paintState = painting; PAINTSTRUCT ps; BeginPaint(wMain.GetID(), &ps); @@ -311,7 +316,14 @@ LRESULT ScintillaWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { FullPaint(); } paintState = notPainting; - //Platform::DebugPrintf("Paint took %g\n", ce.End()); + QueryPerformanceCounter(&perfEnd); + __int64 start = perfStart.QuadPart; + __int64 end = perfEnd.QuadPart; + __int64 freq = performanceFreq.QuadPart; + __int64 dur = end - start; + double per = double(dur) / double(freq); + Platform::DebugPrintf("Paint took %5.03g\n", per); + //Platform::DebugPrintf("Paint took %g\n", ce.End()); } break; |