/* This file is part of
 * ======================================================
 * 
 *           LyX, the High Level Word Processor 	 
 *	    Copyright (C) 1995 Matthias Ettrich
 *
 *           This file is Copyleft (C) 1996
 *           Lars Gullik Bjønnes
 *
 *======================================================
 */

#include "config.h"
#include "definitions.h"
#include "buffer.h"
#include "file.h"
#include "lyx_cb.h"
#include "paths.h"
#include "minibuffer.h"

// small workaround until mathinsets work: (Matthias 04.07.1996)
//#define MATHINSET_WORKAROUND if (current()->the_locking_inset){current()->the_locking_inset->InsetUnlock();current()->the_locking_inset = NULL;}
#define MATHINSET_WORKAROUND current()->InsetSleep();

/* Lars, when chaning this file sometime in the future to a list,
 * please check out the figinsets-sideeffects described at the
 * beginning of figinset.C    Matthias (04.07.1996)
 */


extern void MenuWrite(Buffer*);
extern void CloseBuffer();

// this is the global bufferlist object
BufferList bufferlist;


BufferList::BufferList()
{
	for (int i=NUMBER_OF_BUFFERS-1; i >= 0; i--) {
		buffer[i] = new Buffer();
	}
	current_buffer = 0;
	old_current_buffer = 0;
}


BufferList::~BufferList()
{
	// I am sure something should be done here too.
}

bool BufferList::isEmpty()
{
	return false;
}

Buffer* BufferList::current()
{
	return buffer[current_buffer];
}


void BufferList::QwriteAll()
{
	for (int i=0; i < NUMBER_OF_BUFFERS; i++) {
		if (buffer[i]->parameters.paragraph
		    && !buffer[i]->isLyxClean()) {
			if (fl_show_question("Changes in document:",
					     buffer[i]->filename,
					     "Save document?")){
			   
			   // this is because of some strange 
			   // side effect with figinsets...(see figinset.C)
			   int tmp_current_buffer = current_buffer;
			   current_buffer = i;
			   MenuWrite(buffer[i]);
			   current_buffer = tmp_current_buffer;
			}
		}
	}
}


void BufferList::write(Buffer *buf)
{
	if (buf->parameters.paragraph) {
		minibuffer.Set("Saving document", buf->filename,"...");
		/* revise this: dabn100 */
		/* make a backup */ 
		char * s = AddExtension (NULL, buf->filename, "~");
		rename(buf->filename, s);
		delete s;
		
		if (buf->text)
			buf->parameters.cursor = buf->text->cursor;
	   
		buf->parameters.writeFile(buf->filename,0);
		buf->lyx_clean = true;
		//buf->markLyXClean();
		minibuffer.Set("Document saved as", buf->filename);
	}
}


void BufferList::closeAll()
{
	for (int i = 0; i < NUMBER_OF_BUFFERS; ++i) if (buffer[i]->text) {
		current_buffer = i;
		CloseBuffer();
	}
}


void BufferList::resize()
{
	for (int i =0; i < NUMBER_OF_BUFFERS; i++) {
		if (buffer[i]->screen)
			delete buffer[i]->screen;
		buffer[i]->screen = NULL;
	}
}


void BufferList::close()
{
	int i;
	
	/* This doesn't make sense if there is no document */
	if (!bufferlist.current()->parameters.paragraph)
		return;
    
        current()->InsetUnlock();
	
	/* doit save buffer etc */
	i = current_buffer;
	if (buffer[i]->parameters.paragraph && !buffer[i]->isLyxClean()
	    && !quitting) {
		ProhibitInput();
		if (fl_show_question("Changes in document:",
				     buffer[i]->filename,
				     "Save document?"))
			MenuWrite(buffer[i]);
		AllowInput();
	}
	
	if (bufferlist.current()->filename) {
		delete bufferlist.current()->filename;
		bufferlist.current()->filename = NULL;
	}
	if (bufferlist.current()->tmppath) {
		DestroyBufferTmpDir (bufferlist.current()->tmppath);
		delete bufferlist.current()->tmppath;
		bufferlist.current()->tmppath = NULL;
	}
	LyXParagraph *par = bufferlist.current()->parameters.paragraph;
	LyXParagraph *tmppar = par;
	while(par){
		tmppar = par->next;
		delete par;
		par = tmppar;
	}
	bufferlist.current()->parameters.paragraph = NULL;

	// clear the undo stacks
	bufferlist.current()->parameters.undostack.Clear();
	bufferlist.current()->parameters.redostack.Clear();

	// clear the_locking_inset
//	bufferlist.current()->the_locking_inset = NULL;
    
	if (bufferlist.current()->text) {
		delete bufferlist.current()->text;
		bufferlist.current()->text = NULL;
	}
	
	if (bufferlist.current()->screen) {
		delete bufferlist.current()->screen;
		bufferlist.current()->screen = NULL;
	}
	
	bufferlist.current()->markDirty();
	
	bufferlist.current()->parameters.Copy(lyxrc.parameters);
	
	// current buffer must be reset here
	i=0;
	while(i<NUMBER_OF_BUFFERS && !buffer[i]->text) i++;
	current_buffer = i;
	if (i==NUMBER_OF_BUFFERS)
		current_buffer = 0;

    current()->InsetWakeup();
}


