1 From: Thorsten Haude <yoo@vranx.de>
2 Subject: Show the line number while scrolling with the scrollbar
7 source/calltips.c | 226 ++++++++++++++++++++++++++++++++++++++++++++-------
8 source/calltips.h | 5 +
9 source/preferences.c | 8 +
10 source/preferences.h | 1
13 source/textDisp.c | 51 ++++++++++-
14 source/textDisp.h | 8 +
17 11 files changed, 273 insertions(+), 41 deletions(-)
19 diff --quilt old/doc/help.etx new/doc/help.etx
22 @@ -4611,6 +4611,12 @@ X Resources
24 Basic time-out period used in communication with an NEdit server (seconds).
26 +**nedit.showScrolltip**: True
28 + If this resource is set to True, NEdit will show a tooltip displaying the
29 + line number if the user grabs and moves the scroll handle. Set to False to
32 ----------------------------------------------------------------------
33 ~The following are Selected widget names (to which you may append~
34 ~.background, .foreground, .fontList, etc., to change colors, fonts~
35 diff --quilt old/source/calltips.c new/source/calltips.c
36 --- old/source/calltips.c
37 +++ new/source/calltips.c
40 static char *expandAllTabs( char *text, int tab_width );
42 +/* lowlevel tip functions */
43 +static Widget createTip(const char *name, Widget grandfather,
44 + Pixel foreground, Pixel background, unsigned char alignment);
45 +static Widget shellOfTip(Widget tip);
46 +static void setTipText(Widget tip, const char *text);
47 +static void showTip(Widget tip);
48 +static void hideTip(Widget tip);
49 +static void realizeTip(Widget tip);
50 +static void getTipMetrics(Widget tip,
51 + Position *widthPtr, Position *heightPtr,
52 + Position *borderWidthPtr);
53 +static void moveTip(Widget tip, Position x, Position y);
56 ** Pop-down a calltip if one exists, else do nothing
58 @@ -62,7 +75,7 @@ void TextDKillCalltip(textDisp *textD, i
59 if( textD->calltip.ID == 0 )
61 if( calltipID == 0 || calltipID == textD->calltip.ID ) {
62 - XtPopdown( textD->calltipShell );
63 + hideTip(textD->calltip.tip);
64 textD->calltip.ID = 0;
67 @@ -131,8 +144,7 @@ void TextDRedrawCalltip(textDisp *textD,
68 rel_x = textD->calltip.pos;
71 - XtVaGetValues(textD->calltipShell, XmNwidth, &tipWidth, XmNheight,
72 - &tipHeight, XmNborderWidth, &borderWidth, NULL);
73 + getTipMetrics(textD->calltip.tip, &tipWidth, &tipHeight, &borderWidth);
75 rel_y += lineHeight/2 + borderWidth;
77 @@ -176,8 +188,8 @@ void TextDRedrawCalltip(textDisp *textD,
78 /* If no case applied, just go with the default placement. */
82 - XtVaSetValues( textD->calltipShell, XmNx, abs_x, XmNy, abs_y, NULL );
84 + moveTip(textD->calltip.tip, abs_x, abs_y);
88 @@ -245,9 +257,6 @@ int ShowCalltip(WindowInfo *window, char
89 textCpy = expandAllTabs( text, BufGetTabDistance(textD->buffer) );
91 return 0; /* Out of memory */
92 - str = XmStringCreateLtoR(textCpy, XmFONTLIST_DEFAULT_TAG);
93 - if( textCpy != text )
96 /* Get the location/dimensions of the text area */
97 XtVaGetValues(textD->w,
98 @@ -256,30 +265,20 @@ int ShowCalltip(WindowInfo *window, char
101 /* Create the calltip widget on first request */
102 - if (textD->calltipW == NULL) {
105 - XtSetArg(args[argcnt], XmNsaveUnder, True); argcnt++;
106 - XtSetArg(args[argcnt], XmNallowShellResize, True); argcnt++;
108 - textD->calltipShell = CreatePopupShellWithBestVis("calltipshell",
109 - overrideShellWidgetClass, textD->w, args, argcnt);
111 - /* Might want to make this a read-only XmText eventually so that
112 - users can copy from it */
113 - textD->calltipW = XtVaCreateManagedWidget(
114 - "calltip", xmLabelWidgetClass, textD->calltipShell,
115 - XmNborderWidth, 1, /* Thin borders */
116 - XmNhighlightThickness, 0,
117 - XmNalignment, XmALIGNMENT_BEGINNING,
118 - XmNforeground, textD->calltipFGPixel,
119 - XmNbackground, textD->calltipBGPixel,
121 + if (textD->calltip.tip == NULL) {
122 + textD->calltip.tip = createTip("calltip", textD->w,
123 + textD->calltipFGPixel, textD->calltipBGPixel,
124 + XmALIGNMENT_BEGINNING);
125 + if (textD->calltip.tip == NULL) {
130 /* Set the text on the label */
131 - XtVaSetValues( textD->calltipW, XmNlabelString, str, NULL );
132 - XmStringFree( str );
133 + setTipText(textD->calltip.tip, textCpy);
134 + if (textCpy != text) {
138 /* Figure out where to put the tip */
140 @@ -317,9 +316,174 @@ int ShowCalltip(WindowInfo *window, char
143 /* Realize the calltip's shell so that its width & height are known */
144 - XtRealizeWidget( textD->calltipShell );
145 + realizeTip(textD->calltip.tip);
146 /* Move the calltip and pop it up */
147 TextDRedrawCalltip(textD, 0);
148 - XtPopup( textD->calltipShell, XtGrabNone );
149 + showTip(textD->calltip.tip);
150 return textD->calltip.ID;
154 +** Pop up a scrolltip.
156 +Boolean TextDShowScrolltip(textDisp *textD, unsigned line, int x, int y,
161 + char lineBuf[TYPE_INT_STR_SIZE(int)];
163 + if (NULL == textD->scrolltip) {
164 + textD->scrolltip = createTip("scrolltip", textD->w,
165 + textD->calltipFGPixel, textD->calltipBGPixel,
166 + XmALIGNMENT_CENTER);
167 + if (NULL == textD->scrolltip) {
172 + /* Set the text on the tip's label. */
173 + sprintf(lineBuf, "%u", line);
174 + setTipText(textD->scrolltip, lineBuf);
176 + /* Realize the calltip's shell so that its width and height are known */
177 + realizeTip(textD->scrolltip);
179 + /* Get the width of the tip to right align it on the x position */
180 + if (SCROLLTIP_RIGHT == align) {
181 + getTipMetrics(textD->scrolltip, &w, NULL, NULL);
184 + /* Move the tip where it belongs and pop it up. */
185 + moveTip(textD->scrolltip, x - w, y);
186 + showTip(textD->scrolltip);
192 +** Pop down scrolltip if it exists
194 +void TextDKillScrolltip(textDisp *textD)
196 + if (NULL != textD->scrolltip
197 + && NULL != shellOfTip(textD->scrolltip)) {
198 + hideTip(textD->scrolltip);
203 +** This creates a calltip of class XmLabel and its parent, a shell of class
204 +** OverrideShell (which in turn will be the child of the grandfather
205 +** parameter). The tip will have minimum size but will resize to match
206 +** the text entered (see XmNallowShellResize).
208 +** Color is picked by the two parameters foreground and background.
210 +** The alignment is one of XmALIGNMENT_BEGINNING, XmALIGNMENT_CENTER or
211 +** XmALIGNMENT_END, taken from the XmLabel class.
213 +** TODO: Some helper functions are still desirable to make this function
214 +** available from other parts of the code. At the moment the caller must
215 +** use calls to Motif/Intrinsics functions to handle it.
218 +static Widget createTip(const char *name, Widget grandfather,
219 + Pixel foreground, Pixel background, unsigned char alignment)
222 + Widget shell = NULL;
225 + char *shellNameBuf;
227 + shellNameBuf = XtMalloc(strlen(name) + strlen("shell") + 1);
228 + if (NULL == shellNameBuf) {
229 + fprintf(stderr, "nedit: Out of heap memory in createTip!\n");
233 + strcpy(shellNameBuf, name);
234 + strcat(shellNameBuf, "shell");
236 + XtSetArg(args[argcnt], XmNsaveUnder, True); argcnt++;
237 + XtSetArg(args[argcnt], XmNallowShellResize, True); argcnt++;
239 + shell = CreatePopupShellWithBestVis(shellNameBuf,
240 + overrideShellWidgetClass, grandfather, args, argcnt);
242 + XtFree(shellNameBuf);
244 + /* Might want to make this a read-only XmText eventually so that
245 + users can copy from it */
246 + tip = XtVaCreateManagedWidget(name,
247 + xmLabelWidgetClass, shell,
248 + XmNborderWidth, 1, /* Thin borders */
249 + XmNhighlightThickness, 0,
250 + XmNalignment, XmALIGNMENT_BEGINNING,
251 + XmNforeground, foreground,
252 + XmNbackground, background,
258 +static Widget shellOfTip(Widget tip)
260 + return tip ? XtParent(tip) : NULL;
263 +static void setTipText(Widget tip, const char *text)
267 + str = XmStringCreateLtoR((char *)text, XmFONTLIST_DEFAULT_TAG);
268 + XtVaSetValues(tip, XmNlabelString, str, NULL);
272 +static void showTip(Widget tip)
274 + XtPopup(shellOfTip(tip), XtGrabNone);
277 +static void hideTip(Widget tip)
279 + XtPopdown(shellOfTip(tip));
282 +static void realizeTip(Widget tip)
284 + XtRealizeWidget(shellOfTip(tip));
287 +static void getTipMetrics(Widget tip,
288 + Position *widthPtr, Position *heightPtr,
289 + Position *borderWidthPtr)
291 + Position width, height, borderWidth;
293 + XtVaGetValues(shellOfTip(tip),
295 + XmNheight, &height,
296 + XmNborderWidth, &borderWidth,
303 + *heightPtr = height;
305 + if (borderWidthPtr) {
306 + *borderWidthPtr = borderWidth;
310 +static void moveTip(Widget tip, Position x, Position y)
312 + XtVaSetValues(shellOfTip(tip),
317 diff --quilt old/source/textDisp.c new/source/textDisp.c
318 --- old/source/textDisp.c
319 +++ new/source/textDisp.c
320 @@ -197,7 +197,8 @@ textDisp *TextDCreate(Widget widget, Wid
321 int continuousWrap, int wrapMargin, XmString bgClassString,
322 Pixel calltipFGPixel, Pixel calltipBGPixel,
323 Pixel cursorlineBGPixel, Boolean showCursorline,
324 - Pixel wrapMarginFGPixel, Boolean showWrapMargin)
325 + Pixel wrapMarginFGPixel, Boolean showWrapMargin,
326 + Boolean showScrolltip)
330 @@ -260,13 +261,12 @@ textDisp *TextDCreate(Widget widget, Wid
331 textD->cursorFGGC = XtGetGC(widget, GCForeground, &gcValues);
332 textD->lineStarts = (int *)XtMalloc(sizeof(int) * textD->nVisibleLines);
333 textD->lineStarts[0] = 0;
334 - textD->calltipW = NULL;
335 - textD->calltipShell = NULL;
336 + for (i=1; i<textD->nVisibleLines; i++)
337 + textD->lineStarts[i] = -1;
338 + textD->calltip.tip = NULL;
339 textD->calltip.ID = 0;
340 textD->calltipFGPixel = calltipFGPixel;
341 textD->calltipBGPixel = calltipBGPixel;
342 - for (i=1; i<textD->nVisibleLines; i++)
343 - textD->lineStarts[i] = -1;
344 textD->bgClassPixel = NULL;
345 textD->bgClass = NULL;
346 TextDSetupBGClasses(widget, bgClassString, &textD->bgClassPixel,
347 @@ -279,6 +279,8 @@ textDisp *TextDCreate(Widget widget, Wid
348 textD->showCursorline = showCursorline;
349 textD->oldCursorPos = 0;
350 textD->oldLineStart = 0;
351 + textD->showScrolltip = showScrolltip;
352 + textD->scrolltip = NULL;
354 /* Attach an event handler to the widget so we can know the visibility
355 (used for choosing the fastest drawing method) */
356 @@ -3154,9 +3156,46 @@ static void vScrollCB(Widget w, XtPointe
357 textDisp *textD = (textDisp *)clientData;
358 int newValue = ((XmScrollBarCallbackStruct *)callData)->value;
359 int lineDelta = newValue - textD->topLineNum;
360 + int reason = ((XmScrollBarCallbackStruct *)callData)->reason;
362 - if (lineDelta == 0)
363 + if (lineDelta == 0) {
364 + TextDKillScrolltip(textD);
368 + /* lineDelta is always != 0 for XmCR_DRAG */
369 + /* Scrolltip does not work for continuous wrap. The only way to get the
370 + line number is through textDisp->absTopLineNum, but this value is very
371 + inaccurate for large files. So no tip. */
372 + if (XmCR_DRAG == reason
373 + && !textD->continuousWrap
374 + && textD->showScrolltip) {
375 + /* Display a scrolltip showing the line number about one third down
376 + from the top, the position a search jumps to. */
377 + XEvent *event = ((XmScrollBarCallbackStruct *)callData)->event;
378 + XMotionEvent *motionEvent = (XMotionEvent *)event;
379 + unsigned char placement = -1;
380 + int align = SCROLLTIP_RIGHT;
382 + Dimension margin = 4;
384 + XtVaGetValues(XtParent(XtParent(textD->w)),
385 + XmNscrollBarPlacement, &placement,
387 + if (XmBOTTOM_LEFT == placement || XmTOP_LEFT == placement) {
388 + XtVaGetValues(textD->vScrollBar, XmNwidth, &w, NULL);
389 + align = SCROLLTIP_LEFT;
392 + /* SCROLLTIP_RIGHT */
396 + TextDShowScrolltip(textD, newValue + (textD->nVisibleLines / 3),
397 + motionEvent->x_root - motionEvent->x + w,
398 + motionEvent->y_root, align);
401 setScroll(textD, newValue, textD->horizOffset, False, True);
403 static void hScrollCB(Widget w, XtPointer clientData, XtPointer callData)
404 diff --quilt old/source/textDisp.h new/source/textDisp.h
405 --- old/source/textDisp.h
406 +++ new/source/textDisp.h
407 @@ -67,6 +67,7 @@ typedef struct graphicExposeTranslationE
408 typedef void (*unfinishedStyleCBProc)();
410 typedef struct _calltipStruct {
411 + Widget tip; /* this tip widget */
412 int ID; /* ID of displayed calltip. Equals
413 zero if none is displayed. */
414 Boolean anchored; /* Is it anchored to a position */
415 @@ -147,8 +148,6 @@ typedef struct _textDisp {
416 Pixel *bgClassPixel; /* table of colors for each BG class */
417 unsigned char *bgClass; /* obtains index into bgClassPixel[] */
419 - Widget calltipW; /* The Label widget for the calltip */
420 - Widget calltipShell; /* The Shell that holds the calltip */
421 calltipStruct calltip; /* The info for the calltip itself */
422 Pixel calltipFGPixel;
423 Pixel calltipBGPixel;
424 @@ -168,6 +167,8 @@ typedef struct _textDisp {
427 Boolean showCursorline;
428 + Boolean showScrolltip;
432 textDisp *TextDCreate(Widget widget, Widget hScrollBar, Widget vScrollBar,
433 @@ -179,7 +180,8 @@ textDisp *TextDCreate(Widget widget, Wid
434 int continuousWrap, int wrapMargin, XmString bgClassString,
435 Pixel calltipFGPixel, Pixel calltipBGPixel,
436 Pixel cursorlineBGPixel, Boolean showCursorline,
437 - Pixel wrapMarginFGPixel, Boolean showWrapMargin);
438 + Pixel wrapMarginFGPixel, Boolean showWrapMargin,
439 + Boolean showScrolltip);
440 void TextDFree(textDisp *textD);
441 void TextDSetBuffer(textDisp *textD, textBuffer *buffer);
442 void TextDAttachHighlightData(textDisp *textD, textBuffer *styleBuffer,
443 diff --quilt old/source/textP.h new/source/textP.h
444 --- old/source/textP.h
445 +++ new/source/textP.h
446 @@ -79,6 +79,7 @@ typedef struct _TextPart {
449 Boolean showWrapMargin;
450 + Boolean showScrolltip;
454 diff --quilt old/source/text.c new/source/text.c
455 --- old/source/text.c
456 +++ new/source/text.c
457 @@ -718,6 +718,8 @@ static XtResource resources[] = {
458 XtOffset(TextWidget, text.cursorVPadding), XmRString, "0"},
459 {textNshowCursorline, textCshowCursorline, XmRBoolean, sizeof(Boolean),
460 XtOffset(TextWidget, text.showCursorline), XmRString, "False"},
461 + {textNshowScrolltip, textCshowScrolltip, XmRBoolean, sizeof(Boolean),
462 + XtOffset(TextWidget, text.showScrolltip), XmRString, "False"},
465 static TextClassRec textClassRec = {
466 @@ -837,7 +839,8 @@ static void initialize(TextWidget reques
467 new->text.backlightCharTypes, new->text.calltipFGPixel,
468 new->text.calltipBGPixel,
469 new->text.cursorlineBGPixel, new->text.showCursorline,
470 - new->text.wrapMarginFGPixel, new->text.showWrapMargin);
471 + new->text.wrapMarginFGPixel, new->text.showWrapMargin,
472 + new->text.showScrolltip);
474 /* Add mandatory delimiters blank, tab, and newline to the list of
475 delimiters. The memory use scheme here is that new values are
476 diff --quilt old/source/text.h new/source/text.h
477 --- old/source/text.h
478 +++ new/source/text.h
480 #define textCBacklightCharTypes "BacklightCharTypes"
481 #define textNshowCursorline "showCursorline"
482 #define textCshowCursorline "ShowCursorline"
483 +#define textNshowScrolltip "showScrolltip"
484 +#define textCshowScrolltip "ShowScrolltip"
487 extern WidgetClass textWidgetClass;
488 diff --quilt old/source/calltips.h new/source/calltips.h
489 --- old/source/calltips.h
490 +++ new/source/calltips.h
492 enum TipHAlignMode {TIP_LEFT, TIP_CENTER, TIP_RIGHT};
493 enum TipVAlignMode {TIP_ABOVE, TIP_BELOW};
494 enum TipAlignStrict {TIP_SLOPPY, TIP_STRICT};
495 +enum ScrolltipAlignMode {SCROLLTIP_LEFT, SCROLLTIP_RIGHT};
497 int ShowCalltip(WindowInfo *window, char *text, Boolean anchored,
498 int pos, int hAlign, int vAlign, int alignMode);
499 @@ -46,4 +47,8 @@ void TextDKillCalltip(textDisp *textD, i
500 int GetCalltipID(WindowInfo *window, int calltipID);
501 void TextDRedrawCalltip(textDisp *textD, int calltipID);
503 +Boolean TextDShowScrolltip(textDisp *textD, unsigned line, int x, int y,
505 +void TextDKillScrolltip(textDisp *textD);
507 #endif /* ifndef NEDIT_CALLTIPS_H_INCLUDED */
508 diff --quilt old/source/preferences.c new/source/preferences.c
509 --- old/source/preferences.c
510 +++ new/source/preferences.c
511 @@ -335,6 +335,7 @@ static struct prefData {
512 Boolean honorSymlinks;
513 int truncSubstitution;
514 Boolean forceOSConversion;
515 + Boolean showScrolltip;
518 /* Temporary storage for preferences strings which are discarded after being
519 @@ -1098,6 +1099,8 @@ static PrefDescripRec PrefDescrip[] = {
520 &PrefData.honorSymlinks, NULL, False},
521 {"showCursorline", "ShowCursorline", PREF_BOOLEAN, "True",
522 &PrefData.showCursorline, NULL, True},
523 + {"showScrolltip", "ShowScrolltip", PREF_BOOLEAN, "True",
524 + &PrefData.showScrolltip, NULL, False},
527 static XrmOptionDescRec OpTable[] = {
528 @@ -2238,6 +2241,11 @@ Boolean GetPrefShowCursorline(void)
529 return PrefData.showCursorline;
532 +Boolean GetPrefShowScrolltip(void)
534 + return PrefData.showScrolltip;
538 ** If preferences don't get saved, ask the user on exit whether to save
540 diff --quilt old/source/window.c new/source/window.c
541 --- old/source/window.c
542 +++ new/source/window.c
543 @@ -2313,6 +2313,7 @@ static Widget createTextArea(Widget pare
544 textNhidePointer, (Boolean) GetPrefTypingHidesPointer(),
545 textNcursorVPadding, GetVerticalAutoScroll(),
546 textNshowCursorline, False,
547 + textNshowScrolltip, GetPrefShowScrolltip(),
550 XtVaSetValues(sw, XmNworkWindow, frame, XmNhorizontalScrollBar,
551 diff --quilt old/source/preferences.h new/source/preferences.h
552 --- old/source/preferences.h
553 +++ new/source/preferences.h
554 @@ -217,5 +217,6 @@ Boolean GetPrefFocusOnRaise(void);
555 Boolean GetPrefHonorSymlinks(void);
556 Boolean GetPrefForceOSConversion(void);
557 void SetPrefFocusOnRaise(Boolean);
558 +Boolean GetPrefShowScrolltip(void);
560 #endif /* NEDIT_PREFERENCES_H_INCLUDED */