Annotation of researchv9/X11/src/X.V11R1/clients/xedit/EDiskSrc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.