|
|
1.1 root 1: #ifndef lint
2: static char rcsid[] = "$Header: DiskSrc.c,v 1.3 87/09/13 13:28:37 swick Exp $";
3: #endif lint
4:
5: /*
6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
7: *
8: * All Rights Reserved
9: *
10: * Permission to use, copy, modify, and distribute this software and its
11: * documentation for any purpose and without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and that
13: * both that copyright notice and this permission notice appear in
14: * supporting documentation, and that the name of Digital Equipment
15: * Corporation not be used in advertising or publicity pertaining to
16: * distribution of the software without specific, written prior permission.
17: *
18: *
19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25: * SOFTWARE.
26: */
27: /* File: DiskSource.c */
28: /* Documentation for source specfic routine semantics may be found in the
29: * TextPrivate.h file.
30: */
31:
32: #include "Xlib.h"
33: #include <stdio.h>
34: #include "Intrinsic.h"
35: #include "Atoms.h"
36: #include "Text.h"
37: #include "TextP.h" /** included in all text subwindow files **/
38:
39: void bcopy();
40:
41: /** private DiskSource definitions **/
42:
43: typedef struct _DiskSourceData {
44: char *fileName;
45: FILE *file;
46: XtTextPosition position, /* file position of first char in buffer */
47: length; /* length of file */
48: char *buffer; /* piece of file in memory */
49: int charsInBuffer; /* number of bytes used in memory */
50: XtEditType editMode; /* append, read */
51: } DiskSourceData, *DiskSourcePtr;
52:
53: #define bufSize 1000
54:
55: #define Increment(data, position, direction)\
56: {\
57: if (direction == XtsdLeft) {\
58: if (position > 0) \
59: position -= 1;\
60: }\
61: else {\
62: if (position < data->length)\
63: position += 1;\
64: }\
65: }
66:
67: static XtResource diskResources[] = {
68: {XtNfile, XtCFile, XrmRString, sizeof (char *),
69: XtOffset(DiskSourcePtr, fileName), XrmRString, ""},
70: {XtNeditType, XtCEditType, XtREditMode, sizeof(int),
71: XtOffset(DiskSourcePtr, editMode), XrmRString, "read"},
72: };
73:
74: static char Look(data, position, direction)
75: DiskSourcePtr data;
76: XtTextPosition position;
77: ScanDirection direction;
78: {
79:
80: if (direction == XtsdLeft) {
81: if (position == 0)
82: return('\n');
83: else {
84: FillBuffer(data, position - 1);
85: return(data->buffer[position - data->position - 1]);
86: }
87: }
88: else {
89: if (position == data->length)
90: return('\n');
91: else {
92: FillBuffer(data, position);
93: return(data->buffer[position - data->position]);
94: }
95: }
96: }
97:
98:
99:
100: int DiskReadText (src, pos, text, maxRead)
101: XtTextSource *src;
102: XtTextPosition pos; /** starting position */
103: XtTextBlock *text; /** RETURNED: text read in */
104: int maxRead; /** max number of bytes to read **/
105: {
106: XtTextPosition count;
107: DiskSourcePtr data;
108:
109: data = (DiskSourcePtr) src->data;
110: FillBuffer(data, pos);
111: text->firstPos = pos;
112: text->ptr = data->buffer + (pos - data->position);
113: count = data->charsInBuffer - (pos - data->position);
114: text->length = (maxRead > count) ? count : maxRead;
115: return pos + text->length;
116: }
117:
118: /*
119: * this routine reads text starting at "pos" into memory.
120: * Contains heuristic for keeping the read position centered in the buffer.
121: */
122: static int FillBuffer (data, pos)
123: DiskSourcePtr data;
124: XtTextPosition pos;
125: {
126: long readPos;
127: if ((pos < data->position ||
128: pos >= data->position + data->charsInBuffer - 100) &&
129: data->charsInBuffer != data->length) {
130: if (pos < (bufSize / 2))
131: readPos = 0;
132: else
133: if (pos >= data->length - bufSize)
134: readPos = data->length - bufSize;
135: else
136: if (pos >= data->position + data->charsInBuffer - 100)
137: readPos = pos - (bufSize / 2);
138: else
139: readPos = pos;
140: (void) fseek(data->file, readPos, 0);
141: data->charsInBuffer = fread(data->buffer, sizeof(char), bufSize,
142: data->file);
143: data->position = readPos;
144: }
145: }
146:
147: /*
148: * This is a dummy routine for read only disk sources.
149: */
150: /*ARGSUSED*/ /* keep lint happy */
151: static int DummyReplaceText (src, startPos, endPos, text, delta)
152: XtTextSource *src;
153: XtTextPosition startPos, endPos;
154: XtTextBlock *text;
155: int *delta;
156: {
157: return(EDITERROR);
158: }
159:
160:
161: /*
162: * This routine will only append to the end of a source. If incorrect
163: * starting and ending positions are given, an error will be returned.
164: */
165: static int DiskAppendText (src, startPos, endPos, text, delta)
166: XtTextSource *src;
167: XtTextPosition startPos, endPos;
168: XtTextBlock *text;
169: int *delta;
170: {
171: long topPosition = 0;
172: char *tmpPtr;
173: DiskSourcePtr data;
174: data = (DiskSourcePtr) src->data;
175: if (startPos != endPos || endPos != data->length)
176: return (POSITIONERROR);
177: /* write the new text to the end of the file */
178: if (text->length > 0) {
179: (void) fseek(data->file, data->length, 0);
180: (void) fwrite(text->ptr, sizeof(char), text->length, data->file);
181: } else
182: /* if the delete key was hit, blank out last char in the file */
183: if (text->length < 0) {
184: (void) fseek(data->file, data->length-1, 0);
185: (void) fwrite(" ", sizeof(char), 1, data->file);
186: }
187: /* need this in case the application trys to seek to end of file. */
188: (void) fseek(data->file, topPosition, 2);
189:
190: /* put the new text into the buffer in memory */
191: data->length += text->length;
192: if (data->charsInBuffer + text->length <= bufSize) {
193: /**** NOTE: need to check if text won't fit in the buffer ***/
194: if (text->length > 0) {
195: tmpPtr = data->buffer + data->charsInBuffer;
196: bcopy(text->ptr, tmpPtr, text->length);
197: }
198: data->charsInBuffer += text->length;
199: } else
200: FillBuffer(data, data->length - text->length);
201:
202: *delta = text->length;
203: return (EDITDONE);
204: }
205:
206:
207: static int DiskSetLastPos (src, lastPos)
208: XtTextSource *src;
209: XtTextPosition lastPos;
210: {
211: ((DiskSourceData *)(src->data))->length = lastPos;
212: }
213:
214: /*
215: * This routine will start at
216: * the "pos" position of the source and scan in the appropriate
217: * direction until it finds something of the right sType. It returns
218: * the new position. If upon reading it hits the end of the buffer
219: * in memory, it will refill the buffer.
220: */
221: static XtTextPosition DiskScan (src, pos, sType, dir, count, include)
222: XtTextSource *src;
223: XtTextPosition pos;
224: ScanType sType;
225: ScanDirection dir;
226: int count;
227: Boolean include;
228: {
229: DiskSourcePtr data;
230: XtTextPosition position;
231: int i, whiteSpace;
232: char c;
233:
234: data = (DiskSourcePtr) src->data;
235: position = pos;
236: switch (sType) {
237: case XtstPositions:
238: if (!include && count > 0)
239: count -= 1;
240: for (i = 0; i < count; i++) {
241: Increment(data, position, dir);
242: }
243: break;
244: case XtstWhiteSpace:
245: for (i = 0; i < count; i++) {
246: whiteSpace = 0;
247: while (position >= 0 && position <= data->length) {
248: FillBuffer(data, position);
249: c = Look(data, position, dir);
250: whiteSpace = (c == ' ') || (c == '\t') || (c == '\n');
251: if (whiteSpace)
252: break;
253: Increment(data, position, dir);
254: }
255: if (i + 1 != count)
256: Increment(data, position, dir);
257: }
258: if (include)
259: Increment(data, position, dir);
260: break;
261: case XtstEOL:
262: for (i = 0; i < count; i++) {
263: while (position >= 0 && position <= data->length) {
264: if (Look(data, position, dir) == '\n')
265: break;
266: Increment(data, position, dir);
267: }
268: if (i + 1 != count)
269: Increment(data, position, dir);
270: }
271: if (include) {
272: /* later!!!check for last char in file # eol */
273: Increment(data, position, dir);
274: }
275: break;
276: case XtstFile:
277: case XtselectAll:
278: if (dir == XtsdLeft)
279: position = 0;
280: else
281: position = data->length;
282: }
283: return(position);
284: }
285:
286:
287: static XtEditType DiskGetEditType(src)
288: XtTextSource *src;
289: {
290: DiskSourcePtr data;
291: data = (DiskSourcePtr) src->data;
292: return(data->editMode);
293: }
294:
295: /******* Public routines **********/
296:
297: int *XtDiskSourceCreate(w, args, argCount)
298: Widget w;
299: ArgList args;
300: Cardinal argCount;
301: {
302: XtTextSource *src;
303: DiskSourcePtr data;
304: long topPosition = 0;
305: char *tmpName;
306:
307: src = (XtTextSource *) XtMalloc(sizeof(XtTextSource));
308: src->read = DiskReadText;
309: src->setLastPos = DiskSetLastPos;
310: src->scan = DiskScan;
311: src->editType = DiskGetEditType;
312: src->data = (int *) (XtMalloc(sizeof(DiskSourceData)));
313: data = (DiskSourcePtr) src->data;
314:
315: /* XXX name and class??? */
316: XtGetSubresources (w, data, "subclass" , "subclass",
317: diskResources, XtNumber(diskResources),
318: args, argCount);
319:
320: /* NOTE: Do not want to leave temp file around. Must be unlinked
321: somewhere */
322: if (data->fileName == NULL) {
323: tmpName = tmpnam (data->fileName);
324: data->fileName = XtMalloc (sizeof (tmpName));
325: (void) strcpy (data->fileName, tmpName);
326: }
327:
328: switch (data->editMode) {
329: case XttextRead:
330: if ((data->file = fopen(data->fileName, "r")) == 0)
331: XtError("Cannot open source file in XtDiskSourceCreate");
332: src->replace = DummyReplaceText;
333: break;
334: case XttextAppend:
335: if ((data->file = fopen(data->fileName, "r+")) == 0)
336: XtError("Cannot open source file in XtDiskSourceCreate");
337: src->replace = DiskAppendText;
338: break;
339: default:
340: if ((data->file = fopen(data->fileName, "r")) == 0)
341: XtError("Cannot open source file in XtDiskSourceCreate");
342: src->replace = DummyReplaceText;
343: }
344: (void) fseek(data->file, topPosition, 2);
345: data->length = ftell (data->file);
346: data->buffer = (char *) XtMalloc(bufSize);
347: data->position = 0;
348: data->charsInBuffer = 0;
349: src->data = (int *) (data);
350: return(int *) src;
351: }
352:
353: void XtDiskSourceDestroy (src)
354: XtTextSource *src;
355: {
356: DiskSourcePtr data;
357: data = (DiskSourcePtr) src->data;
358: XtFree((char *) data->buffer);
359: XtFree((char *) src->data);
360: XtFree((char *) src);
361: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.