home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
xpdf
/
apdf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-07-12
|
106KB
|
4,068 lines
//========================================================================
//
// Apdf.c
//
// Copyright 1999 Emmanuel Lesueur
//
//========================================================================
//#define DEBUGMSG
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libraries/asl.h>
#include <libraries/mui.h>
#include <libraries/gadtools.h>
#include <libraries/iffparse.h>
#include <dos/dostags.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/layers.h>
#include <hardware/blit.h>
#include <cybergraphics/cybergraphics.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#define NO_INLINE_STDARG
#include <proto/muimaster.h>
#undef NO_INLINE_STDARG
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#define NO_INLINE_STDARG
#include <proto/intuition.h>
#undef NO_INLINE_STDARG
#include <proto/layers.h>
#include <proto/utility.h>
#include <proto/cybergraphics.h>
#include <proto/icon.h>
#include <proto/diskfont.h>
#include <proto/iffparse.h>
#include "config.h"
#include "AComm.h"
#ifdef POWERUP
# include <powerup/ppclib/message.h>
# include <powerup/ppclib/tasks.h>
# include <powerup/proto/ppc.h>
# include "AGfxcomm.h"
#endif
#ifndef AFF_68060
# define AFF_68060 (1L<<7)
#endif
#define DB(x) //x
#ifdef __SASC
# define SAVEDS __saveds
# define ASM __asm
# define REG(r,a) register __ ## r a
#elif defined(__GNUC__)
# define SAVEDS
# define ASM
# define STR(x) #x
# define REG(r,a) a __asm(STR(r))
#endif
static void copystr(char** p,const char* q) {
if(q) {
size_t l=strlen(q)+1;
char* t=malloc(l);
if(t) {
if(*p)
free(*p);
*p=t;
memcpy(t,q,l);
}
}
}
static char* gzipcmd_arg;
static char* urlcmd_arg;
static char* deficon_arg;
static char* diskobj_arg;
static int page_arg=1;
static int zoom_arg=1;
static int colors_arg=16;
static int cachesz_arg=256;
static int blocsz_arg=4;
#define TEMPLATE "PDFFILE,P=PAGE/N/K,Z=ZOOM/N/K,C=COLORS/N/K,G=GZIPCMD/K,U=URLCMD/K,I=DEFICON/K,F=FONTMAP/M,D=DISKOBJECT/K,S=CACHESIZE/N/K,B=CACHEBLOCSIZE/N/K"
#define PDFFILE ((const char*)args[0])
#define PAGE (args[1]?*(int*)args[1]:page_arg)
#define ZOOM (args[2]?*(int*)args[2]:zoom_arg)
#define COLORS (args[3]?*(int*)args[3]:16)
#define GZIPCMD (args[4]?(const char*)args[4]:(gzipcmd_arg?gzipcmd_arg:"gzip -d -q"))
#define URLCMD (args[5]?(const char*)args[5]:(urlcmd_arg?urlcmd_arg:"OpenURL %s"))
#define DEFICON (args[6]?(const char*)args[6]:(deficon_arg?deficon_arg:"env:sys/def_pdf"))
#define FONTMAP ((const char**)args[7])
#define DISKOBJ (args[8]?(const char*)args[8]:diskobj_arg)
#define CACHESZ (args[9]?*(int*)args[9]:cachesz_arg)
#define BLOCSZ (args[10]?*(int*)args[10]:blocsz_arg)
#define NARGS 11
#define SET_PAGE(x) (args[1]=NULL,page_arg=x)
#define SET_ZOOM(x) (args[2]=NULL,zoom_arg=x)
#define SET_COLORS(x) (args[3]=NULL,colors_arg=x)
#define SET_CACHESZ(x) (args[9]=NULL,cachesz_arg=x)
#define SET_BLOCSZ(x) (args[10]=NULL,blocsz_arg=x)
static LONG args[NARGS];
#if defined(__SASC) || defined(__libnix__)
char __stdiowin[]="CON://600/200/Apdf/AUTO/WAIT/CLOSE";
extern struct WBStartup *_WBenchMsg;
static void parse_tooltypes(BPTR lock,const char* name) {
struct DiskObject *dob;
BPTR olddir=CurrentDir(lock);
if(dob=GetDiskObject((char*)name)) {
if(dob->do_ToolTypes) {
char* s=FindToolType(dob->do_ToolTypes,"PAGE");
if(s)
SET_PAGE(atoi(s));
s=FindToolType(dob->do_ToolTypes,"ZOOM");
if(s)
SET_ZOOM(atoi(s));
s=FindToolType(dob->do_ToolTypes,"COLORS");
if(s)
SET_COLORS(atoi(s));
s=FindToolType(dob->do_ToolTypes,"GZIPCMD");
if(s)
copystr(&gzipcmd_arg,s);
s=FindToolType(dob->do_ToolTypes,"URLCMD");
if(s)
copystr(&urlcmd_arg,s);
s=FindToolType(dob->do_ToolTypes,"DEFICON");
if(s)
copystr(&deficon_arg,s);
s=FindToolType(dob->do_ToolTypes,"DISKOBJECT");
if(s)
copystr(&diskobj_arg,s);
s=FindToolType(dob->do_ToolTypes,"CACHESIZE");
if(s)
SET_CACHESZ(atoi(s));
s=FindToolType(dob->do_ToolTypes,"CACHEBLOCSIZE");
if(s)
SET_BLOCSZ(atoi(s));
}
FreeDiskObject(dob);
}
CurrentDir(olddir);
}
#endif
#define MYTAG_START TAG_USER
#define MYATTR_Page (MYTAG_START+1)
#define MYATTR_Zoom (MYTAG_START+2)
#define MYATTR_Selected (MYTAG_START+5)
#define MYATTR_Selection (MYTAG_START+6)
#define MYATTR_NewDoc (MYTAG_START+7)
#define MYATTR_NumPages (MYTAG_START+8)
#define MYATTR_Value (MYTAG_START+9)
#define MYATTR_ListID (MYTAG_START+10)
#define MYM_Reset (MYTAG_START+100)
#define ID_ABOUT 1
#define ID_ABOUTMUI 2
#define ID_SEARCH 3
#define ID_OPEN 4
#define ID_SAVEAS 5
#define ID_WRITE 6
#define ID_MUIPREFS 7
#define ID_COPY 8
#define ID_DEFAULTFONTS 9
#define ID_DEFFONTS 10
#define ID_DOCFONTS 11
#define ID_APPLYFONTMAP 12
#define ID_SCANFONTS 13
#define ID_ABORT 14
#define ID_OPENSCANFONTS 15
#define ID_PRINT 16
#define ID_HIDE 17
#define MYASSERT(x) if(!(x)) { printf("Internal error: %s/%d\n",__FILE__,__LINE__); exit(EXIT_FAILURE); }
#define ID_FTXT MAKE_ID('F','T','X','T')
#define ID_CHRS MAKE_ID('C','H','R','S')
#if defined(__SASC) || defined(__libnix__)
long __stack=30000;
#endif
#define btop 1
#define bbottom 1
#define bleft 1
#define bright 1
struct IntuitionBase* IntuitionBase;
struct GfxBase* GfxBase;
struct Library* LayersBase;
struct UtilityBase* UtilityBase;
struct Library* MUIMasterBase;
struct Library* PPCLibBase;
struct Library* CyberGfxBase;
struct Library* IconBase;
struct Library* DiskfontBase;
struct Library* IFFParseBase;
/* zoom factor is 1.2 (similar to DVI magsteps) */
#define minZoom -5
#define maxZoom 5
static int zoomDPI[maxZoom - minZoom + 1] = {
29, 35, 42, 50, 60,
72,
86, 104, 124, 149, 179
};
#define defZoom 1
BPTR input,oldinput;
BPTR progdir;
char* progname;
BPTR docdir;
char* docname;
struct RDArgs* rda;
struct DiskObject* diskobj;
struct MUI_CustomClass* mcc;
struct MUI_CustomClass* slider_mcc;
struct MUI_CustomClass* rotate_slider_mcc;
struct MUI_CustomClass* list_mcc;
Object* App;
Object* pageobj;
Object* zoomobj;
Object* bitmapobj;
Object* vgroup;
Object* win;
Object* linkobj;
Object* searchobj;
Object* psstartobj;
Object* psstopobj;
Object* scanstartobj;
Object* scanstopobj;
Object* pagegroup;
Object* gaugewin;
Object* gaugeobj;
Object* abortobj;
struct FileRequester* req;
BPTR olddir;
#ifdef POWERUP
void* elfobject;
PPCPort* port;
PPCPort* reply_port;
PPCPortList* portlist;
PPCMsg* startupmsg;
struct StartupData* startup_data;
size_t startup_length;
PPCTask* ppctask;
PPCPort* ports[3];
PPCMsg* quitmsg;
PPCMsg* cmdmsg;
BOOL cmd_sent;
void* cmddata;
PPCPort* ppcport;
BOOL quitting=FALSE;
BOOL ppc_quitted=TRUE;
#endif
struct clip_rect {
struct clip_rect *next;
short minx;
short miny;
short maxx;
short maxy;
};
struct clip_poly {
struct clip_poly *next;
int num;
short data[1];
};
struct font_entry {
struct TextFont *font;
short style;
short pad;
};
static short area_minx,area_miny,area_maxx,area_maxy;
static short* area_buf;
void cleararea(void) {
DB(printf("--cleararea\n");)
if(area_buf) {
free(area_buf);
area_buf=NULL;
}
}
void initarea(struct RastPort* rp,int n) {
static struct AreaInfo areainfo;
DB(printf("--initarea(%d)\n",n);)
cleararea();
if(area_buf=malloc((n+1)*5)) {
InitArea(&areainfo,area_buf,n+1);
rp->AreaInfo=&areainfo;
}
area_minx=32767;
area_miny=32767;
area_maxx=-32768;
area_maxy=-32768;
}
void areapoly(struct RastPort* rp,int n,short* p,short dx,short dy) {
DB(printf("--areapoly(%d,%d,%d)\n",n,dx,dy);)
if(rp->AreaInfo) {
int k=n;
while(--k>=0) {
if(*p>area_maxx)
area_maxx=*p;
if(*p<area_minx)
area_minx=*p;
++p;
if(*p>area_maxy)
area_maxy=*p;
if(*p<area_miny)
area_miny=*p;
++p;
}
p-=2*n;
AreaMove(rp,p[0]-dx,p[1]-dy);
while(--n) {
p+=2;
AreaDraw(rp,p[0]-dx,p[1]-dy);
}
}
}
void areaend(struct RastPort* rp) {
DB(printf("--areaend\n");)
if(rp->AreaInfo) {
int w=area_maxx-area_minx+17;
int h=area_maxy-area_miny+1;
void* plane;
if(plane=AllocRaster(w,h)) {
struct TmpRas tmpras;
InitTmpRas(&tmpras,plane,RASSIZE(w,h));
rp->TmpRas=&tmpras;
AreaEnd(rp);
WaitBlit();
rp->TmpRas=NULL;
FreeRaster(plane,w,h);
}
free(area_buf);
area_buf=NULL;
rp->AreaInfo=NULL;
}
}
/* workaround for a bug in egcs */
static void MyReadPixelArray(APTR dest,UWORD dx,UWORD dy,UWORD mod,struct RastPort* rp,UWORD x,UWORD y,UWORD w,UWORD h,UBYTE fmt) {
ReadPixelArray(dest,dx,dy,mod,rp,x,y,w,h,fmt);
}
static void MyWritePixelArray(APTR src,UWORD sx,UWORD sy,UWORD mod,struct RastPort* rp,UWORD x,UWORD y,UWORD w,UWORD h,UBYTE fmt) {
WritePixelArray(src,sx,sy,mod,rp,x,y,w,h,fmt);
}
struct DocData {
int width;
int height;
int page;
int num_pages;
int page_width;
int page_height;
int zoom;
int last_page;
int last_width;
int last_height;
int last_zoom;
struct ColorMap* colormap;
struct BitMap *friendbm;
struct BitMap *bm;
struct Layer_Info *layerinfo;
struct Layer *layer;
struct Region *region;
struct BitMap *clipbm;
struct Layer_Info *cliplayerinfo;
struct Layer *cliplayer;
struct Region *clipregion;
struct Region *clipregion2;
struct clip_rect *rects;
struct clip_poly *polys;
Object* obj;
struct Rectangle selection;
struct Rectangle old_selection;
struct font_entry *fonts;
int maxfont;
ULONG* pens;
int curpen;
int maxpen;
struct RastPort rp;
short depth;
short dx;
short dy;
short clipwidth;
short clipheight;
short minx;
short maxx;
short miny;
short maxy;
BOOL hidden;
BOOL selected;
BOOL selecting;
BOOL select_displayed;
#ifndef POWERUP
struct RastPort** rpp;
short* dxp;
short* dyp;
#endif
};
typedef struct DocData DocData;
#ifndef POWERUP
void initgfx(DocData** dp,struct RastPort** rpp,short* dxp,short* dyp) {
DocData* dat=INST_DATA(mcc->mcc_Class,bitmapobj);
*dp=dat;
*rpp=&dat->rp;
dat->rpp=rpp;
dat->dxp=dxp;
dat->dyp=dyp;
}
#endif
/*
* Pen sharing functions.
*/
ULONG get_pen(DocData* dat,short n) {
DB(printf("--getpen(%d)\n",n);)
return n<dat->maxpen?dat->pens[n]:1;
}
static void clear_pens(DocData* dat) {
ULONG* p=dat->pens;
int n;
for(n=dat->curpen<dat->maxpen?dat->curpen:dat->maxpen;--n>=0;)
ReleasePen(dat->colormap,p[n]);
dat->curpen=0;
}
ULONG add_pen(DocData* dat,ULONG r,ULONG g,ULONG b) {
DB(printf("--addpen %d=%08lx,%08lx,%08lx\n",dat->curpen,r,g,b);)
if(dat->curpen>=dat->maxpen) {
int maxpen=((dat->curpen*3)>>1)+16;
ULONG* p=realloc(dat->pens,maxpen*sizeof(*dat->pens));
if(p) {
dat->maxpen=maxpen;
dat->pens=p;
}
}
if(dat->curpen<dat->maxpen)
return dat->pens[dat->curpen++]=ObtainBestPenA(dat->colormap,r,g,b,NULL);
else
return 1;
}
void add_pens(DocData* dat,ULONG* t,int num) {
while(--num>=0) {
t[0]=add_pen(dat,t[1],t[2],t[3]);
GetRGB32(dat->colormap,t[0],1,t+1);
t+=4;
}
}
void reset_pens(DocData* dat) {
clear_pens(dat);
add_pen(dat,0,0,0);
add_pen(dat,0xffffffffUL,0xffffffffUL,0xffffffffUL);
}
/*
* Font handling functions.
*/
void openfont(DocData* dat,int id,const char* name,short size,short style) {
if(id>=dat->maxfont) {
int maxfont=(id*3)/2+16;
struct font_entry* p=realloc(dat->fonts,maxfont*sizeof(*p));
if(p) {
memset(p+dat->maxfont,0,(maxfont-dat->maxfont)*sizeof(*p));
dat->fonts=p;
dat->maxfont=maxfont;
}
}
if(id<dat->maxfont) {
struct TextAttr ta;
ta.ta_Name=(char*)name;
ta.ta_YSize=size;
ta.ta_Style=style;
ta.ta_Flags=0;
dat->fonts[id].style=style;
if(!(dat->fonts[id].font=OpenDiskFont(&ta)))
printf("Can't open font \"%s\"/%d.\n",name,size);
}
}
void closefont(DocData* dat,int id) {
if(id<dat->maxfont && dat->fonts[id].font) {
CloseFont(dat->fonts[id].font);
dat->fonts[id].font=NULL;
}
}
void setfont(DocData* dat,int id) {
if(id<dat->maxfont && dat->fonts[id].font) {
SetFont(&dat->rp,dat->fonts[id].font);
SetSoftStyle(&dat->rp,dat->fonts[id].style,FSF_BOLD|FSF_ITALIC);
}
}
static void clear_fonts(DocData* dat) {
int k;
for(k=0;k<dat->maxfont;++k)
if(dat->fonts[k].font)
CloseFont(dat->fonts[k].font);
free(dat->fonts);
dat->fonts=NULL;
dat->maxfont=0;
}
/*
* Clip handling functions.
*/
static void free_clip_polys(DocData *dat) {
struct clip_poly *p;
DB(printf("--free_clip_polys\n");)
p=dat->polys;
while(p) {
struct clip_poly *q=p->next;
free(p);
p=q;
}
dat->polys=NULL;
}
static void free_clip_rects(DocData *dat) {
struct clip_rect *p;
DB(printf("--free_clip_rects\n");)
p=dat->rects;
while(p) {
struct clip_rect *q=p->next;
free(p);
p=q;
}
dat->rects=NULL;
}
static void clip_path(DocData* dat,int n,short* p) {
short dx=dat->dx;
short dy=dat->dy;
if(dx || dy) {
while(--n>=0) {
*p++-=dx;
*p++-=dy;
}
}
}
static void tfr_clip(DocData *dat) {
DB(printf("--tfr_clip\n");)
if(dat->bm && dat->polys && dat->clipbm) {
/*
* Non rectangular clipping region.
*
* Ideally, we would draw a mask and call
* BltMaskBitMapRastPort. However, due to the
* bogus way the mask parameter is given to this function
* it is quite unusable with anything but standard
* non-interleaved bitmaps. So we emulate this
* function instead. This is slow, uses lots of memory
* and is non-optimal, but this is rarely used anyway...
*/
struct BitMap *bm1;
struct BitMap *bm2;
struct RastPort rp1;
struct RastPort rp2;
UBYTE* mask;
UBYTE* src;
UBYTE* dest;
size_t sz=((dat->clipwidth+15)&~15)*dat->clipheight+4;
DB(printf("--non trivial tfr_clip\n");)
InitRastPort(&rp1);
if(mask=malloc(sz)) {
if(bm1=AllocBitMap(dat->clipwidth,dat->clipheight,1,BMF_MINPLANES,dat->bm)) {
if(bm2=AllocBitMap(dat->clipwidth,1,1,BMF_MINPLANES,bm1)) {
struct Layer_Info *layerinfo;
struct Layer *layer;
rp1.BitMap=bm1;
if(layerinfo=NewLayerInfo()) {
if(layer=CreateUpfrontLayer(layerinfo,bm1,0,0,dat->clipwidth-1,dat->clipheight-1,LAYERSIMPLE,NULL)) {
int n;
struct clip_rect *q;
struct clip_poly *p;
InstallClipRegion(dat->cliplayer,NULL);
InstallClipRegion(layer,dat->clipregion2);
rp1.Layer=layer;
SetAPen(&rp1,1);
for(q=dat->rects;q;q=q->next)
RectFill(&rp1,q->minx-dat->dx,q->miny-dat->dy,q->maxx-dat->dx,q->maxy-dat->dy);
n=0;
for(p=dat->polys;p;p=p->next)
n+=p->num+1;
initarea(&rp1,n);
for(p=dat->polys;p;p=p->next)
areapoly(&rp1,p->num,p->data,dat->dx,dat->dy);
areaend(&rp1);
InstallClipRegion(layer,NULL);
InstallClipRegion(dat->cliplayer,dat->clipregion2);
rp1.Layer=NULL;
rp2=rp1;
rp2.BitMap=bm2;
ReadPixelArray8(&rp1,0,0,dat->clipwidth-1,dat->clipheight-1,mask,&rp2);
DeleteLayer(0,layer);
}
DisposeLayerInfo(layerinfo);
}
FreeBitMap(bm2);
}
FreeBitMap(bm1);
}
if(dat->depth<=8) {
if(src=malloc(sz)) {
if(bm2=AllocBitMap(dat->clipwidth,1,dat->depth,BMF_MINPLANES,dat->bm)) {
rp2=dat->rp;
rp2.BitMap=bm2;
rp2.Layer=NULL;
dat->rp.BitMap=dat->clipbm;
dat->rp.Layer=NULL;
ReadPixelArray8(&dat->rp,0,0,dat->clipwidth-1,dat->clipheight-1,src,&rp2);
if(dest=malloc(sz)) {
UBYTE *s=src;
UBYTE *d=dest;
UBYTE *m=mask;
UBYTE x=(1<<dat->depth)-1;
dat->rp.BitMap=dat->bm;
ReadPixelArray8(&dat->rp,dat->dx,dat->dy,dat->dx+dat->clipwidth-1,dat->dy+dat->clipheight-1,dest,&rp2);
do {
UBYTE t=((BYTE)(*m<<7)>>7)&x;
*d=(*d&~t)|(*s&t);
++d;
++s;
++m;
} while(--sz);
dat->rp.Layer=dat->layer;
WritePixelArray8(&dat->rp,dat->dx,dat->dy,dat->dx+dat->clipwidth-1,dat->dy+dat->clipheight-1,dest,&rp2);
free(dest);
}
FreeBitMap(bm2);
}
free(src);
}
} else {
if(src=malloc(sz*3)) {
UWORD mod=((dat->clipwidth+15)&~15)*3;
dat->rp.BitMap=dat->clipbm;
dat->rp.Layer=NULL;
MyReadPixelArray(src,0,0,mod,&dat->rp,0,0,dat->clipwidth,dat->clipheight,RECTFMT_RGB);
if(dest=malloc(sz*3)) {
UBYTE *s=src;
UBYTE *d=dest;
UBYTE *m=mask;
dat->rp.BitMap=dat->bm;
MyReadPixelArray(dest,0,0,mod,&dat->rp,dat->dx,dat->dy,dat->clipwidth,dat->clipheight,RECTFMT_RGB);
do {
UBYTE t=(BYTE)(*m<<7)>>7;
*d=(*d&~t)|(*s&t);
++d;
++s;
*d=(*d&~t)|(*s&t);
++d;
++s;
*d=(*d&~t)|(*s&t);
++d;
++s;
++m;
} while(--sz);
dat->rp.Layer=dat->layer;
MyWritePixelArray(dest,0,0,mod,&dat->rp,dat->dx,dat->dy,dat->clipwidth,dat->clipheight,RECTFMT_RGB);
free(dest);
}
free(src);
}
}
free(mask);
}
}
}
void clear_clip(DocData* dat) {
DB(printf("--clear_clip\n");)
if(dat->polys) {
tfr_clip(dat);
free_clip_polys(dat);
}
free_clip_rects(dat);
dat->rp.Layer=dat->layer;
dat->rp.BitMap=dat->bm;
if(dat->clipregion) {
InstallClipRegion(dat->layer,dat->region);
DisposeRegion(dat->clipregion);
dat->clipregion=NULL;
}
if(dat->clipregion2) {
InstallClipRegion(dat->cliplayer,NULL);
DisposeRegion(dat->clipregion2);
dat->clipregion2=NULL;
}
if(dat->cliplayer) {
DeleteLayer(0,dat->cliplayer);
dat->cliplayer=NULL;
}
if(dat->cliplayerinfo) {
DisposeLayerInfo(dat->cliplayerinfo);
dat->cliplayerinfo=NULL;
}
FreeBitMap(dat->clipbm);
dat->clipbm=NULL;
dat->dx=0;
dat->dy=0;
#ifndef POWERUP
*dat->dxp=0;
*dat->dyp=0;
#endif
}
void init_clip(DocData* dat) {
DB(printf("--init_clip\n");)
clear_clip(dat);
dat->minx=dat->width;
dat->miny=dat->height;
dat->maxx=-1;
dat->maxy=-1;
}
void rect_clip(DocData* dat,short x1,short y1,short x2,short y2) {
struct clip_rect *q;
DB(printf("--rect_clip (%d,%d)-(%d,%d)\n",x1,y1,x2,y2);)
if(dat->minx>x1)
dat->minx=x1;
if(dat->miny>y1)
dat->miny=y1;
if(dat->maxx<x2)
dat->maxx=x2;
if(dat->maxy<y2)
dat->maxy=y2;
if(q=malloc(sizeof(*q))) {
q->next=dat->rects;
dat->rects=q;
q->minx=x1;
q->miny=y1;
q->maxx=x2;
q->maxy=y2;
}
}
void poly_clip(DocData *dat,int n,short* p) {
DB(printf("--poly_clip %d:",n);)
if(n) {
size_t sz=sizeof(struct clip_poly)+(n*2-1)*sizeof(short);
struct clip_poly *q;
if(q=malloc(sz)) {
q->next=dat->polys;
dat->polys=q;
q->num=n;
memcpy(q->data,p,n*2*sizeof(short));
}
do {
DB(printf(" (%d,%d)",p[0],p[1]);)
if(dat->minx>p[0])
dat->minx=p[0];
if(dat->maxx<p[0])
dat->maxx=p[0];
if(dat->miny>p[1])
dat->miny=p[1];
if(dat->maxy<p[1])
dat->maxy=p[1];
p+=2;
} while(--n);
}
DB(printf("\n");)
}
void install_clip(DocData* dat) {
DB(printf("--install_clip\n");)
dat->rp.Layer=dat->layer;
if(dat->polys) {
if(dat->minx<0)
dat->minx=0;
if(dat->miny<0)
dat->miny=0;
if(dat->maxx>dat->width-1)
dat->maxx=dat->width-1;
if(dat->maxy>dat->height-1)
dat->maxy=dat->height-1;
dat->clipwidth=dat->maxx-dat->minx+1;
dat->clipheight=dat->maxy-dat->miny+1;
DB(printf("--install_clip %d×%d\n",dat->clipwidth,dat->clipheight);)
if(dat->clipwidth>0 && dat->clipheight>0 &&
(dat->clipbm=AllocBitMap(dat->clipwidth,dat->clipheight,dat->depth,BMF_MINPLANES,dat->bm))) {
if(dat->cliplayerinfo=NewLayerInfo()) {
if(dat->cliplayer=CreateUpfrontHookLayer(dat->cliplayerinfo,
dat->clipbm,
0,0,
dat->clipwidth-1,
dat->clipheight-1,
LAYERSIMPLE,
LAYERS_NOBACKFILL,
NULL)) {
if(dat->clipregion2=NewRegion()) {
struct Rectangle rect;
rect.MinX=0;
rect.MinY=0;
rect.MaxX=dat->clipwidth-1;
rect.MaxY=dat->clipheight-1;
if(OrRectRegion(dat->clipregion2,&rect)) {
InstallClipRegion(dat->cliplayer,dat->clipregion2);
DB(printf("--installed.\n");)
dat->rp.BitMap=dat->clipbm;
dat->rp.Layer=dat->cliplayer;
dat->dx=dat->minx;
dat->dy=dat->miny;
#ifndef POWERUP
*dat->dxp=dat->dx;
*dat->dyp=dat->dy;
#endif
BltBitMapRastPort(dat->bm,dat->dx,dat->dy,&dat->rp,0,0,dat->clipwidth,dat->clipheight,0xc0);
return;
}
DisposeRegion(dat->clipregion2);
dat->clipregion2=NULL;
}
DeleteLayer(0,dat->cliplayer);
dat->cliplayer=NULL;
}
DisposeLayerInfo(dat->cliplayerinfo);
dat->cliplayerinfo=NULL;
}
FreeBitMap(dat->clipbm);
dat->clipbm=NULL;
} else
printf("Can't allocate bitmap\n");
} else if(dat->rects) {
if(dat->clipregion=NewRegion()) {
struct clip_rect *p;
struct Rectangle rect;
for(p=dat->rects;p;p=p->next) {
rect.MinX=p->minx;
rect.MinY=p->miny;
rect.MaxX=p->maxx;
rect.MaxY=p->maxy;
OrRectRegion(dat->clipregion,&rect);
}
rect.MinX=0;
rect.MinY=0;
rect.MaxX=dat->width-1;
rect.MaxY=dat->height-1;
AndRectRegion(dat->clipregion,&rect); /* Can't fail */
InstallClipRegion(dat->layer,dat->clipregion);
} else
InstallClipRegion(dat->layer,dat->region);
} else {
DB(printf("--simple install_clip\n");)
InstallClipRegion(dat->layer,dat->region);
}
}
/*
* Misc functions.
*/
static void sleep(BOOL x) {
if(App)
set(App,MUIA_Application_Sleep,x);
}
static void quit(void) {
#ifdef POWERUP
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,quitmsg,NULL,0,MSGID_QUIT);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
quitting=TRUE;
#else
exit(EXIT_SUCCESS);
#endif
}
/*
* PowerUP inter process communication functions.
*/
#ifdef POWERUP
static int get_info(int* num_pages) {
struct msg_info* p=cmddata;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_INFO);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
*num_pages=p->num_pages;
return p->base.success;
}
static int get_page_size(int page,int* width,int* height) {
struct msg_pagesize* p=cmddata;
p->page=page;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_PAGESIZE);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
*width=p->width;
*height=p->height;
return p->base.success;
}
static int create_doc(BPTR dir,const char* filename,size_t cachesz,size_t blocsz) {
if(!quitting && !ppc_quitted) {
struct msg_createdoc* p=cmddata;
p->dir=dir;
strncpy(p->filename,filename,sizeof(p->filename)-1);
p->filename[sizeof(p->filename)-1]='\0';
p->cachesz=cachesz;
p->blocsz=blocsz;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_CREATEDOC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
#if 0
static void delete_doc(void) {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_DELETEDOC);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
#endif
static void create_output_dev(int depth,struct ColorMap* colormap) {
if(!quitting && !ppc_quitted) {
struct msg_create_output_dev* p=(struct msg_create_output_dev*)cmddata;
p->depth=depth;
p->colormap=colormap;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_CREATEOUTPUTDEV);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static void delete_output_dev(void) {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_DELETEOUTPUTDEV);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static int simple_find(const char* str,int top,int* xmin,int* ymin,int* xmax,int* ymax) {
if(!quitting && !ppc_quitted) {
struct msg_find* p=cmddata;
p->top=top;
p->xmin=*xmin;
p->ymin=*ymin;
p->xmax=*xmax;
p->ymax=*ymax;
strcpy(p->str,str);
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_SIMPLEFIND);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
*xmin=p->xmin;
*ymin=p->ymin;
*xmax=p->xmax;
*ymax=p->ymax;
return p->base.success;
}
return 0;
}
static int init_find(const char* str) {
if(!quitting && !ppc_quitted) {
struct msg_find* p=cmddata;
strcpy(p->str,str);
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_INITFIND);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
static int find(int start,int stop,int* xmin,int* ymin,int* xmax,int* ymax,int* page) {
if(!quitting && !ppc_quitted) {
struct msg_find* p=cmddata;
p->top=start;
p->bottom=stop;
/*p->xmin=*xmin;
p->ymin=*ymin;
p->xmax=*xmax;
p->ymax=*ymax;
p->page=*page;*/
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_FIND);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
*xmin=p->xmin;
*ymin=p->ymin;
*xmax=p->xmax;
*ymax=p->ymax;
*page=p->page;
return p->base.success;
}
return 0;
}
static void end_find() {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_ENDFIND);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static int chklink(int x,int y,void** action,char* str,size_t len) {
if(!quitting && !ppc_quitted) {
struct msg_chklink* p=cmddata;
p->x=x;
p->y=y;
p->action=*action;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_CHKLINK);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
strncpy(str,p->str,len);
*action=p->action;
return p->base.success;
}
return 0;
}
static int dolink(int* x,int* y,int* state,int* page,char* buf,size_t len) {
if(!quitting && !ppc_quitted) {
struct msg_dolink* p=cmddata;
p->x=*x;
p->y=*y;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_DOLINK);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
*state=p->state;
*page=p->page;
*x=p->x;
*y=p->y;
strncpy(buf,p->str,len);
return p->base.success;
}
return 0;
}
static int init_write(const char* filename,int first_page,int last_page,int zoom,int rotate,int type) {
if(!quitting && !ppc_quitted) {
struct msg_write* p=cmddata;
strncpy(p->filename,filename,sizeof(p->filename)-1);
p->filename[sizeof(p->filename)-1]='\0';
p->first_page=first_page;
p->last_page=last_page;
p->zoom=zoom;
p->rotate=rotate;
p->type=type;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_INITWRITE);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
static void writefile(int first_page,int last_page) {
if(!quitting && !ppc_quitted) {
struct msg_write* p=cmddata;
p->first_page=first_page;
p->last_page=last_page;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_WRITE);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static void end_write() {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_ENDWRITE);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static char* gettext(int xmin,int ymin,int xmax,int ymax) {
char* r=NULL;
if(!quitting && !ppc_quitted) {
struct msg_gettext* p=cmddata;
p->xmin=xmin;
p->ymin=ymin;
p->xmax=xmax;
p->ymax=ymax;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_GETTEXT);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
if(p->base.success) {
char* buf=NULL;
size_t sz=p->size+1;
char* q;
if(sz>sizeof(union msg_max)) {
buf=PPCAllocVec(sz,MEMF_ANY);
if(buf)
q=buf;
else {
q=cmddata;
sz=sizeof(union msg_max);
}
} else
q=cmddata;
PPCSendMessage(ppcport,cmdmsg,q,sz,MSGID_GETTEXT);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
if(r=malloc(sz))
memcpy(r,q,sz);
if(buf)
PPCFreeVec(buf);
}
}
return r;
}
static void add_fontmap(const char* pdffont,const char* afont,
int m,int style,int encoding) {
if(!quitting && !ppc_quitted) {
struct msg_fontmap* p=cmddata;
strncpy(p->pdffont,pdffont,sizeof(p->pdffont)-1);
p->pdffont[sizeof(p->pdffont)-1]='\0';
strncpy(p->afont,afont,sizeof(p->afont)-1);
p->afont[sizeof(p->afont)-1]='\0';
p->m=m;
p->style=style;
p->encoding=encoding;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_ADDFONTMAP);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
#if 0
static void rem_fontmap(const char* pdffont) {
if(!quitting && !ppc_quitted) {
struct msg_fontmap* p=cmddata;
strncpy(p->pdffont,pdffont,sizeof(p->pdffont)-1);
p->pdffont[sizeof(p->pdffont)-1]='\0';
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_REMFONTMAP);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
#endif
static int init_scan(void) {
if(!quitting && !ppc_quitted) {
struct msg_scan_fonts* p=cmddata;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_INITSCAN);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
static int scan_fonts(int first_page,int last_page) {
if(!quitting && !ppc_quitted) {
struct msg_scan_fonts* p=cmddata;
p->first_page=first_page;
p->last_page=last_page;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_SCANFONTS);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
static int scan_default_fonts(void) {
if(!quitting && !ppc_quitted) {
struct msg_scan_fonts* p=cmddata;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_DEFAULTFONTS);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
return p->base.success;
}
return 0;
}
static void end_scan_fonts(void) {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_ENDSCANFONTS);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
static int get_font(int n,char* pdffont,int pdffontlen,
char* afont,int afontlen,
int* m,int* style,int* encoding) {
if(!quitting && !ppc_quitted) {
struct msg_fontmap* p=cmddata;
p->m=n;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_GETFONT);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
strncpy(pdffont,p->pdffont,pdffontlen-1);
pdffont[pdffontlen-1]='\0';
strncpy(afont,p->afont,afontlen-1);
afont[afontlen-1]='\0';
*m=p->m;
*style=p->style;
*encoding=p->encoding;
return p->base.success;
} else
return 0;
}
static void clear_fontmap(void) {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_CLEARFONTMAP);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}
/*static void set_fontmap(void) {
if(!quitting && !ppc_quitted) {
PPCSendMessage(ppcport,cmdmsg,NULL,0,MSGID_SETFONTMAP);
PPCWaitPort(reply_port);
PPCGetMessage(reply_port);
}
}*/
static PPCMsg* putimage(DocData* dat,PPCMsg* msg,short x,short y,short w,short h) {
UBYTE* pic;
struct BitMap* bm;
PPCReplyMessage(msg);
PPCWaitPort(port);
msg=PPCGetMessage(port);
pic=(UBYTE*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
if(bm=AllocBitMap((w+15)&~15,1,8,BMF_MINPLANES,dat->bm)) {
struct RastPort rp2;
rp2=dat->rp;
rp2.Layer=NULL;
rp2.BitMap=bm;
WritePixelArray8(&dat->rp,x,y,x+w-1,y+h-1,pic,&rp2);
WaitBlit();
FreeBitMap(bm);
}
return msg;
}
static PPCMsg* getimage(DocData* dat,PPCMsg* msg,short x,short y,short w,short h) {
UBYTE* pic;
struct BitMap* bm;
PPCReplyMessage(msg);
PPCWaitPort(port);
msg=PPCGetMessage(port);
pic=(UBYTE*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
if(bm=AllocBitMap((w+15)&~15,1,8,BMF_MINPLANES,dat->bm)) {
struct RastPort rp2;
rp2=dat->rp;
rp2.Layer=NULL;
rp2.BitMap=bm;
ReadPixelArray8(&dat->rp,x,y,x+w-1,y+h-1,pic,&rp2);
FreeBitMap(bm);
}
return msg;
}
static PPCMsg* putimage24(DocData* dat,PPCMsg* msg,short x,short y,short w,short h) {
UBYTE* pic;
PPCReplyMessage(msg);
PPCWaitPort(port);
msg=PPCGetMessage(port);
pic=(UBYTE*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
MyWritePixelArray(pic,0,0,w*3,&dat->rp,x,y,w,h,RECTFMT_RGB);
return msg;
}
static PPCMsg* getimage24(DocData* dat,PPCMsg* msg,short x,short y,short w,short h) {
UBYTE* pic;
PPCReplyMessage(msg);
PPCWaitPort(port);
msg=PPCGetMessage(port);
pic=(UBYTE*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
MyReadPixelArray(pic,0,0,w*3,&dat->rp,x,y,w,h,RECTFMT_RGB);
return msg;
}
static PPCMsg* decode(DocData* dat,PPCMsg* msg,short* p,short* q) {
while(p<q) {
switch(*p++) {
case AGFX_STARTPAGE:
reset_pens(dat);
SetRast(&dat->rp,get_pen(dat,1));
SetAPen(&dat->rp,get_pen(dat,0));
break;
/*case AGFX_ENDPAGE:
***
break;*/
case AGFX_PENCOLOR: {
ULONG r=((ULONG*)p)[0];
ULONG g=((ULONG*)p)[1];
ULONG b=((ULONG*)p)[2];
p+=6;
add_pen(dat,r,g,b);
break;
}
case AGFX_SETAPEN:
SetAPen(&dat->rp,get_pen(dat,*p++));
break;
case AGFX_OPENFONT:
openfont(dat,*(int*)p,(const char*)(p+3),p[p[2]+3],p[p[2]+4]);
p+=p[2]+5;
break;
case AGFX_CLOSEFONT:
closefont(dat,*(int*)p);
p+=2;
break;
case AGFX_SETFONT:
setfont(dat,*(int*)p);
p+=2;
break;
case AGFX_LINEPTRN:
dat->rp.LinePtrn=*p++;
dat->rp.linpatcnt=*p++;
break;
case AGFX_POLYDRAW:
++p;
if(p[-1]) {
clip_path(dat,p[-1],p);
Move(&dat->rp,p[0],p[1]);
PolyDraw(&dat->rp,p[-1]-1,p+2);
}
p+=p[-1]*2;
break;
case AGFX_ADDCHAR:
clip_path(dat,1,p);
Move(&dat->rp,p[0],p[1]);
Text(&dat->rp,((char*)p)+5,1);
p+=3;
break;
case AGFX_RECTFILL:
clip_path(dat,2,p);
RectFill(&dat->rp,p[0],p[1],p[2],p[3]);
p+=4;
break;
case AGFX_INITAREA:
initarea(&dat->rp,*p++);
break;
case AGFX_AREAPOLY:
++p;
if(p[-1]) {
clip_path(dat,p[-1],p);
areapoly(&dat->rp,p[-1],p,0,0);
}
p+=p[-1]*2;
break;
case AGFX_AREAEND:
areaend(&dat->rp);
break;
case AGFX_INITCLIP:
init_clip(dat);
break;
case AGFX_POLYCLIP:
++p;
poly_clip(dat,p[-1],p);
p+=p[-1]*2;
break;
case AGFX_RECTCLIP:
rect_clip(dat,p[0],p[1],p[2],p[3]);
p+=4;
break;
case AGFX_INSTALLCLIP:
install_clip(dat);
break;
case AGFX_GETCOLORS: {
int num=*p++;
ULONG* t;
PPCReplyMessage(msg);
PPCWaitPort(port);
msg=PPCGetMessage(port);
p=q=NULL;
t=(ULONG*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
add_pens(dat,t,num);
break;
}
case AGFX_IMAGE:
clip_path(dat,1,p);
msg=putimage(dat,msg,p[0],p[1],p[2],p[3]);
p=q=NULL;
break;
case AGFX_IMAGE24:
clip_path(dat,1,p);
msg=putimage24(dat,msg,p[0],p[1],p[2],p[3]);
p=q=NULL;
break;
case AGFX_GETIMAGE:
clip_path(dat,1,p);
msg=getimage(dat,msg,p[0],p[1],p[2],p[3]);
p=q=NULL;
break;
case AGFX_GETIMAGE24:
clip_path(dat,1,p);
msg=getimage24(dat,msg,p[0],p[1],p[2],p[3]);
p=q=NULL;
break;
default:
MYASSERT(FALSE);
break;
}
}
return msg;
}
static void show_page(DocData* dat,int page,int zoom) {
if(!quitting && !ppc_quitted && dat->rp.BitMap) {
struct msg_page* p=(struct msg_page*)cmddata;
p->page_num=page;
p->zoom=zoom;
PPCSendMessage(ppcport,cmdmsg,p,sizeof(*p),MSGID_PAGE);
while(1) {
PPCMsg* msg;
PPCWaitPortList(portlist);
while(msg=PPCGetMessage(port)) {
switch(PPCGetMessageAttr(msg,PPCMSGTAG_MSGID)) {
#ifdef USE_GFX_PIPE
case MSGID_GFXPIPE: {
volatile struct GfxPipe *pipe=(volatile struct GfxPipe *)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
short* p=pipe->readp;
while(!pipe->done) {
short* q=pipe->writep;
if(p<q) {
msg=decode(dat,msg,p,q);
p=q;
pipe->readp=q;
}
}
msg=decode(dat,msg,p,pipe->writep);
break;
}
#endif
case MSGID_GFX: {
short* p=(short*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
short* q=p+PPCGetMessageAttr(msg,PPCMSGTAG_DATALENGTH)/2;
msg=decode(dat,msg,p,q);
break;
}
default:
MYASSERT(FALSE);
break;
}
WaitBlit();
PPCReplyMessage(msg);
}
if(msg=PPCGetMessage(reply_port)) {
if(msg==startupmsg) // should not happen, but if the user
ppc_quitted=TRUE; // kills the ppc task for some reason,
// this helps cleanup a bit.
else {
MYASSERT(msg==cmdmsg);
}
break;
}
}
}
}
#else
int get_info(int* num_pages);
int get_page_size(int page,int* width,int* height);
int create_doc(BPTR,const char* filename,size_t,size_t);
int create_output_dev(int depth,struct ColorMap* colormap);
void delete_output_dev(void);
int simple_find(const char* str,int top,int* xmin,int* ymin,int* xmax,int* ymax);
int init_find(const char* str);
int find(int start,int stop,int* xmin,int* ymin,int* xmax,int* ymax,int* page);
void end_find(void);
int chklink(int x,int y,void** action,char* str,size_t len);
int dolink(int* x,int* y,int* state,int* page,char* buf,size_t len);
int init_file(const char* filename,int first_page,int last_page,int zoom,int rotate,int type);
void writefile(int first_page,int last_page);
void end_write(void);
char* gettext(int xmin,int ymin,int xmax,int ymax);
int show_page(int page,int zoom);
int init(int,const char*);
void add_fontmap(const char*,const char*,int,int,int);
/*void rem_fontmap(const char*);*/
void clear_fontmap(void);
/*void set_fontmap(void);*/
int init_scan(void);
int scan_fonts(int,int);
int scan_default_fonts(void);
void end_scan_fonts(void);
int get_font(int,char*,int,char*,int,int*,int*,int*);
#endif
static BOOL setbitmap(DocData*);
static void display_page(DocData* dat) {
if(dat->last_page!=dat->page ||
dat->last_zoom!=dat->zoom) {
if(dat->last_width!=dat->width || dat->last_height!=dat->height)
setbitmap(dat);
if(dat->rp.BitMap) {
sleep(TRUE);
dat->selected=FALSE;
#ifdef POWERUP
show_page(dat,dat->page,zoomDPI[dat->zoom-minZoom]);
#else
show_page(dat->page,zoomDPI[dat->zoom-minZoom]);
#endif
tfr_clip(dat);
clear_clip(dat);
dat->last_page=dat->page;
dat->last_zoom=dat->zoom;
sleep(FALSE);
}
}
}
static void search(const char* str) {
struct Rectangle rect;
int pg,pages;
int page,top,bottom,xmin,ymin,xmax,ymax;
BOOL found=FALSE;
get(bitmapobj,MYATTR_Page,&page);
get(bitmapobj,MYATTR_Selection,&rect);
bottom=0;
if(rect.MinX==-1)
top=1;
else {
top=0;
xmin=rect.MaxX;
ymin=(rect.MinY+rect.MaxY)/2;
xmax=0;
ymax=0;
if(simple_find(str,top,&xmin,&ymin,&xmax,&ymax))
found=TRUE;
}
if(!found) {
int k,l=0;
struct List* winlist;
Object* o;
struct Node* state;
ULONG sigs=0;
get(pageobj,MUIA_Numeric_Max,&pages);
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,TRUE);
SetAttrs(gaugeobj,
MUIA_Gauge_Current,0,
MUIA_Gauge_Max,pages,
TAG_END);
SetAttrs(gaugewin,
MUIA_Window_Title,"Searching...",
MUIA_Window_Open,TRUE,
TAG_END);
pg=page;
if(init_find(str)) {
LONG r=0;
for(k=pg+1;k<=pages;++k) {
if(find(k,k+1,&xmin,&ymin,&xmax,&ymax,&page)) {
found=TRUE;
break;
}
set(gaugeobj,MUIA_Gauge_Current,++l);
r=DoMethod(App,MUIM_Application_NewInput,&sigs);
if(r==MUIV_Application_ReturnID_Quit ||
r==ID_ABORT)
break;
}
if(!found && r!=ID_ABORT && r!=MUIV_Application_ReturnID_Quit) {
for(k=1;k<pg;++k) {
if(find(k,k+1,&xmin,&ymin,&xmax,&ymax,&page)) {
found=TRUE;
break;
}
set(gaugeobj,MUIA_Gauge_Current,++l);
r=DoMethod(App,MUIM_Application_NewInput,&sigs);
if(r==MUIV_Application_ReturnID_Quit ||
r==ID_ABORT)
break;
}
}
end_find();
}
if(found) {
set(pageobj,MYATTR_Value,page);
simple_find(str,TRUE,&xmin,&ymin,&xmax,&ymax);
}
set(gaugewin,MUIA_Window_Open,FALSE);
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,FALSE);
}
if(found) {
LONG left,width,top,height,t;
rect.MinX=xmin;
rect.MinY=ymin;
rect.MaxX=xmax;
rect.MaxY=ymax;
set(bitmapobj,MYATTR_Selection,&rect);
xmin+=bleft;
ymin+=btop;
xmax+=bleft;
ymax+=btop;
get(vgroup,MUIA_Width,&width);
get(vgroup,MUIA_InnerRight,&t);
width-=t;
get(vgroup,MUIA_InnerLeft,&t);
width-=t;
get(vgroup,MUIA_Height,&height);
get(vgroup,MUIA_InnerBottom,&t);
height-=t;
get(vgroup,MUIA_InnerTop,&t);
height-=t;
get(vgroup,MUIA_Virtgroup_Left,&left);
get(vgroup,MUIA_Virtgroup_Top,&top);
if(xmin<left)
left=xmin;
else if(xmax>left+width)
left=xmax-width;
if(ymin<top)
top=ymin;
else if(ymax>top+height)
top=ymax-height;
SetAttrs(vgroup,
MUIA_Virtgroup_Left,left,
MUIA_Virtgroup_Top,top,
TAG_END);
} else {
set(pageobj,MYATTR_Selection,NULL);
set(linkobj,MUIA_Text_Contents,"Not found");
}
}
static void save(const char* filename,int first_page,int last_page,int zoom,int rotate,int type) {
int k,l=0;
struct List* winlist;
Object* o;
struct Node* state;
ULONG sigs=0;
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,TRUE);
SetAttrs(gaugeobj,
MUIA_Gauge_Current,0,
MUIA_Gauge_Max,last_page-first_page+1,
TAG_END);
SetAttrs(gaugewin,
MUIA_Window_Title,"Saving...",
MUIA_Window_Open,TRUE,
TAG_END);
if(init_write(filename,first_page,last_page,zoom,rotate,type)) {
LONG r;
for(k=first_page;k<=last_page;++k) {
writefile(k,k+1);
set(gaugeobj,MUIA_Gauge_Current,++l);
r=DoMethod(App,MUIM_Application_NewInput,&sigs);
if(r==MUIV_Application_ReturnID_Quit ||
r==ID_ABORT)
break;
}
end_write();
} else
set(linkobj,MUIA_Text_Contents,"Failed...");
set(gaugewin,MUIA_Window_Open,FALSE);
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,FALSE);
}
static int scan_doc_fonts(int first_page,int last_page) {
int k,l=0;
struct List* winlist;
Object* o;
struct Node* state;
ULONG sigs=0;
int ret=0;
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,TRUE);
SetAttrs(gaugeobj,
MUIA_Gauge_Current,0,
MUIA_Gauge_Max,last_page-first_page+1,
TAG_END);
SetAttrs(gaugewin,
MUIA_Window_Title,"Scanning...",
MUIA_Window_Open,TRUE,
TAG_END);
if(init_scan()) {
LONG r;
for(k=first_page;k<=last_page;++k) {
ret=scan_fonts(k,k+1);
set(gaugeobj,MUIA_Gauge_Current,++l);
r=DoMethod(App,MUIM_Application_NewInput,&sigs);
if(r==MUIV_Application_ReturnID_Quit ||
r==ID_ABORT)
break;
}
if(!ret)
end_scan_fonts();
}
set(gaugewin,MUIA_Window_Open,FALSE);
get(App,MUIA_Application_WindowList,&winlist);
for(state=winlist->lh_Head;o=NextObject(&state);)
if(o!=gaugewin)
set(o,MUIA_Window_Sleep,FALSE);
return ret;
}
static void check_link(int x,int y) {
static void* last_action;
void* action=last_action;
char str[256];
if(chklink(x,y,&action,str,sizeof(str))) {
if(action!=last_action) {
last_action=action;
set(linkobj,MUIA_Text_Contents,str);
}
} else if(last_action) {
last_action=NULL;
set(linkobj,MUIA_Text_Contents,NULL);
}
}
static void get_page_info(void) {
int num_pages;
get_info(&num_pages);
SetAttrs(bitmapobj,
MYATTR_Zoom,defZoom,
MYATTR_NumPages,num_pages,
MYATTR_Page,1,
MYATTR_NewDoc,TRUE,
TAG_END);
SetAttrs(pageobj,
MUIA_Numeric_Max,num_pages,
MYATTR_Value,1,
TAG_END);
set(psstartobj,MUIA_Numeric_Max,num_pages);
set(psstopobj,MUIA_Numeric_Max,num_pages);
set(scanstartobj,MUIA_Numeric_Max,num_pages);
set(scanstopobj,MUIA_Numeric_Max,num_pages);
set(zoomobj,MYATTR_Value,defZoom);
}
static int do_link(int x,int y) {
int state,page,r;
char buf[256];
if(r=dolink(&x,&y,&state,&page,buf,sizeof(buf))) {
switch(state) {
case st_changed:
copystr(&docname,buf);
get_page_info();
/* fall through */
case st_unchanged:
if(page!=-1)
set(pageobj,MYATTR_Value,page);
set(linkobj,MUIA_Text_Contents,NULL);
break;
case st_run:
if(MUI_Request(App,win,0,"Execute command ?","Ok|Cancel",buf))
system(buf);
break;
case st_url:
if(URLCMD) {
char buf2[256];
buf2[0]='r';
buf2[1]='u';
buf2[2]='n';
buf2[3]=' ';
sprintf(buf2+4,URLCMD,buf);
system(buf2);
}
break;
}
if(x!=-1 || y!=-1)
SetAttrs(vgroup,
x==-1?TAG_IGNORE:MUIA_Virtgroup_Left,x,
y==-1?TAG_IGNORE:MUIA_Virtgroup_Top,y,
TAG_END);
}
return r;
}
static void toclip(int x1,int y1,int x2,int y2) {
char* txt;
if(x1>x2) {
int t=x1;
x1=x2;
x2=t;
}
if(y1>y2) {
int t=y1;
y1=y2;
y2=t;
}
if(txt=gettext(x1,y1,x2,y2)) {
struct IFFHandle *iff;
if(iff=AllocIFF()) {
if(iff->iff_Stream=(ULONG)OpenClipboard(PRIMARY_CLIP)) {
size_t sz=strlen(txt);
InitIFFasClip(iff);
if(!OpenIFF(iff,IFFF_WRITE)) {
if(PushChunk(iff,ID_FTXT,ID_FORM,IFFSIZE_UNKNOWN) ||
PushChunk(iff,0,ID_CHRS,sz) ||
WriteChunkBytes(iff,txt,sz)!=sz ||
PopChunk(iff) ||
PopChunk(iff))
printf("Error writing to clipboard.\n");
CloseIFF(iff);
}
CloseClipboard((struct ClipboardHandle *)iff->iff_Stream);
}
FreeIFF(iff);
}
free(txt);
}
}
static void clearbitmap(DocData* dat) {
dat->rp.BitMap=NULL;
dat->rp.Layer=NULL;
if(dat->region) {
InstallClipRegion(dat->layer,NULL);
DisposeRegion(dat->region);
dat->region=NULL;
}
if(dat->layer) {
DeleteLayer(0,dat->layer);
dat->layer=NULL;
}
if(dat->layerinfo) {
DisposeLayerInfo(dat->layerinfo);
dat->layerinfo=NULL;
}
WaitBlit();
FreeBitMap(dat->bm);
dat->bm=NULL;
}
static BOOL setbitmap(DocData* dat) {
if(!dat->hidden && (!dat->bm ||
dat->width!=dat->last_width ||
dat->height!=dat->last_height)) {
clearbitmap(dat);
dat->last_width=dat->width;
dat->last_height=dat->height;
if(dat->bm=AllocBitMap(dat->width,dat->height,dat->depth,BMF_MINPLANES,dat->friendbm)) {
dat->dx=0;
dat->dy=0;
if((dat->layerinfo=NewLayerInfo()) &&
(dat->layer=CreateUpfrontLayer(dat->layerinfo,dat->bm,0,0,dat->width-1,dat->height-1,LAYERSIMPLE,NULL)) &&
(dat->region=NewRegion())) {
struct Rectangle rect;
rect.MinX=0;
rect.MinY=0;
rect.MaxX=dat->width-1;
rect.MaxY=dat->height-1;
if(OrRectRegion(dat->region,&rect)) {
InstallClipRegion(dat->layer,dat->region);
dat->rp.Layer=dat->layer;
dat->rp.BitMap=dat->bm;
return TRUE;
}
}
printf("Can't install clipping region.\n");
} else
printf("Can't alloc bitmap.\n");
clearbitmap(dat);
return FALSE;
}
return TRUE;
}
#define DocObject NewObject(mcc->mcc_Class,NULL
static ULONG mNew(struct IClass *cl,Object *obj,Msg msg) {
DocData* dat;
if(obj=(Object *)DoSuperMethodA(cl,obj,msg)) {
dat=INST_DATA(cl,obj);
memset(dat,0,sizeof(*dat));
InitRastPort(&dat->rp);
SetDrMd(&dat->rp,JAM1);
dat->hidden=TRUE;
dat->last_page=-1;
dat->obj=obj;
set(obj,MUIA_FillArea,FALSE);
}
return (ULONG)obj;
}
static ULONG mDispose(struct IClass *cl,Object *obj,Msg msg) {
DocData* dat=INST_DATA(cl,obj);
free(dat->pens);
clear_fonts(dat);
return DoSuperMethodA(cl,obj,msg);
}
static ULONG mSet(struct IClass *cl,Object *obj,struct opSet *msg) {
DocData *dat=INST_DATA(cl,obj);
struct TagItem *tags=msg->ops_AttrList;
struct TagItem *tag;
BOOL redraw=FALSE;
while(tag=NextTagItem(&tags)) {
switch(tag->ti_Tag) {
case MYATTR_NumPages:
dat->num_pages=(int)tag->ti_Data;
break;
case MYATTR_Page:
if(dat->page!=(int)tag->ti_Data) {
dat->page=(int)tag->ti_Data;
if(dat->page<1)
dat->page=1;
else if(dat->page>dat->num_pages)
dat->page=dat->num_pages;
redraw=TRUE;
set(vgroup,MUIA_Virtgroup_Top,0);
}
break;
case MYATTR_Zoom:
if(dat->zoom!=(int)tag->ti_Data) {
dat->zoom=(int)tag->ti_Data;
redraw=TRUE;
}
break;
case MYATTR_Selection:
if(tag->ti_Data) {
dat->selection=*(struct Rectangle*)tag->ti_Data;
dat->selected=TRUE;
redraw=TRUE;
} else if(dat->selected) {
dat->selected=FALSE;
redraw=TRUE;
}
break;
case MYATTR_NewDoc:
dat->last_page=-1;
dat->last_zoom=-1;
redraw=TRUE;
break;
}
}
if(redraw) {
if(get_page_size(dat->page,&dat->page_width,&dat->page_height)) {
dat->width=(dat->page_width*zoomDPI[dat->zoom-minZoom])/72;
dat->height=(dat->page_height*zoomDPI[dat->zoom-minZoom])/72;
if(dat->width!=dat->last_width || dat->height!=dat->last_height) {
DoMethod(vgroup,MUIM_Group_InitChange);
DoMethod(vgroup,MUIM_Group_ExitChange);
} else
MUI_Redraw(obj,MADF_DRAWOBJECT);
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
}
static ULONG mGet(struct IClass *cl,Object *obj,struct opGet *msg) {
DocData* dat=INST_DATA(cl,obj);
switch(msg->opg_AttrID) {
case MYATTR_Page:
*msg->opg_Storage=dat->page;
return TRUE;
case MYATTR_Selected:
*msg->opg_Storage=dat->selected;
break;
case MYATTR_Selection:
*(struct Rectangle*)msg->opg_Storage=dat->selection;
return TRUE;
}
return DoSuperMethodA(cl,obj,(Msg)msg);
}
static ULONG mSetup(struct IClass *cl,Object *obj,Msg msg) {
DocData* dat=INST_DATA(cl,obj);
if(!DoSuperMethodA(cl,obj,(Msg)msg))
return FALSE;
dat->colormap=_screen(obj)->ViewPort.ColorMap;
dat->depth=GetBitMapAttr(_screen(obj)->RastPort.BitMap,BMA_DEPTH);
if(dat->depth>8 && !CyberGfxBase)
dat->depth=8;
sleep(TRUE);
create_output_dev(dat->depth,dat->colormap);
sleep(FALSE);
dat->friendbm=_screen(obj)->RastPort.BitMap;
dat->hidden=FALSE;
dat->selected=FALSE;
dat->selecting=FALSE;
setbitmap(dat);
MUI_RequestIDCMP(obj,IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_VANILLAKEY|IDCMP_RAWKEY);
return TRUE;
}
static ULONG mCleanup(struct IClass *cl,Object *obj,Msg msg) {
DocData* dat=INST_DATA(cl,obj);
MUI_RejectIDCMP(obj,IDCMP_MOUSEMOVE|IDCMP_MOUSEBUTTONS|IDCMP_VANILLAKEY|IDCMP_RAWKEY);
clearbitmap(dat);
clear_pens(dat);
dat->hidden=TRUE;
delete_output_dev();
dat->last_page=-1;
clear_fonts(dat);
return DoSuperMethodA(cl,obj,msg);
}
static ULONG mReset(struct IClass *cl,Object *obj,Msg msg) {
DocData* dat=INST_DATA(cl,obj);
if(!dat->hidden) {
sleep(TRUE);
delete_output_dev();
dat->last_page=-1;
clear_fonts(dat);
create_output_dev(dat->depth,dat->colormap);
MUI_Redraw(obj,MADF_DRAWOBJECT);
sleep(FALSE);
}
return 0;
}
static ULONG mAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg) {
DocData* dat=INST_DATA(cl,obj);
int w=dat->width+bright+bleft;
int h=dat->height+bbottom+btop;
DoSuperMethodA(cl,obj,(Msg)msg);
msg->MinMaxInfo->MinWidth+=w;
msg->MinMaxInfo->DefWidth+=w;
msg->MinMaxInfo->MaxWidth+=MUI_MAXMAX;
msg->MinMaxInfo->MinHeight+=h;
msg->MinMaxInfo->DefHeight+=h;
msg->MinMaxInfo->MaxHeight+=MUI_MAXMAX;
return 0;
}
static ULONG mDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg) {
DocData* dat=INST_DATA(cl,obj);
int x,y,w,h;
struct RastPort *rp;
DoSuperMethodA(cl,obj,(Msg)msg);
x=_mleft(obj);
y=_mtop(obj);
w=_mwidth(obj);
h=_mheight(obj);
rp=_rp(obj);
if(dat->bm) {
if(msg->flags&MADF_DRAWOBJECT) {
display_page(dat);
if(w>dat->width+2 || h>dat->height+2) {
int h1=(h-dat->height-2)/2;
int h2=h-dat->height-h1;
int w1=(w-dat->width-2)/2;
int w2=w-dat->width-w1;
h-=h1+h2;
if(h1)
DoMethod(obj,MUIM_DrawBackground,x,y,w,h1,0);
if(h2)
DoMethod(obj,MUIM_DrawBackground,x,y+h1+h,w,h2,0);
w-=w1+w2;
y+=h1;
if(w1)
DoMethod(obj,MUIM_DrawBackground,x,y,w1,h,0);
if(w2)
DoMethod(obj,MUIM_DrawBackground,x+w1+w,y,w2,h,0);
x+=w1;
}
if(w && h) {
SetAPen(rp,_dri(obj)->dri_Pens[SHINEPEN]);
Move(rp,x,y+h-1);
Draw(rp,x,y);
Draw(rp,x+w-1,y);
if(w>1 && h>1) {
SetAPen(rp,_dri(obj)->dri_Pens[SHADOWPEN]);
Move(rp,x+w-1,y+1);
Draw(rp,x+w-1,y+h-1);
Draw(rp,x+1,y+h-1);
if(w>2 && h>2)
BltBitMapRastPort(dat->bm,0,0,rp,x+1,y+1,w-2,h-2,0xc0);
}
}
} else if(msg->flags&MADF_DRAWUPDATE) {
x+=(w-dat->width-2)/2;
w=dat->width-2;
y+=(h-dat->height-2)/2;
h=dat->height-2;
if(dat->select_displayed) {
int x1=dat->old_selection.MinX;
int y1=dat->old_selection.MinY;
int x2=dat->old_selection.MaxX;
int y2=dat->old_selection.MaxY;
if(x1>x2) {
int t=x2;
x2=x1;
x1=t;
}
if(y1>y2) {
int t=y2;
y2=y1;
y1=t;
}
if(x1>=0 && x1<w && y2>=0 && y1<h) {
int y3=y1<0?0:y1;
int y4=y2>=h?h-1:y2;
BltBitMapRastPort(dat->bm,x1,y3,rp,x+1+x1,y+1+y3,1,y4-y3+1,0xc0);
if(x1<0)
x1=0;
}
if(x2>=0 && x2<w && y2>=0 && y1<h) {
int y3=y1<0?0:y1;
int y4=y2>=h?h-1:y2;
BltBitMapRastPort(dat->bm,x2,y3,rp,x+1+x2,y+1+y3,1,y4-y3+1,0xc0);
if(x2>=w)
x2=w-1;
}
if(y1>=0 && y1<h)
BltBitMapRastPort(dat->bm,x1,y1,rp,x+1+x1,y+1+y1,x2-x1+1,1,0xc0);
if(y2>=0 && y2<h)
BltBitMapRastPort(dat->bm,x1,y2,rp,x+1+x1,y+1+y2,x2-x1+1,1,0xc0);
}
}
if(msg->flags&(MADF_DRAWOBJECT|MADF_DRAWUPDATE)) {
dat->select_displayed=dat->selected || dat->selecting;
if(dat->select_displayed) {
SetAPen(rp,_dri(obj)->dri_Pens[FILLPEN]);
Move(rp,x+dat->selection.MinX+bleft,y+dat->selection.MinY+btop);
Draw(rp,x+dat->selection.MinX+bleft,y+dat->selection.MaxY+btop);
Draw(rp,x+dat->selection.MaxX+bleft,y+dat->selection.MaxY+btop);
Draw(rp,x+dat->selection.MaxX+bleft,y+dat->selection.MinY+btop);
Draw(rp,x+dat->selection.MinX+bleft,y+dat->selection.MinY+btop);
dat->old_selection=dat->selection;
}
}
} else if(w && h) {
EraseRect(_rp(obj),x,y,x+w-1,y+h-1);
}
return 0;
}
static void upkey(void) {
LONG top,height,totheight,t;
get(vgroup,MUIA_Virtgroup_Height,&totheight);
get(vgroup,MUIA_Virtgroup_Top,&top);
get(vgroup,MUIA_Height,&height);
get(vgroup,MUIA_InnerBottom,&t);
height-=t;
get(vgroup,MUIA_InnerTop,&t);
height-=t;
if(top>0)
set(vgroup,MUIA_Virtgroup_Top,top-height+10);
else {
DoMethod(pageobj,MUIM_Numeric_Decrease,1);
set(vgroup,MUIA_Virtgroup_Top,totheight-height);
}
}
static void downkey(void) {
LONG top,height,totheight,t;
get(vgroup,MUIA_Virtgroup_Height,&totheight);
get(vgroup,MUIA_Virtgroup_Top,&top);
get(vgroup,MUIA_Height,&height);
get(vgroup,MUIA_InnerBottom,&t);
height-=t;
get(vgroup,MUIA_InnerTop,&t);
height-=t;
if(top<totheight-height)
set(vgroup,MUIA_Virtgroup_Top,top+height-10);
else {
DoMethod(pageobj,MUIM_Numeric_Increase,1);
set(vgroup,MUIA_Virtgroup_Top,0);
}
}
static ULONG mHandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg) {
DocData* dat=INST_DATA(cl,obj);
int x=_mleft(obj);
int y=_mtop(obj);
int w=_mwidth(obj);
int h=_mheight(obj);
x+=(w-dat->width-bleft-bright)/2+bleft;
w=dat->width-bleft-bright;
y+=(h-dat->height-btop-bbottom)/2+btop;
h=dat->height-btop-bbottom;
#define _between(a,x,b) ((x)>=(a) && (x)<(b))
#define _isinobject(u,v) (_between(x,(u),x+w) && _between(y,(v),y+h))
if(msg->imsg) {
switch(msg->imsg->Class) {
case IDCMP_MOUSEBUTTONS:
if(msg->imsg->Code==SELECTDOWN) {
if(_isinobject(msg->imsg->MouseX,msg->imsg->MouseY)) {
dat->selection.MinX=msg->imsg->MouseX-x;
dat->selection.MinY=msg->imsg->MouseY-y;
dat->selection.MaxX=dat->selection.MinX;
dat->selection.MaxY=dat->selection.MinY;
if(!do_link(dat->selection.MinX,dat->selection.MinY)) {
dat->selecting=TRUE;
dat->selected=TRUE;
MUI_Redraw(obj,MADF_DRAWUPDATE);
}
} else {
dat->selected=FALSE;
dat->selecting=FALSE;
}
} else if(msg->imsg->Code==SELECTUP) {
if(dat->selecting) {
dat->selection.MaxX=msg->imsg->MouseX-x;
if(dat->selection.MaxX<0)
dat->selection.MaxX=0;
else if(dat->selection.MaxX>=w)
dat->selection.MaxX=w-1;
dat->selection.MaxY=msg->imsg->MouseY-y;
if(dat->selection.MaxY<0)
dat->selection.MaxY=0;
else if(dat->selection.MaxY>=h)
dat->selection.MaxY=h-1;
dat->selected=TRUE;
dat->selecting=FALSE;
MUI_Redraw(obj,MADF_DRAWUPDATE);
}
}
break;
case IDCMP_MOUSEMOVE:
if(dat->selecting) {
dat->selection.MaxX=msg->imsg->MouseX-x;
if(dat->selection.MaxX<0)
dat->selection.MaxX=0;
else if(dat->selection.MaxX>=w)
dat->selection.MaxX=w-1;
dat->selection.MaxY=msg->imsg->MouseY-y;
if(dat->selection.MaxY<0)
dat->selection.MaxY=0;
else if(dat->selection.MaxY>=h)
dat->selection.MaxY=h-1;
MUI_Redraw(obj,MADF_DRAWUPDATE);
} else if(_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
check_link(msg->imsg->MouseX-x,msg->imsg->MouseY-y);
break;
/*case IDCMP_RAWKEY:
switch(msg->imsg->Code) {
case :
break;
}
break; */
case IDCMP_VANILLAKEY:
switch(msg->imsg->Code) {
case 8: /* BS */
upkey();
break;
case 'o':
DoMethod(App,MUIM_Application_ReturnID,ID_OPEN);
break;
case 'f':
set(win,MUIA_Window_ActiveObject,(ULONG)searchobj);
break;
case ' ':
downkey();
break;
case 'q':
DoMethod(App,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
break;
case '+':
DoMethod(zoomobj,MUIM_Numeric_Increase,1);
break;
case '-':
DoMethod(zoomobj,MUIM_Numeric_Decrease,1);
break;
}
break;
}
}
switch(msg->muikey) {
case MUIKEY_UP:
upkey();
break;
case MUIKEY_DOWN:
downkey();
break;
case MUIKEY_PAGEUP:
DoMethod(pageobj,MUIM_Numeric_Decrease,1);
break;
case MUIKEY_PAGEDOWN:
DoMethod(pageobj,MUIM_Numeric_Increase,1);
break;
case MUIKEY_TOP:
set(pageobj,MUIA_Numeric_Value,1);
break;
case MUIKEY_BOTTOM: {
LONG t;
get(pageobj,MUIA_Numeric_Max,&t);
set(pageobj,MUIA_Numeric_Value,t);
break;
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
#undef _between
#undef _isinobject
}
SAVEDS ASM ULONG dispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1, Msg msg)) {
switch(msg->MethodID) {
case OM_NEW : return mNew (cl,obj,(APTR)msg);
case OM_DISPOSE : return mDispose (cl,obj,(APTR)msg);
case OM_SET : return mSet (cl,obj,(APTR)msg);
case OM_GET : return mGet (cl,obj,(APTR)msg);
case MUIM_Setup : return mSetup (cl,obj,(APTR)msg);
case MUIM_Cleanup : return mCleanup (cl,obj,(APTR)msg);
case MUIM_AskMinMax : return mAskMinMax (cl,obj,(APTR)msg);
case MUIM_Draw : return mDraw (cl,obj,(APTR)msg);
case MUIM_HandleInput: return mHandleInput(cl,obj,(APTR)msg);
case MYM_Reset : return mReset (cl,obj,(APTR)msg);
}
return DoSuperMethodA(cl,obj,msg);
}
/*
* Custom slider class: maintains MYATTR_Value, that
* is similar to MUIA_Numeric_Value, except that it is
* updated only when the slider is released.
*/
struct SliderData {
LONG value;
BOOL pressed;
BOOL lock;
};
typedef struct SliderData SliderData;
#define MySliderObject NewObject(slider_mcc->mcc_Class,NULL
static ULONG msNew(struct IClass *cl,Object *obj,Msg msg) {
SliderData* dat;
if(obj=(Object *)DoSuperMethodA(cl,obj,msg)) {
dat=INST_DATA(cl,obj);
dat->pressed=FALSE;
dat->lock=FALSE;
}
return (ULONG)obj;
}
static ULONG msSet(struct IClass *cl,Object *obj,struct opSet *msg) {
SliderData *dat=INST_DATA(cl,obj);
struct TagItem *tags=msg->ops_AttrList;
struct TagItem *tag;
while(tag=NextTagItem(&tags)) {
switch(tag->ti_Tag) {
case MYATTR_Value:
if(!dat->lock) {
dat->lock=TRUE;
set(obj,MUIA_Numeric_Value,tag->ti_Data);
dat->lock=FALSE;
}
get(obj,MUIA_Numeric_Value,&dat->value);
break;
case MUIA_Numeric_Value: {
LONG r=DoSuperMethodA(cl,obj,(Msg)msg);
if(!dat->pressed && !dat->lock) {
dat->lock=TRUE;
set(obj,MYATTR_Value,tag->ti_Data);
dat->lock=FALSE;
}
return (ULONG)r;
}
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
}
static ULONG msGet(struct IClass *cl,Object *obj,struct opGet *msg) {
switch(msg->opg_AttrID) {
case MYATTR_Value: {
SliderData* dat=INST_DATA(cl,obj);
*msg->opg_Storage=dat->value;
return TRUE;
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
}
static ULONG msSetup(struct IClass *cl,Object *obj,Msg msg) {
if(DoSuperMethodA(cl,obj,msg)) {
MUI_RequestIDCMP(obj,IDCMP_MOUSEBUTTONS);
return TRUE;
} else
return FALSE;
}
static ULONG msCleanup(struct IClass *cl,Object *obj,Msg msg) {
MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS);
return DoSuperMethodA(cl,obj,msg);
}
static ULONG msHandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg) {
#define _between(a,x,b) ((x)>=(a) && (x)<=(b))
#define _isinobject(x,y) (_between(_mleft(obj),(x),_mright(obj)) && _between(_mtop(obj),(y),_mbottom(obj)))
SliderData* dat=INST_DATA(cl,obj);
if(msg->imsg) {
switch(msg->imsg->Class) {
case IDCMP_MOUSEBUTTONS:
if(msg->imsg->Code==SELECTDOWN) {
if(_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
dat->pressed=TRUE;
} else if(msg->imsg->Code==SELECTUP) {
ULONG r=DoSuperMethodA(cl,obj,(Msg)msg);
LONG x;
dat->pressed=FALSE;
get(obj,MUIA_Numeric_Value,&x);
set(obj,MYATTR_Value,x);
return r;
}
break;
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
#undef _between
#undef _isinobject
}
SAVEDS ASM ULONG mysliderdispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1,Msg msg)) {
switch(msg->MethodID) {
case OM_NEW : return msNew (cl,obj,(APTR)msg);
case OM_SET : return msSet (cl,obj,(APTR)msg);
case OM_GET : return msGet (cl,obj,(APTR)msg);
case MUIM_Setup : return msSetup (cl,obj,(APTR)msg);
case MUIM_Cleanup : return msCleanup (cl,obj,(APTR)msg);
case MUIM_HandleInput: return msHandleInput(cl,obj,(APTR)msg);
}
return DoSuperMethodA(cl,obj,msg);
}
/*
* Custom rotate slider class: displays multiples of 90°
*/
struct RotateSliderData {
char buf[5];
};
typedef struct RotateSliderData RotateSliderData;
#define MyRotateSliderObject NewObject(rotate_slider_mcc->mcc_Class,NULL
SAVEDS ASM ULONG myrotatesliderdispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1,Msg msg)) {
if(msg->MethodID==MUIM_Numeric_Stringify) {
RotateSliderData *dat=INST_DATA(cl,obj);
struct MUIP_Numeric_Stringify *m=(APTR)msg;
sprintf(dat->buf,"%ld°",m->value*90);
return (ULONG)dat->buf;
} else
return DoSuperMethodA(cl,obj,msg);
}
/*
* Custom list class: allows drag and drop
*/
struct ListData {
LONG id;
};
typedef struct ListData ListData;
#define MyListObject NewObject(list_mcc->mcc_Class,NULL
static ULONG mlNew(struct IClass *cl,Object *obj,struct opSet *msg) {
ListData* dat;
if(obj=(Object *)DoSuperMethodA(cl,obj,(Msg)msg)) {
dat=INST_DATA(cl,obj);
dat->id=GetTagData(MYATTR_ListID,0,msg->ops_AttrList);
}
return (ULONG)obj;
}
static ULONG mlGet(struct IClass *cl,Object *obj,struct opGet *msg) {
switch(msg->opg_AttrID) {
case MYATTR_ListID: {
ListData* dat=INST_DATA(cl,obj);
*msg->opg_Storage=dat->id;
return TRUE;
}
}
return DoSuperMethodA(cl,obj,(Msg)msg);
}
static ULONG mlDragQuery(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg) {
ListData *dat=INST_DATA(cl,obj);
LONG x;
if(msg->obj==obj)
return DoSuperMethodA(cl,obj,(Msg)msg);
else if(get(msg->obj,MYATTR_ListID,&x) && x==dat->id)
return MUIV_DragQuery_Accept;
else
return MUIV_DragQuery_Refuse;
}
static ULONG mlDragDrop(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg) {
if(msg->obj==obj)
return DoSuperMethodA(cl,obj,(Msg)msg);
else {
LONG dropmark;
LONG id=MUIV_List_NextSelected_Start;
get(obj,MUIA_List_DropMark,&dropmark);
while(1) {
APTR entry;
DoMethod(msg->obj,MUIM_List_NextSelected,&id);
if(id==MUIV_List_NextSelected_End)
break;
DoMethod(msg->obj,MUIM_List_GetEntry,id,&entry);
DoMethod(obj,MUIM_List_InsertSingle,entry,dropmark);
}
DoMethod(msg->obj,MUIM_List_Remove,MUIV_List_Remove_Selected);
get(obj,MUIA_List_InsertPosition,&dropmark);
set(obj,MUIA_List_Active,dropmark);
set(msg->obj,MUIA_List_Active,MUIV_List_Active_Off);
return 0;
}
}
SAVEDS ASM ULONG mylistdispatcher(REG(a0,struct IClass *cl),REG(a2,Object *obj),REG(a1,Msg msg)) {
switch(msg->MethodID) {
case OM_NEW: return mlNew (cl,obj,(APTR)msg);
case OM_GET: return mlGet (cl,obj,(APTR)msg);
case MUIM_DragQuery: return mlDragQuery(cl,obj,(APTR)msg);
case MUIM_DragDrop : return mlDragDrop (cl,obj,(APTR)msg);
}
return DoSuperMethodA(cl,obj,msg);
}
void cleanup(void) {
if(MUIMasterBase) {
MUI_FreeAslRequest(req);
MUI_DisposeObject(App);
if(list_mcc)
MUI_DeleteCustomClass(list_mcc);
if(rotate_slider_mcc)
MUI_DeleteCustomClass(rotate_slider_mcc);
if(slider_mcc)
MUI_DeleteCustomClass(slider_mcc);
if(mcc)
MUI_DeleteCustomClass(mcc);
CloseLibrary(MUIMasterBase);
}
#ifdef POWERUP
while(!ppc_quitted) {
quit();
PPCWaitPort(reply_port);
if(PPCGetMessage(reply_port)==startupmsg)
ppc_quitted=TRUE;
}
if(startup_data)
PPCFreeVec(startup_data);
if(startupmsg)
PPCDeleteMessage(startupmsg);
if(quitmsg)
PPCDeleteMessage(quitmsg);
if(cmdmsg)
PPCDeleteMessage(cmdmsg);
if(cmddata)
PPCFreeVec(cmddata);
if(portlist)
PPCDeletePortList(portlist);
if(port)
PPCDeletePort(port);
if(reply_port)
PPCDeletePort(reply_port);
if(elfobject)
PPCUnLoadObject(elfobject);
CloseLibrary(PPCLibBase);
#endif
if(diskobj)
FreeDiskObject(diskobj);
CloseLibrary(CyberGfxBase);
CloseLibrary(IFFParseBase);
CloseLibrary(DiskfontBase);
CloseLibrary(IconBase);
CloseLibrary((struct Library*)UtilityBase);
CloseLibrary(LayersBase);
CloseLibrary((struct Library*)GfxBase);
CloseLibrary((struct Library*)IntuitionBase);
FreeArgs(rda);
CurrentDir(olddir);
UnLock(docdir);
free(progname);
free(docname);
free(gzipcmd_arg);
free(urlcmd_arg);
free(deficon_arg);
free(diskobj_arg);
if(input) {
SelectInput(oldinput);
Close(input);
}
}
/*
* MUI data and hooks.
*/
static struct NewMenu menudata[]={
{NM_TITLE,"Project" ,0,0,0,NULL},
{NM_ITEM , "About..." ,"?",0,0,(APTR)ID_ABOUT},
{NM_ITEM , "About MUI...",0,0,0,(APTR)ID_ABOUTMUI},
{NM_ITEM , NM_BARLABEL ,0,0,0,NULL},
{NM_ITEM , "Open..." ,"O",0,0,(APTR)ID_OPEN},
{NM_ITEM , "Save as..." ,"A",0,0,(APTR)ID_SAVEAS},
{NM_ITEM , "Print..." ,"P",0,0,(APTR)ID_PRINT},
{NM_ITEM , NM_BARLABEL ,0,0,0,NULL},
{NM_ITEM , "Hide" ,"H",0,0,(APTR)ID_HIDE},
{NM_ITEM , "Quit" ,"Q",0,0,(APTR)MUIV_Application_ReturnID_Quit},
{NM_TITLE,"Edit" ,0,0,0,NULL},
{NM_ITEM , "Copy" ,"C",0,0,(APTR)ID_COPY},
{NM_TITLE,"Settings" ,0,0,0,NULL},
{NM_ITEM , "Default font mapping..." ,0,0,0,(APTR)ID_DEFFONTS},
{NM_ITEM , "Document font mapping..." ,0,0,0,(APTR)ID_DOCFONTS},
{NM_ITEM , "MUI..." ,0,0,0,(APTR)ID_MUIPREFS},
{NM_END ,NULL ,0,0,0,NULL}
};
static const char* save_types[]={
"Postscript (level 2)","Postscript (level 1)","Text","PBM/PPM Images","PBM/PPM/JPEG Images",NULL
};
static ULONG SAVEDS ASM setnum_func(REG(a2,Object* obj),REG(a1,Object** p)) {
int n=1;
get(*p,MUIA_String_Integer,&n);
set(obj,MUIA_Numeric_Value,n);
return 0;
}
static struct Hook setnum_hook={{NULL,NULL},setnum_func};
struct fontmapentry {
char pdffont[128];
char afont[128];
int mwidth;
int encoding;
BOOL bold;
BOOL italic;
};
static const char* encodings[]={
"Latin 1","Latin 2","Symbols","Dingbats",NULL
};
static APTR SAVEDS ASM fontmapctor_func(REG(a2,APTR pool),REG(a1,struct fontmapentry* p)) {
struct fontmapentry* q=AllocPooled(pool,sizeof(*q));
if(q)
*q=*p;
return q;
}
static struct Hook fontmapctor_hook={{NULL,NULL},(ULONG(*)())fontmapctor_func};
static void SAVEDS ASM fontmapdtor_func(REG(a2,APTR pool),REG(a1,struct fontmapentry* p)) {
FreePooled(pool,p,sizeof(*p));
}
static struct Hook fontmapdtor_hook={{NULL,NULL},(ULONG(*)())fontmapdtor_func};
static APTR SAVEDS ASM fontmapdisp_func(REG(a2,const char** array),REG(a1,struct fontmapentry* p)) {
if(p) {
static char buf[4];
sprintf(buf,"%3d",p->mwidth);
*array++=p->pdffont;
*array++=p->afont;
*array++=buf;
*array++=p->bold?"×":" ";
*array++=p->italic?"×":" ";
*array++=encodings[p->encoding];
} else {
*array++="\33u\33bPDF font";
*array++="\33u\33bAmiga font";
*array++="\33u\33bScale";
*array++="\33u\33bBold";
*array++="\33u\33bItalic";
*array++="\33u\33bEncoding";
}
return 0;
}
static struct Hook fontmapdisp_hook={{NULL,NULL},(ULONG(*)())fontmapdisp_func};
static void SAVEDS ASM fontreq_func(REG(a2,Object* obj),REG(a1,struct FontRequester* p)) {
set(obj,MUIA_String_Contents,p->fo_Attr.ta_Name);
}
static struct Hook fontreq_hook={{NULL,NULL},(ULONG(*)())fontreq_func};
static void setfontmap(Object* o) {
LONG entries;
int k;
get(o,MUIA_List_Entries,&entries);
for(k=0;k<entries;++k) {
struct fontmapentry* e;
DoMethod(o,MUIM_List_GetEntry,k,&e);
add_fontmap(e->pdffont,e->afont,e->mwidth,(e->bold?FSF_BOLD:0)|(e->italic?FSF_ITALIC:0),e->encoding);
}
/*set_fontmap();*/
}
static void parse_fontmap_entry(Object* obj,const char* q) {
struct fontmapentry e;
const char *p=q;
while(*p && *p!='/')
++p;
if(*p=='/' && p!=q && p-q<sizeof(e.pdffont)) {
memcpy(e.pdffont,q,p-q);
e.pdffont[p-q]='\0';
e.mwidth=100;
e.bold=FALSE;
e.italic=FALSE;
e.encoding=0;
if(*++p=='[') {
while(*++p && *p!=']') {
switch(*p) {
case '1':
e.encoding=0;
break;
case '2':
e.encoding=1;
break;
case 's':
e.encoding=2;
break;
case 'z':
e.encoding=3;
break;
case 'B':
e.bold=TRUE;
break;
case 'I':
e.italic=TRUE;
break;
case '%': {
e.mwidth=0;
while(p[1]>='0' && p[1]<='9') {
e.mwidth*=10;
e.mwidth+=*++p-'0';
}
if(e.mwidth>999)
e.mwidth=999;
else if(e.mwidth<1)
e.mwidth=1;
break;
}
}
}
if(*p!=']') {
printf("Invalid fontmap entry: \"%s\".\n",q);
return;
}
++p;
}
strncpy(e.afont,p,sizeof(e.afont)-1);
e.afont[sizeof(e.afont)-1]='\0';
DoMethod(obj,MUIM_List_InsertSingle,&e,MUIV_List_Insert_Bottom);
} else
printf("Invalid fontmap entry: \"%s\".\n",q);
}
static void parse_fontmap(Object* o,const char** args) {
while(*args) {
parse_fontmap_entry(o,*args);
++args;
}
}
static void parse_fontmap_tooltypes(Object* o,BPTR lock,const char* name) {
struct DiskObject *dob;
BPTR olddir=CurrentDir(lock);
if(dob=GetDiskObject((char*)name)) {
char** p=(char**)dob->do_ToolTypes;
if(p) {
while(*p) {
if(!Strnicmp(*p,"FONTMAP=",8))
parse_fontmap_entry(o,*p+8);
++p;
}
}
FreeDiskObject(dob);
}
CurrentDir(olddir);
}
static BOOL save_fontmap(Object* o,BPTR lock,const char* name) {
struct DiskObject* dob;
BOOL ret=FALSE;
BPTR olddir=CurrentDir(lock);
if((dob=GetDiskObject((char*)name)) ||
(dob=GetDiskObject((char*)DEFICON)) ||
(dob=GetDiskObjectNew((char*)name))) {
char** oldtt=dob->do_ToolTypes;
LONG entries;
LONG numoldtt=0;
char** p;
char** newtt;
get(o,MUIA_List_Entries,&entries);
if(oldtt)
for(p=oldtt;*p;++p)
if(Strnicmp(*p,"FONTMAP",7))
++numoldtt;
if(newtt=malloc(sizeof(*newtt)*(numoldtt+entries+1))) {
char** q=newtt;
int k;
BOOL err=FALSE;
if(oldtt)
for(p=oldtt;*p;++p)
if(Strnicmp(*p,"FONTMAP",7))
*q++=*p;
for(k=0;k<entries;++k) {
struct fontmapentry* e;
size_t l1,l2;
char* s;
DoMethod(o,MUIM_List_GetEntry,k,&e);
l1=strlen(e->pdffont);
l2=strlen(e->afont);
if(s=malloc(l1+l2+32)) {
*q++=s;
memcpy(s,"FONTMAP=",8);
s+=8;
memcpy(s,e->pdffont,l1);
s+=l1;
*s++='/';
*s++='[';
*s++="12sz"[e->encoding];
if(e->bold)
*s++='B';
if(e->italic)
*s++='I';
if(e->mwidth!=100) {
int m=e->mwidth;
*s++='%';
*s++='0'+m/100;
m%=100;
*s++='0'+m/10;
m%=10;
*s++='0'+m;
}
*s++=']';
memcpy(s,e->afont,l2+1);
} else
err=TRUE;
}
*q=NULL;
dob->do_ToolTypes=newtt;
if(PutDiskObject((char*)name,dob) && !err)
ret=TRUE;
p=newtt+numoldtt;
while(*p)
free(*p++);
free(newtt);
}
dob->do_ToolTypes=oldtt;
FreeDiskObject(dob);
}
CurrentDir(olddir);
if(!ret)
printf("Can't save fonts map.\n");
return ret;
}
/*
* fontmap windows.
*/
struct fontmap_window {
Object *win;
Object *fontmapobj;
BPTR* dir;
char** filename;
Object *pdffontobj;
Object *afontobj;
Object *popobj;
Object *scaleobj;
Object *boldobj;
Object *italicobj;
Object *encodingobj;
Object *remfontobj;
};
static int changed_disabled; // kludge...
static void SAVEDS ASM activefonts_func(REG(a2,Object* obj),REG(a1,struct fontmap_window** p)) {
struct fontmap_window* fmw=*p;
LONG x;
get(obj,MUIA_List_Active,&x);
DoMethod(obj,MUIM_MultiSet,MUIA_Disabled,x==MUIV_List_Active_Off,
fmw->pdffontobj,fmw->popobj,fmw->scaleobj,fmw->boldobj,
fmw->italicobj,fmw->encodingobj,fmw->remfontobj,NULL);
if(x!=MUIV_List_Active_Off) {
struct fontmapentry* e;
++changed_disabled;
DoMethod(obj,MUIM_List_GetEntry,x,&e);
if(e) {
nnset(fmw->pdffontobj,MUIA_String_Contents,e->pdffont);
nnset(fmw->afontobj,MUIA_String_Contents,e->afont);
nnset(fmw->encodingobj,MUIA_Cycle_Active,e->encoding);
nnset(fmw->scaleobj,MUIA_String_Integer,e->mwidth);
nnset(fmw->boldobj,MUIA_Selected,e->bold);
nnset(fmw->italicobj,MUIA_Selected,e->italic);
--changed_disabled;
}
}
}
static struct Hook activefonts_hook={{NULL,NULL},(ULONG(*)())activefonts_func};
static void SAVEDS ASM fontmapchanged_func(REG(a2,Object* obj),REG(a1,struct fontmap_window** q)) {
struct fontmap_window* fmw=*q;
LONG x;
if(changed_disabled)
return;
get(obj,MUIA_List_Active,&x);
if(x!=MUIV_List_Active_Off) {
struct fontmapentry* e;
const char* p;
DoMethod(obj,MUIM_List_GetEntry,x,&e);
if(e) {
get(fmw->pdffontobj,MUIA_String_Contents,&p);
strcpy(e->pdffont,p);
get(fmw->afontobj,MUIA_String_Contents,&p);
strcpy(e->afont,p);
get(fmw->encodingobj,MUIA_Cycle_Active,&e->encoding);
get(fmw->scaleobj,MUIA_String_Integer,&e->mwidth);
if(e->mwidth<1)
e->mwidth=1;
else if(e->mwidth>999)
e->mwidth=999;
get(fmw->boldobj,MUIA_Selected,&x);
e->bold=x;
get(fmw->italicobj,MUIA_Selected,&x);
e->italic=x;
DoMethod(obj,MUIM_List_Redraw,MUIV_List_Redraw_Active);
}
}
}
static struct Hook fontmapchanged_hook={{NULL,NULL},(ULONG(*)())fontmapchanged_func};
static void SAVEDS ASM addfont_func(REG(a2,Object* obj),REG(a1,struct fontmap_window** q)) {
struct fontmap_window* fmw=*q;
struct fontmapentry e;
e.pdffont[0]='\0';
e.afont[0]='\0';
e.mwidth=100;
e.encoding=0;
e.bold=FALSE;
e.italic=FALSE;
DoMethod(obj,MUIM_List_InsertSingle,&e,MUIV_List_Insert_Bottom);
set(obj,MUIA_List_Active,MUIV_List_Active_Bottom);
set(fmw->win,MUIA_Window_ActiveObject,fmw->pdffontobj);
}
static struct Hook addfont_hook={{NULL,NULL},(ULONG(*)())addfont_func};
static void SAVEDS ASM savefontmap_func(REG(a2,Object* obj),REG(a1,struct fontmap_window** q)) {
struct fontmap_window* fmw=*q;
save_fontmap(fmw->fontmapobj,*fmw->dir,*fmw->filename);
}
static struct Hook savefontmap_hook={{NULL,NULL},(ULONG(*)())savefontmap_func};
static void make_fontmap_win(struct fontmap_window* fmw,const char* title,
BPTR* dir,char** filename,unsigned long id,
Object* scanfontsobj) {
Object *applyfontmapobj,*saveobj;
Object *addfontobj,*win,*fontmapobj;
fmw->dir=dir;
fmw->filename=filename;
fontmapobj=fmw->fontmapobj=ListviewObject,
MUIA_Listview_Input,TRUE,
MUIA_Listview_DragType,MUIV_Listview_DragType_Immediate,
MUIA_Listview_MultiSelect,MUIV_Listview_MultiSelect_Default,
MUIA_Listview_List,MyListObject,
InputListFrame,
MUIA_List_Title,TRUE,
MUIA_List_Format,"BAR,BAR,P=\33l BAR,P=\33c BAR,P=\33c BAR,",
MUIA_List_ConstructHook,&fontmapctor_hook,
MUIA_List_DestructHook,&fontmapdtor_hook,
MUIA_List_DisplayHook,&fontmapdisp_hook,
MUIA_List_DragSortable,TRUE,
MUIA_List_ShowDropMarks,TRUE,
MYATTR_ListID,1,
End,
End;
win=fmw->win=WindowObject,
MUIA_Window_Title,title,
MUIA_Window_ID,id,
MUIA_Window_DefaultObject,fontmapobj,
WindowContents,VGroup,
Child,fontmapobj,
Child,HGroup,
Child,addfontobj=SimpleButton("_Add"),
Child,fmw->remfontobj=SimpleButton("_Remove"),
End,
Child,ColGroup(2),
Child,Label2("PDF Font"),
Child,fmw->pdffontobj=StringObject,
StringFrame,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_String_MaxLen,sizeof(((struct fontmapentry*)NULL)->pdffont),
MUIA_String_AttachedList,fontmapobj,
MUIA_CycleChain,TRUE,
MUIA_Disabled,TRUE,
End,
Child,Label2("Amiga Font"),
Child,fmw->popobj=PopaslObject,
MUIA_Popasl_Type,ASL_FontRequest,
MUIA_Popasl_StopHook,&fontreq_hook,
MUIA_Popstring_String,fmw->afontobj=StringObject,
StringFrame,
MUIA_String_MaxLen,sizeof(((struct fontmapentry*)NULL)->afont)-5,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_String_AttachedList,fontmapobj,
MUIA_CycleChain,TRUE,
MUIA_Disabled,TRUE,
End,
MUIA_Popstring_Button,PopButton(MUII_PopUp),
ASLFO_TitleText,"Select a font...",
End,
End,
Child,HGroup,
Child,Label1("_Scale"),
Child,fmw->scaleobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Integer,100,
MUIA_String_MaxLen,4,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_String_AttachedList,fontmapobj,
MUIA_CycleChain,TRUE,
End,
Child,Label1("_Bold"),
Child,fmw->boldobj=MUI_MakeObject(MUIO_Checkmark,"_Bold"),
Child,Label1("_Italic"),
Child,fmw->italicobj=MUI_MakeObject(MUIO_Checkmark,"_Italic"),
Child,Label1("_Encoding"),
Child,fmw->encodingobj=MUI_MakeObject(MUIO_Cycle,"_Encoding",encodings),
End,
Child,HGroup,
Child,RectangleObject,
End,
Child,saveobj=SimpleButton("Sa_ve"),
Child,applyfontmapobj=SimpleButton("Appl_y"),
Child,scanfontsobj,
Child,RectangleObject,
End,
End,
End,
End;
if(win) {
DoMethod(App,OM_ADDMEMBER,win);
DoMethod(win,MUIM_MultiSet,MUIA_Disabled,TRUE,
fmw->remfontobj,fmw->pdffontobj,fmw->popobj,fmw->encodingobj,
fmw->boldobj,fmw->italicobj,fmw->scaleobj,NULL);
DoMethod(win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
win,3,MUIM_Set,MUIA_Window_Open,FALSE);
DoMethod(fontmapobj,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&activefonts_hook,fmw);
DoMethod(fmw->pdffontobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->pdffontobj,MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->afontobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->afontobj,MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->scaleobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->scaleobj,MUIM_Notify,MUIA_String_Contents,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->boldobj,MUIM_Notify,MUIA_Selected,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->italicobj,MUIM_Notify,MUIA_Selected,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(fmw->encodingobj,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
fontmapobj,3,MUIM_CallHook,&fontmapchanged_hook,fmw);
DoMethod(addfontobj,MUIM_Notify,MUIA_Pressed,FALSE,
fontmapobj,3,MUIM_CallHook,&addfont_hook,fmw);
DoMethod(fmw->remfontobj,MUIM_Notify,MUIA_Pressed,FALSE,
fontmapobj,2,MUIM_List_Remove,MUIV_List_Remove_Selected);
DoMethod(applyfontmapobj,MUIM_Notify,MUIA_Pressed,FALSE,
App,2,MUIM_Application_ReturnID,ID_APPLYFONTMAP);
DoMethod(saveobj,MUIM_Notify,MUIA_Pressed,FALSE,
fontmapobj,3,MUIM_CallHook,&savefontmap_hook,fmw);
}
}
static void do_scan_fonts(struct fontmap_window* fmw,int n) {
if(n) {
int k;
set(fmw->fontmapobj,MUIA_List_Quiet,TRUE);
for(k=0;k<n;++k) {
struct fontmapentry e;
int style;
if(get_font(k,e.pdffont,sizeof(e.pdffont),e.afont,sizeof(e.afont),&e.mwidth,&style,&e.encoding)) {
int entries;
int k;
e.bold=(style&FSF_BOLD)!=0;
e.italic=(style&FSF_ITALIC)!=0;
get(fmw->fontmapobj,MUIA_List_Entries,&entries);
for(k=0;k<entries;++k) {
struct fontmapentry *e2;
DoMethod(fmw->fontmapobj,MUIM_List_GetEntry,k,&e2);
if(!strcmp(e.pdffont,e2->pdffont) &&
!strcmp(e.afont,e2->afont) &&
e.mwidth==e2->mwidth &&
e.bold==e2->bold &&
e.italic==e2->italic &&
e.encoding==e2->encoding)
break;
}
if(k==entries)
DoMethod(fmw->fontmapobj,MUIM_List_InsertSingle,&e,MUIV_List_Insert_Bottom);
}
}
end_scan_fonts();
set(fmw->fontmapobj,MUIA_List_Quiet,FALSE);
set(fmw->win,MUIA_Window_ActiveObject,fmw->pdffontobj);
}
}
static struct fontmap_window def_fmw;
static struct fontmap_window doc_fmw;
static void open_file(BPTR lock,const char* name) {
sleep(TRUE);
set(win,MUIA_Window_Title,"Loading...");
if(create_doc(lock,name,CACHESZ,BLOCSZ)) {
BPTR lock2=DupLock(lock);
CurrentDir(lock2);
UnLock(docdir);
docdir=lock2;
copystr(&docname,name);
DoMethod(doc_fmw.fontmapobj,MUIM_List_Clear);
parse_fontmap_tooltypes(doc_fmw.fontmapobj,docdir,docname);
get_page_info();
}
set(win,MUIA_Window_Title,docname);
sleep(FALSE);
}
static ULONG SAVEDS ASM appwin_func(REG(a2,Object* obj),REG(a1,struct AppMessage** p)) {
struct AppMessage *msg=*p;
if(msg->am_Version>=AM_VERSION && msg->am_NumArgs>=1)
open_file(msg->am_ArgList->wa_Lock,msg->am_ArgList->wa_Name);
return 0;
}
static struct Hook appwin_hook={{NULL,NULL},appwin_func};
static int open_req(void) {
struct Screen *scr=NULL;
if(win) /* NULL for the initial requester */
get(win,MUIA_Window_Screen,&scr);
if((req ||
(req=MUI_AllocAslRequestTags(ASL_FileRequest,
ASLFR_TitleText,"Open...",
ASLFR_PositiveText,"Open",
ASLFR_NegativeText,"Cancel",
ASLFR_RejectIcons,TRUE,
ASLFR_DoPatterns,TRUE,
ASLFR_InitialPattern,"#?.pdf",
TAG_END))) &&
MUI_AslRequestTags(req,
scr?ASLFR_Screen:TAG_IGNORE,scr,
TAG_END))
return 1;
return 0;
}
static void open_req_file(void) {
if(req) {
BPTR lock=Lock(req->fr_Drawer,ACCESS_READ);
open_file(lock,req->fr_File);
UnLock(lock);
}
}
int main() {
Object *nxtsrchobj,*strobj,*menu;
Object *pssaveobj,*pscancelobj,*psrotateobj,*pszoomobj;
Object *psstartstrobj,*psstopstrobj,*pstypeobj;
Object *pspopobj,*pswin,*psfilenameobj;
Object *scanstartstrobj,*scanstopstrobj,*scanwin,*scanobj;
Object *defaultfontsobj,*scanfontsobj;
ULONG sigs;
struct Process* proc=(struct Process*)FindTask(NULL);
/* This test is probably useless. If run on 68000 or */
/* 68010, we have probably already crashed at this point. */
if(!(SysBase->AttnFlags&AFF_68020)) {
printf("This version requires at least a 68020.\n");
exit(EXIT_FAILURE);
}
#ifndef POWERUP
# if defined(__HAVE_68881__)
if(!(SysBase->AttnFlags&AFF_68881)) {
printf("This version requires a FPU.\n");
exit(EXIT_FAILURE);
}
# endif
# if defined(__mc68060__) /* should work on 68040 too */
if(!(SysBase->AttnFlags&(AFF_68060|AFF_68040))) {
printf("This version requires a 68060.\n");
exit(EXIT_FAILURE);
}
# elif defined(__mc68040__) /* should work on 68060 too */
if(!(SysBase->AttnFlags&(AFF_68060|AFF_68040))) {
printf("This version requires a 68040.\n");
exit(EXIT_FAILURE);
}
# endif
#endif
olddir=CurrentDir(0);
CurrentDir(olddir);
atexit(&cleanup);
IntuitionBase=(struct IntuitionBase*)OpenLibrary("intuition.library",39);
GfxBase=(struct GfxBase*)OpenLibrary("graphics.library",39);
LayersBase=OpenLibrary("layers.library",39);
UtilityBase=(struct UtilityBase*)OpenLibrary("utility.library",39);
IconBase=OpenLibrary("icon.library",39);
DiskfontBase=OpenLibrary("diskfont.library",39);
IFFParseBase=OpenLibrary("iffparse.library",39);
if(!IntuitionBase || !GfxBase || !LayersBase || !UtilityBase ||
!IconBase || !DiskfontBase || !IFFParseBase) {
printf("Requires AmigaOS 3.0+\n");
exit(EXIT_FAILURE);
}
if(proc->pr_CLI) {
size_t l=16;
char* path;
const char* endpath;
while(1) {
progname=malloc(l);
if(!progname)
break;
if(GetProgramName(progname,l))
break;
free(progname);
l+=16;
}
if(!(rda=ReadArgs(TEMPLATE,args,NULL))) {
PrintFault(IoErr(),"Error: ");
exit(EXIT_FAILURE);
}
if(PDFFILE) {
endpath=PathPart((char*)PDFFILE);
path=malloc(endpath-PDFFILE+1);
if(path) {
memcpy(path,PDFFILE,endpath-PDFFILE);
path[endpath-PDFFILE]='\0';
docdir=Lock(path,ACCESS_READ);
free(path);
copystr(&docname,FilePart((char*)PDFFILE));
}
}
} else {
#if defined(__SASC) || defined(__libnix__)
size_t l;
if(_WBenchMsg && _WBenchMsg->sm_NumArgs>=1) {
copystr(&progname,_WBenchMsg->sm_ArgList[0].wa_Name);
if(_WBenchMsg->sm_NumArgs>=2) {
docdir=DupLock(_WBenchMsg->sm_ArgList[1].wa_Lock);
copystr(&docname,_WBenchMsg->sm_ArgList[1].wa_Name);
}
} else {
printf("I don't understand the startup method !?\n");
exit(EXIT_FAILURE);
}
#else
/* adapt for other compilers/libraries */
exit(EXIT_FAILURE);
#endif
}
progdir=GetProgramDir();
/* gzip sometimes tries to open "*" for input, */
/* which opens and locks the stdiowin. */
/* Let's prevent that: */
if(input=Open("nil:",MODE_OLDFILE))
oldinput=SelectInput(input);
MUIMasterBase=OpenLibrary(MUIMASTER_NAME,MUIMASTER_VMIN);
if(!MUIMasterBase) {
printf("Can't open \"muimaster.library\".\n");
exit(EXIT_FAILURE);
}
if(!docname && open_req()) {
UnLock(docdir); /* there is a slight chance that docdir is locked... */
docdir=Lock(req->fr_Drawer,ACCESS_READ);
copystr(&docname,req->fr_File);
}
if(!progname || !docname)
exit(EXIT_FAILURE);
parse_tooltypes(progdir,progname);
parse_tooltypes(docdir,docname);
{
BPTR olddir=CurrentDir(progdir);
if(DISKOBJ)
diskobj=GetDiskObject((char*)DISKOBJ);
else
diskobj=GetDiskObject(progname);
CurrentDir(olddir);
}
CyberGfxBase=OpenLibrary("cybergraphics.library",41); /* may fail */
#ifdef POWERUP
PPCLibBase=OpenLibrary("ppc.library",46);
if(!PPCLibBase) {
printf("Can't open \"ppc.library\".\n");
exit(EXIT_FAILURE);
}
elfobject=PPCLoadObject("PROGDIR:apdf.elf");
if(!elfobject) {
printf("Can't load \"apdf.elf\".\n");
exit(EXIT_FAILURE);
}
port=PPCCreatePort(NULL);
reply_port=PPCCreatePort(NULL);
if(!port || !reply_port) {
printf("Can't create port.\n");
exit(EXIT_FAILURE);
}
ports[0]=port;
ports[1]=reply_port;
ports[2]=NULL;
portlist=PPCCreatePortList(ports,0);
if(!portlist) {
printf("Can't create port list.\n");
exit(EXIT_FAILURE);
}
#endif
mcc=MUI_CreateCustomClass(NULL,MUIC_Area,NULL,sizeof(DocData),dispatcher);
slider_mcc=MUI_CreateCustomClass(NULL,MUIC_Slider,NULL,sizeof(SliderData),mysliderdispatcher);
rotate_slider_mcc=MUI_CreateCustomClass(NULL,MUIC_Slider,NULL,sizeof(RotateSliderData),myrotatesliderdispatcher);
list_mcc=MUI_CreateCustomClass(NULL,MUIC_List,NULL,sizeof(ListData),mylistdispatcher);
if(!mcc || !slider_mcc || !rotate_slider_mcc || !list_mcc) {
printf("Can't create custom class.\n");
exit(EXIT_FAILURE);
}
App=ApplicationObject,
MUIA_Application_Title, "Apdf",
MUIA_Application_Version, "$VER: " apdfVerString,
MUIA_Application_Copyright, xpdfCopyright,
MUIA_Application_Author, "Derek B. Noonburg, Emmanuel Lesueur",
MUIA_Application_Description, "PDF documents viewer",
MUIA_Application_Base, "Apdf",
MUIA_Application_DiskObject, diskobj,
/*
* Main window
*/
SubWindow,win=WindowObject,
MUIA_Window_Title,docname,
MUIA_Window_ID,MAKE_ID('A','P','D','F'),
MUIA_Window_Menustrip,menu=MUI_MakeObject(MUIO_MenustripNM,menudata,0),
MUIA_Window_AppWindow,TRUE,
WindowContents,VGroup,
Child,ScrollgroupObject,
MUIA_Scrollgroup_Contents,vgroup=VirtgroupObject,
VirtualFrame,
Child,bitmapobj=DocObject,
MUIA_CycleChain,TRUE,
End,
End,
End,
Child,HGroup,
Child,Label2("Page"),
Child,pageobj=MySliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,1,
MUIA_Numeric_Max,1,
MYATTR_Value,1,
End,
Child,BalanceObject,
End,
Child,strobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Contents,"1",
MUIA_String_MaxLen,10,
MUIA_Weight,10,
MUIA_CycleChain,TRUE,
End,
End,
Child,HGroup,
Child,Label2("Zoom"),
Child,zoomobj=MySliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,minZoom,
MUIA_Numeric_Max,maxZoom,
MUIA_Numeric_Value,defZoom,
MUIA_CycleChain,TRUE,
End,
Child,BalanceObject,
End,
Child,Label2("Search"),
Child,searchobj=StringObject,
StringFrame,
MUIA_String_MaxLen,99,
MUIA_Weight,200,
MUIA_CycleChain,TRUE,
End,
Child,nxtsrchobj=SimpleButton("_Next"),
Child,BalanceObject,
End,
Child,linkobj=TextObject,
TextFrame,
MUIA_Background,MUII_TextBack,
End,
End,
End,
End,
/*
* Gauge window
*/
SubWindow,gaugewin=WindowObject,
MUIA_Window_ID,MAKE_ID('P','R','G','S'),
MUIA_Window_CloseGadget,FALSE,
WindowContents,VGroup,
Child,gaugeobj=GaugeObject,
GaugeFrame,
MUIA_Gauge_Horiz,TRUE,
End,
Child,HGroup,
Child,RectangleObject,
End,
Child,abortobj=SimpleButton("_Abort"),
Child,RectangleObject,
End,
End,
End,
End,
/*
* Save window
*/
SubWindow,pswin=WindowObject,
MUIA_Window_Title,"Save as...",
MUIA_Window_ID,MAKE_ID('S','A','V','E'),
WindowContents,VGroup,
Child,ColGroup(2),
Child,Label2("File"),
Child,pspopobj=PopaslObject,
MUIA_Popasl_Type,ASL_FileRequest,
MUIA_Popstring_String,psfilenameobj=StringObject,
StringFrame,
MUIA_String_MaxLen,255,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_CycleChain,TRUE,
End,
MUIA_Popstring_Button,PopButton(MUII_PopFile),
ASLFR_TitleText,"Select a file name...",
End,
Child,Label2("Mode"),
Child,pstypeobj=CycleObject,
MUIA_Cycle_Entries,save_types,
MUIA_CycleChain,TRUE,
End,
Child,Label2("First page"),
Child,HGroup,
Child,psstartobj=SliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,1,
MUIA_Numeric_Max,1,
End,
Child,BalanceObject,
End,
Child,psstartstrobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Contents,"1",
MUIA_String_MaxLen,10,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_Weight,10,
MUIA_CycleChain,TRUE,
End,
End,
Child,Label2("Last page"),
Child,HGroup,
Child,psstopobj=SliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,1,
MUIA_Numeric_Max,1,
End,
Child,BalanceObject,
End,
Child,psstopstrobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Contents,"1",
MUIA_String_MaxLen,10,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_Weight,10,
MUIA_CycleChain,TRUE,
End,
End,
Child,Label2("Zoom"),
Child,pszoomobj=SliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,minZoom,
MUIA_Numeric_Max,maxZoom,
MUIA_Numeric_Value,0,
MUIA_CycleChain,TRUE,
End,
Child,Label2("Rotate"),
Child,psrotateobj=MyRotateSliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,0,
MUIA_Numeric_Max,3,
MUIA_Numeric_Value,0,
MUIA_CycleChain,TRUE,
End,
End,
Child,HGroup,
Child,pssaveobj=SimpleButton("_Save"),
Child,pscancelobj=SimpleButton("_Cancel"),
End,
End,
End,
SubWindow,scanwin=WindowObject,
MUIA_Window_Title,"Scan...",
MUIA_Window_ID,MAKE_ID('S','C','A','N'),
WindowContents,VGroup,
Child,HGroup,
Child,VGroup,
Child,Label2("First page"),
Child,Label2("Last page"),
End,
Child,VGroup,
Child,scanstartobj=SliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,1,
MUIA_Numeric_Max,1,
End,
Child,scanstopobj=SliderObject,
SliderFrame,
MUIA_Background,MUII_SliderBack,
MUIA_Slider_Horiz,TRUE,
MUIA_Numeric_Min,1,
MUIA_Numeric_Max,1,
End,
End,
Child,BalanceObject,
End,
Child,VGroup,
MUIA_Weight,10,
Child,scanstartstrobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Contents,"1",
MUIA_String_MaxLen,10,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_CycleChain,TRUE,
End,
Child,scanstopstrobj=StringObject,
StringFrame,
MUIA_String_Accept,"0123456789",
MUIA_String_Contents,"1",
MUIA_String_MaxLen,10,
MUIA_String_AdvanceOnCR,TRUE,
MUIA_CycleChain,TRUE,
End,
End,
End,
Child,HGroup,
Child,RectangleObject,
End,
Child,scanobj=SimpleButton("_Scan"),
Child,RectangleObject,
End,
End,
End,
End,
MUIA_Application_DropObject,win,
End;
if(!App) {
printf("Can't create MUI application.\n");
exit(EXIT_FAILURE);
}
make_fontmap_win(&def_fmw,"Default font mapping",
&progdir,&progname,MAKE_ID('F','N','T','1'),
defaultfontsobj=SimpleButton("_Scan"));
make_fontmap_win(&doc_fmw,"Document font mapping",
&docdir,&docname,MAKE_ID('F','N','T','2'),
scanfontsobj=SimpleButton("_Scan..."));
set(win,MUIA_Window_DefaultObject,bitmapobj);
DoMethod(win,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
App,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
DoMethod(win,MUIM_Notify,MUIA_AppMessage,MUIV_EveryTime,
win,3,MUIM_CallHook,&appwin_hook,MUIV_TriggerValue);
DoMethod(pageobj,MUIM_Notify,MYATTR_Value,MUIV_EveryTime,
strobj,3,MUIM_Set,MUIA_String_Integer,MUIV_TriggerValue);
DoMethod(strobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
pageobj,3,MUIM_CallHook,&setnum_hook,strobj);
DoMethod(pageobj,MUIM_Notify,MYATTR_Value,MUIV_EveryTime,
bitmapobj,3,MUIM_Set,MYATTR_Page,MUIV_TriggerValue);
DoMethod(zoomobj,MUIM_Notify,MYATTR_Value,MUIV_EveryTime,
bitmapobj,3,MUIM_Set,MYATTR_Zoom,MUIV_TriggerValue);
DoMethod(searchobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
App,2,MUIM_Application_ReturnID,ID_SEARCH);
DoMethod(nxtsrchobj,MUIM_Notify,MUIA_Selected,FALSE,
App,2,MUIM_Application_ReturnID,ID_SEARCH);
DoMethod(pswin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
pswin,3,MUIM_Set,MUIA_Window_Open,FALSE);
DoMethod(psstartobj,MUIM_Notify,MUIA_Numeric_Value,MUIV_EveryTime,
psstartstrobj,3,MUIM_Set,MUIA_String_Integer,MUIV_TriggerValue);
DoMethod(psstopobj,MUIM_Notify,MUIA_Numeric_Value,MUIV_EveryTime,
psstopstrobj,3,MUIM_Set,MUIA_String_Integer,MUIV_TriggerValue);
DoMethod(psstartstrobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
psstartobj,3,MUIM_CallHook,&setnum_hook,psstartstrobj);
DoMethod(psstopstrobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
psstopobj,3,MUIM_CallHook,&setnum_hook,psstopstrobj);
DoMethod(pscancelobj,MUIM_Notify,MUIA_Pressed,FALSE,
pswin,3,MUIM_Set,MUIA_Window_Open,FALSE);
DoMethod(pssaveobj,MUIM_Notify,MUIA_Pressed,FALSE,
App,2,MUIM_Application_ReturnID,ID_WRITE);
DoMethod(defaultfontsobj,MUIM_Notify,MUIA_Pressed,FALSE,
App,2,MUIM_Application_ReturnID,ID_DEFAULTFONTS);
DoMethod(scanfontsobj,MUIM_Notify,MUIA_Pressed,FALSE,
App,2,MUIM_Application_ReturnID,ID_OPENSCANFONTS);
DoMethod(scanwin,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
scanwin,3,MUIM_Set,MUIA_Window_Open,FALSE);
DoMethod(scanstartobj,MUIM_Notify,MUIA_Numeric_Value,MUIV_EveryTime,
scanstartstrobj,3,MUIM_Set,MUIA_String_Integer,MUIV_TriggerValue);
DoMethod(scanstopobj,MUIM_Notify,MUIA_Numeric_Value,MUIV_EveryTime,
scanstopstrobj,3,MUIM_Set,MUIA_String_Integer,MUIV_TriggerValue);
DoMethod(scanstartstrobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
scanstartobj,3,MUIM_CallHook,&setnum_hook,scanstartstrobj);
DoMethod(scanstopstrobj,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
scanstopobj,3,MUIM_CallHook,&setnum_hook,scanstopstrobj);
DoMethod(scanobj,MUIM_Notify,MUIA_Pressed,FALSE,
App,2,MUIM_Application_ReturnID,ID_SCANFONTS);
DoMethod(abortobj,MUIM_Notify,MUIA_Selected,FALSE,
App,2,MUIM_Application_ReturnID,ID_ABORT);
#ifdef POWERUP
{
size_t l=strlen(GZIPCMD);
startup_length=sizeof(struct StartupData)+1+l;
startup_data=PPCAllocVec(startup_length,MEMF_ANY);
startup_data->port=port;
startup_data->in=Input();
startup_data->out=Output();
/* libnix startup code does not initialize pr_CES */
/* when started from Workbench. Use Output() instead. */
startup_data->err=proc->pr_CLI?proc->pr_CES:Output();
startup_data->status=0;
startup_data->flags=0;
startup_data->colors=COLORS;
startup_data->id=VMAGIC;
memcpy(startup_data->gzipcmd,GZIPCMD,l+1);
}
quitmsg=PPCCreateMessage(reply_port,0);
cmdmsg=PPCCreateMessage(reply_port,sizeof(union msg_max));
startupmsg=PPCCreateMessage(reply_port,startup_length);
cmddata=PPCAllocVec(sizeof(union msg_max),MEMF_ANY);
if(!startupmsg || !quitmsg || !cmdmsg || !cmddata) {
printf("Can't create message.\n");
exit(EXIT_FAILURE);
}
ppctask=PPCCreateTaskTags(elfobject,
PPCTASKTAG_NAME,"PDF decoder",
PPCTASKTAG_STACKSIZE,50000,
//PPCTASKTAG_PRIORITY,0,
PPCTASKTAG_STARTUP_MSG,startupmsg,
PPCTASKTAG_STARTUP_MSGDATA,startup_data,
PPCTASKTAG_STARTUP_MSGLENGTH,startup_length,
PPCTASKTAG_MSGPORT,TRUE,
NP_Input,startup_data->in,
NP_CloseInput,FALSE,
NP_Output,startup_data->out,
NP_CloseOutput,FALSE,
NP_Error,startup_data->err,
NP_CloseError,FALSE,
TAG_END);
if(!ppctask) {
printf("Can't create PPC task.\n");
exit(EXIT_FAILURE);
}
ppcport=(void*)PPCGetTaskAttrsTags(ppctask,PPCTASKINFOTAG_MSGPORT,NULL,TAG_END);
while(1) {
void* msg;
PPCWaitPortList(portlist);
if(msg=PPCGetMessage(port)) {
/* syncmsg */
BOOL ok=VMAGIC==(int)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
PPCReplyMessage(msg);
if(!ok) {
printf("Wrong version of the PPC module.\n");
quit();
exit(EXIT_FAILURE);
}
break;
} else if(PPCGetMessage(reply_port)) {
/* startupmsg */
printf("PPC task initialization failed.\n");
exit(EXIT_FAILURE);
}
}
ppc_quitted=FALSE;
#else
if(!init(COLORS,GZIPCMD))
exit(EXIT_FAILURE);
#endif
#ifdef POWERUP
if(quitting)
;
else
#endif
if(!create_doc(docdir,docname,CACHESZ,BLOCSZ))
quit();
else {
CurrentDir(docdir);
get_page_info();
parse_fontmap_tooltypes(def_fmw.fontmapobj,progdir,progname);
setfontmap(def_fmw.fontmapobj);
do_scan_fonts(&def_fmw,scan_default_fonts());
parse_fontmap_tooltypes(doc_fmw.fontmapobj,docdir,docname);
if(FONTMAP) {
parse_fontmap(def_fmw.fontmapobj,FONTMAP);
setfontmap(def_fmw.fontmapobj);
}
setfontmap(doc_fmw.fontmapobj);
set(pageobj,MUIA_Numeric_Value,PAGE);
set(zoomobj,MUIA_Numeric_Value,ZOOM);
set(win,MUIA_Window_Open,TRUE);
{
LONG x;
get(win,MUIA_Window_Open,&x);
if(!x)
quit();
}
}
sigs=0;
while(
#ifdef POWERUP
!ppc_quitted
#else
1
#endif
) {
void* msg;
if(App) {
do {
LONG id=DoMethod(App,MUIM_Application_NewInput,&sigs);
switch(id) {
case MUIV_Application_ReturnID_Quit:
set(win,MUIA_Window_Open,FALSE);
quit();
break;
case ID_ABOUT:
MUI_Request(App,win,0,"Apdf "apdfVersion,"OK",
MUIX_C
"Apdf "apdfVersion"\n"
#ifdef POWERUP
"PowerUp"
#else
# if defined(__mc68060__)
"68060"
# elif defined(__mc68040__)
"68040"
# elif defined(__mc68030__)
"68030"
# elif defined(__mc68020__)
"68020"
# endif
" "
# if defined(__HAVE_68881__)
"FPU"
# else
"no FPU"
# endif
#endif
" version.\n\n"
"Based on xpdf "xpdfVersion"\n"
xpdfCopyright"\n"
"derekn@foolabs.com\n\n"
"Supports PDF version "pdfVersion"\n"
"The PDF data structures, operators, and specification\n"
"are copyright 1995 Adobe Systems Inc.\n\n"
"http://www.foolabs.com/xpdf/\n\n"
"Amiga port by Emmanuel Lesueur\n"
"lesueur@club-internet.fr\n");
break;
case ID_ABOUTMUI:
DoMethod(App,MUIM_Application_AboutMUI,win);
break;
case ID_OPEN:
if(open_req())
open_req_file();
break;
case ID_SEARCH: {
const char* str;
get(searchobj,MUIA_String_Contents,&str);
search(str);
break;
}
case ID_PRINT:
set(psfilenameobj,MUIA_String_Contents,"PRT:");
set(pstypeobj,MUIA_Cycle_Active,0);
/* Fall through */
case ID_SAVEAS: {
LONG x;
get(pageobj,MUIA_Numeric_Value,&x);
set(psstartobj,MUIA_Numeric_Value,x);
set(psstopobj,MUIA_Numeric_Value,x);
set(psrotateobj,MUIA_Numeric_Value,0);
set(pswin,MUIA_Window_Open,TRUE);
break;
}
case ID_WRITE: {
int first_page;
int last_page;
int zoom;
int rotate;
int type;
const char* filename;
LONG active;
get(psfilenameobj,MUIA_String_Contents,&filename);
get(psstartobj,MUIA_Numeric_Value,&first_page);
get(psstopobj,MUIA_Numeric_Value,&last_page);
get(pszoomobj,MUIA_Numeric_Value,&zoom);
get(psrotateobj,MUIA_Numeric_Value,&rotate);
get(pspopobj,MUIA_Popasl_Active,&active);
get(pstypeobj,MUIA_Cycle_Active,&type);
zoom=zoomDPI[zoom-minZoom];
rotate*=90;
if(!active && filename && last_page>=first_page) {
SetAttrs(pswin,
MUIA_Window_Open,FALSE,
MUIA_Window_ActiveObject,psfilenameobj,
TAG_END);
save(filename,first_page,last_page,zoom,rotate,type);
} else
DisplayBeep(NULL);
break;
}
case ID_COPY: {
LONG selected;
get(bitmapobj,MYATTR_Selected,&selected);
if(selected) {
struct Rectangle rect;
get(bitmapobj,MYATTR_Selection,&rect);
toclip(rect.MinX,rect.MinY,rect.MaxX,rect.MaxY);
}
break;
}
case ID_MUIPREFS:
DoMethod(App,MUIM_Application_OpenConfigWindow,0);
break;
case ID_DEFFONTS:
set(def_fmw.win,MUIA_Window_Open,TRUE);
break;
case ID_DOCFONTS:
set(doc_fmw.win,MUIA_Window_Open,TRUE);
break;
case ID_APPLYFONTMAP:
clear_fontmap();
setfontmap(def_fmw.fontmapobj);
setfontmap(doc_fmw.fontmapobj);
DoMethod(bitmapobj,MYM_Reset);
break;
case ID_OPENSCANFONTS: {
LONG x;
get(pageobj,MUIA_Numeric_Value,&x);
set(scanstartobj,MUIA_Numeric_Value,x);
set(scanstopobj,MUIA_Numeric_Value,x);
set(scanwin,MUIA_Window_Open,TRUE);
break;
}
case ID_SCANFONTS: {
int first_page;
int last_page;
get(scanstartobj,MUIA_Numeric_Value,&first_page);
get(scanstopobj,MUIA_Numeric_Value,&last_page);
if(last_page>=first_page) {
do_scan_fonts(&doc_fmw,scan_doc_fonts(first_page,last_page));
set(scanwin,MUIA_Window_Open,FALSE);
} else
DisplayBeep(NULL);
break;
}
case ID_DEFAULTFONTS:
do_scan_fonts(&def_fmw,scan_default_fonts());
break;
case ID_HIDE:
set(App,MUIA_Application_Iconified,TRUE);
break;
}
} while(sigs==0);
}
#ifdef POWERUP
PPCSetPortListAttr(portlist,PPCPORTLISTTAG_EXTENDEDSIGNALS,sigs|SIGBREAKF_CTRL_C);
PPCWaitPortList(portlist);
if(msg=PPCGetMessage(reply_port)) {
MYASSERT(msg==startupmsg);
ppc_quitted=TRUE;
exit(EXIT_SUCCESS);
}
if(PPCGetMessage(port)) {
MYASSERT(FALSE);
}
sigs=PPCGetPortListAttr(portlist,PPCPORTLISTTAG_RECEIVEDSIGNALS);
#else
sigs=Wait(sigs|SIGBREAKF_CTRL_C);
#endif
if(sigs&SIGBREAKF_CTRL_C) {
set(win,MUIA_Window_Open,FALSE);
quit();
}
}
return EXIT_SUCCESS;
}