/*
 * re_data.h
 *
 * 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>

#define MAXPLUGINNAME 32

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 redata_plugin_t {
        int active;
        char name[MAXPLUGINNAME];
        int (*unregister)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/);
        int (*wipe)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/);
        /* loadquestion returns -1 if no question needed */
        int (*loadquestion)(/*redata_t *redata, redata_plugin_t *plugin,char *filename, char **title, char **body, int *nopts, char **opts[] */);
        int (*postload)(/*redata_t *redata, redata_plugin_t *plugin,char *filename,int questionreply */);
        int (*postsave)(/*redata_t *redata, redata_plugin_t *plugin,char *oldfilename,char *newfilename*/);
        int (*add)(/*redata_t *redata, redata_plugin_t *plugin,undo_t *undo*/);
        int (*unadd)(/*redata_t *redata, redata_plugin_t *plugin,undo_t *undo*/);
        int (*commit)(/*redata_t *redata, redata_plugin_t *plugin,char *filename*/);
        void *userptr;
} redata_plugin_t;

typedef struct redata_t {
        char filename[PATH_MAX];
        /* data */
        long chunkdatasize;
        int sizechunks;
        rechunk_t **chunks;
        long available;
        rechunk_t *tmpchunk;
        /* undo */
        undostack_t undostack;
        undostack_t redostack;
        /* plugins */
        int sizeplugins;
        redata_plugin_t plugins[1];
} redata_t;

redata_t *redata_init( int (*pluginregisterfn)(redata_t *redata, redata_plugin_t *slot), ...);
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_chunk_splithere(redata_t *redata, int chunkno, int pos);
int redata_chunk_fillfromnext(redata_t *redata, int chunkno, int 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);
int redata_undo_inactivatelast(redata_t *redata, undostack_t *stack);
int redata_undo_reactivatelast(redata_t *redata, undostack_t *stack);

/* high level stuff */
int redata_load(redata_t *redata, char *filename, int (*callback_question)(/*char *title, char *body, int nopts, char *opts[],void *userptr*/), void *userptr);
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_compact(redata_t *redata);

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);
undostack_t *redata_getstack(redata_t *redata, undo_t *undo);
char *redata_generic_genname(char *filename,char *prefix, char *postfix, char *buf, int bufsize);