File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / Xtk / DiskSrc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static char rcsid[] = "$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/Xtk/DiskSrc.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $";
#endif lint

/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its 
 * documentation for any purpose and without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in 
 * supporting documentation, and that the name of Digital Equipment
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior permission.  
 * 
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
/* File: DiskSource.c */
/* Documentation for source specfic routine semantics may be found in the
 * TextPrivate.h file.
 */

#include "Xlib.h"
#include <stdio.h>
#include "Intrinsic.h"
#include "Atoms.h"
#include "Text.h"
#include "TextP.h"   /** included in all text subwindow files **/

void bcopy();

/** private DiskSource definitions **/

typedef struct _DiskSourceData {
    char       *fileName;
    FILE *file;		
    XtTextPosition position, 	/* file position of first char in buffer */
 		  length; 	/* length of file */
    char *buffer;		/* piece of file in memory */
    int charsInBuffer;		/* number of bytes used in memory */
    XtEditType editMode;		/* append, read */
} DiskSourceData, *DiskSourcePtr;

#define bufSize 1000

#define Increment(data, position, direction)\
{\
    if (direction == XtsdLeft) {\
	if (position > 0) \
	    position -= 1;\
    }\
    else {\
	if (position < data->length)\
	    position += 1;\
    }\
}

static XtResource diskResources[] = {
    {XtNfile, XtCFile, XrmRString, sizeof (char *),
        XtOffset(DiskSourcePtr, fileName), XrmRString, ""},
    {XtNeditType, XtCEditType, XtREditMode, sizeof(int), 
        XtOffset(DiskSourcePtr, editMode), XrmRString, "read"},
};

static char Look(data, position, direction)
  DiskSourcePtr data;
  XtTextPosition position;
  ScanDirection direction;
{

    if (direction == XtsdLeft) {
	if (position == 0)
	    return('\n');
	else {
	    FillBuffer(data, position - 1);
	    return(data->buffer[position - data->position - 1]);
	}
    }
    else {
	if (position == data->length)
	    return('\n');
	else {
	    FillBuffer(data, position);
	    return(data->buffer[position - data->position]);
	}
    }
}



int DiskReadText (src, pos, text, maxRead)
  XtTextSource *src;
  XtTextPosition pos;	/** starting position */
  XtTextBlock *text;	/** RETURNED: text read in */
  int maxRead;		/** max number of bytes to read **/
{
    XtTextPosition count;
    DiskSourcePtr data;

    data = (DiskSourcePtr) src->data;
    FillBuffer(data, pos);
    text->firstPos = pos;
    text->ptr = data->buffer + (pos - data->position);
    count = data->charsInBuffer - (pos - data->position);
    text->length = (maxRead > count) ? count : maxRead;
    return pos + text->length;
}

/*
 * this routine reads text starting at "pos" into memory.
 * Contains heuristic for keeping the read position centered in the buffer.
 */
static int FillBuffer (data, pos)
  DiskSourcePtr data;
  XtTextPosition pos;
{
    long readPos;
    if ((pos < data->position ||
	    pos >= data->position + data->charsInBuffer - 100) &&
	    data->charsInBuffer != data->length) {
	if (pos < (bufSize / 2))
	    readPos = 0;
	else
	    if (pos >= data->length - bufSize)
		readPos = data->length - bufSize;
	    else
		if (pos >= data->position + data->charsInBuffer - 100)
		    readPos = pos - (bufSize / 2);
		else
		    readPos = pos;
	(void) fseek(data->file, readPos, 0);
	data->charsInBuffer = fread(data->buffer, sizeof(char), bufSize,
				data->file);
	data->position = readPos;
    }
}

/*
 * This is a dummy routine for read only disk sources.
 */
/*ARGSUSED*/  /* keep lint happy */
static int DummyReplaceText (src, startPos, endPos, text, delta)
  XtTextSource *src;
  XtTextPosition startPos, endPos;
  XtTextBlock *text;
  int *delta;
{
    return(EDITERROR);
}


/*
 * This routine will only append to the end of a source.  If incorrect
 * starting and ending positions are given, an error will be returned.
 */
static int DiskAppendText (src, startPos, endPos, text, delta)
  XtTextSource *src;
  XtTextPosition startPos, endPos;
  XtTextBlock *text;
  int *delta;
{
    long topPosition = 0;
    char *tmpPtr;
    DiskSourcePtr data;
    data = (DiskSourcePtr) src->data;
    if (startPos != endPos || endPos != data->length)
        return (POSITIONERROR);
    /* write the new text to the end of the file */
    if (text->length > 0) {
	(void) fseek(data->file, data->length, 0);
	(void) fwrite(text->ptr, sizeof(char), text->length, data->file);
    } else
	/* if the delete key was hit, blank out last char in the file */
	if (text->length < 0) {
		(void) fseek(data->file, data->length-1, 0);
		(void) fwrite(" ", sizeof(char), 1, data->file);
	}
    /* need this in case the application trys to seek to end of file. */
     (void) fseek(data->file, topPosition, 2);	
     
    /* put the new text into the buffer in memory */
    data->length += text->length;
    if (data->charsInBuffer + text->length <= bufSize) {
/**** NOTE: need to check if text won't fit in the buffer ***/
	if (text->length > 0) {
		tmpPtr = data->buffer + data->charsInBuffer;
		bcopy(text->ptr, tmpPtr, text->length);
	}
	data->charsInBuffer += text->length;
    } else
	FillBuffer(data, data->length - text->length);

    *delta = text->length;
    return (EDITDONE);
}


