/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#include "dbsrv.h"

/*
 *	Finds an author in the author id list of a database
 */
dbAuthor
find_author_by_id(db,id)
	dbDatabase db ;
{
	dbAuthor author = db->authors ;
	while(author != NULL)
	{
		if (author->aid == id)
		{
			return author ;
		}
		author = author->next ;
	}
	return NULL ;
}

/*
 *	Adds an author to a database
 */
dbAuthor
add_author(db,aid)
	dbDatabase db ;
{
	dbAuthor author = (dbAuthor)malloc(sizeof *author) ;
	author->aid = aid ;
	author->next = db->authors ;
	db->authors = author ;
	return author ;
}

/*
 *	Finds author's access in a notebook
 */
Access_List
find_access(author,note)
	dbAuthor author ;
	dbNotebook note ;
{
	Access_List al = note->al ;
	while(al != NULL)
	{
		if (author == al->author)
		{
			return al ;
		}
		al = al->next ;
	}
	return NULL ;
}

/*
 *	Adds access to a nothebook
 */
add_access(note,author,access)
	dbNotebook note ;
	dbAuthor author ;
{
	Access_List al = (Access_List)malloc(sizeof *al) ;
	al->access = access ;
	al->author = author ;
	al->next = note->al ;
	note->al = al ;
}

/*
 *	Removes access from a notebook.
 */
rmv_access(db,note,author)
	dbDatabase db ;
	dbNotebook note ;
	dbAuthor author ;
{
    Access_List *al = &(note->al) ;

    while(*al != NULL && (*al)->author != author)
    {
        al = &(*al)->next ;
    }

	if (*al != NULL)
	{
        Access_List old = *al ;

        /* Remove author from access list */
        if (sy_call_exec(db,"Rmv_Access","dd",note->nid,author->aid) < 0)
        {
            return ;
        }

        *al = old->next ;
        free((char *)old) ;
	}
}

/*
 *	Adds a new notebook to a database
 */
dbNotebook
add_notebook(db,nid,author,name,create_date,modify_date,home_page)
	dbDatabase db ;
	dbAuthor author ;
	char *name ;
	char *create_date ;
	char *modify_date ;
{
	dbNotebook note = (dbNotebook)malloc(sizeof *note) ;
	note->nid = nid ;
	note->title = add_string(name) ;
	note->author = author ;
	note->create_date = add_string(create_date) ;
	note->modify_date = add_string(modify_date) ;
	note->pages = NULL ;
	note->home_page = home_page ;
	note->next = db->notebooks ;
	note->next_page_id = 1 ;
	note->al = NULL ;
	if (nid + 1 > db->next_notebook_id)
	{
		db->next_notebook_id = nid + 1 ;
	}
	db->notebooks = note ;
	return note ;
}

/*
 *	Adds a new page to a notebook
 */
dbPage
add_page(note,pid,author,name,create_date,modify_date,width,height,color)
	dbNotebook note ;
	dbAuthor author ;
	char *name ;
	char *create_date ;
	char *modify_date ;
	char *color ;
{
	dbPage page = (dbPage)malloc(sizeof *page) ;
	page->pid = pid ;
	page->title = add_string(name) ;
	page->author = author ;
	page->create_date = add_string(create_date) ;
	page->modify_date = add_string(modify_date) ;
	page->width = width ;
	page->height = height ;
	page->color = add_string(color) ;
	page->objects = NULL ;
	page->next = note->pages ;
	page->link_list = NULL ;
	page->next_object_id = 1 ;
	note->pages = page ;
	if (pid + 1 > note->next_page_id)
	{
		note->next_page_id = pid + 1 ;
	}
	return page ;
}

/*
 *	Adds a generic object to a page.
 */
static
dbObject
add_object(page,oid,author,create_date,modify_date,type,x,y,width,height)
    dbPage page ;
	dbAuthor author ;
    char *create_date ;
    char *modify_date ;
{
	dbObject object = (dbObject)malloc(sizeof *object) ;
	object->oid = oid ;
	object->author = author ;
	object->create_date = add_string(create_date) ;
	object->modify_date = add_string(modify_date) ;
	object->type = type ;
	object->x = x ;
	object->y = y ;
	object->width = width ;
	object->height = height ;
	object->next = page->objects ;
	page->objects = object ;
	if (oid + 1 > page->next_object_id)
	{
		page->next_object_id = oid + 1 ;
	}
	return object ;
}

