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