Fix for a crash which happened when a document couldn't be opened.
[AROS-Contrib.git] / arospdf / xpdf / AROSPDFApp.cc
blobde1008d7e7b14104bc5a7d581aa41f78016aa440
1 //========================================================================
2 //
3 // AROSPDFApp.cc
4 //
5 // Copyright 2009 Craig Kiesau
6 //
7 //========================================================================
9 #include <time.h>
10 #include <limits.h>
11 #include "PDFDoc.h"
12 #include "AROSPDFApp.h"
13 long __stack = 8192;
15 #define RES_LOWER_LIMIT 200
16 #define RES_HIGHER_LIMIT 2000
18 #define XGET(OBJ, ATTR) ({IPTR b; GetAttr(ATTR, OBJ, &b); b; })
20 enum {
21 ADD_METHOD=1,
22 MEN_PROJECT,MEN_OPEN, MEN_ABOUT,MEN_QUIT,
23 MEN_EDIT,MEN_FIND,MEN_FINDNEXT,
24 MEN_VIEW,MEN_FULLSCREEN,MEN_CONTINUOUS,MEN_ZOOMIN,MEN_ZOOMOUT,MEN_BESTFIT,MEN_FITWIDTH,
25 MEN_GO,MEN_FIRSTPAGE,MEN_PREVPAGE,MEN_NEXTPAGE,MEN_LASTPAGE
28 static struct NewMenu MenuData1[]=
30 {NM_TITLE, "AROSPDF", 0, 0, 0, (APTR)MEN_PROJECT },
31 {NM_ITEM, "Open File...", "O", 0, 0, (APTR)MEN_OPEN },
32 {NM_ITEM, NM_BARLABEL, 0, 0, 0, (APTR)0 },
33 {NM_ITEM, "About AROSPDF", "?", 0, 0, (APTR)MEN_ABOUT },
34 {NM_ITEM, NM_BARLABEL, 0, 0, 0, (APTR)0 },
35 {NM_ITEM, "Quit", "Q", 0, 0, (APTR)MEN_QUIT },
37 {NM_TITLE, "Edit", 0, NM_MENUDISABLED, 0, (APTR)MEN_EDIT },
38 {NM_ITEM, "Find...", 0, 0, 0, (APTR)MEN_FIND },
39 {NM_ITEM, "Find Next", 0, 0, 0, (APTR)MEN_FINDNEXT },
41 {NM_TITLE, "View", 0, 0, 0, (APTR)MEN_VIEW },
42 //{NM_ITEM, "Fullscreen", 0, NM_ITEMDISABLED, 0, (APTR)MEN_FULLSCREEN },
43 //{NM_ITEM, "Continuous", 0, NM_ITEMDISABLED, 0, (APTR)MEN_CONTINUOUS }, //CHECKIT|MENUTOGGLE|
44 {NM_ITEM, NM_BARLABEL, 0, 0, 0, (APTR)0 },
45 {NM_ITEM, "Zoom In", 0, 0, 0, (APTR)MEN_ZOOMIN },
46 {NM_ITEM, "Zoom Out", 0, 0, 0, (APTR)MEN_ZOOMOUT },
47 {NM_ITEM, "Best Fit", 0, CHECKIT|MENUTOGGLE, 0, (APTR)MEN_BESTFIT },
48 {NM_ITEM, "Fit Width", 0, CHECKIT|MENUTOGGLE, 0, (APTR)MEN_FITWIDTH },
50 {NM_TITLE, "Go", 0, 0, 0, (APTR)MEN_GO },
51 {NM_ITEM, "First Page", 0, 0, 0, (APTR)MEN_FIRSTPAGE },
52 {NM_ITEM, "Previous Page", 0, 0, 0, (APTR)MEN_PREVPAGE },
53 {NM_ITEM, NM_BARLABEL, 0, 0, 0, (APTR)0 },
54 {NM_ITEM, "Next Page", 0, 0, 0, (APTR)MEN_NEXTPAGE },
55 {NM_ITEM, "Last Page", 0, 0, 0, (APTR)MEN_LASTPAGE },
56 {NM_END, NULL, 0, 0, 0, (APTR)0 },
59 static struct Hook sliderhook;
60 static struct Hook buttonhook;
61 static struct Hook menuhook;
63 char about_text[] ="\33cAROSPDF\n\nCopyright 2009-2010 Craig Kiesau\nver 0.2.32 (2010/07/01)\nckiesau@aros.org\n\nBased on xpdf 3.0.2 Copyright 1996-2007 Glyph and Cog";
65 long min(long a, long b)
67 return (a < b ? a : b);
70 BOOL LoadASL(struct Screen * curscreen,STRPTR filename,STRPTR title,STRPTR ifile,STRPTR pattern,BOOL folders) {
71 char current_dir[300] = "";
72 BOOL ok=FALSE;
73 struct FileRequester * freq=NULL;
75 if ((freq = (struct FileRequester *)AllocAslRequest(ASL_FileRequest,NULL))) {
76 if (AslRequestTags(freq,
77 ASLFR_TitleText, (IPTR)title,
78 ASLFR_Window, 0,
79 ASLFR_Flags1, FRF_DOPATTERNS,
80 ASLFR_InitialFile, (IPTR)ifile,
81 ASLFR_InitialDrawer, (IPTR)current_dir,
82 ASLFR_InitialPattern, (IPTR)pattern,
83 ASLFR_DrawersOnly, folders,
84 ASLFR_Screen, curscreen,
85 /*ASLFR_UserData, app,
86 ASLFR_IntuiMsgFunc, &IntuiMsgHook,*/
87 TAG_DONE)) {
88 strcpy(current_dir,freq->rf_Dir);
90 strcpy(filename,freq->rf_Dir);
91 if(AddPart(filename,freq->rf_File,255))//MAXFILENAME))
92 ok=TRUE;
94 FreeAslRequest(freq);
96 return ok;
99 struct CustomImageData
101 AROSPDFApp * app;
102 struct MUI_EventHandlerNode ehnode;
103 struct BitMap * bitmap;
104 LONG width, height;
106 #define MY_APP 0x8022UL
107 #define MY_RP 0x8023UL
108 #define MY_BM 0x8024UL
109 #define MY_BMWIDTH 0x8025UL
110 #define MY_BMHEIGHT 0x8026UL
112 IPTR mNew(struct IClass *cl,Object *obj,Msg msg) {
113 struct CustomImageData *data;
114 struct TagItem *tags,*tag;
116 if (!(obj = (Object *)DoSuperMethodA(cl,obj,(Msg)msg)))
117 return(0);
119 data = (CustomImageData*)INST_DATA(cl,obj);
121 for (tags=((struct opSet *)msg)->ops_AttrList ; (tag=NextTagItem(&tags));) {
122 switch (tag->ti_Tag) {
123 case MY_APP:
124 if (tag->ti_Data)
125 data->app = ((AROSPDFApp *)tag->ti_Data);
126 break;
127 case MY_BM:
128 if (tag->ti_Data) {
129 data->bitmap = ((struct BitMap *)tag->ti_Data);
131 break;
132 case MY_BMWIDTH:
133 if (tag->ti_Data)
134 data->width = tag->ti_Data;
135 break;
136 case MY_BMHEIGHT:
137 if (tag->ti_Data)
138 data->height = tag->ti_Data;
139 break;
142 return (IPTR)obj;
145 IPTR mSet(struct IClass *cl,Object *obj,Msg msg) {
146 struct CustomImageData *data = (CustomImageData*)INST_DATA(cl,obj);
147 struct TagItem *tags,*tag;
149 for (tags=((struct opSet *)msg)->ops_AttrList ; (tag=NextTagItem(&tags));) {
150 switch (tag->ti_Tag) {
151 case MY_APP:
152 if (tag->ti_Data)
153 data->app = ((AROSPDFApp *)tag->ti_Data);
154 break;
155 case MY_BM:
156 if (tag->ti_Data) {
157 data->bitmap = ((struct BitMap *)tag->ti_Data);
159 break;
160 case MY_BMWIDTH:
161 if (tag->ti_Data)
162 data->width = tag->ti_Data;
163 break;
164 case MY_BMHEIGHT:
165 if (tag->ti_Data)
166 data->height = tag->ti_Data;
167 break;
170 return DoSuperMethodA(cl,obj,msg);
173 IPTR mGet(struct IClass *cl,Object *obj,Msg msg) {
174 //struct CustomImageData *data = INST_DATA(cl,obj);
175 //IPTR *store = ((struct opGet *)msg)->opg_Storage;
177 switch (((struct opGet *)msg)->opg_AttrID) {
181 return DoSuperMethodA(cl,obj,msg);
184 IPTR mAskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg) {
185 //struct CustomImageData *data = INST_DATA(cl,obj);
186 DoSuperMethodA(cl,obj,(Msg)msg);
187 msg->MinMaxInfo->MinWidth += 1;
188 msg->MinMaxInfo->DefWidth += _width(obj);
189 msg->MinMaxInfo->MaxWidth += MUI_MAXMAX;
191 msg->MinMaxInfo->MinHeight += 1;
192 msg->MinMaxInfo->DefHeight += _mheight(obj);
193 msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
194 return 0;
197 IPTR mDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg) {
198 struct CustomImageData *data = (CustomImageData*)INST_DATA(cl,obj);
199 struct RastPort *rp;
200 ULONG mleft, mtop, mwidth, mheight;
202 DoSuperMethodA(cl, obj, (Msg)msg);
203 if (data->app->isReady()) {
204 if ((data->width != XGET(data->app->getBM(),MUIA_Width)) || (data->height != XGET(data->app->getBM(),MUIA_Height)))
205 data->app->ResizeBitMap(XGET(data->app->getBM(),MUIA_Width),XGET(data->app->getBM(),MUIA_Height));
208 rp = _rp(obj);
209 mleft = _mleft(obj);
210 mtop = _mtop(obj);
211 mwidth = _width(obj);
212 mheight = _mheight(obj);
214 mwidth = min(mwidth, data->width);
215 mheight = min(mheight, data->height);
217 if (data->app->isReady()) {
218 BltBitMapRastPort(data->bitmap, 0, 0, rp, mleft, mtop, mwidth-5, mheight-1, 0xc0);
220 return 0;
223 IPTR mSetup(struct IClass *cl,Object *obj,Msg msg) {
224 struct CustomImageData *data = INST_DATA(cl,obj);
226 if (!DoSuperMethodA(cl,obj,msg))
227 return(FALSE);
229 data->ehnode.ehn_Object = obj;
230 data->ehnode.ehn_Class = cl;
231 data->ehnode.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
232 DoMethod(_win(obj),MUIM_Window_AddEventHandler,&data->ehnode);
234 return TRUE;
237 IPTR mHandleEvent(struct IClass *cl, Object *obj, struct MUIP_HandleEvent *msg) {
238 struct CustomImageData *data = INST_DATA(cl,obj);
240 if (msg->imsg) {
241 switch (msg->imsg->Class) {
242 case IDCMP_RAWKEY:
243 switch (msg->imsg->Code) {
244 case RAWKEY_UP:
245 case RAWKEY_NM_WHEEL_UP:
246 data->app->ScrollUpDown(FALSE);
247 break;
248 case RAWKEY_DOWN:
249 case RAWKEY_NM_WHEEL_DOWN:
250 data->app->ScrollUpDown(TRUE);
251 break;
252 case RAWKEY_PAGEUP:
253 data->app->PageForwardBack(FALSE);
254 break;
255 case RAWKEY_PAGEDOWN:
256 data->app->PageForwardBack(TRUE);
257 break;
259 break;
262 return 0;
265 IPTR mCleanup(struct IClass *cl,Object *obj,Msg msg) {
266 struct CustomImageData *data = INST_DATA(cl,obj);
268 DoMethod(_win(obj),MUIM_Window_RemEventHandler,&data->ehnode);
269 return DoSuperMethodA(cl,obj,msg);
272 BOOPSI_DISPATCHER(IPTR, MyDispatcher, cl, obj, msg)
274 switch (msg->MethodID)
276 case OM_NEW : return(mNew (cl,obj,(APTR)msg));
277 case OM_SET : return(mSet (cl,obj,(APTR)msg));
278 case OM_GET : return(mGet (cl,obj,(APTR)msg));
279 case MUIM_AskMinMax : return(mAskMinMax(cl,obj,(APTR)msg));
280 case MUIM_Draw : return(mDraw (cl,obj,(APTR)msg));
281 case MUIM_Setup : return(mSetup (cl,obj,(APTR)msg));
282 case MUIM_Cleanup : return(mCleanup (cl,obj,(APTR)msg));
283 case MUIM_HandleEvent : return(mHandleEvent(cl,obj,(struct MUIP_HandleEvent*)msg));
286 return DoSuperMethodA(cl,obj,msg);
288 BOOPSI_DISPATCHER_END
290 void AROSPDFApp::OpenFile(GString *fileNameA, GString *ownerPWA, GString *userPWA) {
291 PDFDoc *newdoc = new PDFDoc(fileNameA, ownerPWA, userPWA);
292 if (userPWA) {
293 delete userPWA;
295 if (ownerPWA) {
296 delete ownerPWA;
299 if (newdoc->isOk()) {
300 if (docLoaded) {
301 delete doc;
302 ready=FALSE;
303 docLoaded=FALSE;
304 } else {
305 dispW=BITMAPX;
306 dispH=BITMAPY;
308 doc = newdoc;
309 GString * title = new GString("AROSPDF - ");
310 title->append(fileNameA);
311 SetAttrs(wnd,MUIA_Window_Title,title->getCString() ,TAG_DONE);
312 delete title;
313 resolution = 100;
314 page = 1;
315 posX = 0;
316 posY = 0;
318 splashOut->startDoc(doc->getXRef());
319 JumpToPage(1);
320 } else {
321 MUI_Request(muiapp, wnd, 0, "AROSPDF", "Continue", "Can't open file '%s'", fileNameA->getCString());
322 delete newdoc;
326 void AROSPDFApp::BackFillFullScreen() {
327 BltBitMapRastPort(bm, 0, 0, &fsscreen->RastPort, 0, 0, dispW-5, dispH-1, 0xc0);
330 void AROSPDFApp::ToggleFullscreen() {
331 FullScreen=!FullScreen;
332 if (FullScreen) {
333 origscreen=XGET(wnd,MUIA_Window_Screen);
334 int scx=origscreen->Width;
335 int scy=origscreen->Height;
336 fsscreen=OpenScreenTags(NULL, SA_Width,scx,
337 SA_Height,scy,TAG_DONE);
338 if (fsscreen!=NULL) {
339 SetRast( &fsscreen->RastPort, 1 );
340 fswindow=OpenWindowTags(NULL,
341 WA_Width, fsscreen->Width,
342 WA_Height, fsscreen->Height,
343 WA_CustomScreen, (IPTR)fsscreen,
344 WA_Backdrop, TRUE,
345 WA_Borderless, TRUE,
346 WA_RMBTrap, TRUE,
347 WA_Activate, TRUE,
348 WA_ReportMouse, TRUE,
349 WA_IDCMP, IDCMP_MOUSEBUTTONS
350 | IDCMP_RAWKEY
351 | IDCMP_DISKINSERTED
352 | IDCMP_DISKREMOVED
353 | IDCMP_ACTIVEWINDOW
354 | IDCMP_INACTIVEWINDOW
355 | IDCMP_MOUSEMOVE
356 | IDCMP_DELTAMOVE,
357 TAG_DONE);
358 BestFit=TRUE;
359 DisableFitWidth();
360 ResizeBitMap(scx,scy);
361 ZoomToFit(FALSE);
362 SetAttrs(wnd,MUIA_Window_Open,FALSE,TAG_DONE);
363 BackFillFullScreen();
365 } else {
366 if (fsscreen!=NULL) {
367 SetAttrs(wnd,MUIA_Window_Open,TRUE,TAG_DONE);
368 CloseWindow(fswindow);
369 CloseScreen(fsscreen);
374 AROSPDFApp::AROSPDFApp() {
375 ready=FALSE;
376 docLoaded=FALSE;
377 if (initAROS() != 0) {
378 fprintf(stderr, "error initializing AROS\n");
379 ok = gFalse;
380 return;
382 EnableDisableGUI();
383 ok = gTrue;
386 void AROSPDFApp::JumpToPage(int pageno) {
387 int pw,ph;
389 if (pageno==0)
390 return;
391 if ((pageno > (doc->getNumPages())) && (page==(doc->getNumPages())))
392 return;
394 page=pageno;
396 if (page > (doc->getNumPages())) page=(doc->getNumPages());
397 if (!FullScreen) {
398 SetAttrs(txtPage, MUIA_NoNotify,TRUE, MUIA_String_Integer, page, TAG_DONE);
399 DoMethod(txtPageCount, MUIM_SetAsString, MUIA_Text_Contents, "of %ld", doc->getNumPages());
401 posY=0;
402 if (FitWidth) {
403 int cropwidth=doc->getPageCropWidth(page);
404 resolution=72*(double)dispW/cropwidth;
406 if (BestFit) {
407 int cropheight=doc->getPageCropHeight(page);
408 resolution=72*(double)dispH/cropheight;
411 doc->displayPage(splashOut, page, resolution, resolution, 0, gFalse,
412 gFalse, gFalse);
414 pw = splashOut->getBitmapWidth();
415 ph = splashOut->getBitmapHeight();
416 resLowLimit = gTrue;
417 resHiLimit = gTrue;
418 if (pw <= RES_HIGHER_LIMIT && ph <= RES_HIGHER_LIMIT)
419 resHiLimit = gFalse;
420 if (pw >= RES_LOWER_LIMIT && pw >= RES_LOWER_LIMIT)
421 resLowLimit = gFalse;
422 ready=TRUE;
423 docLoaded=TRUE;
424 if (!FullScreen)
425 EnableDisableGUI();
426 SetAttrs(vslider, MUIA_Prop_Entries, (LONG)(ph/SCROLLSPEED),MUIA_Prop_Visible,(LONG)(dispH/SCROLLSPEED),TAG_DONE);
427 SetAttrs(hslider, MUIA_Prop_Entries, (LONG)(pw/SCROLLSPEED),MUIA_Prop_Visible,(LONG)(dispW/SCROLLSPEED),TAG_DONE);
428 ok = gTrue;
429 SetAttrs(vslider, MUIA_NoNotify,TRUE,MUIA_Prop_First, 0,hslider, MUIA_Prop_First, 0,TAG_DONE);
430 DoMethod(Bmp,MUIM_Draw);
433 void AROSPDFApp::PageForwardBack(bool Forward) {
434 //Page forward true = next page, false = prev page
435 int pageno=page;
436 if (Forward)
437 pageno+=1;
438 else
439 pageno-=1;
440 JumpToPage(pageno);
443 void AROSPDFApp::ScrollUpDown(bool Down) {
444 if (Down) {
445 DoMethod(vslider,MUIM_Prop_Increase,SCROLLSPEED);
446 } else {
447 DoMethod(vslider,MUIM_Prop_Decrease,SCROLLSPEED);
451 AROSPDFApp::AROSPDFApp(GString *fileNameA, GString *ownerPWA, GString *userPWA) {
452 ready=FALSE;
453 docLoaded=FALSE;
454 if (initAROS() != 0) {
455 fprintf(stderr, "error initializing AROS\n");
456 ok = gFalse;
457 return;
459 OpenFile(fileNameA,ownerPWA,userPWA);
462 void AROSPDFApp::quit() {
463 exitAROS();
464 delete splashOut;
465 if (docLoaded==TRUE) {
466 delete doc;
470 int AROSPDFApp::run() {
471 // Check that the window opened
472 if (XGET(wnd, MUIA_Window_Open)) {
473 DoMethod(muiapp, MUIM_Application_Execute);
475 return 0;
478 AROS_UFH3(ULONG, sliderfunction,
479 AROS_UFHA(struct Hook *, h, A0),
480 AROS_UFHA(Object *, object, A2),
481 AROS_UFHA(APTR *, msg, A1)) {
482 AROS_USERFUNC_INIT
484 AROSPDFApp *me=(AROSPDFApp *)msg[0];
485 int item=(int)msg[1]; //vert=1, horiz=2
486 LONG val=(LONG)msg[2]; //position in scrollbar
487 if (item==1)
488 me->setVert(val*SCROLLSPEED);
489 else if (item==2)
490 me->setHoriz(val*SCROLLSPEED);
492 return 0;
494 AROS_USERFUNC_EXIT
497 AROS_UFH3(ULONG, buttonhookfunc,
498 AROS_UFHA(struct Hook *, h, A0),
499 AROS_UFHA(Object *, object, A2),
500 AROS_UFHA(APTR *, msg, A1)) {
501 AROS_USERFUNC_INIT
503 AROSPDFApp *me=(AROSPDFApp *)msg[0];
504 int item=(int)msg[1]; //vert=1, horiz=2
505 switch (item) {
506 case 2:
507 me->PageForwardBack(FALSE);
508 break;
509 case 3:
510 me->PageForwardBack(TRUE);
511 break;
512 case 4:
513 me->JumpToPage(INT_MAX);
514 break;
515 case 1:
516 me->JumpToPage(1);
517 break;
518 case 5:
519 me->ZoomInOut(FALSE);
520 break;
521 case 6:
522 me->ZoomInOut(TRUE);
523 break;
524 case 7:
525 me->JumpToPageTextbox();
527 return 0;
529 AROS_USERFUNC_EXIT
532 AROS_UFH3(ULONG, menufunction,
533 AROS_UFHA(struct Hook *, h, A0),
534 AROS_UFHA(Object *, object, A2),
535 AROS_UFHA(APTR *, msg, A1)) {
536 AROS_USERFUNC_INIT
538 AROSPDFApp *me=(AROSPDFApp *)msg[0];
539 int menuitem=(int)msg[1];
540 switch (menuitem) {
541 case MEN_ABOUT:
542 me->AboutMenu();
543 break;
544 case MEN_OPEN:
545 me->RequestOpenFile();
546 break;
547 case MEN_PREVPAGE:
548 me->PageForwardBack(FALSE);
549 break;
550 case MEN_NEXTPAGE:
551 me->PageForwardBack(TRUE);
552 break;
553 case MEN_LASTPAGE:
554 me->JumpToPage(INT_MAX);
555 break;
556 case MEN_FIRSTPAGE:
557 me->JumpToPage(1);
558 break;
559 case MEN_FITWIDTH:
560 me->ToggleFitWidth();
561 me->DisableBestFit();
562 me->JumpToPageTextbox();
563 break;
564 case MEN_BESTFIT:
565 me->ToggleBestFit();
566 me->DisableFitWidth();
567 me->ZoomToFit(FALSE);
568 break;
569 case MEN_FULLSCREEN:
570 me->ToggleFullscreen();
571 break;
573 return 0;
575 AROS_USERFUNC_EXIT
578 void AROSPDFApp::ZoomInOut(bool In) {
579 //int pw,ph;
580 if (In) {
581 if (resHiLimit==gTrue)
582 return;
583 else resolution+=20;
584 } else {
585 if (resLowLimit==gTrue)
586 return;
587 else
588 resolution-=20;
590 DisableFitWidth();
591 DisableBestFit();
592 JumpToPage(page);
595 void AROSPDFApp::DisableBestFit() {
596 BestFit=FALSE;
597 SetAttrs((APTR)DoMethod(menustrip,MUIM_FindUData,MEN_BESTFIT), MUIA_Menuitem_Checked, FALSE, TAG_DONE);
600 void AROSPDFApp::DisableFitWidth() {
601 FitWidth=FALSE;
602 SetAttrs((APTR)DoMethod(menustrip,MUIM_FindUData,MEN_FITWIDTH), MUIA_Menuitem_Checked, FALSE, TAG_DONE);
605 void AROSPDFApp::JumpToPageTextbox() {
606 JumpToPage(XGET(txtPage,MUIA_String_Integer));
609 void AROSPDFApp::RequestOpenFile() {
610 static char infile[1024] = "";
611 GString *fileName;
612 struct Screen * curscreen;
613 curscreen=XGET(wnd,MUIA_Window_Screen);
614 if (LoadASL(curscreen,infile,"Open file:","","#?.pdf",FALSE)) {
615 fileName=new GString(infile);
616 OpenFile(fileName,(GString*)NULL,(GString*)NULL);
620 void AROSPDFApp::AboutMenu() {
621 MUI_RequestA(muiapp,wnd,0,"About AROSPDF","*OK",about_text,NULL);
624 int AROSPDFApp::initAROS() {
625 SplashColor paperColor;
626 FitWidth=FALSE;
627 BestFit=FALSE;
628 FullScreen=FALSE;
629 dobj = GetDiskObject("PROGDIR:AROSPDF");
630 mcc = MUI_CreateCustomClass(NULL,MUIC_Area,NULL,sizeof(struct CustomImageData),MyDispatcher);
631 // GUI creation
632 muiapp = ApplicationObject,
633 MUIA_Application_Title , "AROSPDF",
634 MUIA_Application_Version , "$VER: AROSPDF 0.3 (30.3.2015)",
635 MUIA_Application_Copyright , "(C) 2009, Craig Kiesau",
636 MUIA_Application_Author , "Craig Kiesau",
637 MUIA_Application_Description, "A PDF viewer",
638 MUIA_Application_Base , "APDF",
639 MUIA_Application_DiskObject, (IPTR)dobj,
640 SubWindow, wnd = WindowObject,
641 MUIA_Window_Title, "AROSPDF",
642 MUIA_Window_ID, MAKE_ID('P', 'D', 'F', 'W'),
643 MUIA_Window_Width, 640,
644 MUIA_Window_Height, 480,
645 MUIA_Window_Menustrip, menustrip=MUI_MakeObject(MUIO_MenustripNM,MenuData1,0),
646 WindowContents, VGroup,
647 Child, HGroup,
648 Child, butFirst = ImageObject,
649 MUIA_Frame, MUIV_Frame_ImageButton,
650 MUIA_InputMode, MUIV_InputMode_RelVerify,
651 MUIA_Image_Spec, "3:PROGDIR:resources/dblLeftArrow.png",
652 End,
653 Child, butPrev = ImageObject,
654 MUIA_Frame, MUIV_Frame_ImageButton,
655 MUIA_InputMode, MUIV_InputMode_RelVerify,
656 MUIA_Image_Spec, "3:PROGDIR:resources/leftArrow.png",
657 End,
658 Child, txtPage=StringObject,
659 MUIA_Frame, MUIV_Frame_String,
660 MUIA_FixWidth, 40,
661 MUIA_Background, MUII_TextBack,
662 MUIA_String_Accept, "0123456789",
663 MUIA_String_Format, MUIV_String_Format_Right,
664 End,
665 Child, txtPageCount=TextObject,
666 MUIA_FixWidth, 40,
667 MUIA_Text_PreParse, "\33l",
668 End,
669 Child, butNext = ImageObject,
670 MUIA_Frame, MUIV_Frame_ImageButton,
671 MUIA_InputMode, MUIV_InputMode_RelVerify,
672 MUIA_Image_Spec, "3:PROGDIR:resources/rightArrow.png",
673 End,
674 Child, butLast = ImageObject,
675 MUIA_Frame, MUIV_Frame_ImageButton,
676 MUIA_InputMode, MUIV_InputMode_RelVerify,
677 MUIA_Image_Spec, "3:PROGDIR:resources/dblRightArrow.png",
678 End,
679 Child, butZoomOut = TextObject,
680 MUIA_FixWidth, 40,
681 MUIA_Frame, MUIV_Frame_Button,
682 MUIA_InputMode, MUIV_InputMode_RelVerify,
683 MUIA_Text_Contents, "\33c-",
684 End,
685 Child, butZoomIn = TextObject,
686 MUIA_FixWidth, 40,
687 MUIA_Frame, MUIV_Frame_Button,
688 MUIA_InputMode, MUIV_InputMode_RelVerify,
689 MUIA_Text_Contents, "\33c+",
690 End,
691 Child, RectangleObject,End,
692 End,//HGroup
693 Child, HGroup,
694 Child, Bmp = NewObject(mcc->mcc_Class,NULL,
695 TextFrame,MY_APP,(void *)this, MY_BMWIDTH, BITMAPX, MY_BMHEIGHT, BITMAPY,
696 MUIA_Background, MUII_BACKGROUND,
697 TAG_DONE),
698 //End, //Bmp
699 Child, vslider = ScrollbarObject,
700 MUIA_Prop_Entries, 100,
701 End,
702 End, // HGroup
703 Child, hslider = ScrollbarObject,
704 MUIA_Group_Horiz, TRUE,
705 MUIA_Prop_Entries, 100,
706 End,
707 End,
708 End, //VGroup
709 End;
711 if (muiapp != NULL) {
712 sliderhook.h_Entry = (HOOKFUNC)sliderfunction;
713 menuhook.h_Entry = (HOOKFUNC)menufunction;
714 buttonhook.h_Entry = (HOOKFUNC)buttonhookfunc;
716 DoMethod(vslider, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
717 (IPTR)vslider, 5, MUIM_CallHook, (IPTR)&sliderhook,(AROSPDFApp *)this,1,MUIV_TriggerValue);
718 DoMethod(hslider, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
719 (IPTR)hslider, 5, MUIM_CallHook, (IPTR)&sliderhook,(AROSPDFApp *)this,2,MUIV_TriggerValue);
720 DoMethod(wnd, MUIM_Notify, MUIA_Window_MenuAction, MUIV_EveryTime,
721 (IPTR)wnd, 4, MUIM_CallHook, (IPTR)&menuhook, (AROSPDFApp *)this, MUIV_TriggerValue);
722 DoMethod(butFirst,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,1);
723 DoMethod(butPrev,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,2);
724 DoMethod(butNext,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,3);
725 DoMethod(butLast,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,4);
726 DoMethod(butZoomOut,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,5);
727 DoMethod(butZoomIn,MUIM_Notify,MUIA_Pressed,FALSE,(IPTR)muiapp,4,MUIM_CallHook,(IPTR)&buttonhook,(AROSPDFApp*)this,6);
728 DoMethod(txtPage,MUIM_Notify,MUIA_String_Acknowledge, MUIV_EveryTime,(IPTR)muiapp, 4, MUIM_CallHook, (IPTR)&buttonhook, (AROSPDFApp*)this,7);
729 // Click Close gadget or hit Escape to quit
730 DoMethod(wnd, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
731 (IPTR)muiapp, 2,
732 MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
733 DoMethod((APTR)DoMethod(menustrip,MUIM_FindUData,MEN_QUIT), MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
734 (IPTR) muiapp, 2, MUIM_Application_ReturnID,
735 MUIV_Application_ReturnID_Quit);
737 // Open the window
738 SetAttrs(wnd, MUIA_Window_Open, (LONG)TRUE,TAG_DONE);
740 struct Window *window = (struct Window *)XGET(wnd, MUIA_Window_Window);
741 rp=CreateRastPort();
742 bm = AllocBitMap(BITMAPX, BITMAPY,
743 GetBitMapAttr(window->RPort->BitMap, BMA_DEPTH), BMF_CLEAR,
744 window->RPort->BitMap);
745 rp->BitMap=bm;
746 SetAttrs(Bmp, MY_BM,bm,TAG_DONE);
748 paperColor[0] = paperColor[1] = paperColor[2] = 255;
749 splashOut = new AROSSplashOutputDev(rp, gFalse, paperColor, gFalse,
750 &redraw, (AROSPDFApp *)this);
752 return 0;
755 void AROSPDFApp::exitAROS()
757 FreeRastPort(rp);
758 FreeBitMap(bm);
759 SetAttrs(wnd, MUIA_Window_Open, FALSE,TAG_DONE);
760 if (FullScreen)
761 CloseScreen(fsscreen);
762 MUI_DisposeObject(muiapp);
763 MUI_DeleteCustomClass(mcc);
764 if (dobj)
765 FreeDiskObject(dobj);
768 void AROSPDFApp::redraw(AROSPDFApp *data)
770 AROSPDFApp *me = (AROSPDFApp *)data;
771 int pw, ph;
772 int localx, localy;
773 int destw, desth;
774 pw = me->splashOut->getBitmapWidth();
775 ph = me->splashOut->getBitmapHeight();
777 if (me->posX + me->dispW > pw) {
778 me->posX = pw - me->dispW;
779 if (me->posX < 0)
780 me->posX = 0;
782 if (me->posY + me->dispH > ph || me->posY == INT_MAX) {
783 me->posY = ph - me->dispH;
784 if (me->posY < 0)
785 me->posY = 0;
787 localx=0;
788 localy=0;
789 destw=me->dispW;
790 desth=me->dispH;
791 //do we need to center the doc because it's smaller than the display?
792 if (pw<(me->dispW)) {
793 localx=localx+(me->dispW-pw)/2;
794 destw=destw-(localx*2);
796 if (ph<(me->dispH)) {
797 localy=localy+(me->dispH-ph)/2;
798 desth=desth-(localy*2);
800 me->splashOut->redraw(me->posX, me->posY, localx, localy, destw, desth,me->dispW,me->dispH);
801 DoMethod(me->Bmp, MUIM_Draw);
804 AROSPDFApp::~AROSPDFApp() {
805 return;
808 void AROSPDFApp::ZoomToFit(bool WidthOnly) {
809 int cropwidth,cropheight;
810 if (!docLoaded)
811 return;
812 if (!BestFit)
813 return;
814 cropwidth=doc->getPageCropWidth(page);
815 cropheight=doc->getPageCropHeight(page);
816 //determine what res should be based on our display size
817 if (WidthOnly) {
818 //we're gonna fit by width
819 resolution=72*(double)dispW/cropwidth;
820 } else {
821 //we're gonna fit by height
822 resolution=72*(double)dispH/cropheight;
824 JumpToPage(page);
827 void AROSPDFApp::EnableDisableGUI() {
828 //based on status we enable/disable buttons and menu options
829 //LONG docInvert=!docLoaded;
830 DoMethod(wnd,MUIM_MultiSet,MUIA_Disabled, (LONG)!docLoaded,
831 butFirst,butPrev,butNext,butLast,butZoomOut,butZoomIn,txtPage,NULL);
832 DoMethod(wnd,MUIM_MultiSet,MUIA_Menuitem_Enabled,(LONG)docLoaded,
833 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_PREVPAGE),
834 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_NEXTPAGE),
835 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_FIRSTPAGE),
836 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_LASTPAGE),
837 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_ZOOMIN),
838 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_ZOOMOUT),
839 NULL);
840 if (docLoaded) {
841 //we only do this stuff when there's a doc
842 if (page==1) {
843 DoMethod(wnd,MUIM_MultiSet,MUIA_Disabled,TRUE,butFirst,butPrev,NULL);
844 DoMethod(wnd,MUIM_MultiSet,MUIA_Menuitem_Enabled, FALSE,
845 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_PREVPAGE),
846 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_FIRSTPAGE),
847 NULL);
849 if (page==doc->getNumPages()) {
850 DoMethod(wnd,MUIM_MultiSet,MUIA_Disabled,TRUE,butNext,butLast,NULL);
851 DoMethod(wnd,MUIM_MultiSet,MUIA_Menuitem_Enabled, FALSE,
852 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_NEXTPAGE),
853 (APTR)DoMethod(menustrip,MUIM_FindUData,MEN_LASTPAGE),
854 NULL);
859 void AROSPDFApp::ResizeBitMap(int width, int height){
860 //get rid of old bitmap, set new one and change the slidebars accordingly
861 int pw,ph;
862 FreeBitMap(bm);
863 if (!FullScreen) {
864 struct Window *window = (struct Window *)XGET(wnd, MUIA_Window_Window);
865 bm = AllocBitMap(width, height,
866 GetBitMapAttr(window->RPort->BitMap, BMA_DEPTH), BMF_CLEAR, window->RPort->BitMap);
867 rp->BitMap=bm;
868 SetAttrs(Bmp, MY_BM, bm,MY_BMHEIGHT, height, MY_BMWIDTH,width,TAG_DONE);
869 } else {
870 bm = AllocBitMap(width, height,
871 GetBitMapAttr(fsscreen->RastPort.BitMap, BMA_DEPTH), BMF_CLEAR,
872 fsscreen->RastPort.BitMap);
873 rp->BitMap=bm;
875 dispW=width;
876 dispH=height;
877 if (FitWidth) {
878 int cropwidth=doc->getPageCropWidth(page);
879 resolution=72*(double)dispW/cropwidth;
880 doc->displayPage(splashOut, page, resolution, resolution, 0, gFalse, gFalse, gFalse);
882 if(BestFit) {
883 int cropheight=doc->getPageCropHeight(page);
884 resolution=72*(double)dispH/cropheight;
885 doc->displayPage(splashOut, page, resolution, resolution, 0, gFalse, gFalse, gFalse);
887 pw = splashOut->getBitmapWidth();
888 ph = splashOut->getBitmapHeight();
889 if (!FullScreen) {
890 SetAttrs(vslider, MUIA_Prop_Entries, (LONG)(ph/SCROLLSPEED),MUIA_Prop_Visible,(LONG)(height/SCROLLSPEED),TAG_DONE);
891 SetAttrs(hslider, MUIA_Prop_Entries, (LONG)(pw/SCROLLSPEED),MUIA_Prop_Visible,(LONG)(width/SCROLLSPEED),TAG_DONE);
893 bug("Before redraw\n");
894 redraw((void *)this);
897 void AROSPDFApp::setVert(int n) {
898 if (docLoaded) {
899 posY=n;
900 redraw((void *)this);
904 void AROSPDFApp::setHoriz(int n) {
905 if (docLoaded) {
906 posX=n;
907 redraw((void *)this);