void BufferList::makePup(int pup)
{
	int ant=0;
	char * relbuf;
	for(int n=0; n<NUMBER_OF_BUFFERS; n++){
		if(buffer[n]->parameters.paragraph){
			relbuf = MakeDisplayPath (NULL, buffer[n]->filename);
			fl_addtopup(pup, relbuf);
			ant++;
			delete relbuf;
		}
	}
	if (ant == 0) fl_addtopup(pup,"No Documents Open!%t");
}


void BufferList::switchBuffer(int choice)
{
  
  MATHINSET_WORKAROUND

	// should perhaps move this func to menus.C   
	int i=0;
	while (choice--) {
		while (!buffer[i++]->parameters.paragraph);
	}
	i--; // this is ok since choice never == 0
	
	if (i>=NUMBER_OF_BUFFERS) return;
	
	old_current_buffer = current_buffer;
	current_buffer = i;

   current()->InsetWakeup(); 
}


void BufferList::prev()
{

MATHINSET_WORKAROUND

	int tmp;
	tmp = current_buffer;
	current_buffer = old_current_buffer;
	old_current_buffer = tmp;

   current()->InsetWakeup();
}


void BufferList::updateInset(Inset *inset, bool mark_dirty)
{
        int i=0;
	while (i < NUMBER_OF_BUFFERS - 1){
		if (buffer[i]->text){
			if (buffer[i]->text->UpdateInset(inset)){
			  if (mark_dirty)
			    buffer[i]->markDirty();
			  return;
			}
		}
		i++;
	}
}

int BufferList::unlockInset(UpdatableInset *inset)
{
	int i=0;
	while (i < NUMBER_OF_BUFFERS - 1){
		if (inset && buffer[i]->the_locking_inset == inset) {
		  buffer[i]->InsetUnlock();
		  return 0;
		}
		i++;
	}

	return 1;
}


void BufferList::emergencyWriteAll()
{
	int a, buf, i,n;
	char *s;
	for (buf=0; buf < NUMBER_OF_BUFFERS; buf++) {
		if (buffer[buf]->parameters.paragraph &&
		    !buffer[buf]->isLyxClean()) {
			
			for (n=0; buffer[buf]->filename[n]; n++);
			s = new char[n+10];
			for (i=0; i<n; i++) 
				s[i] = buffer[buf]->filename[i];
			s[i] = '#';
			s[i+1] = '\0';
			for (a=i+2; a && s[a-1]!='/'; a--) {
				s[a] = s[a-1];
			}
			s[a]='#';
			
			fprintf(stderr,
				"lyx: attempting to save"
				" document %s in %s...\n", 
				buffer[buf]->filename, s);
			
			if (buffer[buf]->text)
				buffer[buf]->parameters.cursor =
					buffer[buf]->text->cursor;
			
			buffer[buf]->parameters.writeFile(s,1);
			buffer[buf]->lyx_clean = true;
			//buffer[buf]->markLyxClean();
			delete s;
		}
	}
}


void BufferList::readFile(const char* s, bool ronly)
{

MATHINSET_WORKAROUND

	int i=0;
	while (i < NUMBER_OF_BUFFERS - 1
	       && buffer[i]->parameters.paragraph) i++;

	if (lyx_debug_level)
	fprintf(stderr,"assigning to buffer %d\n",i);
	
	// here we should asure that the parameters are correct.
	buffer[i]->init();
	
	buffer[i]->filename = StringCopy(s);
	if (ronly || lyxrc.use_tempdir) {
	   buffer[i]->tmppath = CreateBufferTmpDir (system_tempdir);
	} else buffer [i]->tmppath = NULL;

	// must be BEFORE readFile due to some strange 
	// side effect with figinsets...(see figinset.C)
	old_current_buffer = current_buffer;
	current_buffer = i;

	buffer[i]->parameters.readFile();
	
	buffer[i]->lyx_clean = true;
	buffer[i]->bak_clean = true;
	buffer[i]->dvi_clean = false;
	buffer[i]->read_only = ronly;
}


bool BufferList::exists(const char* s)
{
	int i;
	
	for (i=0; i < NUMBER_OF_BUFFERS; i++)
		     if (StringEqual(buffer[i]->filename,s))
			     return true;
	
	return false;
}


void BufferList::newFile(const char* s,const char* fname)
{
	/* find a free buffer */ 
	int i=0;
	while (i < NUMBER_OF_BUFFERS - 1
	       && buffer[i]->parameters.paragraph)
		i++;
	//_must_ be done before reading template
	//otherwise figinsets flake
	buffer[i]->filename = StringCopy(s);
	if (lyxrc.use_tempdir) {
	   buffer[i]->tmppath = CreateBufferTmpDir (system_tempdir);
	} else buffer [i]->tmppath = NULL;
	// setdefaults
	buffer[i]->parameters.Copy(lyxrc.parameters); 
	// read template
	if (fname && OpenFile(fname)){
	        buffer[i]->init();
		buffer[i]->parameters.readFile();
		CloseFile();
	}
	else {  // start with empty buffer
		buffer[i]->parameters.paragraph = new LyXParagraph();
	}

	buffer[i]->markDirty();
	
	old_current_buffer = current_buffer;
	current_buffer = i;
}