/*
 *	Changes a generic object on a page.
 */
static
change_object(object,x,y,width,height,modify_date)
	dbObject object ;
	char *modify_date ;
{
	change_str(&object->modify_date,modify_date) ;
	object->x = x ;
	object->y = y ;
	object->width = width ;
	object->height = height ;
}

/*
 *	Adds an image object to a page.
 */
add_image_object(page,oid,author,create_date,modify_date,type,x,y,width,height,create_colormap,low_res_sw)
    dbPage page ;
	dbAuthor author ;
    char *create_date ;
    char *modify_date ;
{
	dbObject object = add_object(page,oid,author,create_date,modify_date,type,x,y,width,height) ;
	object->data.image.create_colormap = create_colormap ;
	object->data.image.low_res_sw = low_res_sw ;
}

/*
 *	Changes an image object on a page.
 */
change_image_object(db,note,page,object,x,y,width,height,create_colormap,low_res_sw)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	dbObject object ;
{
	char modify_date[256] ;
	get_cur_date(modify_date) ;
	if (sy_call_exec(db,"Update_Image_Object","dddddddddq",
			note->nid,page->pid,object->oid,
			x,y,width,height,
			create_colormap,
			low_res_sw,
			modify_date) < 0)
	{
		return ;
	}

	change_object(object,x,y,width,height,modify_date) ;
	object->data.image.create_colormap = create_colormap ;
	object->data.image.low_res_sw = low_res_sw ;
}

/*
 *	Changes a text object on a page.
 */
change_text_object(db,note,page,object,x,y,width,height,color,font)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	char *color ;
	char *font ;
	dbObject object ;
{
	char modify_date[256] ;
	get_cur_date(modify_date) ;
	if (sy_call_exec(db,"Update_Txt_Object","dddddddqqq",
			note->nid,page->pid,object->oid,
			x,y,width,height,
			font,
			color,
			modify_date) < 0)
	{
		return ;
	}

	change_object(object,x,y,width,height,modify_date) ;
	change_str(&object->data.text.color,color) ;
	change_str(&object->data.text.font,font) ;
}

/*
 *	Adds a text object to a page.
 */
add_text_object(page,oid,author,create_date,modify_date,type,x,y,width,height,color,font,contents)
    dbPage page ;
	dbAuthor author ;
    char *create_date ;
    char *modify_date ;
	char *color ;
	char *font ;
	char *contents ;
{
	dbObject object = add_object(page,oid,author,create_date,modify_date,type,x,y,width,height) ;
	object->data.text.color = add_string(color) ;
	object->data.text.font = add_string(font) ;
	object->data.text.contents = add_string(contents) ;
}

/* Finds the link object that referenced a page within that page's list */
static
LinkList *
find_link_in_list(object,page)
	dbObject object ;
	dbPage page ;
{
	LinkList *lx = NULL;
	LinkList *ll ;
	if (page == NULL) return lx;
	for(ll = &page->link_list; *ll != NULL && (*ll)->object != object; ll = &(*ll)->next) ;
	return ll ;
}

/*
 * Changes a link object on a page.
 */
