1 /*************************************<+>*************************************
2  *****************************************************************************
3  **
4  **   File:        SourceStr.c
5  **
6  **   Project:     X Widgets
7  **
8  **   Description: Code for TextEdit widget string source
9  **
10  *****************************************************************************
11  **
12  **   Copyright (c) 1988 by Hewlett-Packard Company
13  **   Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
14  **             Massachusetts, and the Massachusetts Institute of Technology,
15  **             Cambridge, Massachusetts
16  **
17  **   Permission to use, copy, modify, and distribute this software
18  **   and its documentation for any purpose and without fee is hereby
19  **   granted, provided that the above copyright notice appear in all
20  **   copies and that both that copyright notice and this permission
21  **   notice appear in supporting documentation, and that the names of
22  **   Hewlett-Packard, Digital or  M.I.T.  not be used in advertising or
23  **   publicity pertaining to distribution of the software without
24  **   written prior permission.
25  **
26  **   DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27  **   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
28  **   DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29  **   ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30  **   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
31  **   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32  **   SOFTWARE.
33  **
34  *****************************************************************************
35  *************************************<+>*************************************/
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <X11/Xlib.h>
40 #include <X11/IntrinsicP.h>
41 #include <X11/StringDefs.h>
42 #include <Xw/Xw.h>
43 #include <Xw/XwP.h>
44 #include <Xw/TextEdit.h>
45 #include <Xw/TextEditP.h>
46 #include <Xw/SourceP.h>
47 
48 /* Private StringSource Definitions */
49 
50 #define MAGICVALUE		-1
51 #define DEFAULTBUFFERSIZE        512
52 
53 
54 #define Increment(data, position, direction)\
55 {\
56     if (direction == XwsdLeft) {\
57 	if (position > 0) \
58 	    position -= 1;\
59     }\
60     else {\
61 	if (position < data->length)\
62 	    position += 1;\
63     }\
64 }
65 
66 static long magic_value = MAGICVALUE;
67 
68 static XtResource stringResources[] = {
69     {XtNstring, XtCString, XtRString, sizeof (char *),
70         XtOffset(StringSourcePtr, initial_string), XtRString, NULL},
71     {XtNmaximumSize, XtCMaximumSize, XtRLong, sizeof (long),
72         XtOffset(StringSourcePtr, max_size), XtRLong, (caddr_t)&magic_value},
73     {XtNeditType, XtCEditType, XtREditMode, sizeof(XwEditType),
74         XtOffset(StringSourcePtr, editMode), XtRString, "edit"},
75 };
76 
77 /*--------------------------------------------------------------------------+*/
Look(data,position,direction)78 static unsigned char Look(data, position, direction)
79 /*--------------------------------------------------------------------------+*/
80   StringSourcePtr data;
81   XwTextPosition  position;
82   XwScanDirection direction;
83 {
84 /* Looking left at pos 0 or right at position data->length returns newline */
85     if (direction == XwsdLeft) {
86 	if (position == 0)
87 	    return(0);
88 	else
89 	    return(data->buffer[position-1]);
90     }
91     else {
92 	if (position == data->length)
93 	    return(0);
94 	else
95 	    return(data->buffer[position]);
96     }
97 }
98 
99 /*--------------------------------------------------------------------------+*/
StringReadText(src,pos,text,maxRead)100 static int StringReadText (src, pos, text, maxRead)
101 /*--------------------------------------------------------------------------+*/
102   XwTextSource *src;
103   int pos;
104   XwTextBlock *text;
105   int maxRead;
106 {
107     int     charsLeft;
108     StringSourcePtr data;
109 
110     data = (StringSourcePtr) src->data;
111     text->firstPos = pos;
112     text->ptr = data->buffer + pos;
113     charsLeft = data->length - pos;
114     text->length = (maxRead > charsLeft) ? charsLeft : maxRead;
115     return pos + text->length;
116 }
117 
118 /*--------------------------------------------------------------------------+*/
StringReplaceText(src,startPos,endPos,text,delta)119 static XwEditResult StringReplaceText (src, startPos, endPos, text, delta)
120 /*--------------------------------------------------------------------------+*/
121   XwTextSource *src;
122   XwTextPosition startPos, endPos;
123   XwTextBlock *text;
124   int *delta;
125 {
126     StringSourcePtr data;
127     int     i, length;
128 
129     data = (StringSourcePtr) src->data;
130     switch (data->editMode) {
131         case XwtextAppend:
132 	    if (startPos != endPos || endPos!= data->length)
133 		return (XweditPosError);
134 	    break;
135 	case XwtextRead:
136 	    return (XweditError);
137 	case XwtextEdit:
138 	    break;
139 	default:
140 	    return (XweditError);
141     }
142     length = endPos - startPos;
143     *delta = text->length - length;
144     if ((data->length + *delta) > data->buffer_size) {
145       if (data->max_size_flag)
146 	return (XweditError);
147       else {
148 	while ((data->length + *delta) > data->buffer_size)
149 	  data->buffer_size += DEFAULTBUFFERSIZE;
150 	data->buffer = (unsigned char *)
151 	  XtRealloc(data->buffer, data->buffer_size);
152       }
153     };
154 
155 
156     if (*delta < 0)		/* insert shorter than delete, text getting
157 				   shorter */
158 	for (i = startPos; i < data->length + *delta; ++i)
159 	    data->buffer[i] = data->buffer[i - *delta];
160     else
161 	if (*delta > 0)	{	/* insert longer than delete, text getting
162 				   longer */
163 	    for (i = data->length; i > startPos-1; --i)
164 		data->buffer[i + *delta] = data->buffer[i];
165 	}
166     if (text->length != 0)	/* do insert */
167 	for (i = 0; i < text->length; ++i)
168 	    data->buffer[startPos + i] = text->ptr[i];
169     data->length = data->length + *delta;
170     data->buffer[data->length] = 0;
171     return (XweditDone);
172 }
173 
174 /*--------------------------------------------------------------------------+*/
StringSetLastPos(src,lastPos)175 static StringSetLastPos (src, lastPos)
176 /*--------------------------------------------------------------------------+*/
177   XwTextSource *src;
178   XwTextPosition lastPos;
179 {
180     ((StringSourceData *) (src->data))->length = lastPos;
181 }
182 
183 /*--------------------------------------------------------------------------+*/
StringGetLastPos(src)184 static XwTextPosition StringGetLastPos (src)
185 /*--------------------------------------------------------------------------+*/
186   XwTextSource *src;
187 {
188     return( ((StringSourceData *) (src->data))->length );
189 }
190 
191 /*--------------------------------------------------------------------------+*/
StringScan(src,pos,sType,dir,count,include)192 static XwTextPosition StringScan (src, pos, sType, dir, count, include)
193 /*--------------------------------------------------------------------------+*/
194   XwTextSource	  *src;
195   XwTextPosition  pos;
196   XwScanType	  sType;
197   XwScanDirection dir;
198   int		  count;
199   Boolean	  include;
200 {
201     StringSourcePtr data;
202     XwTextPosition position;
203     int     i, whiteSpace;
204     unsigned char c;
205     int ddir = (dir == XwsdRight) ? 1 : -1;
206 
207     data = (StringSourcePtr) src->data;
208     position = pos;
209     switch (sType) {
210 	case XwstPositions:
211 	    if (!include && count > 0)
212 		count -= 1;
213 	    for (i = 0; i < count; i++) {
214 		Increment(data, position, dir);
215 	    }
216 	    break;
217 	case XwstWhiteSpace:
218 
219 	    for (i = 0; i < count; i++) {
220 		whiteSpace = -1;
221 		while (position >= 0 && position <= data->length) {
222 		    c = Look(data, position, dir);
223 		    if ((c == ' ') || (c == '\t') || (c == '\n')){
224 		        if (whiteSpace < 0) whiteSpace = position;
225 		    } else if (whiteSpace >= 0)
226 			break;
227 		    position += ddir;
228 		}
229 	    }
230 	    if (!include) {
231 		if(whiteSpace < 0 && dir == XwsdRight) whiteSpace = data->length;
232 		position = whiteSpace;
233 	    }
234 	    break;
235 	case XwstEOL:
236 	    for (i = 0; i < count; i++) {
237 		while (position >= 0 && position <= data->length) {
238 		    if (Look(data, position, dir) == '\n')
239 			break;
240 		    if(((dir == XwsdRight) && (position == data->length)) ||
241 			(dir == XwsdLeft) && ((position == 0)))
242 			break;
243 		    Increment(data, position, dir);
244 		}
245 		if (i + 1 != count)
246 		    Increment(data, position, dir);
247 	    }
248 	    if (include) {
249 	    /* later!!!check for last char in file # eol */
250 		Increment(data, position, dir);
251 	    }
252 	    break;
253 	case XwstLast:
254 	    if (dir == XwsdLeft)
255 		position = 0;
256 	    else
257 		position = data->length;
258     }
259     if (position < 0) position = 0;
260     if (position > data->length) position = data->length;
261     return(position);
262 }
263 
264 /*--------------------------------------------------------------------------+*/
StringGetEditType(src)265 static XwEditType StringGetEditType(src)
266 /*--------------------------------------------------------------------------+*/
267   XwTextSource *src;
268 {
269     StringSourcePtr data;
270     data = (StringSourcePtr) src->data;
271     return(data->editMode);
272 }
273 
274 /*--------------------------------------------------------------------------+*/
XwStringSourceCheckData(src)275 static Boolean XwStringSourceCheckData(src)
276 /*--------------------------------------------------------------------------+*/
277     XwTextSource *src;
278 {   int  initial_size = 0;
279     StringSourcePtr data = (StringSourcePtr)src->data;
280 
281     data->max_size_flag = (data->max_size != MAGICVALUE);
282 
283     if (data->initial_string == NULL) {
284 	if (data->max_size_flag)
285 	  data->buffer_size = data->max_size;
286 	else
287 	  data->buffer_size = DEFAULTBUFFERSIZE;
288 	if (!data->buffer) data->length = 0;
289       }
290     else {
291       initial_size = XwStrlen(data->initial_string);
292       if (data->max_size_flag) {
293 	if (data->max_size < initial_size) {
294 	  XtWarning("Initial string size larger than XtNmaximumSize");
295 	  data->max_size = initial_size;
296 	}
297 	data->buffer_size = data->max_size;
298       }
299       else {
300 	data->buffer_size =
301 	  (initial_size < DEFAULTBUFFERSIZE) ? DEFAULTBUFFERSIZE :
302 	    ((initial_size / DEFAULTBUFFERSIZE) + 1) * DEFAULTBUFFERSIZE;
303       };
304       data->length = initial_size;
305     };
306 
307     if (data->buffer && initial_size)
308       data->buffer =
309 	(unsigned char *) XtRealloc(data->buffer, data->buffer_size);
310     else if (!data->buffer)
311       data->buffer = (unsigned char *) XtMalloc(data->buffer_size);
312 
313     if (initial_size) {
314       strcpy(data->buffer, data->initial_string);
315       data->initial_string = NULL;
316     }
317 }
318 
319 /***** Public routines *****/
320 
321 /*--------------------------------------------------------------------------+*/
XwStringSourceDestroy(src)322 void XwStringSourceDestroy (src)
323 /*--------------------------------------------------------------------------+*/
324   XwTextSource *src;
325 {
326     XtFree((char *) src->data);
327     XtFree((char *) src);
328 }
329 
330 /*--------------------------------------------------------------------------+*/
XwStringSourceCreate(w,args,argCount)331 XwTextSource *XwStringSourceCreate (w, args, argCount)
332 /*--------------------------------------------------------------------------+*/
333     Widget w;
334     ArgList args;
335     int     argCount;
336 {
337     XwTextSource *src;
338     StringSourcePtr data;
339 
340 
341     src = XtNew(XwTextSource);
342     src->read = StringReadText;
343     src->replace = StringReplaceText;
344     src->setLastPos = StringSetLastPos;
345     src->getLastPos = StringGetLastPos;
346     src->scan = StringScan;
347     src->editType = StringGetEditType;
348     src->resources = stringResources;
349     src->resource_num = XtNumber(stringResources);
350     src->check_data = XwStringSourceCheckData;
351     src->destroy = XwStringSourceDestroy;
352     data = XtNew(StringSourceData);
353     data->editMode = XwtextRead;
354     data->buffer = NULL;
355     data->initial_string = NULL;
356     data->length = 0;
357     data->buffer_size = 0;
358     data->max_size = 0;
359     data->max_size_flag = 0;
360     src->data = (int *)data;
361 
362     /* Use the name given to the TextEdit widget this source will go with.
363        This could be a problem if we allow multiple views on one source */
364 
365     XtGetSubresources (w, data, XtNstringSrc, "StringSrc",
366         stringResources, XtNumber(stringResources), args, argCount);
367 
368     src->data = (int *) (data);
369 
370     XwStringSourceCheckData(src);
371 
372     return src;
373 }
374 
375