home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Exec 3
/
CD_Magazyn_EXEC_nr_3.iso
/
Recent
/
misc
/
edu
/
WhirlDisc.lha
/
WhirlDisc
/
Source
/
paedia.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-08-15
|
11KB
|
433 lines
/*
File: paedia.c
Author: Neil Cafferkey
Copyright (C) 2000 Neil Cafferkey
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
*/
#include "viewer.h"
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <stdio.h>
#include <string.h>
#include "paedia_protos.h"
#include "general_protos.h"
#include "deflated_sequence_protos.h"
#include "article_protos.h"
#include "index_protos.h"
#include <proto/exec.h>
#include <proto/dos.h>
#define BLOCK_SIZE 512
#define MAX_LINK_FILE_NAME_LENGTH 20
const TEXT main_file_name[]="info_dat/wb.dat";
/*const TEXT link_file_name[]="links";*/
const TEXT master_file_name[]="info_dat/master.ndx";
const TEXT index_file_name[]="info_dat/ssubject.ndx";
const TEXT orig_link_file_name[]="info_dat/rom_link.dat";
static VOID GetBlocks(BPTR file,ULONG start_block,ULONG block_count,
UBYTE *buffer);
static MediaLink GetPaediaLink(Paedia paedia,ULONG link_no);
/* Function: ConvertLinkFile
* =========================
* Converts the original link file into a new file with a non-textual
* format.
*/
BOOL ConvertLinkFile(TEXT *old_file_name,TEXT *new_file_name)
{
FILE *old_file;
ULONG line_count=0,i;
char ch;
MediaLink media_links,p;
BPTR new_file;
BOOL success=TRUE;
/* Convert "rom link" text file into an array in memory */
if(old_file=fopen(old_file_name,"rb"))
{
/* Count the lines in the text file and allocate enough memory to
* hold its converted contents. */
for(ch=0;!feof(old_file);ch=getc(old_file))
if(ch=='\n')
line_count++;
line_count;
media_links=(MediaLink)AllocMem(sizeof(MediaLink_imp)
*line_count,MEMF_CLEAR);
/* Fill array of media links */
if(media_links)
{
rewind(old_file);
p=media_links;
for(i=0;i<line_count;i++)
{
fscanf(old_file,"%lu|%*[^|]|%*[^|]|%*[^|]|%*[^|]|%lu|%hu",
&(p->link_no),&(p->start_block),&(p->block_count));
getc(old_file);
p++;
}
/* Write converted links into a new file */
if(new_file=Open(new_file_name,MODE_NEWFILE))
{
if(Write(new_file,media_links,line_count
*sizeof(MediaLink_imp))==-1)
success=FALSE;
Close(new_file);
}
FreeMem(media_links,sizeof(MediaLink_imp)*line_count);
}
fclose(old_file);
}
else
{
success=FALSE;
}
return success;
}
/* Function: CreatePaedia
* ======================
* Creates a Paedia.
*/
Paedia CreatePaedia(TEXT *data_dir_name,TEXT *paedia_dir_name)
{
Paedia paedia;
ULONG line_count=0;
TEXT *path_name,*index_path_name,*link_file_name,*orig_link_path;
struct FileInfoBlock *temp_fib;
BPTR link_file=NULL,master_file=NULL;
BOOL success=TRUE;
if(paedia=AllocMem(sizeof(Paedia_imp),MEMF_CLEAR))
{
/* Construct the full path name for main file */
if(path_name=AllocVec(strlen(paedia_dir_name)+
strlen(main_file_name)+2,0))
{
strcpy(path_name,paedia_dir_name);
AddPart(path_name,main_file_name,strlen(paedia_dir_name)+strlen(
main_file_name)+2);
/* Open the main file and free its path name buffer */
if(!(paedia->main_file=Open(path_name,MODE_OLDFILE)))
{
ReportError(NULL,ERROR_REPORT_FILE,path_name,0);
success=FALSE;
}
FreeVec(path_name);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
/* Make a string specifying the main file size */
if(success)
{
if((temp_fib=AllocDosObjectTags(DOS_FIB,TAG_END))&&
(link_file_name=AllocVec(MAX_LINK_FILE_NAME_LENGTH+1,
MEMF_PUBLIC)))
{
ExamineFH(paedia->main_file,temp_fib);
sprintf(link_file_name,"%ld",temp_fib->fib_Size);
FreeDosObject(DOS_FIB,temp_fib);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
/* Construct the full path name for link file */
if(success)
{
if(success&&(path_name=AllocVec(strlen(data_dir_name)+
strlen(link_file_name)+2,0)))
{
strcpy(path_name,data_dir_name);
AddPart(path_name,link_file_name,strlen(data_dir_name)+
strlen(link_file_name)+2);
/* Open the link file and free its path name buffer */
if(!(link_file=Open(path_name,MODE_OLDFILE)))
{
/* Create a new link file from the original textual link
* file */
if(orig_link_path=AllocVec(strlen(paedia_dir_name)+
strlen(orig_link_file_name)+2,0))
{
/* TODO: should let user know what's happening */
strcpy(orig_link_path,paedia_dir_name);
AddPart(orig_link_path,orig_link_file_name,
strlen(paedia_dir_name)+strlen(orig_link_file_name)
+2);
ConvertLinkFile(orig_link_path,path_name);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
/* Retry to open the apropriate link file */
if(!(link_file=Open(path_name,MODE_OLDFILE)))
{
ReportError(NULL,ERROR_REPORT_FILE,path_name,0);
success=FALSE;
}
}
FreeVec(path_name);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
}
FreeVec(link_file_name);
}
/* Copy link file into memory */
if(link_file)
{
if(temp_fib=AllocDosObjectTags(DOS_FIB,TAG_END))
{
/* Get link file size */
ExamineFH(link_file,temp_fib);
paedia->link_count=temp_fib->fib_Size/sizeof(MediaLink_imp);
FreeDosObject(DOS_FIB,temp_fib);
/* Allocate memory for link data */
paedia->media_links=AllocMem(sizeof(MediaLink_imp)
*paedia->link_count,MEMF_CLEAR);
/* Read link data into memory */
if(paedia->media_links)
Read(link_file,paedia->media_links,paedia->link_count
*sizeof(MediaLink_imp));
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
Close(link_file);
}
/* Construct the full path names for the index files */
path_name=AllocVec(strlen(paedia_dir_name)+
strlen(master_file_name)+2,0);
index_path_name=AllocVec(strlen(paedia_dir_name)+
strlen(index_file_name)+2,0);
if(path_name&&index_path_name)
{
strcpy(path_name,paedia_dir_name);
strcpy(index_path_name,paedia_dir_name);
AddPart(path_name,master_file_name,strlen(paedia_dir_name)+strlen(
master_file_name)+2);
AddPart(index_path_name,index_file_name,strlen(paedia_dir_name)+
strlen(index_file_name)+2);
paedia->index=CreateIndex(path_name,index_path_name);
if(!paedia->index)
success=FALSE;
FreeVec(path_name);
FreeVec(index_path_name);
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
success=FALSE;
}
if(!success)
{
KillPaedia(paedia);
paedia=NULL;
}
}
else
{
ReportError(NULL,ERROR_REPORT_MEM,NULL,0);
}
return paedia;
}
/* Function: GetPaediaItem
* =======================
* Extracts an article,picture etc. from a Paedia.
*/
Sequence GetPaediaItem(Paedia paedia,ULONG link_no)
{
MediaLink link=GetPaediaLink(paedia,link_no);
Sequence inflated=NULL;
DeflatedSequence deflated;
UBYTE *compressed_buffer;
compressed_buffer=AllocMem(link->block_count*BLOCK_SIZE,MEMF_ANY);
if(compressed_buffer)
{
GetBlocks(paedia->main_file,link->start_block,link->block_count,
compressed_buffer);
deflated=CreateSequence(link->block_count*BLOCK_SIZE,
compressed_buffer);
if(deflated)
{
inflated=InflateSequence(deflated);
KillSequence(deflated);
}
FreeMem(compressed_buffer,link->block_count*BLOCK_SIZE);
}
#ifdef TEST
BPTR extract_file;
if(extract_file=Open("T:extract",MODE_NEWFILE))
{
Write(extract_file,inflated->data,inflated->length);
Close(extract_file);
}
#endif
return inflated;
}
/* Function: KillPaedia
* ====================
* Destroys a Paedia.
*/
VOID KillPaedia(Paedia paedia)
{
if(paedia->index)
KillIndex(paedia->index);
if(paedia->main_file)
Close(paedia->main_file);
if(paedia->media_links)
FreeMem(paedia->media_links,paedia->link_count*sizeof(MediaLink_imp));
FreeMem(paedia,sizeof(Paedia_imp));
return;
}
/* Function: GetPaediaLink
* =======================
* Finds a specific link in a paedia's link array.
*/
static MediaLink GetPaediaLink(Paedia paedia,ULONG link_no)
{
MediaLink p;
for(p=paedia->media_links;p->link_no!=link_no;p++);
return p;
}
/* Function: GetBlocks
* ===================
* Reads data blocks from the main paedia file.
*/
static VOID GetBlocks(BPTR file,ULONG start_block,ULONG block_count,
UBYTE *buffer)
{
Seek(file,start_block*BLOCK_SIZE,OFFSET_BEGINNING);
Read(file,buffer,block_count*BLOCK_SIZE);
return;
}