change_link_object(db,note,page,object,x,y,width,height,color,font,title,dest_note,dest_page)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	char *title ;
	char *color ;
	char *font ;
	dbObject object ;
{
	dbNotebook r_dest_note ;
	char modify_date[256] ;

	/* modify the database */
	get_cur_date(modify_date) ;
	if (sy_call_exec(db,"Update_Link_Object","dddddddddqqqqq",
			note->nid,page->pid,object->oid,
			x,y,width,height,
			dest_note,dest_page,title,
			font,
			color,
			modify_date,db->name) < 0)
	{
		return ;
	}

	/* remove the old link destination if it was valid */
	if ((object->data.link.dest_note != NULL) &&
		(object->data.link.dest_page != NULL))
	{
		LinkList *ll = find_link_in_list(object,object->data.link.dest_page) ;
		if (*ll != NULL)
		{
			LinkList old = *ll ;
			*ll = old->next ;
			free((char *)old);
		}
	}

	/* update the link object structure */
	change_object(object,x,y,width,height,modify_date) ;
	change_str(&object->data.link.color,color) ;
	change_str(&object->data.link.font,font) ;
	change_str(&object->data.link.title,title) ;
	object->data.link.dest_note = (dbNotebook)NULL ;
	object->data.link.dest_page = (dbPage)NULL ;

	/* check if the new destination is valid */
	r_dest_note = find_note_by_id(db,dest_note) ;
	if (r_dest_note != NULL)
	{
		dbPage r_dest_page = find_page_by_id(r_dest_note,dest_page) ;
		if (r_dest_page != NULL)
		{
			LinkList ll = (LinkList)malloc(sizeof *ll) ;
			ll->next = r_dest_page->link_list ;
			ll->note = note ;
			ll->page = page ;
			ll->object = object ;
			r_dest_page->link_list = ll ;

			/* update the destination notebook and page */
			object->data.link.dest_note = r_dest_note ;
			object->data.link.dest_page = r_dest_page ;
		}
	}
}

/*
 *	Changes an action link object on a page.
 */
change_action_link_object(db,note,page,object,x,y,width,height,color,font,title,command)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	char *title ;
	char *color ;
	char *font ;
	char *command ;
	dbObject object ;
{
	char modify_date[256] ;
	get_cur_date(modify_date) ;
	if (sy_call_exec(db,"Update_Action_Link_Object","dddddddqqqqq",
			note->nid,page->pid,object->oid,
			x,y,width,height,
			command,title,
			font,
			color,
			modify_date) < 0)
	{
		return ;
	}

	change_object(object,x,y,width,height,modify_date) ;
	change_str(&object->data.action_link.color,color) ;
	change_str(&object->data.action_link.font,font) ;
	change_str(&object->data.action_link.title,title) ;
	change_str(&object->data.action_link.command,command) ;
}

/*
 * Adds a link object to a page.
 * 12/18/90: modified to allow dangling links.
 */
add_link_object(db,note,page,oid,author,create_date,modify_date,type,x,y,width,height,color,font,title,dest_note,dest_page)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	dbAuthor author ;
    char *create_date ;
    char *modify_date ;
	char *color ;
	char *font ;
	char *title ;
{
	dbNotebook r_dest_note;
	dbPage r_dest_page;

	dbObject object = add_object(page,oid,author,create_date,modify_date,
		type,x,y,width,height) ;
	object->data.link.dest_note = NULL ;
	object->data.link.dest_page = NULL ;
	object->data.link.color = add_string(color) ;
	object->data.link.font = add_string(font) ;
	object->data.link.title = add_string(title) ;

	r_dest_note = find_note_by_id(db,dest_note) ;
	if (r_dest_note != NULL)
	{
		r_dest_page = find_page_by_id(r_dest_note,dest_page) ;
		if (r_dest_page != NULL)
		{
			LinkList ll = (LinkList)malloc(sizeof *ll) ;
			ll->next = r_dest_page->link_list ;
			ll->note = note ;
			ll->page = page ;
			ll->object = object ;
			r_dest_page->link_list = ll ;
			object->data.link.dest_note = r_dest_note ;
			object->data.link.dest_page = r_dest_page ;
		}
	}
}

/*
 *	Adds an action link object to a page.
 */
add_action_link_object(page,oid,author,create_date,modify_date,type,x,y,width,height,color,font,title,command)
	dbPage page ;
	dbAuthor author ;
    char *create_date ;
    char *modify_date ;
	char *color ;
	char *font ;
	char *title ;
	char *command ;
{
	dbObject object = add_object(page,oid,author,create_date,modify_date,type,x,y,width,height) ;
	object->data.action_link.color = add_string(color) ;
	object->data.action_link.font = add_string(font) ;
	object->data.action_link.title = add_string(title) ;
	object->data.action_link.command = add_string(command) ;
}

/*
 *	Reallocates and copies a new string into an old one.
 */
change_str(s,t)
	char **s ;
	char *t ;
{
	char *p = add_string(t) ;
	rmv_string(*s) ;
	*s = p ;
}

