Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

incomplete text editor in C

Name: Anonymous 2008-04-26 6:12

Supports buffers, with a few lines added supports regex, and pretty much any text manipulation as long as you provide the function to manipulate the text in some way.
It's in standard C so should compile everywhere.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#define MAXBUF    64

typedef struct _list {
    char buf[BUFSIZ];    /* text of line */
    size_t n;        /* sizeof text */
    struct _list *next;    /* next line */
} list;



typedef struct {

    list *lines;            /* actual lines in the file */
    size_t nlines;            /* number of lines in the file */
    FILE *stream;            /* stream we edit, if a stream is present */
    char name[FILENAME_MAX+1];    /* name of stream, or anonymous */

#define FBUF_A 0
#define FBUF_R 1
#define FBUF_W 2
    int mode;            /* read/write/anon buf */

    size_t curline;            /* current line we operate on */

} filebuf;

struct foo {

    filebuf *fbuf[MAXBUF];
    size_t nbuf;
    size_t curbuf;

};

typedef int cmdfunc(const char *, struct foo *);


#define funcname(x) (CMD_##x)

#define getname(x) ((x)->name[0] == 0 ? "[noname]" : (const char *)(x)->name)
void setname(filebuf *, const char *);
filebuf *newbuf(const char *);
int addbuf(struct foo *, const char *);
void killbuf(filebuf *);
void rembuf(struct foo *, size_t);
void destroylist(list *);
void destroyfiles(struct foo *);

int cmd_exec(const char *, struct foo *);
int cmd_result(FILE *, int);
void getword(char *, const char *);
int changebuf(struct foo *, size_t);
int changeline(filebuf *, size_t);
void printbufname(const struct foo *, size_t);

/* CMD commands */

cmdfunc funcname(ls);
cmdfunc funcname(b);

int main(int argc, char **argv) {

    size_t i = 0;
    struct foo files;
    int ret;
    char buf[BUFSIZ];
    char *p, *s;
    const char *prompt = "> ";

    if(argc < 2)
        return 0;

    memset(&files, 0, sizeof files);

    for(i = 1; i < (size_t)argc; i++) {
        ret = addbuf(&files, argv[i]);
        if(ret == -1)
            perror(argv[i]);
        else if(ret == 1)
            fprintf(stderr, "too many buffers. (%lu)\n", (unsigned long)MAXBUF);
        else printf("opened %s\n", argv[i][0] == 0 ? "[noname]" : argv[i]);

    }

    printf("%s", prompt);
    fflush(stdout);

    while(fgets(buf, sizeof buf, stdin) != NULL) {

        ret = 0;

        for(p = buf;  *p; p = s + 1) {
            s = strpbrk(p, ";\n");
            if(s != NULL)
                *s = 0;

            if((ret = cmd_exec(p, &files)) != 0)
                fprintf(stderr, "%lu %s: ", (unsigned long)files.curbuf, getname(files.fbuf[files.curbuf]));
           
            cmd_result(stderr, ret);
            printf("%s", prompt);
            fflush(stdout);
        }
    }
   
    destroyfiles(&files);
    putchar('\n');

    return 0;
}

int funcname(ls)(const char *str, struct foo *files) {

    size_t n;

    (void)str;

    for(n = 0; n < files->nbuf; n++)
        printbufname(files, n);

    return 0;
}


int funcname(b)(const char *str, struct foo *files) {

    const char *p;

    if(*str == 0) {
        printbufname(files, files->curbuf);
        return 0;
    }

    for(p = str; *p && isdigit((unsigned char)*p); p++)
        ;
    if(*p != 0 && !isspace((unsigned char)*p)) {
        /*
           EDIT HERE
           return bad buf id
         */
        return -1;
    }

    return    changebuf(files, atoi(str));
}

void printbufname(const struct foo *files, size_t id) {

    printf("%lu %s\n", (unsigned long)id, getname(files->fbuf[id]));
}


int changeline(filebuf *file, size_t id) {

    if(id >= file->nlines)
        return -1;

    file->curline = id;
    return 0;
}

int cmd_result(FILE *out , int ret) {

    if(ret != 0)
        fprintf(out, "some error\n");

    return 0;

}

int changebuf(struct foo *files, size_t id) {

    if(id < files->nbuf) {
        files->curbuf = id;
        return 0;
    }
    /* EDIT HERE
       return BADBUFID
       */
    else return -1;

}

