1
// Scintilla source code edit control
3
** Code for displaying call tips.
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.
13
#include "Scintilla.h"
18
inCallTipMode = false;
21
rectUp = PRectangle(0,0,0,0);
22
rectDown = PRectangle(0,0,0,0);
27
colourBG.desired = ColourDesired(0xff, 0xff, 0xff);
28
colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80);
29
colourSel.desired = ColourDesired(0, 0, 0x80);
30
colourShade.desired = ColourDesired(0, 0, 0);
31
colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0);
41
const int widthArrow = 14;
43
void CallTip::RefreshColourPalette(Palette &pal, bool want) {
44
pal.WantFind(colourBG, want);
45
pal.WantFind(colourUnSel, want);
46
pal.WantFind(colourSel, want);
47
pal.WantFind(colourShade, want);
48
pal.WantFind(colourLight, want);
51
static bool IsArrowCharacter(char ch) {
52
return (ch == 0) || (ch == '\001') || (ch == '\002');
55
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
56
int posStart, int posEnd, int ytext, PRectangle rcClient,
57
bool highlight, bool draw) {
59
int len = posEnd - posStart;
62
for (int i=0;i<len;i++) {
63
if (IsArrowCharacter(s[i])) {
72
for (int seg = 0; seg<maxEnd; seg++) {
73
int endSeg = ends[seg];
74
if (endSeg > startSeg) {
75
if (IsArrowCharacter(s[startSeg])) {
76
xEnd = x + widthArrow;
79
rcClient.right = xEnd;
81
const int halfWidth = widthArrow / 2 - 3;
82
const int centreX = x + widthArrow / 2 - 1;
83
const int centreY = (rcClient.top + rcClient.bottom) / 2;
84
surface->FillRectangle(rcClient, colourBG.allocated);
85
PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
86
surface->FillRectangle(rcClientInner, colourUnSel.allocated);
88
if (s[startSeg] == '\001') {
91
Point(centreX - halfWidth, centreY + halfWidth / 2),
92
Point(centreX + halfWidth, centreY + halfWidth / 2),
93
Point(centreX, centreY - halfWidth + halfWidth / 2),
95
surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
96
colourBG.allocated, colourBG.allocated);
100
Point(centreX - halfWidth, centreY - halfWidth / 2),
101
Point(centreX + halfWidth, centreY - halfWidth / 2),
102
Point(centreX, centreY + halfWidth - halfWidth / 2),
104
surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
105
colourBG.allocated, colourBG.allocated);
108
if (s[startSeg] == '\001') {
110
} else if (s[startSeg] == '\002') {
114
xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
117
rcClient.right = xEnd;
118
surface->DrawTextNoClip(rcClient, font, ytext,
119
s+startSeg, endSeg - startSeg,
120
highlight ? colourSel.allocated : colourUnSel.allocated,
130
int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
131
PRectangle rcClientPos = wCallTip.GetClientPosition();
132
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
133
rcClientPos.bottom - rcClientPos.top);
134
PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
136
// To make a nice small call tip window, it is only sized to fit most normal characters without accents
137
int ascent = surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font);
140
// Draw the definition in three parts: before highlight, highlighted, after highlight
141
int ytext = rcClient.top + ascent + 1;
142
rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
143
char *chunkVal = val;
144
bool moreChunks = true;
147
char *chunkEnd = strchr(chunkVal, '\n');
148
if (chunkEnd == NULL) {
149
chunkEnd = chunkVal + strlen(chunkVal);
152
int chunkOffset = chunkVal - val;
153
int chunkLength = chunkEnd - chunkVal;
154
int chunkEndOffset = chunkOffset + chunkLength;
155
int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
156
thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
157
thisStartHighlight -= chunkOffset;
158
int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
159
thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
160
thisEndHighlight -= chunkOffset;
161
rcClient.top = ytext - ascent - 1;
165
DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
166
ytext, rcClient, false, draw);
167
DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
168
ytext, rcClient, true, draw);
169
DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
170
ytext, rcClient, false, draw);
172
chunkVal = chunkEnd + 1;
174
rcClient.bottom += lineHeight;
175
maxWidth = Platform::Maximum(maxWidth, x);
180
void CallTip::PaintCT(Surface *surfaceWindow) {
183
PRectangle rcClientPos = wCallTip.GetClientPosition();
184
PRectangle rcClientSize(0, 0, rcClientPos.right - rcClientPos.left,
185
rcClientPos.bottom - rcClientPos.top);
186
PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1);
188
surfaceWindow->FillRectangle(rcClient, colourBG.allocated);
191
PaintContents(surfaceWindow, true);
193
// Draw a raised border around the edges of the window
194
surfaceWindow->MoveTo(0, rcClientSize.bottom - 1);
195
surfaceWindow->PenColour(colourShade.allocated);
196
surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1);
197
surfaceWindow->LineTo(rcClientSize.right - 1, 0);
198
surfaceWindow->PenColour(colourLight.allocated);
199
surfaceWindow->LineTo(0, 0);
200
surfaceWindow->LineTo(0, rcClientSize.bottom - 1);
203
void CallTip::MouseClick(Point pt) {
205
if (rectUp.Contains(pt))
207
if (rectDown.Contains(pt))
211
PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
212
const char *faceName, int size,
213
int codePage_, int characterSet, Window &wParent) {
217
val = new char[strlen(defn) + 1];
221
codePage = codePage_;
222
Surface *surfaceMeasure = Surface::Allocate();
225
surfaceMeasure->Init(wParent.GetID());
226
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
227
surfaceMeasure->SetDBCSMode(codePage);
230
inCallTipMode = true;
231
posStartCallTip = pos;
232
int deviceHeight = surfaceMeasure->DeviceHeightFont(size);
233
font.Create(faceName, characterSet, deviceHeight, false, false);
234
// Look for multiple lines in the text
235
// Only support \n here - simply means container must avoid \r!
238
const char *look = val;
239
rectUp = PRectangle(0,0,0,0);
240
rectDown = PRectangle(0,0,0,0);
242
int width = PaintContents(surfaceMeasure, false) + 5;
243
while ((newline = strchr(look, '\n')) != NULL) {
247
lineHeight = surfaceMeasure->Height(font);
248
// Extra line for border and an empty line at top and bottom
249
int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2;
250
delete surfaceMeasure;
251
return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height);
254
void CallTip::CallTipCancel() {
255
inCallTipMode = false;
256
if (wCallTip.Created()) {
261
void CallTip::SetHighlight(int start, int end) {
262
// Avoid flashing by checking something has really changed
263
if ((start != startHighlight) || (end != endHighlight)) {
264
startHighlight = start;
266
if (wCallTip.Created()) {
267
wCallTip.InvalidateAll();