/*
 *	Chanes a notebook.
 */
change_notebook(db,note,name,home_page)
	dbDatabase db ;
	dbNotebook note ;
	char *name ;
{
	char modify_date[256] ;
	get_cur_date(modify_date) ;
    if (sy_call_exec(db,"Update_Notebook","dqqd",note->nid,name,modify_date,home_page) < 0)
    {
        return ;
    }
	note->home_page = home_page ;
	change_str(&note->title,name) ;
	change_str(&note->modify_date,modify_date) ;
}

/*
 * 	Changes a page.
 */
change_page(db,note,page,name,width,height,color)
	dbDatabase db ;
	dbNotebook note ;
	dbPage page ;
	char *name ;
	char *color ;
{
	char modify_date[256] ;
	get_cur_date(modify_date) ;
    if (sy_call_exec(db,"Update_Page","ddqddqq",note->nid,page->pid,name,width,height,color,modify_date) < 0)
    {
        return ;
    }
	change_str(&page->title,name) ;
	change_str(&page->color,color) ;
	change_str(&page->modify_date,modify_date) ;
	page->width = width ;
	page->height = height ;
}

/*
 *	Loads in all objects from database.
 */
static
load_objects(db)
	dbDatabase db ;
{
	if (sy_call_exec(db,"Retrieve_Image_Objects","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int nid ;
		int pid ;
		int oid ;
		int aid ;
		char create_date[256] ;
		char modify_date[256] ;
		int type ;
		int x ;
		int y ;
		int width ;
		int height ;
		int create_colormap ;
		int low_res_sw ;
		dbNotebook note ;
		dbPage page ;
		dbAuthor author ;
		nid = get_int_result() ;
		pid = get_int_result() ;
		oid = get_int_result() ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		type = get_int_result() ;
		x = get_int_result() ;
		y = get_int_result() ;
		width = get_int_result() ;
		height = get_int_result() ;
		create_colormap = get_int_result() ;
		low_res_sw = get_int_result() ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for object %d %d %d is invalid\n",
				aid,nid,pid,oid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d is for object %d %d %d is invalid\n",
				nid,nid,pid,oid) ;
			continue ;
		}
		page = find_page_by_id(note,pid) ;
		if (page == NULL)
		{
			fprintf(stderr,"Page %d is for object %d %d %d is invalid\n",
				pid,nid,pid,oid) ;
			continue ;
		}
		add_image_object(page,oid,author,create_date,modify_date,type,x,y,width,height,
			create_colormap,low_res_sw) ;
	}
	if (sy_call_exec(db,"Retrieve_Txt_Objects","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int nid ;
		int pid ;
		int oid ;
		int aid ;
		char create_date[256] ;
		char modify_date[256] ;
		int type ;
		int x ;
		int y ;
		int width ;
		int height ;
		dbNotebook note ;
		dbPage page ;
		dbAuthor author ;
		char color[256] ;
		char font[256] ;
		char contents[256] ;
		int contents_valid ;
		nid = get_int_result() ;
		pid = get_int_result() ;
		oid = get_int_result() ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		type = get_int_result() ;
		x = get_int_result() ;
		y = get_int_result() ;
		width = get_int_result() ;
		height = get_int_result() ;
		get_str_result(font) ;
		get_str_result(color) ;
		contents_valid = (get_str_result(contents) >= 0) ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for object %d %d %d is invalid\n",
				aid,nid,pid,oid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d is for object %d %d %d is invalid\n",
				nid,nid,pid,oid) ;
			continue ;
		}
		page = find_page_by_id(note,pid) ;
		if (page == NULL)
		{
			fprintf(stderr,"Page %d is for object %d %d %d is invalid\n",
				pid,nid,pid,oid) ;
			continue ;
		}
		add_text_object(page,oid,author,create_date,modify_date,type,x,y,width,height,
			color,font,(contents_valid ? contents : NULL)) ;
	}
	if (sy_call_exec(db,"Retrieve_Link_Objects","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int nid ;
		int pid ;
		int oid ;
		int aid ;
		char create_date[256] ;
		char modify_date[256] ;
		int type ;
		int x ;
		int y ;
		int width ;
		int height ;
		dbNotebook note ;
		dbPage page ;
		dbAuthor author ;
		char color[256] ;
		char font[256] ;
		char title[256] ;
		int dest_note ;
		int dest_page ;
		nid = get_int_result() ;
		pid = get_int_result() ;
		oid = get_int_result() ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		type = get_int_result() ;
		x = get_int_result() ;
		y = get_int_result() ;
		width = get_int_result() ;
		height = get_int_result() ;
		dest_note = get_int_result() ;
		dest_page = get_int_result() ;
		get_str_result(title) ;
		get_str_result(font) ;
		get_str_result(color) ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for object %d %d %d is invalid\n",
				aid,nid,pid,oid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d is for object %d %d %d is invalid\n",
				nid,nid,pid,oid) ;
			continue ;
		}
		page = find_page_by_id(note,pid) ;
		if (page == NULL)
		{
			fprintf(stderr,"Page %d is for object %d %d %d is invalid\n",
				pid,nid,pid,oid) ;
			continue ;
		}
		add_link_object(db,note,page,oid,author,create_date,modify_date,type,x,y,width,height,
				color,font,title,dest_note,dest_page) ;
	}
	if (sy_call_exec(db,"Retrieve_Action_Link_Objects","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int nid ;
		int pid ;
		int oid ;
		int aid ;
		char create_date[256] ;
		char modify_date[256] ;
		int type ;
		int x ;
		int y ;
		int width ;
		int height ;
		char color[256] ;
		char font[256] ;
		char title[256] ;
		char command[256] ;
		dbNotebook note ;
		dbPage page ;
		dbAuthor author ;
		nid = get_int_result() ;
		pid = get_int_result() ;
		oid = get_int_result() ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		type = get_int_result() ;
		x = get_int_result() ;
		y = get_int_result() ;
		width = get_int_result() ;
		height = get_int_result() ;
		get_str_result(command) ;
		get_str_result(title) ;
		get_str_result(font) ;
		get_str_result(color) ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for object %d %d %d is invalid\n",
				aid,nid,pid,oid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d is for object %d %d %d is invalid\n",
				nid,nid,pid,oid) ;
			continue ;
		}
		page = find_page_by_id(note,pid) ;
		if (page == NULL)
		{
			fprintf(stderr,"Page %d is for object %d %d %d is invalid\n",
				pid,nid,pid,oid) ;
			continue ;
		}
		add_action_link_object(page,oid,author,create_date,modify_date,type,x,y,width,height,
				color,font,title,command) ;
	}
}