void getword(char *buf, const char *str) {
   
    char *p;

    p = strchr(str, ' ');
    if(p == NULL)
        strcpy(buf, str);
    else {
        strncpy(buf, str, p - str);
        buf[p - str] = 0;
    }


}

int cmd_exec(const char *str, struct foo *files) {

    char buf[BUFSIZ];
    size_t n;

    /* EDIT HERE */

    struct {
        const char *cmd;
        cmdfunc *f;
    } commands[] = {
        { "ls", funcname(ls) },
        { "b", funcname(b) }
    };

    getword(buf, str);

    for(n = 0; n < sizeof commands / sizeof commands[0]; n++)
        if(strcmp(buf, commands[n].cmd) == 0)
            return commands[n].f(str + strlen(buf) + 1, files);

    /* EDIT HERE
       return BAD COMMAND
       */

    return -1;

}

void destroyfiles(struct foo *files) {
   
    size_t i;
   
    for(i = files->nbuf - 1; i != (size_t)-1; i--) {
#ifdef TED_DEBUG
        printf("filename: '%s'\n", getname(files->fbuf[i]));
        printf("mode opened: %d\n", files->fbuf[i]->mode);
        printf("%p\n", (void *)files->fbuf[i]->lines);
#endif
        rembuf(files, i);

    }

}
void setname(filebuf *file, const char *name) {

    memset(file->name, 0, sizeof file->name);
    if(name != NULL)
        strncpy(file->name, name, sizeof file->name - 1);
}

void rembuf(struct foo *ptr, size_t n) {

    if(n > ptr->nbuf)
        return;

    killbuf(ptr->fbuf[n]);

    if(n != ptr->nbuf)
        memmove(&ptr->fbuf[n], &ptr->fbuf[n + 1],
                (ptr->nbuf - n) * sizeof ptr->nbuf);
    ptr->nbuf--;


}


void killbuf(filebuf *file) {

    if(file->stream != NULL) {
        fflush(file->stream);
        fclose(file->stream);
    }

    destroylist(file->lines);

}

void destroylist(list *lines) {
    list *p = NULL;

    if(lines)
        p = lines->next;
    free(lines);

    while(p != NULL) {
        lines = p->next;
        free(p);
        p = lines;
    }

}

filebuf *newbuf(const char *path) {

    filebuf *ret;
    FILE *fp;
    int mode;
    char buf[BUFSIZ];
    list **p;

    if(path != NULL && *path != 0) {

        fp = fopen(path, "r+");
        mode = FBUF_W;
        if(fp == NULL) {
            fp = fopen(path, "r");
            mode = FBUF_R;
        }
        if(fp == NULL) {
            fp = fopen(path, "w");
            mode = FBUF_W;
        }
   
        if(fp == NULL)
            return NULL;
   
        ret = malloc(sizeof *ret);
        if(ret == NULL) {
            fclose(fp);
            return NULL;
        }
    }
    else {
        fp = NULL;
        mode = FBUF_A;
        ret = malloc(sizeof *ret);
        if(ret == NULL)
            return NULL;
    }

    memset(ret, 0, sizeof *ret);

    ret->mode = mode;
    ret->stream = fp;


    p = &ret->lines;

    /* in case of anonbuf
       curline = 0, nlines = 0
       which is the same with opening an empty file
       !FIX!
       */

    while(fp && fgets(buf, sizeof buf, fp) != NULL) {

        *p = malloc(sizeof **p);

        if(*p == NULL) {
            free(ret);
            fclose(fp);
            return NULL;
        }
       
        (*p)->next = NULL;
        strcpy((*p)->buf, buf);
        (*p)->n = strlen(buf);
        p = &(*p)->next;
        ret->nlines++;
    }

    return ret;

}

int addbuf(struct foo *files, const char *path) {


    if(files->nbuf != MAXBUF) {
        files->fbuf[files->nbuf] = newbuf(path);
        if(files->fbuf[files->nbuf] == NULL)
            return -1;
        setname(files->fbuf[files->nbuf], path);
        files->nbuf++;
        return 0;
    }
    return 1;
}

Name: Anonymous 2008-04-27 15:47

>>15
80s abandonware are not text editors.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List