From: pizzi@nervous.com (Riccardo Pizzi)
Subject: Re: How to have XmTextSetString(3X) not setting cursor position to start of text?
Followup-To: poster
Reply-To: pizzi@nervous.com (Riccardo Pizzi) 
Organization: The Nervous XTC Public Access Unix System, Rimini, ITALY
Date: Wed, 11 Nov 92 15:08:30 GMT

In article <1992Nov10.140622.650@nervous.com> I wrote:

>I am writing an application using Motif 1.1.3 and X11R5.
>In this application I have a ScrolledText widget that monitors a constantly
>growing file (specifically, a log file).
>Whenever the file grows a little further, I use XmTextSetString to replace
>the contents of the Text widget, but this has the undesirable effect that
>the ScrolledWindow always redisplays the new string starting from the beginning
>of text. What I would like to have is a way to replace the Text buffer but
>to redisplay the bottom part of the text. I tried:
>
>	XmTextSetString(w, text);
>        XmTextShowPosition(w, XmTextGetLastPosition(w));
>        XmTextScroll(w, -7);	/* the scrolled window is 8 rows total */
>
>and this works as intended, but has the drawback of a very nasty flickering
>because the XmTextSetString call resets the visible position to 0 (beginning)
>and redisplays that part of text, before the other two calls restore things
>in the desired form.

Here is the solution I found for the above problem.
First let me say "thanks!!" to all those who replied to my help request!
A particular acknowledgement goes to Kalidoss Sivasamy
<ksivasam@ha21.eng.ua.edu> who sent me the following piece of code:

	XmTextInsert(w, pos, buf);
	XtVaSetValues(w, XmNcursorPosition, pos, NULL);
	XmTextShowPosition(w, pos);

I immediately substituted XmTextInsert with XmTextReplace (I need to substitute
the buffer, not to add to it); unfortunately, there still were two problems:

1) The XmTextReplace also caused the beginning of text to be displayed in the
   visible window, regardless of the current insert cursor;
2) The last line of text was displayed on the first visible window row while
   I was looking for a way to have it displayed as the last visible window
   row.

After experimenting for a while, I wrote the following piece of code that works
pretty well. To reduce flickering I ended up setting XmNshadowThickness to 0
and adding an external frame widget myself, in order to be able to map/unmap
the scrolled window work area without having the shadow flickering.
The unmapping is, again, required to avoid bad-looking display effects.

Widget w, ww;	/* w is the text widget id */
short r;

		XtVaGetValues(XtParent(w), 
			XmNworkWindow, &ww,
			NULL);		/* get the working area id */
		XtVaGetValues(w,
			XmNrows, &r,
			NULL);		/* get the actual XmNcolumns value
					for further use in XmTextScroll */
		XtUnmapWidget(ww);
		/* this cause text to be redisplayed at pos = 0 :-( */
		XmTextReplace(w, 0, XmTextGetLastPosition(w), buf);
		pos = XmTextGetLastPosition(w);
		XtVaSetValues(w, XmNcursorPosition, pos, NULL);
		XmTextShowPosition(w, pos);
		XtMapWidget(ww);
		XmTextScroll(w, 1 - r);

Note that I needed to apply the patch to the Xm library Text.c file as
explained in README-1.1.3 in order to have XmTextScroll working ok.
This patch may be already included in later Motif releases.

If someone has something to ask/add on this topic, please email!

Ciao

Rick
-- 
Riccardo Pizzi @ the Nervous XTC Public Access Unix System, Rimini, ITALY
E-Mail -> pizzi@nervous.com        <*>      Bang-path -> uunet!nervous!pizzi
Nervous XTC, the home of the UniBoard package * Data: +39-541-27135 HST/PEP/V32
Newsgroups: comp.windows.x.motif