geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

CallTip.cxx
Go to the documentation of this file.
1// Scintilla source code edit control
2/** @file CallTip.cxx
3 ** Code for displaying call tips.
4 **/
5// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6// The License.txt file describes the conditions under which this software may be distributed.
7
8#include <cstddef>
9#include <cstdlib>
10#include <cassert>
11#include <cstring>
12#include <cstdio>
13#include <cmath>
14
15#include <stdexcept>
16#include <string>
17#include <vector>
18#include <algorithm>
19#include <memory>
20
21#include "Platform.h"
22
23#include "Scintilla.h"
24
25#include "Position.h"
26#include "IntegerRectangle.h"
27#include "CallTip.h"
28
29using namespace Scintilla;
30
31size_t Chunk::Length() const noexcept {
32 return end - start;
33}
34
35CallTip::CallTip() noexcept {
36 wCallTip = {};
37 inCallTipMode = false;
39 rectUp = PRectangle(0,0,0,0);
40 rectDown = PRectangle(0,0,0,0);
41 lineHeight = 1;
42 offsetMain = 0;
43 tabSize = 0;
44 above = false;
45 useStyleCallTip = false; // for backwards compatibility
46
47 insetX = 5;
48 widthArrow = 14;
49 borderHeight = 2; // Extra line for border and an empty line at top and bottom.
51
52#ifdef __APPLE__
53 // proper apple colours for the default
54 colourBG = ColourDesired(0xff, 0xff, 0xc6);
55 colourUnSel = ColourDesired(0, 0, 0);
56#else
57 colourBG = ColourDesired(0xff, 0xff, 0xff);
58 colourUnSel = ColourDesired(0x80, 0x80, 0x80);
59#endif
60 colourSel = ColourDesired(0, 0, 0x80);
61 colourShade = ColourDesired(0, 0, 0);
62 colourLight = ColourDesired(0xc0, 0xc0, 0xc0);
63 codePage = 0;
64 clickPlace = 0;
65}
66
68 font.Release();
70}
71
72// We ignore tabs unless a tab width has been set.
73bool CallTip::IsTabCharacter(char ch) const noexcept {
74 return (tabSize > 0) && (ch == '\t');
75}
76
77int CallTip::NextTabPos(int x) const noexcept {
78 if (tabSize > 0) { // paranoia... not called unless this is true
79 x -= insetX; // position relative to text
80 x = (x + tabSize) / tabSize; // tab "number"
81 return tabSize*x + insetX; // position of next tab
82 } else {
83 return x + 1; // arbitrary
84 }
85}
86
87namespace {
88
89// Although this test includes 0, we should never see a \0 character.
90constexpr bool IsArrowCharacter(char ch) noexcept {
91 return (ch == 0) || (ch == '\001') || (ch == '\002');
92}
93
94void DrawArrow(Scintilla::Surface *surface, const PRectangle &rc, bool upArrow, ColourDesired colourBG, ColourDesired colourUnSel) {
95 surface->FillRectangle(rc, colourBG);
96 const int width = static_cast<int>(rc.Width());
97 const int halfWidth = width / 2 - 3;
98 const int quarterWidth = halfWidth / 2;
99 const int centreX = static_cast<int>(rc.left) + width / 2 - 1;
100 const int centreY = static_cast<int>(rc.top + rc.bottom) / 2;
101 const PRectangle rcClientInner(rc.left + 1, rc.top + 1, rc.right - 2, rc.bottom - 1);
102 surface->FillRectangle(rcClientInner, colourUnSel);
103
104 if (upArrow) { // Up arrow
105 Point pts[] = {
106 Point::FromInts(centreX - halfWidth, centreY + quarterWidth),
107 Point::FromInts(centreX + halfWidth, centreY + quarterWidth),
108 Point::FromInts(centreX, centreY - halfWidth + quarterWidth),
109 };
110 surface->Polygon(pts, Sci::size(pts), colourBG, colourBG);
111 } else { // Down arrow
112 Point pts[] = {
113 Point::FromInts(centreX - halfWidth, centreY - quarterWidth),
114 Point::FromInts(centreX + halfWidth, centreY - quarterWidth),
115 Point::FromInts(centreX, centreY + halfWidth - quarterWidth),
116 };
117 surface->Polygon(pts, Sci::size(pts), colourBG, colourBG);
118 }
119}
120
121}
122
123// Draw a section of the call tip that does not include \n in one colour.
124// The text may include tabs or arrow characters.
125int CallTip::DrawChunk(Surface *surface, int x, const char *s, size_t len,
126 int ytext, PRectangle rcClient, bool asHighlight, bool draw) {
127 if (len == 0) {
128 return x;
129 }
130
131 // Divide the text into sections that are all text, or that are
132 // single arrows or single tab characters (if tabSize > 0).
133 // Start with single element 0 to simplify append checks.
134 std::vector<size_t> ends(1);
135 for (size_t i=0; i<len; i++) {
136 if (IsArrowCharacter(s[i]) || IsTabCharacter(s[i])) {
137 if (ends.back() != i)
138 ends.push_back(i);
139 ends.push_back(i+1);
140 }
141 }
142 if (ends.back() != len)
143 ends.push_back(len);
144 ends.erase(ends.begin()); // Remove initial 0.
145
146 size_t startSeg = 0;
147 for (const size_t endSeg : ends) {
148 assert(endSeg > 0);
149 int xEnd;
150 if (IsArrowCharacter(s[startSeg])) {
151 xEnd = x + widthArrow;
152 const bool upArrow = s[startSeg] == '\001';
153 rcClient.left = static_cast<XYPOSITION>(x);
154 rcClient.right = static_cast<XYPOSITION>(xEnd);
155 if (draw) {
156 DrawArrow(surface, rcClient, upArrow, colourBG, colourUnSel);
157 }
158 offsetMain = xEnd;
159 if (upArrow) {
160 rectUp = rcClient;
161 } else {
162 rectDown = rcClient;
163 }
164 } else if (IsTabCharacter(s[startSeg])) {
165 xEnd = NextTabPos(x);
166 } else {
167 const char *segText = s + startSeg;
168 xEnd = x + static_cast<int>(Sci::lround(surface->WidthText(font, segText, endSeg - startSeg)));
169 if (draw) {
170 rcClient.left = static_cast<XYPOSITION>(x);
171 rcClient.right = static_cast<XYPOSITION>(xEnd);
172 surface->DrawTextTransparent(rcClient, font, static_cast<XYPOSITION>(ytext),
173 segText, endSeg - startSeg,
174 asHighlight ? colourSel : colourUnSel);
175 }
176 }
177 x = xEnd;
178 startSeg = endSeg;
179 }
180 return x;
181}
182
183int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
184 const PRectangle rcClientPos = wCallTip.GetClientPosition();
185 const PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left,
186 rcClientPos.bottom - rcClientPos.top);
187 PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1);
188
189 // To make a nice small call tip window, it is only sized to fit most normal characters without accents
190 const int ascent = static_cast<int>(Sci::round(surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font)));
191
192 // For each line...
193 // Draw the definition in three parts: before highlight, highlighted, after highlight
194 int ytext = static_cast<int>(rcClient.top) + ascent + 1;
195 rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
196 const char *remaining = val.c_str();
197 int maxWidth = 0;
198 size_t lineStart = 0;
199 while (*remaining) {
200 const char *chunkVal = remaining;
201 const char *chunkEnd = strchr(remaining, '\n');
202 if (!chunkEnd) {
203 chunkEnd = chunkVal + strlen(chunkVal);
204 }
205 const size_t chunkLength = static_cast<size_t>(chunkEnd - chunkVal);
206 remaining += chunkLength;
207 if (*remaining) {
208 remaining++; // Skip \n
209 }
210
211 const Chunk chunkLine(lineStart, lineStart + chunkLength);
212 Chunk chunkHighlight(
213 Sci::clamp(highlight.start, chunkLine.start, chunkLine.end),
214 Sci::clamp(highlight.end, chunkLine.start, chunkLine.end)
215 );
216 chunkHighlight.start -= lineStart;
217 chunkHighlight.end -= lineStart;
218
219 rcClient.top = static_cast<XYPOSITION>(ytext - ascent - 1);
220
221 int x = insetX; // start each line at this inset
222
223 x = DrawChunk(surfaceWindow, x, chunkVal, chunkHighlight.start,
224 ytext, rcClient, false, draw);
225 x = DrawChunk(surfaceWindow, x, chunkVal + chunkHighlight.start, chunkHighlight.Length(),
226 ytext, rcClient, true, draw);
227 x = DrawChunk(surfaceWindow, x, chunkVal + chunkHighlight.end, chunkLength - chunkHighlight.end,
228 ytext, rcClient, false, draw);
229
230 ytext += lineHeight;
231 rcClient.bottom += lineHeight;
232 maxWidth = std::max(maxWidth, x);
233 lineStart += chunkLength + 1;
234 }
235 return maxWidth;
236}
237
238void CallTip::PaintCT(Surface *surfaceWindow) {
239 if (val.empty())
240 return;
241 const PRectangle rcClientPos = wCallTip.GetClientPosition();
242 const PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left,
243 rcClientPos.bottom - rcClientPos.top);
244 const PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1);
245
246 surfaceWindow->FillRectangle(rcClient, colourBG);
247
248 offsetMain = insetX; // initial alignment assuming no arrows
249 PaintContents(surfaceWindow, true);
250
251#ifndef __APPLE__
252 // OSX doesn't put borders on "help tags"
253 // Draw a raised border around the edges of the window
254 const IntegerRectangle ircClientSize(rcClientSize);
255 surfaceWindow->MoveTo(0, ircClientSize.bottom - 1);
256 surfaceWindow->PenColour(colourShade);
257 surfaceWindow->LineTo(ircClientSize.right - 1, ircClientSize.bottom - 1);
258 surfaceWindow->LineTo(ircClientSize.right - 1, 0);
259 surfaceWindow->PenColour(colourLight);
260 surfaceWindow->LineTo(0, 0);
261 surfaceWindow->LineTo(0, ircClientSize.bottom - 1);
262#endif
263}
264
265void CallTip::MouseClick(Point pt) noexcept {
266 clickPlace = 0;
267 if (rectUp.Contains(pt))
268 clickPlace = 1;
269 if (rectDown.Contains(pt))
270 clickPlace = 2;
271}
272
273PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
274 const char *faceName, int size,
275 int codePage_, int characterSet,
276 int technology, const Window &wParent) {
277 clickPlace = 0;
278 val = defn;
279 codePage = codePage_;
280 std::unique_ptr<Surface> surfaceMeasure(Surface::Allocate(technology));
281 surfaceMeasure->Init(wParent.GetID());
282 surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
283 surfaceMeasure->SetDBCSMode(codePage);
284 highlight = Chunk();
285 inCallTipMode = true;
287 const XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size));
288 const FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet);
289 font.Create(fp);
290 // Look for multiple lines in the text
291 // Only support \n here - simply means container must avoid \r!
292 const int numLines = 1 + static_cast<int>(std::count(val.begin(), val.end(), '\n'));
293 rectUp = PRectangle(0,0,0,0);
294 rectDown = PRectangle(0,0,0,0);
295 offsetMain = insetX; // changed to right edge of any arrows
296 const int width = PaintContents(surfaceMeasure.get(), false) + insetX;
297 lineHeight = static_cast<int>(Sci::lround(surfaceMeasure->Height(font)));
298
299 // The returned
300 // rectangle is aligned to the right edge of the last arrow encountered in
301 // the tip text, else to the tip text left edge.
302 const int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font)) + borderHeight * 2;
303 if (above) {
304 return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset);
305 } else {
306 return PRectangle(pt.x - offsetMain, pt.y + verticalOffset + textHeight, pt.x + width - offsetMain, pt.y + verticalOffset + textHeight + height);
307 }
308}
309
311 inCallTipMode = false;
312 if (wCallTip.Created()) {
314 }
315}
316
317void CallTip::SetHighlight(size_t start, size_t end) {
318 // Avoid flashing by checking something has really changed
319 if ((start != highlight.start) || (end != highlight.end)) {
320 highlight.start = start;
321 highlight.end = (end > start) ? end : start;
322 if (wCallTip.Created()) {
324 }
325 }
326}
327
328// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
329// use of the STYLE_CALLTIP.
330void CallTip::SetTabSize(int tabSz) noexcept {
331 tabSize = tabSz;
332 useStyleCallTip = true;
333}
334
335// Set the calltip position, below the text by default or if above is false
336// else above the text.
337void CallTip::SetPosition(bool aboveText) noexcept {
338 above = aboveText;
339}
340
341bool CallTip::UseStyleCallTip() const noexcept {
342 return useStyleCallTip;
343}
344
345// It might be better to have two access functions for this and to use
346// them for all settings of colours.
347void CallTip::SetForeBack(const ColourDesired &fore, const ColourDesired &back) noexcept {
348 colourBG = back;
349 colourUnSel = fore;
350}
Interface to the call tip control.
A rectangle with integer coordinates.
Interface to platform facilities.
Defines global type name Position in the Sci internal namespace.
Interface to the edit control.
#define SC_WEIGHT_NORMAL
Definition: Scintilla.h:260
#define SC_FONT_SIZE_MULTIPLIER
Definition: Scintilla.h:257
#define SC_CP_UTF8
Definition: Scintilla.h:105
int DrawChunk(Surface *surface, int x, const char *s, size_t len, int ytext, PRectangle rcClient, bool asHighlight, bool draw)
Definition: CallTip.cxx:125
Sci::Position posStartCallTip
Definition: CallTip.h:46
bool UseStyleCallTip() const noexcept
Used to determine which STYLE_xxxx to use for call tip information.
Definition: CallTip.cxx:341
void PaintCT(Surface *surfaceWindow)
Definition: CallTip.cxx:238
ColourDesired colourBG
Definition: CallTip.h:47
CallTip() noexcept
Definition: CallTip.cxx:35
void SetPosition(bool aboveText) noexcept
Set calltip position.
Definition: CallTip.cxx:337
int NextTabPos(int x) const noexcept
Definition: CallTip.cxx:77
PRectangle CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn, const char *faceName, int size, int codePage_, int characterSet, int technology, const Window &wParent)
Setup the calltip and return a rectangle of the area required.
Definition: CallTip.cxx:273
ColourDesired colourLight
Definition: CallTip.h:51
bool IsTabCharacter(char ch) const noexcept
Definition: CallTip.cxx:73
ColourDesired colourShade
Definition: CallTip.h:50
bool useStyleCallTip
Definition: CallTip.h:33
bool inCallTipMode
Definition: CallTip.h:45
void SetForeBack(const ColourDesired &fore, const ColourDesired &back) noexcept
Definition: CallTip.cxx:347
void SetTabSize(int tabSz) noexcept
Set the tab size in pixels for the call tip. 0 or -ve means no tab expand.
Definition: CallTip.cxx:330
PRectangle rectUp
Definition: CallTip.h:28
ColourDesired colourUnSel
Definition: CallTip.h:48
std::string val
Definition: CallTip.h:26
Window wCallTip
Definition: CallTip.h:43
void SetHighlight(size_t start, size_t end)
Set a range of characters to be displayed in a highlight style.
Definition: CallTip.cxx:317
int PaintContents(Surface *surfaceWindow, bool draw)
Definition: CallTip.cxx:183
void CallTipCancel()
Definition: CallTip.cxx:310
PRectangle rectDown
Definition: CallTip.h:29
void MouseClick(Point pt) noexcept
Definition: CallTip.cxx:265
ColourDesired colourSel
Definition: CallTip.h:49
virtual void Create(const FontParameters &fp)
Definition: PlatGTK.cxx:123
virtual void Release()
Definition: PlatGTK.cxx:128
A geometric rectangle class.
Definition: Platform.h:131
XYPOSITION right
Definition: Platform.h:135
constexpr XYPOSITION Width() const noexcept
Definition: Platform.h:176
XYPOSITION bottom
Definition: Platform.h:136
A geometric point class.
Definition: Platform.h:99
static constexpr Point FromInts(int x_, int y_) noexcept
Definition: Platform.h:107
XYPOSITION y
Definition: Platform.h:102
XYPOSITION x
Definition: Platform.h:101
A surface abstracts a place to draw.
Definition: Platform.h:340
virtual XYPOSITION Descent(Font &font_)=0
static Surface * Allocate(int technology)
Definition: PlatGTK.cxx:964
virtual void PenColour(ColourDesired fore)=0
virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0
virtual void Polygon(Point *pts, size_t npts, ColourDesired fore, ColourDesired back)=0
virtual void MoveTo(int x_, int y_)=0
virtual XYPOSITION Ascent(Font &font_)=0
virtual void LineTo(int x_, int y_)=0
virtual void FillRectangle(PRectangle rc, ColourDesired back)=0
virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0
virtual XYPOSITION InternalLeading(Font &font_)=0
Class to hide the details of window manipulation.
Definition: Platform.h:396
bool Created() const noexcept
Definition: Platform.h:413
PRectangle GetClientPosition() const
Definition: PlatGTK.cxx:1059
WindowID GetID() const noexcept
Definition: Platform.h:412
void InvalidateAll()
Definition: PlatGTK.cxx:1069
gint pos
Definition: editor.c:87
unsigned int count
unsigned int max
ptrdiff_t Position
Definition: Position.h:19
Styling buffer using one element for each run rather than using a filled buffer.
Definition: Converter.h:9
float XYPOSITION
Definition: Platform.h:81
size_t Length() const noexcept
Definition: CallTip.cxx:31
size_t start
Definition: CallTip.h:14
size_t end
Definition: CallTip.h:15
Font management.
Definition: Platform.h:285