Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGHtmlIndex.cxx
Go to the documentation of this file.
1// $Id: TGHtmlIndex.cxx,v 1.2 2007/05/20 23:22:13 rdm Exp $
2// Author: Valeriy Onuchin 03/05/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**************************************************************************
13
14 HTML widget for xclass. Based on tkhtml 1.28
15 Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
16 Copyright (C) 2002-2003 Hector Peraza.
17
18 This library is free software; you can redistribute it and/or
19 modify it under the terms of the GNU Library General Public
20 License as published by the Free Software Foundation; either
21 version 2 of the License, or (at your option) any later version.
22
23 This library is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 Library General Public License for more details.
27
28 You should have received a copy of the GNU Library General Public
29 License along with this library; if not, write to the Free
30 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
32**************************************************************************/
33
34// Routines that deal with indexes
35
36#include <cctype>
37#include <cstring>
38#include <cstdlib>
39
40#include "TGHtml.h"
41#include "strlcpy.h"
42
43////////////////////////////////////////////////////////////////////////////////
44/// Return a pointer to the Nth TGHtmlElement in the list. If there
45/// is no Nth element, return 0 if flag==0 and return either the first
46/// or last element (whichever is closest) if flag!=0
47
49{
51
52 if (N == 0) return fPFirst;
53
54 if (N > fNToken / 2) {
55 // Start at the end and work back toward the beginning
56 for (p = fPLast; p; p = p->fPPrev) {
57 if (p->fType != Html_Block) {
58 if (p->fElId == N) break;
59 }
60 }
61 } else {
62 // Start at the beginning and work forward
63 for (p = fPFirst; p; p = p->fPNext) {
64 if (p->fType != Html_Block) {
65 --N;
66 if (N == p->fElId) break;
67 }
68 }
69 }
70
71 return p;
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Return the token number for the given TGHtmlElement
76
78{
79 //int n = 0;
80
81 if (!p) return -1;
82 return p->fElId;
83
84/// while (p) {
85/// if (p->fType != Html_Block) ++n;
86/// p = p->fPPrev;
87/// }
88///
89/// return n;
90}
91
92////////////////////////////////////////////////////////////////////////////////
93/// Find the maximum index for the given token
94
95void TGHtml::MaxIndex(TGHtmlElement *p, int *pIndex, int isLast)
96{
97 if (p == 0) {
98 *pIndex = 0;
99 } else {
100 switch (p->fType) {
101 case Html_Text:
102 *pIndex = p->fCount - isLast;
103 break;
104
105 case Html_Space:
106 if (p->fStyle.fFlags & STY_Preformatted) {
107 *pIndex = p->fCount - isLast;
108 } else {
109 *pIndex = 0;
110 }
111 break;
112
113 default:
114 *pIndex = 0;
115 break;
116 }
117 }
118}
119
120////////////////////////////////////////////////////////////////////////////////
121/// Given a Block and an x coordinate, find the Index of the character
122/// that is closest to the given x coordinate.
123///
124/// The x-coordinate might specify a point to the left of the block,
125/// in which case the procedure returns the first token and a character
126/// index of 0. Or the x-coordinate might specify a point to the right
127/// of the block, in which case the last token is returned with an index
128/// equal to its last character.
129
132{
134 TGFont *font;
135 int len;
136 int n;
137
138 p = pBlock->fPNext;
139 font = GetFont(p->fStyle.fFont);
140 if (x <= pBlock->fLeft) {
141 *ppToken = p;
142 *pIndex = 0;
143 return;
144 } else if (x >= pBlock->fRight) {
145 *ppToken = p;
146 *pIndex = 0;
147 while (p && p->fType != Html_Block) {
148 *ppToken = p;
149 p = p->fPNext;
150 }
151 p = *ppToken;
152 if (p && p->fType == Html_Text) {
153 *pIndex = p->fCount - 1;
154 }
155 return;
156 }
157 if (pBlock->fN == 0) {
158 *ppToken = p;
159 *pIndex = 0;
160 }
161 n = font->MeasureChars(pBlock->fZ, pBlock->fN, x - pBlock->fLeft, 0, &len);
162 *pIndex = 0;
163 *ppToken = 0;
164 while (p && n >= 0) {
165 switch (p->fType) {
166 case Html_Text:
167 if (n < p->fCount) {
168 *pIndex = n;
169 } else {
170 *pIndex = p->fCount - 1;
171 }
172 *ppToken = p;
173 n -= p->fCount;
174 break;
175
176 case Html_Space:
177 if (p->fStyle.fFlags & STY_Preformatted) {
178 if (n < p->fCount) {
179 *pIndex = n;
180 } else {
181 *pIndex = p->fCount - 1;
182 }
183 *ppToken = p;
184 n -= p->fCount;
185 } else {
186 *pIndex = 0;
187 *ppToken = p;
188 --n;
189 }
190 break;
191
192 default:
193 break;
194 }
195 if (p) p = p->fPNext;
196 }
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Convert an Element-based index into a Block-based index.
201///
202/// In other words, given a pointer to an element and an index
203/// of a particular character within that element, compute a
204/// pointer to the TGHtmlBlock used to display that character and
205/// the index in the TGHtmlBlock of the character.
206
209{
210 int n = sIndex.fI;
212
213 if (sIndex.fP == 0) {
214 *ppBlock = 0;
215 *piIndex = 0;
216 return;
217 }
218 p = sIndex.fP->fPPrev;
219 while (p && p->fType != Html_Block) {
220 switch (p->fType) {
221 case Html_Text:
222 n += p->fCount;
223 break;
224 case Html_Space:
225 if (p->fStyle.fFlags & STY_Preformatted) {
226 n += p->fCount;
227 } else {
228 n++;
229 }
230 break;
231 default:
232 break;
233 }
234 p = p->fPPrev;
235 }
236 if (p) {
237 *ppBlock = (TGHtmlBlock *) p;
238 *piIndex = n;
239 return;
240 }
241 for (p = sIndex.fP; p && p->fType != Html_Block; p = p->fPNext) {}
242 *ppBlock = (TGHtmlBlock *) p;
243 *piIndex = 0;
244}
245
246////////////////////////////////////////////////////////////////////////////////
247/// Modify an index for both pointer and char +/-/=N
248
249int TGHtml::IndexMod(TGHtmlElement **pp, int *ip, char *cp)
250{
251 char nbuf[50];
252 int i, x, cnt, ccnt[2], cflag[2];
253
254 if (pp == 0 || !*pp) return -1;
255 ccnt[0] = ccnt[1] = cflag[0] = cflag[1] = 0;
256 x = 0;
257 while (*cp && x < 2) {
258 cnt = 0;
259 i = 1;
260 while (i < 45 && isdigit(cp[i])) {
261 nbuf[i-1] = cp[i];
262 i++;
263 }
264 if (i > 1) {
265 nbuf[i-1] = 0;
266 cnt = atoi(nbuf);
267 if (cnt < 0) return -1;
268 }
269 switch (*cp) {
270 case '+': if (i == 1) ccnt[x] = 1; else ccnt[x] = cnt; break;
271 case '-': if (i == 1) ccnt[x] = -1; else ccnt[x] = -cnt; break;
272 case '=': ccnt[x] = 0; cflag[x] = 1; break;
273 default: return -1;
274 }
275 cp += i;
276 ++x;
277 }
278 if (ccnt[0] > 0) {
279 for (i = 0; i < ccnt[0] && (*pp)->fPNext; ++i) {
280 *pp = (*pp)->fPNext;
281 while ((*pp)->fType == Html_Block && (*pp)->fPNext) {
282 *pp = (*pp)->fPNext;
283 }
284 }
285 } else if (ccnt[0] < 0) {
286 for (i = 0; ccnt[0] < i && (*pp)->fPPrev; --i) {
287 //printf("i=%d, cnt=%d\n", i, ccnt[0]);
288 *pp = (*pp)->fPPrev;
289 while ((*pp)->fType == Html_Block && (*pp)->fPPrev) {
290 *pp = (*pp)->fPPrev;
291 }
292 }
293 }
294 if (ccnt[1] > 0) {
295 for (i = 0; i < ccnt[1]; ++i) (*ip)++;
296 } else if (ccnt[1] < 0) {
297 for (i = 0; i > ccnt[1]; --i) (*ip)--;
298 }
299 return 0;
300}
301
302////////////////////////////////////////////////////////////////////////////////
303/// Given a base index name (without any modifiers) return a pointer
304/// to the token described, and the character within that token.
305///
306/// Valid input forms include:
307///
308/// N.M Token number N (with numbering starting at 1) and
309/// character number M (with numbering starting at 0).
310///
311/// M.X Like above, but token is markup and X is an attribute.
312///
313/// begin The start of all text
314///
315/// end The end of all text
316///
317/// N.last Last character of token number N.
318///
319/// N.end One past last character of token number N.
320///
321/// sel.first First character of the selection.
322///
323/// sel.last Last character of the selection.
324///
325/// sel.end On past last character of the selection.
326///
327/// insert The character holding the insertion cursor.
328///
329/// @X,Y The character a location X,Y of the clipping window.
330///
331/// &DOM The DOM Address of a token.
332///
333/// Zero is returned if we are successful and non-zero if there is
334/// any kind of error.
335///
336/// If the given token doesn't exist (for example if there are only 10
337/// tokens and 11.5 is requested) then *ppToken is left pointing to NULL.
338/// But the function still returns 0 for success.
339
342{
343 int i, n, x, y;
344 TGHtmlElement *p = 0;
347 int dist = 1000000;
348 int rc = 0;
349 char buf[200], *base = buf, *suffix, *ep;
350
351 strlcpy(buf, baseIx, sizeof(buf));
352
353 while (isspace((unsigned char)*base)) base++;
354 ep = base;
355 while (*ep && !isspace((unsigned char)*ep)) ep++;
356 *ep = 0;
357
358 if ((suffix = strchr(base, ':'))) *suffix = 0;
359
360 switch (*base) {
361 case '1': case '2': case '3': case '4': case '5':
362 case '6': case '7': case '8': case '9': case '0':
363 // coverity[secure_coding]
364 n = sscanf(base, "%d.%d", &x, &y);
365 if (n > 0) {
366 p = *ppToken = TokenByIndex(x, 0);
367 }
368 if (n == 2) {
369 *pIndex = y;
370 } else {
371 for (i = 1; isdigit(base[i]); ++i) {}
372 if (base[i] == 0) {
373 *pIndex = 0;
374 } else if (strcmp(&base[i], ".last") == 0) {
375 MaxIndex(p, pIndex, 1);
376 } else if (strcmp(&base[i], ".end") == 0) {
377 MaxIndex(p, pIndex, 0);
378 (*pIndex)++;
379 } else {
380 if (n == 1 && p && p->IsMarkup() && base[i] == '.' &&
381 p->MarkupArg(fZBase + i + 1, 0)) {
382 *pIndex = 0;
383 } else {
384 rc = 1;
385 }
386 }
387 }
388 break;
389
390 case 'b':
391 if (strcmp(base, "begin") == 0) {
392 *ppToken = fPFirst;
393 *pIndex = 0;
394 } else {
395 rc = 1;
396 }
397 break;
398
399 case 'e':
400 if (strcmp(base, "end") == 0) {
401 p = *ppToken = fPLast;
402 MaxIndex(p, pIndex, 0);
403 } else {
404 rc = 1;
405 }
406 break;
407
408 case 'l':
409 if (strcmp(base, "last") == 0) {
410 p = *ppToken = fPLast;
411 MaxIndex(p, pIndex, 1);
412 } else {
413 rc = 1;
414 }
415 break;
416
417 case 's':
418 if (strcmp(base, "sel.first") == 0) {
421 } else if (strcmp(base, "sel.last") == 0) {
422 *ppToken = fSelEnd.fP;
423 *pIndex = fSelEnd.fI;
424 } else if (strcmp(base, "sel.end") == 0) {
425 *ppToken = fSelEnd.fP;
426 *pIndex = fSelEnd.fI + 1;
427 } else {
428 rc = 1;
429 }
430 break;
431
432 case 'i':
433 if (strcmp(baseIx, "insert") == 0) {
434 *ppToken = fIns.fP;
435 *pIndex = fIns.fI;
436 } else {
437 rc = 1;
438 }
439 break;
440
441#if 0
442 case '&':
443 *pIndex = 0;
444 if (DomIdLookup("id", base + 1, ppToken)) rc = 1;
445 break;
446#endif
447
448 case '@':
449 n = sscanf(base, "@%d,%d", &x, &y);
450 if (n != 2) {
451 rc = 1;
452 break;
453 }
454 x += fVisible.fX;
455 y += fVisible.fY;
456 pNearby = 0;
457 *ppToken = fPLast;
458 *pIndex = 0;
459 for (pBlock = fFirstBlock; pBlock; pBlock = pBlock->fBNext) {
460 int dotest;
461 if (pBlock->fN == 0) {
462 switch (pBlock->fPNext->fType) {
463 case Html_LI:
464 case Html_IMG:
465 case Html_INPUT:
466 case Html_TEXTAREA:
467 case Html_SELECT:
468 dotest = 1;
469 break;
470 default:
471 dotest = 0;
472 break;
473 }
474 } else {
475 dotest = 1;
476 }
477 if (dotest) {
478 if (pBlock->fTop <= y && pBlock->fBottom >= y) {
479 if (pBlock->fLeft > x) {
480 if (pBlock->fLeft - x < dist) {
481 dist = pBlock->fLeft - x;
482 pNearby = pBlock;
483 }
484 } else if (pBlock->fRight < x) {
485 if (x - pBlock->fRight < dist) {
486 dist = x - pBlock->fRight;
487 pNearby = pBlock;
488 }
489 } else {
491 break;
492 }
493 } else {
494 int distY;
495 int distX;
496
497 if (pBlock->fBottom < y) {
498 distY = y - pBlock->fBottom;
499 } else {
500 distY = pBlock->fTop - y;
501 }
502 if (pBlock->fLeft > x) {
503 distX = pBlock->fLeft - x;
504 } else if (pBlock->fRight < x) {
505 distX = x - pBlock->fRight;
506 } else {
507 distX = 0;
508 }
509 if (distX + 4*distY < dist) {
510 dist = distX + 4*distY;
511 pNearby = pBlock;
512 }
513 }
514 }
515 }
516 if (pBlock == 0) {
517 if (pNearby) {
519 }
520 }
521 break;
522
523 default:
524 rc = 1;
525 break;
526 }
527 if (suffix) IndexMod(ppToken, pIndex, suffix + 1);
528
529 return rc;
530}
531
532////////////////////////////////////////////////////////////////////////////////
533/// This routine decodes a complete index specification. A complete
534/// index consists of the base specification followed by modifiers.
535
536int TGHtml::GetIndex(const char *zIndex,
538{
540}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define N
@ Html_TEXTAREA
@ Html_LI
@ Html_Block
@ Html_Space
@ Html_SELECT
@ Html_Text
@ Html_IMG
@ Html_INPUT
#define STY_Preformatted
Definition TGHtml.h:234
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Encapsulate fonts used in the GUI system.
Definition TGFont.h:140
Int_t MeasureChars(const char *source, Int_t numChars, Int_t maxLength, Int_t flags, Int_t *length) const
Determine the number of characters from the string that will fit in the given horizontal span.
Definition TGFont.cxx:485
TGHtmlElement * fPPrev
Definition TGHtml.h:263
TGHtmlElement * fPNext
Definition TGHtml.h:262
SHtmlIndex_t fSelBegin
Definition TGHtml.h:1156
const char * fZBase
Definition TGHtml.h:1268
TGHtmlElement * fPFirst
Definition TGHtml.h:1136
int fNToken
Definition TGHtml.h:1138
virtual TGFont * GetFont(int iFont)
The rendering and layout routines should call this routine in order to get a font structure.
Definition TGHtml.cxx:1464
SHtmlIndex_t fIns
Definition TGHtml.h:1170
void IndexToBlockIndex(SHtmlIndex_t sIndex, TGHtmlBlock **ppBlock, int *piIndex)
Convert an Element-based index into a Block-based index.
void MaxIndex(TGHtmlElement *p, int *pIndex, int isLast)
Find the maximum index for the given token.
int IndexMod(TGHtmlElement **pp, int *ip, char *cp)
Modify an index for both pointer and char +/-/=N.
void FindIndexInBlock(TGHtmlBlock *pBlock, int x, TGHtmlElement **ppToken, int *pIndex)
Given a Block and an x coordinate, find the Index of the character that is closest to the given x coo...
TGHtmlElement * TokenByIndex(int N, int flag)
Return a pointer to the Nth TGHtmlElement in the list.
TGHtmlBlock * fFirstBlock
Definition TGHtml.h:1143
TGHtmlElement * fPLast
Definition TGHtml.h:1137
int TokenNumber(TGHtmlElement *p)
Return the token number for the given TGHtmlElement.
SHtmlIndex_t fSelEnd
Definition TGHtml.h:1157
int GetIndex(const char *zIndex, TGHtmlElement **ppToken, int *pIndex)
This routine decodes a complete index specification.
int DecodeBaseIndex(const char *zBase, TGHtmlElement **ppToken, int *pIndex)
Given a base index name (without any modifiers) return a pointer to the token described,...
Long_t fX
x position
Definition TGDimension.h:56
Long_t fY
y position
Definition TGDimension.h:57
TGLongPosition fVisible
position of visible region
Definition TGView.h:32
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGHtmlElement * fP
Definition TGHtml.h:833