/*
 * recenteditor_data.c
 *
 * A programmers editor
 *
 * Structures to hold the current file contents.
 *
 * HEADER FILE
 *
 * Author: Dario Rodriguez dario@softhome.net
 * This program is licensed under the terms of GNU GPL v2.1+
 */

#include <limits.h>

typedef struct whatin_t {
        int nlcount;
} whatin_t;

typedef struct rechunk_t {
        whatin_t whatin;
        int whatin_fresh;
        int useddata;
        unsigned char data[1];
} rechunk_t;

typedef struct undo_t {
        char type;
        long off;
        long len;
        long posorig;
        long posdest;
        char prehash[129];
        char posthash[129];
} undo_t;

typedef struct undostack_t {
        int sizeundo;
        int usedundo;
        undo_t *undo;
        long sizebuf;
        long usedbuf;
        char *buf;
} undostack_t;

typedef struct unsaved_t {
        long sizebuf;
        long usedbuf;
        char *buf;
        long lastsize;
} unsaved_t;

typedef struct redata_t {
        /* data */
        long chunkdatasize;
        int sizechunks;
        rechunk_t **chunks;
        long available;
        rechunk_t *tmpchunk;
        /* undo */
        undostack_t undostack;
        undostack_t redostack;
        /* unsaved (for recovery when the program closes unexpectedly) */
        char filename[PATH_MAX];
        char initialhash[129];
        int unsavedfd;
        unsaved_t unsaved;
} redata_t;

redata_t *redata_init(void);
void redata_free(redata_t *redata);

int redata_config_chunkdatasize(redata_t *redata, int chunkdatasize);

long redata_getsize(redata_t *redata);
long redata_getused(redata_t *redata);
long redata_getavailable(redata_t *redata);
int redata_getposptr(redata_t *redata, long pos, int *numchunk, long *offset);

/* low level stuff */
int redata_wipe(redata_t *redata);
int redata_preallocate(redata_t *redata, long size);
int redata_chunk_insertnew(redata_t *redata, int afterthischunk);
int redata_chunk_deletechunk(redata_t *redata, int chunkno);
int redata_chunk_movedata(redata_t *redata, int chunkfrom, long posfrom, int chunkto, long posto, long size);
int redata_chunk_insertdata(redata_t *redata, int chunkto, long posto, char *buf, long buflen);
int redata_chunk_deletedata(redata_t *redata, int chunkno, long pos, long n);
int redata_whatin_refresh(redata_t *redata, int chunkno);
int redata_fix_nl(redata_t *redata, int chunkno);
int redata_undobuf_reserve(redata_t *redata, undostack_t *stack, int minavail);
undo_t *redata_undo_new(redata_t *redata, undostack_t *stack, char type);
undo_t *redata_undo_newfromchunks(redata_t *redata, undostack_t *stack, char type, int pos1, int len);
undo_t *redata_undo_newfrombuf(redata_t *redata, undostack_t *stack, char type, char *buf, int buflen);
int redata_undo_movelast(redata_t *redata, undostack_t *from, undostack_t *to);
int redata_undo_removelast(redata_t *redata, undostack_t *stack);
int redata_undo_wipe(redata_t *redata, undostack_t *stack);

/* high level stuff */
int redata_unsaved_exists(redata_t *redata, char *filename);
int redata_unsaved_check(redata_t *redata, char *filename);
int redata_unsaved_loadappend(redata_t *redata);
int redata_unsaved_unlink(redata_t *redata);
int redata_unsaved_trunc(redata_t *redata);
int redata_unsaved_add(redata_t *redata, undo_t *undo);
int redata_unsaved_unadd(redata_t *redata, undo_t *undo);
int redata_unsaved_commit(redata_t *redata);

int redata_load(redata_t *redata, char *filename, int use_unsaved);
int redata_save(redata_t *redata, char *filename);

int redata_op_add(redata_t *redata, long pos, char *buf, long buflen, undostack_t *fromhere);
int redata_op_del(redata_t *redata, long pos, long size, undostack_t *fromhere);
int redata_op_move(redata_t *redata, long posorig, long size, long posdest, undostack_t *fromhere);
int redata_op_undo(redata_t *redata);
int redata_op_redo(redata_t *redata);

int redata_data_compare(redata_t *redata, long pos, char *buf, long buflen);

int redata_hash(redata_t *redata, char *resbuf129bytes);
int redata_filehash(redata_t *redata, char *filename, char *resbuf129bytes);
int redata_memhash(redata_t *redata, char *buf, long buflen, char *resbuf129bytes);