|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcs_id[] = "$Header: EDiskSrc.c,v 1.5 87/09/11 08:21:59 toddb Exp $"; ! 3: #endif ! 4: ! 5: /* ! 6: * COPYRIGHT 1987 ! 7: * DIGITAL EQUIPMENT CORPORATION ! 8: * MAYNARD, MASSACHUSETTS ! 9: * ALL RIGHTS RESERVED. ! 10: * ! 11: * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND ! 12: * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ! 13: * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ! 14: * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ! 15: * ! 16: * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, ! 17: * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT ! 18: * SET FORTH ABOVE. ! 19: * ! 20: * ! 21: * Permission to use, copy, modify, and distribute this software and its ! 22: * documentation for any purpose and without fee is hereby granted, provided ! 23: * that the above copyright notice appear in all copies and that both that ! 24: * copyright notice and this permission notice appear in supporting documentation, ! 25: * and that the name of Digital Equipment Corporation not be used in advertising ! 26: * or publicity pertaining to distribution of the software without specific, ! 27: * written prior permission. ! 28: */ ! 29: ! 30: /* File: TEDiskSource.c - last edit by */ ! 31: /* weissman: 25 Aug 86 */ ! 32: ! 33: #include <sys/types.h> ! 34: #include <sys/stat.h> ! 35: #include <sys/file.h> ! 36: #include "xedit.h" ! 37: /* Private definitions. */ ! 38: ! 39: #define BUFSIZE 512 ! 40: ! 41: extern char *malloc(); ! 42: extern char *realloc(); ! 43: extern char *strcpy(); ! 44: ! 45: typedef struct { ! 46: char *buf; ! 47: int length; ! 48: int maxlength; ! 49: long start; ! 50: } PieceRec, *PiecePtr; ! 51: ! 52: typedef struct { ! 53: int file; ! 54: char *name; ! 55: XtTextPosition length; ! 56: XtTextPosition origlength; ! 57: int numpieces; ! 58: PiecePtr piece; ! 59: short changed, everchanged; ! 60: short startsvalid; ! 61: short eversaved; ! 62: XtEditType editMode; ! 63: } EDiskRec, *EDiskPtr; ! 64: ! 65: ! 66: static CalculateStarts(data) ! 67: EDiskPtr data; ! 68: { ! 69: int i; ! 70: PiecePtr piece; ! 71: long start = 0; ! 72: for (i = 0, piece = data->piece; i < data->numpieces; i++, piece++) { ! 73: piece->start = start; ! 74: start += piece->length; ! 75: } ! 76: data->startsvalid = TRUE; ! 77: } ! 78: ! 79: static ReadPiece(data, i) ! 80: EDiskPtr data; ! 81: int i; ! 82: { ! 83: PiecePtr piece = data->piece + i; ! 84: piece->maxlength = piece->length; ! 85: piece->buf = malloc(piece->maxlength); ! 86: lseek(data->file, i * BUFSIZE, 0); ! 87: read(data->file, piece->buf, piece->length); ! 88: } ! 89: ! 90: ! 91: ! 92: static PiecePtr PieceFromPosition(data, position) ! 93: EDiskPtr data; ! 94: XtTextPosition position; ! 95: { ! 96: int i; ! 97: PiecePtr piece; ! 98: if (!data->everchanged) { ! 99: i = position / BUFSIZE; ! 100: if (i >= data->numpieces) i = data->numpieces - 1; ! 101: piece = data->piece + i; ! 102: } else { ! 103: if (!data->startsvalid) ! 104: CalculateStarts(data); ! 105: for (i = 0, piece = data->piece; i < data->numpieces - 1; i++, piece++) ! 106: if (position < piece->start + piece->length) ! 107: break; ! 108: } ! 109: if (!piece->buf) ReadPiece(data, i); ! 110: return piece; ! 111: } ! 112: ! 113: static XtTextPosition CoerceToLegalPosition(data, position) ! 114: EDiskPtr data; ! 115: XtTextPosition position; ! 116: { ! 117: return (position < 0) ? 0 : ! 118: ((position > data->length) ? data->length : position); ! 119: } ! 120: ! 121: ! 122: /* Semi-public definitions */ ! 123: ! 124: static EDiskReadText(src, position, text, maxRead) ! 125: XtTextSource *src; ! 126: XtTextPosition position; ! 127: XtTextBlock *text; ! 128: int maxRead; ! 129: { ! 130: EDiskPtr data = (EDiskPtr) src->data; ! 131: PiecePtr piece; ! 132: int count; ! 133: text->firstPos = position; ! 134: if (position < data->length) { ! 135: piece = PieceFromPosition(data, position); ! 136: text->ptr = piece->buf + (position - piece->start); ! 137: count = piece->length - (position - piece->start); ! 138: text->length = (count < maxRead) ? count : maxRead; ! 139: } ! 140: else { ! 141: text->length = 0; ! 142: text->ptr = ""; ! 143: } ! 144: return position + text->length; ! 145: } ! 146: ! 147: ! 148: static EDiskReplaceText(src, startPos, endPos, text, Delta) ! 149: XtTextSource *src; ! 150: XtTextPosition startPos, endPos; ! 151: XtTextBlock *text; ! 152: int *Delta; ! 153: { ! 154: EDiskPtr data = (EDiskPtr) src->data; ! 155: PiecePtr piece, piece2; ! 156: int oldlength = endPos - startPos; ! 157: int delta = text->length - oldlength; ! 158: int i; ! 159: switch (data->editMode) { ! 160: case XttextAppend: ! 161: if (startPos != endPos || endPos!= data->length) ! 162: return (POSITIONERROR); ! 163: break; ! 164: case XttextRead: ! 165: return (EDITERROR); ! 166: case XttextEdit: ! 167: break; ! 168: default: ! 169: return (EDITERROR); ! 170: } ! 171: ! 172: if (delta == 0 && oldlength == 0) ! 173: return 0; ! 174: data->length += delta; ! 175: piece = PieceFromPosition(data, startPos); ! 176: if (oldlength > 0) { ! 177: piece2 = PieceFromPosition(data, endPos - 1); ! 178: if (piece != piece2) { ! 179: oldlength = endPos - piece2->start; ! 180: piece2->length -= oldlength; ! 181: for (i = 0; i < piece2->length; i++) ! 182: piece2->buf[i] = piece2->buf[i + oldlength]; ! 183: for (piece2--; piece2 > piece; piece2--) ! 184: piece2->length = 0; ! 185: oldlength = piece->length - (startPos - piece->start); ! 186: delta = text->length - oldlength; ! 187: } ! 188: } ! 189: data->changed = data->everchanged = TRUE; ! 190: data->startsvalid = FALSE; ! 191: piece->length += delta; ! 192: if (piece->length > piece->maxlength) { ! 193: do ! 194: piece->maxlength *= 2; ! 195: while (piece->length > piece->maxlength); ! 196: piece->buf = realloc(piece->buf, piece->maxlength); ! 197: } ! 198: if (delta < 0) /* insert shorter than delete, text getting ! 199: shorter */ ! 200: for (i = startPos - piece->start; i < piece->length; i++) ! 201: piece->buf[i] = piece->buf[i - delta]; ! 202: else ! 203: if (delta > 0) /* insert longer than delete, text getting ! 204: longer */ ! 205: for (i = piece->length - delta; ! 206: i >= startPos - piece->start; ! 207: i--) ! 208: piece->buf[i + delta] = piece->buf[i]; ! 209: if (text->length) /* do insert */ ! 210: for (i = 0; i < text->length; ++i) ! 211: if ((piece->buf[startPos - piece->start + i] = text->ptr[i]) == CR) ! 212: piece->buf[startPos - piece->start + i] = LF; ! 213: *Delta = text->length - (endPos - startPos); ! 214: return EDITDONE; ! 215: } ! 216: ! 217: ! 218: static XtTextPosition EDiskGetLastPos(src) ! 219: XtTextSource *src; ! 220: { ! 221: return ((EDiskPtr) src->data)->length; ! 222: } ! 223: ! 224: ! 225: static EDiskSetLastPos(src) ! 226: XtTextSource *src; ! 227: { ! 228: } ! 229: ! 230: #define Look(index, c)\ ! 231: { \ ! 232: if ((dir == XtsdLeft && index <= 0) || \ ! 233: (dir == XtsdRight && index >= data->length)) \ ! 234: c = 0; \ ! 235: else { \ ! 236: if (index + doff < piece->start || \ ! 237: index + doff >= piece->start + piece->length) \ ! 238: piece = PieceFromPosition(data, index + doff); \ ! 239: c = piece->buf[index + doff - piece->start]; \ ! 240: } \ ! 241: } ! 242: ! 243: ! 244: ! 245: static XtTextPosition EDiskScan(src, position, sType, dir, count, include) ! 246: XtTextSource *src; ! 247: XtTextPosition position; ! 248: ScanType sType; ! 249: ScanDirection dir; ! 250: int count, include; ! 251: { ! 252: EDiskPtr data = (EDiskPtr) src->data; ! 253: XtTextPosition index; ! 254: PiecePtr piece; ! 255: char c; ! 256: int ddir, doff, i, whiteSpace; ! 257: ddir = (dir == XtsdRight) ? 1 : -1; ! 258: doff = (dir == XtsdRight) ? 0 : -1; ! 259: ! 260: index = position; ! 261: piece = data->piece; ! 262: switch (sType) { ! 263: case XtstPositions: ! 264: if (!include && count > 0) ! 265: count--; ! 266: index = CoerceToLegalPosition(data, index + count * ddir); ! 267: break; ! 268: case XtstWhiteSpace: /* %%% This seems to ignore the fact that ! 269: whitespace can come in big chunks */ ! 270: for (i = 0; i < count; i++) { ! 271: whiteSpace = -1; ! 272: while (index >= 0 && index <= data->length) { ! 273: Look(index, c); ! 274: if ((c == ' ') || (c == '\t') || (c == '\n')) { ! 275: if (whiteSpace < 0) whiteSpace = index; ! 276: } else if (whiteSpace >= 0) ! 277: break; ! 278: index += ddir; ! 279: } ! 280: } ! 281: if (!include) { ! 282: if (whiteSpace < 0 && dir == XtsdRight) whiteSpace = data->length; ! 283: index = whiteSpace; ! 284: } ! 285: index = CoerceToLegalPosition(data, index); ! 286: break; ! 287: case XtstEOL: ! 288: for (i = 0; i < count; i++) { ! 289: while (index >= 0 && index <= data->length) { ! 290: Look(index, c); ! 291: if (c == '\n') ! 292: break; ! 293: index += ddir; ! 294: } ! 295: if (i < count - 1) ! 296: index += ddir; ! 297: } ! 298: if (include) ! 299: index += ddir; ! 300: index = CoerceToLegalPosition(data, index); ! 301: break; ! 302: case XtstFile: ! 303: if (dir == XtsdLeft) ! 304: index = 0; ! 305: else ! 306: index = data->length; ! 307: break; ! 308: } ! 309: return index; ! 310: } ! 311: ! 312: static XtEditType TEDiskGetEditType(src) ! 313: XtTextSource *src; ! 314: { ! 315: EDiskPtr data = (EDiskPtr) src->data; ! 316: return(data->editMode); ! 317: } ! 318: ! 319: ! 320: /* Public definitions. */ ! 321: ! 322: XtTextSource *TCreateEDiskSource(name, mode) ! 323: char *name; ! 324: XtEditType mode; ! 325: { ! 326: XtTextSource * src; ! 327: EDiskPtr data; ! 328: struct stat stat; ! 329: int i; ! 330: src = (XtTextSource *) malloc(sizeof(XtTextSource)); ! 331: src->read = EDiskReadText; ! 332: src->replace = EDiskReplaceText; ! 333: src->getLastPos = EDiskGetLastPos; ! 334: src->setLastPos = EDiskSetLastPos; ! 335: src->editType = TEDiskGetEditType; ! 336: src->scan = EDiskScan; ! 337: data = (EDiskPtr) malloc(sizeof(EDiskRec)); ! 338: src->data = (int *) data; ! 339: data->file = open(name, O_RDONLY | O_CREAT, 0666); ! 340: data->name = strcpy(malloc(strlen(name) + 1), name); ! 341: fstat(data->file, &stat); ! 342: data->length = data->origlength = stat.st_size; ! 343: data->numpieces = (data->length + BUFSIZE - 1) / BUFSIZE; ! 344: if (data->numpieces < 1) ! 345: data->numpieces = 1; ! 346: data->piece = (PiecePtr) malloc(data->numpieces * sizeof(PieceRec)); ! 347: for (i = 0; i < data->numpieces; i++) { ! 348: data->piece[i].buf = 0; ! 349: data->piece[i].length = BUFSIZE; ! 350: data->piece[i].start = i * BUFSIZE; ! 351: } ! 352: data->piece[data->numpieces - 1].length -= ! 353: data->numpieces * BUFSIZE - data->length; ! 354: data->startsvalid = TRUE; ! 355: data->changed = data->everchanged = data->eversaved = FALSE; ! 356: if (data->length == 0) { ! 357: data->piece[0].buf = malloc(1); ! 358: data->piece[0].maxlength = 1; ! 359: } ! 360: data->editMode = mode; ! 361: return src; ! 362: } ! 363: ! 364: ! 365: TEDiskChanged(src) ! 366: XtTextSource *src; ! 367: { ! 368: return ((EDiskPtr) src->data)->changed; ! 369: } ! 370: ! 371: TEDiskSaveFile(src) ! 372: XtTextSource *src; ! 373: { ! 374: EDiskPtr data = (EDiskPtr) src->data; ! 375: PiecePtr piece; ! 376: int i, needlseek; ! 377: if (!data->changed) ! 378: return; ! 379: data->changed = FALSE; ! 380: if (!data->eversaved) { ! 381: data->eversaved = TRUE; ! 382: close(data->file); ! 383: data->file = open(data->name, O_RDWR, 0666); ! 384: } ! 385: if (!data->startsvalid) ! 386: CalculateStarts(data); ! 387: for (i = 0, piece = data->piece; i < data->numpieces; i++, piece++) { ! 388: if (!(piece->buf) && i * BUFSIZE != piece->start) ! 389: ReadPiece(data, i); ! 390: } ! 391: needlseek = TRUE; ! 392: for (i = 0, piece = data->piece; i < data->numpieces; i++, piece++) { ! 393: if (piece->buf) { ! 394: if (needlseek) { ! 395: lseek(data->file, piece->start, 0); ! 396: needlseek = FALSE; ! 397: } ! 398: write(data->file, piece->buf, piece->length); ! 399: } ! 400: else ! 401: needlseek = TRUE; ! 402: } ! 403: if (data->length < data->origlength) ! 404: ftruncate(data->file, data->length); ! 405: data->origlength = data->length; ! 406: } ! 407: ! 408: TEDiskSaveAsFile(src, filename) ! 409: XtTextSource *src; ! 410: char *filename; ! 411: { ! 412: EDiskPtr data = (EDiskPtr) src->data; ! 413: int i; ! 414: PiecePtr piece; ! 415: if (strcmp(filename, data->name) != 0) { ! 416: for (i = 0, piece = data->piece; i < data->numpieces; i++, piece++) ! 417: if (!(piece->buf)) ! 418: ReadPiece(data, i); ! 419: data->eversaved = FALSE; ! 420: data->origlength = 0; ! 421: data->file = creat(filename, 0666); ! 422: data->eversaved = TRUE; ! 423: data->origlength = 0; ! 424: free(data->name); ! 425: data->name = strcpy(malloc(strlen(filename) + 1), filename); ! 426: data->changed = TRUE; ! 427: } ! 428: TEDiskSaveFile(src); ! 429: } ! 430: ! 431: ! 432: TDestroyEDiskSource(src) ! 433: XtTextSource *src; ! 434: { ! 435: EDiskPtr data = (EDiskPtr) src->data; ! 436: int i; ! 437: char *ptr; ! 438: close(data->file); ! 439: for (i=0 ; i<data->numpieces ; i++) ! 440: if (ptr = data->piece[i].buf) free(ptr); ! 441: free(data->piece); ! 442: free(data->name); ! 443: free(data); ! 444: free(src); ! 445: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.