/*
 *	Loads in all pages from database.
 */
static
load_pages(db)
	dbDatabase db ;
{
	if (sy_call_exec(db,"Retrieve_Pages","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int pid ;
		int nid ;
		int aid ;
		char name[256] ;
		char create_date[256] ;
		char modify_date[256] ;
		int width ;
		int height ;
		char color[256] ;
		dbNotebook note ;
		dbAuthor author ;
		nid = get_int_result() ;
		pid = get_int_result() ;
		get_str_result(name) ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		width = get_int_result() ;
		height = get_int_result() ;
		get_str_result(color) ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for page %d %d is invalid\n",
				aid,nid,pid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d is for page %d %d is invalid\n",
				nid,nid,pid) ;
			continue ;
		}
		add_page(note,pid,author,name,create_date,modify_date,width,height,color) ;
	}
}

/* Loads in all notebooks in a database */
static
load_notebooks(db)
	dbDatabase db ;
{
	if (sy_call_exec(db,"Retrieve_Notebooks","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int nid ;
		int aid ;
		char name[256] ;
		char create_date[256] ;
		char modify_date[256] ;
		dbAuthor author ;
		int home_page ;
		nid = get_int_result() ;
		get_str_result(name) ;
		aid = get_int_result() ;
		get_str_result(create_date) ;
		get_str_result(modify_date) ;
		author = find_author_by_id(db,aid) ;
		home_page = get_int_result() ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for notebook %d is invalid\n",
				aid,nid) ;
			continue ;
		}
		add_notebook(db,nid,author,name,create_date,modify_date,home_page) ;
	}
}

