1/* $XConsortium: tsource.c,v 2.24 91/10/21 14:32:36 eswu Exp $ */
2
3/*
4 *			  COPYRIGHT 1987
5 *		   DIGITAL EQUIPMENT CORPORATION
6 *		       MAYNARD, MASSACHUSETTS
7 *			ALL RIGHTS RESERVED.
8 *
9 * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
10 * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
11 * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
12 * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
13 *
14 * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
15 * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
16 * SET FORTH ABOVE.
17 *
18 *
19 * Permission to use, copy, modify, and distribute this software and its
20 * documentation for any purpose and without fee is hereby granted, provided
21 * that the above copyright notice appear in all copies and that both that
22 * copyright notice and this permission notice appear in supporting documentation,
23 * and that the name of Digital Equipment Corporation not be used in advertising
24 * or publicity pertaining to distribution of the software without specific,
25 * written prior permission.
26 */
27/* $XFree86: xc/programs/xmh/tsource.c,v 1.3 2002/04/05 21:06:29 dickey Exp $ */
28
29/* File: tsource.c -- the code for a toc source */
30
31#include "xmh.h"
32#include "tocintrnl.h"
33#include <X11/Xatom.h>
34#include "tsourceP.h"
35
36/****************************************************************
37 *
38 * Full class record constant
39 *
40 ****************************************************************/
41
42/* Private Data */
43
44#define Offset(field) XtOffsetOf(TocSourceRec, toc_source.field)
45
46static XtResource resources[] = {
47    {XtNtoc, XtCToc, XtRPointer, sizeof(caddr_t),
48       Offset(toc), XtRPointer, NULL},
49};
50
51#undef Offset
52
53static void Initialize(Widget, Widget, ArgList, Cardinal *num_args);
54static XawTextPosition Read(Widget, XawTextPosition, XawTextBlock *, int);
55static XawTextPosition Scan(Widget, XawTextPosition, XawTextScanType, XawTextScanDirection, int, Bool);
56static XawTextPosition Search(Widget, XawTextPosition, XawTextScanDirection, XawTextBlock *);
57static int Replace(Widget, XawTextPosition, XawTextPosition, XawTextBlock *);
58
59#define SuperClass		(&textSrcClassRec)
60TocSourceClassRec tocSourceClassRec = {
61  {
62/* core_class fields */
63    /* superclass	  	*/	(WidgetClass) SuperClass,
64    /* class_name	  	*/	"TocSrc",
65    /* widget_size	  	*/	sizeof(TocSourceRec),
66    /* class_initialize   	*/	NULL,
67    /* class_part_initialize	*/	NULL,
68    /* class_inited       	*/	FALSE,
69    /* initialize	  	*/	Initialize,
70    /* initialize_hook		*/	NULL,
71    /* realize		  	*/	NULL,
72    /* actions		  	*/	NULL,
73    /* num_actions	  	*/	0,
74    /* resources	  	*/	resources,
75    /* num_resources	  	*/	XtNumber(resources),
76    /* xrm_class	  	*/	NULLQUARK,
77    /* compress_motion	  	*/	FALSE,
78    /* compress_exposure  	*/	FALSE,
79    /* compress_enterleave	*/	FALSE,
80    /* visible_interest	  	*/	FALSE,
81    /* destroy		  	*/	NULL,
82    /* resize		  	*/	NULL,
83    /* expose		  	*/	NULL,
84    /* set_values	  	*/	NULL,
85    /* set_values_hook		*/	NULL,
86    /* set_values_almost	*/	NULL,
87    /* get_values_hook		*/	NULL,
88    /* accept_focus	 	*/	NULL,
89    /* version			*/	XtVersion,
90    /* callback_private   	*/	NULL,
91    /* tm_table		   	*/	NULL,
92    /* query_geometry		*/	NULL,
93    /* display_accelerator	*/	NULL,
94    /* extension		*/	NULL
95  },
96/* textSrc_class fields */
97  {
98    /* Read                     */      Read,
99    /* Replace                  */      Replace,
100    /* Scan                     */      Scan,
101    /* Search                   */      Search,
102    /* SetSelection             */      XtInheritSetSelection,
103    /* ConvertSelection         */      XtInheritConvertSelection
104  },
105/* toc_source_class fields */
106  {
107    /* keeping the compiler happy */	0
108  }
109};
110
111WidgetClass tocSourceWidgetClass = (WidgetClass)&tocSourceClassRec;
112
113/************************************************************
114 *
115 * Class specific methods.
116 *
117 ************************************************************/
118
119Msg MsgFromPosition(
120    Toc toc,
121    XawTextPosition position,
122    XawTextScanDirection dir)
123{
124    Msg msg;
125    int     h, l, m;
126    if (position > toc->lastPos) position = toc->lastPos;
127    if (dir == XawsdLeft) position--;
128    l = 0;
129    h = toc->nummsgs - 1;
130    while (l < h - 1) {
131	m = (l + h) / 2;
132	if (toc->msgs[m]->position > position)
133	    h = m;
134	else
135	    l = m;
136    }
137    msg = toc->msgs[h];
138    if (msg->position > position)
139	msg = toc->msgs[h = l];
140    while (!msg->visible)
141	msg = toc->msgs[h++];
142    if (position < msg->position || position > msg->position + msg->length)
143	Punt("Error in MsgFromPosition!");
144    return msg;
145}
146
147
148static XawTextPosition
149CoerceToLegalPosition(Toc toc, XawTextPosition position)
150{
151    return (position < 0) ? 0 :
152		 ((position > toc->lastPos) ? toc->lastPos : position);
153}
154
155static XawTextPosition
156Read(
157    Widget w,
158    XawTextPosition position,
159    XawTextBlock *block,
160    int length)
161{
162    TocSourceWidget source = (TocSourceWidget) w;
163    Toc toc = source->toc_source.toc;
164    Msg msg;
165    int count;
166
167    if (position < toc->lastPos) {
168        block->firstPos = position;
169	msg = MsgFromPosition(toc, position, XawsdRight);
170	block->ptr = msg->buf + (position - msg->position);
171	count = msg->length - (position - msg->position);
172	block->length = (count < length) ? count : length;
173	position += block->length;
174    }
175    else {
176        block->firstPos = 0;
177	block->length = 0;
178	block->ptr = "";
179    }
180    block->format = FMT8BIT;
181    return position;
182}
183
184/* Right now, we can only replace a piece with another piece of the same size,
185   and it can't cross between lines. */
186
187static int
188Replace(
189    Widget w,
190    XawTextPosition startPos,
191    XawTextPosition endPos,
192    XawTextBlock *block)
193{
194    TocSourceWidget source = (TocSourceWidget) w;
195    Toc toc = source->toc_source.toc;
196    Msg msg;
197    int i;
198
199    if (block->length != endPos - startPos)
200	return XawEditError;
201    msg = MsgFromPosition(toc, startPos, XawsdRight);
202    for (i = 0; i < block->length; i++)
203	msg->buf[startPos - msg->position + i] = block->ptr[i];
204/*    for (i=0 ; i<toc->numwidgets ; i++)
205	XawTextInvalidate(toc->widgets[i], startPos, endPos);
206*
207* CDP 9/1/89
208*/
209    return XawEditDone;
210}
211
212
213#define Look(ti, c)\
214{									\
215    if ((dir == XawsdLeft && ti <= 0) ||				\
216	    (dir == XawsdRight && ti >= toc->lastPos))		\
217	c = 0;								\
218    else {								\
219	if (ti + doff < msg->position ||				\
220		ti + doff >= msg->position + msg->length)		\
221	    msg = MsgFromPosition(toc, ti, dir);			\
222	c = msg->buf[ti + doff - msg->position];			\
223    }									\
224}
225
226
227
228static XawTextPosition
229Scan(
230    Widget w,
231    XawTextPosition position,
232    XawTextScanType sType,
233    XawTextScanDirection dir,
234    int count,
235    Bool include)
236{
237    TocSourceWidget source = (TocSourceWidget) w;
238    Toc toc = source->toc_source.toc;
239    XawTextPosition textindex;
240    Msg msg;
241    char    c;
242    int     ddir, doff, i, whiteSpace = 0;
243    ddir = (dir == XawsdRight) ? 1 : -1;
244    doff = (dir == XawsdRight) ? 0 : -1;
245
246    if (toc->lastPos == 0) return 0;
247    textindex = position;
248    if (textindex + doff < 0) return 0;
249    if (dir == XawsdRight && textindex >= toc->lastPos) return toc->lastPos;
250    msg = MsgFromPosition(toc, textindex, dir);
251    switch (sType) {
252	case XawstPositions:
253	    if (!include && count > 0)
254		count--;
255	    textindex = CoerceToLegalPosition(toc, textindex + count * ddir);
256	    break;
257	case XawstWhiteSpace:
258	    for (i = 0; i < count; i++) {
259		whiteSpace = -1;
260		while (textindex >= 0 && textindex <= toc->lastPos) {
261		    Look(textindex, c);
262		    if ((c == ' ') || (c == '\t') || (c == '\n')) {
263			if (whiteSpace < 0) whiteSpace = textindex;
264		    } else if (whiteSpace >= 0)
265			break;
266		    textindex += ddir;
267		}
268	    }
269	    if (!include) {
270		if (whiteSpace < 0 && dir == XawsdRight)
271		    whiteSpace = toc->lastPos;
272		textindex = whiteSpace;
273	    }
274	    textindex = CoerceToLegalPosition(toc, textindex);
275	    break;
276	case XawstEOL:
277	case XawstParagraph:
278	    for (i = 0; i < count; i++) {
279		while (textindex >= 0 && textindex <= toc->lastPos) {
280		    Look(textindex, c);
281		    if (c == '\n')
282			break;
283		    textindex += ddir;
284		}
285		if (i < count - 1)
286		    textindex += ddir;
287	    }
288	    if (include)
289		textindex += ddir;
290	    textindex = CoerceToLegalPosition(toc, textindex);
291	    break;
292	case XawstAll:
293	    if (dir == XawsdLeft)
294		textindex = 0;
295	    else
296		textindex = toc->lastPos;
297	    break;
298	default:
299	    break;
300    }
301    return textindex;
302}
303
304/*ARGSUSED*/
305static XawTextPosition Search(
306    Widget			w,
307    XawTextPosition		position,
308    XawTextScanDirection	direction,
309    XawTextBlock		*block)
310{
311    /* TocSourceWidget source = (TocSourceWidget) w;
312     * Toc toc = source->toc_source.toc;
313     * not implemented
314     */
315    return XawTextSearchError;
316}
317
318/* Public definitions. */
319
320/* ARGSUSED*/
321static void Initialize(
322    Widget request,
323    Widget new,
324    ArgList args,
325    Cardinal *num_args)
326{
327    Toc toc;
328    TocSourceWidget source = (TocSourceWidget) new;
329
330    source->text_source.edit_mode = XawtextRead; /* force read only. */
331
332    toc = source->toc_source.toc;
333
334    toc->hasselection = FALSE;
335    toc->left = toc->right = 0;
336}
337
338void
339TSourceInvalid(Toc toc, XawTextPosition position, int length)
340{
341  XawTextInvalidate(XtParent(toc->source), position,
342		    (XawTextPosition) position+length-1);
343}
344