static int DiskSetLastPos (src, lastPos)
  XtTextSource *src;
  XtTextPosition lastPos;
{
    ((DiskSourceData *)(src->data))->length = lastPos;
}

/*
 * This routine will start at
 * the "pos" position of the source and scan in the appropriate
 * direction until it finds something of the right sType.  It returns 
 * the new position.  If upon reading it hits the end of the buffer
 * in memory, it will refill the buffer.
 */
static XtTextPosition DiskScan (src, pos, sType, dir, count, include)
  XtTextSource 	 *src;
  XtTextPosition pos;
  ScanType 	 sType;
  ScanDirection  dir;
  int     	 count;
  Boolean	 include;
{
    DiskSourcePtr data;
    XtTextPosition position;
    int     i, whiteSpace;
    char    c;

    data = (DiskSourcePtr) src->data;
    position = pos;
    switch (sType) {
	case XtstPositions: 
	    if (!include && count > 0)
		count -= 1;
	    for (i = 0; i < count; i++) {
		Increment(data, position, dir);
	    }
	    break;
	case XtstWhiteSpace: 
	    for (i = 0; i < count; i++) {
		whiteSpace = 0;
		while (position >= 0 && position <= data->length) {
		    FillBuffer(data, position);
		    c = Look(data, position, dir);
		    whiteSpace = (c == ' ') || (c == '\t') || (c == '\n');
		    if (whiteSpace)
			break;
		    Increment(data, position, dir);
		}
		if (i + 1 != count)
		    Increment(data, position, dir);
	    }
	    if (include)
		Increment(data, position, dir);
	    break;
	case XtstEOL: 
	    for (i = 0; i < count; i++) {
		while (position >= 0 && position <= data->length) {
		    if (Look(data, position, dir) == '\n')
			break;
		    Increment(data, position, dir);
		}
		if (i + 1 != count)
		    Increment(data, position, dir);
	    }
	    if (include) {
	    /* later!!!check for last char in file # eol */
		Increment(data, position, dir);
	    }
	    break;
	case XtstFile: 
	case XtselectAll: 
	    if (dir == XtsdLeft)
		position = 0;
	    else
		position = data->length;
    }
    return(position);
}


static XtEditType DiskGetEditType(src)
  XtTextSource *src;
{
    DiskSourcePtr data;
    data = (DiskSourcePtr) src->data;
    return(data->editMode);
}

/******* Public routines **********/

int *XtDiskSourceCreate(w, args, argCount)
    Widget w;
    ArgList args;
    Cardinal     argCount;
{
    XtTextSource *src;
    DiskSourcePtr data;
    long topPosition = 0;
    char *tmpName;

    src = (XtTextSource *) XtMalloc(sizeof(XtTextSource));
    src->read = DiskReadText;
    src->setLastPos = DiskSetLastPos;
    src->scan = DiskScan;
    src->editType = DiskGetEditType;
    src->data = (int *) (XtMalloc(sizeof(DiskSourceData)));
    data = (DiskSourcePtr) src->data;

/* XXX name and class??? */
    XtGetSubresources (w, data, "subclass" , "subclass",
        diskResources, XtNumber(diskResources),
	args, argCount);

    /* NOTE:  Do not want to leave temp file around.  Must be unlinked
    somewhere */
    if (data->fileName == NULL) {
	tmpName = tmpnam (data->fileName);
	data->fileName = XtMalloc (sizeof (tmpName));	
	(void) strcpy (data->fileName, tmpName);
    }

    switch (data->editMode) {
        case XttextRead:
           if ((data->file = fopen(data->fileName, "r")) == 0)
                XtError("Cannot open source file in XtDiskSourceCreate");
            src->replace = DummyReplaceText;
            break;
        case XttextAppend:
            if ((data->file = fopen(data->fileName, "r+")) == 0)
                XtError("Cannot open source file in XtDiskSourceCreate");
            src->replace = DiskAppendText;
            break;
        default:
            if ((data->file = fopen(data->fileName, "r")) == 0)
                XtError("Cannot open source file in XtDiskSourceCreate");
            src->replace = DummyReplaceText;
    }
    (void) fseek(data->file, topPosition, 2);  
    data->length = ftell (data->file);  
    data->buffer = (char *) XtMalloc(bufSize);
    data->position = 0;
    data->charsInBuffer = 0;
    src->data = (int *) (data);
    return(int *) src;
}

void XtDiskSourceDestroy (src)
  XtTextSource *src;
{
    DiskSourcePtr data;
    data = (DiskSourcePtr) src->data;
    XtFree((char *) data->buffer);
    XtFree((char *) src->data);
    XtFree((char *) src);
}

unix.superglobalmegacorp.com

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