|
|
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.