/* Loads in all authors in a database */
static
load_authors(db)
	dbDatabase db ;
{
	if (sy_call_exec(db,"Retrieve_Authors","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int aid ;
		aid = get_int_result() ;
		add_author(db,aid) ;
	}
}

/* Loads in all accesses */
static
load_accesses(db)
	dbDatabase db ;
{
	if (sy_call_exec(db,"Retrieve_Accesses","") < 0)
	{
		abort() ;
	}
	while(sy_get_one_row() >= 0)
	{
		int access ;
		int aid ;
		int nid ;
		dbAuthor author ;
		dbNotebook note ;
		access = get_int_result() ;
		nid = get_int_result() ;
		aid = get_int_result() ;
		author = find_author_by_id(db,aid) ;
		if (author == NULL)
		{
			fprintf(stderr,"Author %d for access %d %d is invalid\n",
				aid,nid) ;
			continue ;
		}
		note = find_note_by_id(db,nid) ;
		if (note == NULL)
		{
			fprintf(stderr,"Notebook %d for access %d %d is invalid\n",
				aid,nid) ;
			continue ;
		}
		add_access(note,author,access) ;
	}
}

/*
 *	Finds a notebook from its id.
 */
dbNotebook
find_note_by_id(db,id)
	dbDatabase db ;
{
	dbNotebook note = db->notebooks ;
	while(note != NULL)
	{
		if (note->nid == id)
		{
			return note ;
		}
		note = note->next ;
	}
	return NULL ;
}

/*
 *	Finds a page from its id.
 */
dbPage
find_page_by_id(note,id)
	dbNotebook note ;
{
	dbPage page ;
	if (note == NULL) return NULL;
	page = note->pages ;
	while(page != NULL)
	{
		if (page->pid == id)
		{
			return page ;
		}
		page = page->next ;
	}
	return NULL ;
}

/*
 *	Finds an object from its id
 */
dbObject
find_object_by_id(page,id)
	dbPage page ;
{
	dbObject object = page->objects ;
	while(object != NULL)
	{
		if (object->oid == id)
		{
			return object ;
		}
		object = object->next ;
	}
	return NULL ;
}

/*
 *	Deletes a notebook.
 */
delete_notebook(c,note)
	Connection c ;
	dbNotebook note ;
{
	dbNotebook *nb = &(c->db->notebooks) ;
	while(*nb != NULL && *nb != note)
	{
		nb = &((*nb)->next) ;
	}
	if (*nb == note)
	{
		while(note->pages != NULL)
		{
			/* delete pages but not reference links */
			delete_page(c,note,note->pages,0) ;
		}
		while(note->al != NULL)
		{
			rmv_access(c->db,note,note->al->author) ;
		}
		{
			char dir_name[256] ;
			get_note_fname(c->db,note->nid,dir_name) ;
			if (rmdir(dir_name) < 0)
			{
				perror(dir_name) ;
			}
		}
		sy_call_exec(c->db,"Delete_Notebook","d",note->nid) ;
		*nb = note->next ;
		rmv_string(note->title) ;
		rmv_string(note->create_date) ;
		rmv_string(note->modify_date) ;
		free((char *)note) ;
	}
}

/*
 *	Deletes a page.
 */
delete_page(c,note,page,del_links)
	Connection c ;
	dbNotebook note ;
	dbPage page ;
{
	dbPage *pb = &(note->pages) ;
	while(*pb != NULL && *pb != page)
	{
		pb = &((*pb)->next) ;
	}
	if (*pb == page)
	{
		/* delete all the objects on the page */
		while(page->objects != NULL)
		{
			delete_object(c,note,page,page->objects) ;
		}

		/* delete the links to this page */
		if (del_links == 1)
		{
			while(page->link_list != NULL)
			{
				delete_object(c,page->link_list->note,page->link_list->page,
					page->link_list->object) ;
			}
		}
		else
		{
			/* free the link list but don't delete objects */
			LinkList *ll = &page->link_list;
			while(*ll != NULL)
			{
				LinkList old = *ll;
				{
					char modify_date[256] ;
					int null_id = -1;

					/* set the link destinations to NULL */
					old->object->data.link.dest_note = NULL;
					old->object->data.link.dest_page = NULL;

					/* modify the database for null destination */
					get_cur_date(modify_date) ;
					if (sy_call_exec(c->db,"Update_Link_Object",
						"dddddddddqqqqq",
						old->note->nid,
						old->page->pid,
						old->object->oid,
						old->object->x,
						old->object->y,
						old->object->width,
						old->object->height,
						null_id,null_id,
						old->object->data.link.title,
						old->object->data.link.font,
						old->object->data.link.color,
						modify_date,c->db->name) < 0)
					{
						return ;
					}
				}
				*ll = old->next;
				free((char *)old);
			}
		}

		{
			char dir_name[256] ;
			get_page_fname(c->db,note->nid,page->pid,dir_name) ;
			if (rmdir(dir_name) < 0)
			{
				perror(dir_name) ;
			}
		}

		sy_call_exec(c->db,"Delete_Page","dd",note->nid,page->pid) ;

		*pb = page->next ;
		rmv_string(page->title) ;
		rmv_string(page->create_date) ;
		rmv_string(page->modify_date) ;
		free((char *)page) ;
	}
}

/*
 *	Deletes an object.
 */
delete_object(c,note,page,object)
	Connection c ;
	dbNotebook note ;
	dbPage page ;
	dbObject object ;
{
	dbObject *ob = &(page->objects) ;
	while(*ob != NULL && *ob != object)
	{
		ob = &((*ob)->next) ;
	}
	if (*ob == object)
	{
		switch(object->type)
		{
			case TEXT_OBJECT_TYPE :
			{
				sy_call_exec(c->db,"Delete_Text_Object","ddd",note->nid,page->pid,object->oid) ;
				rmv_string(object->data.text.color) ;
				rmv_string(object->data.text.font) ;
				if (object->data.text.contents != NULL)
				{
					rmv_string(object->data.text.contents) ;
				}
				else
				{
					char dir_name[256] ;
					get_object_fname(c->db,note->nid,page->pid,object->oid,dir_name) ;
					unlink(dir_name) ;
				}
				break ;
			}
			case IMAGE_OBJECT_TYPE :
			{
				char dir_name[256] ;
				sy_call_exec(c->db,"Delete_Image_Object","ddd",note->nid,page->pid,object->oid) ;
				get_object_fname(c->db,note->nid,page->pid,object->oid,dir_name) ;
				unlink(dir_name) ;
				break ;
			}
			case LINK_OBJECT_TYPE :
			{
				if ((object->data.link.dest_note != NULL) &&
					(object->data.link.dest_page != NULL))
				{
					LinkList *ll = find_link_in_list(object,object->data.link.dest_page) ;
					if (*ll != NULL)
					{
						LinkList old = *ll ;
						*ll = old->next ;
						free((char *)old) ;
					}
				}
				sy_call_exec(c->db,"Delete_Link_Object","ddd",note->nid,page->pid,object->oid) ;
				rmv_string(object->data.link.color) ;
				rmv_string(object->data.link.font) ;
				rmv_string(object->data.link.title) ;
				break ;
			}
			case ACTION_LINK_OBJECT_TYPE :
				sy_call_exec(c->db,"Delete_Action_Link_Object","ddd",note->nid,page->pid,object->oid) ;
				rmv_string(object->data.action_link.color) ;
				rmv_string(object->data.action_link.font) ;
				rmv_string(object->data.action_link.title) ;
				rmv_string(object->data.action_link.command) ;
				break ;
		}
		*ob = object->next ;
		rmv_string(object->create_date) ;
		rmv_string(object->modify_date) ;
		free((char *)object) ;
	}
}

/*
 *	Loads in the entire database.
 */
load_database(db_name)
	char *db_name ;
{
	dbDatabase db = (dbDatabase)malloc(sizeof *db) ;
	db->name = add_string(db_name) ;
	db->next = pc.dbs ;
	db->notebooks = NULL ;
	db->next_notebook_id = 1 ;
	db->authors = NULL ;
	load_authors(db) ;
	load_notebooks(db) ;
	load_pages(db) ;
	load_objects(db) ;
	load_accesses(db) ;
	pc.dbs = db ;
}
