[4966] in Athena Bugs
Xaw Text widget cursor movement
daemon@ATHENA.MIT.EDU (Jonathan I. Kamens)
Tue May 22 01:07:25 1990
Date: Tue, 22 May 90 01:06:54 -0400
From: "Jonathan I. Kamens" <jik@pit-manager.MIT.EDU>
To: xbugs@expo.lcs.mit.edu
Cc: bugs@ATHENA.MIT.EDU
X Window System Bug Report
xbugs@expo.lcs.mit.edu
VERSION:
R4
CLIENT MACHINE and OPERATING SYSTEM:
NA
DISPLAY TYPE:
NA
WINDOW MANAGER:
NA
AREA:
Xaw Text widget
SYNOPSIS:
Cursor movement commands do not always verify that the insertion
point is visible after the movement is done.
DESCRIPTION:
The commands to move the insertion point (e.g. M-b, M-f, C-b, C-f,
etc.), i.e. the commands which use the "Move" function in
TextAction.c, do not verify that the insertion point is visible
after the cursor movement is complete.
REPEAT BY:
Create a one-line text widget, with auto-fill disabled and
word-wrap enabled. Type enough text on one line to overfill the
visible portion of the text widget (once again, it should scroll
to keep the insertion point visible, and it doesn't, but that's
another bug). Type M-b, and see how your insertion point still
isn't visible.
SAMPLE FIX:
Provided below. The solution provided may not be elegant or
optimal, because I don't really understand the inner workings of
the text widget completely. It does, however, work.
Jonathan Kamens USnail:
MIT Project Athena 11 Ashford Terrace
jik@Athena.MIT.EDU Allston, MA 02134
Office: 617-253-8495 Home: 617-782-0710
*** /tmp/,RCSt1000229 Tue May 22 00:40:19 1990
--- TextAction.c Tue May 22 00:24:19 1990
***************
*** 295,300 ****
--- 295,341 ----
if (ctx->text.insertPos == old_pos)
ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
type, dir, ctx->text.mult + 1, include);
+
+ /*
+ * If the movement moved the insertion point out of view, then scroll
+ * to bring it back into view.
+ */
+ #define IsBeforeStart(ctx) ctx->text.insertPos < ctx->text.lt.info[0].position
+ #define IsAfterEnd(ctx) ctx->text.insertPos >= \
+ ctx->text.lt.info[ctx->text.lt.lines].position
+
+ /*
+ * There are two things you have to realize here. First of all, you
+ * *must* check to see if the position is before the first displayed
+ * position *before* you check to see if the position is after the
+ * last displayed position. Second, even though it appears that if
+ * the body of the first while loop ever gets executed, the cursor
+ * will be visible when it's done executing the last time, this is not
+ * true, and that's why it's necessary to do the second while loop
+ * even if the first one is executed at least once.
+ *
+ * The reason for this is that when the text widget is scrolled down
+ * (the scroll of "-1"), it always scrolls in such a way that the
+ * beginning of the text line (as opposed to the beginning of the
+ * widget line) is displayed when it's done scrolling. This could
+ * leave you looking at the beginning of a wrapped line, while the
+ * insertion point is in the middle of the same line and not visible,
+ * after the first while loop is done. On the other hand, scrolling
+ * forward scrolls by widget lines rather than text lines, and
+ * therefore will fix up any misadjustments by the first loop.
+ */
+ while (IsBeforeStart(ctx)) {
+ _XawTextVScroll(ctx, -1);
+ _XawTextBuildLineTable(ctx, ctx->text.lt.top, FALSE);
+ }
+ while (IsAfterEnd(ctx)) {
+ _XawTextVScroll(ctx, 1);
+ _XawTextBuildLineTable(ctx, ctx->text.lt.top, FALSE);
+ }
+
+ #undef IsBeforeStart
+ #undef IsAfterEnd
+
EndAction(ctx);
}