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