Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / apdf / docscroll.c
blob29561aef698bb42bcbc2ff234aca1a36274c7df5
1 /*************************************************************************\
2 * *
3 * docscroll.c *
4 * *
5 * Copyright 2000-2002 Emmanuel Lesueur *
6 * *
7 \*************************************************************************/
9 #include "config.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <libraries/mui.h>
14 #include <devices/rawkeycodes.h>
15 #include <proto/intuition.h>
16 #include <proto/muimaster.h>
17 #include <proto/utility.h>
18 #include "Apdf.h"
19 #include "docscroll.h"
20 #include "pageset.h"
21 #include "docbitmap.h"
22 #include "document.h"
24 #define DB(x) //x
25 #define Static static
26 #define MEMDBG(x) //x
28 #define kprintf dprintf
30 #if HAS_AA
31 # define AA(x,y,z) x,y,z
32 #else
33 # define AA(x,y,z)
34 #endif
36 #define BROKEN_KILLNOTIFY
38 #define SPACING 0
39 #define SPACING2 4
41 #define historySize 50
42 #define numBookmarks 10
44 struct History {
45 int page;
46 BPTR dir;
47 char *name;
49 typedef struct History History;
51 struct page_info {
52 int width;
53 int height;
56 struct DocScrollData {
57 struct comm_info *comm_info;
58 struct page_info *pages;
59 int num_pages;
60 int page;
61 int total_width;
62 int total_height;
63 int average_width;
64 int average_height;
65 int max_width;
66 int max_height;
67 int columns;
68 int orig_rows;
69 int skip;
70 Object *doc;
71 Object *pageset;
72 Object *pgroup;
73 Object *fgroup;
74 Object *vgroup;
75 Object *hscroll;
76 Object *vscroll;
77 Object *rect;
78 enum ViewMode mode;
79 int quiet;
80 BOOL has_hscroll;
81 BOOL has_vscroll;
82 int zoom;
83 int dpi;
84 Object *docchanged;
85 int histCur;
86 int histTot;
87 History history[historySize];
88 History bookmark[numBookmarks];
89 struct MUI_EventHandlerNode ehn;
92 typedef struct DocScrollData DocScrollData;
96 * Virtual group class that notifies its dimensions changes.
99 struct VGroupData {
100 int width;
101 int height;
102 int vwidth;
103 int vheight;
105 typedef struct VGroupData VGroupData;
107 Static ULONG vgNew(struct IClass *cl,Object *obj,struct opSet *msg) {
108 if(obj=(Object*)DoSuperMethodA(cl,obj,(APTR)msg)) {
109 VGroupData* dat=INST_DATA(cl,obj);
110 memset(dat,0,sizeof(*dat));
112 return (ULONG)obj;
115 Static ULONG vgGet(struct IClass *cl,Object *obj,struct opGet *msg) {
116 if(msg->opg_AttrID==MYATTR_Virtgroup_GeometryChange) {
117 *msg->opg_Storage=0;
118 return TRUE;
120 return DoSuperMethodA(cl,obj,(APTR)msg);
123 Static ULONG vgDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg) {
124 VGroupData *dat=INST_DATA(cl,obj);
125 int w,h,w1,h1;
126 w1=_width(obj);
127 h1=_height(obj);
128 get(obj,MUIA_Virtgroup_Width,&w);
129 get(obj,MUIA_Virtgroup_Height,&h);
130 if(w1!=dat->width || h1!=dat->height || w!=dat->vwidth || h!=dat->vheight) {
131 dat->vwidth=w;
132 dat->vheight=h;
133 dat->width=w1;
134 dat->height=h1;
135 set(obj,MYATTR_Virtgroup_GeometryChange,TRUE);
137 return DoSuperMethodA(cl,obj,(APTR)msg);
140 #if 0
141 Static ULONG vgHandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg) {
142 /* Don't pass middle button events to the superclass */
143 /* We could use MUIA_Virtgroup_Input=FALSE, but then mouse events aren't
144 'clipped' to the virtual frame */
145 if(msg->imsg && msg->imsg->Class==IDCMP_MOUSEBUTTONS &&
146 (msg->imsg->Code==MIDDLEDOWN || msg->imsg->Code==MIDDLEUP)) {
147 struct List *list;
148 APTR state;
149 Object *o;
150 get(obj,MUIA_Group_ChildList,&list);
151 state=list->lh_Head;
152 while(o=NextObject(&state))
153 DoMethodA(o,(APTR)msg);
154 return 0;
156 return DoSuperMethodA(cl,obj,msg);
158 #else
159 /* Only called with MUI 3.8- */
160 Static ULONG vgHandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg) {
161 /* Don't pass mouse events outside the clip box to the children */
162 if(msg->imsg && msg->imsg->Class==IDCMP_MOUSEBUTTONS &&
163 (msg->imsg->Code==SELECTDOWN || msg->imsg->Code==MIDDLEDOWN ||
164 msg->imsg->Code==MENUDOWN) &&
165 (msg->imsg->MouseX<_mleft(obj) || msg->imsg->MouseX>=_mright(obj) ||
166 msg->imsg->MouseY<_mtop(obj) || msg->imsg->MouseY>=_mbottom(obj)))
167 return 0;
168 return DoSuperMethodA(cl,obj,msg);
170 #endif
172 BEGIN_DISPATCHER(vgDispatcher,cl,obj,msg) {
173 switch(msg->MethodID) {
174 case OM_NEW: return vgNew(cl,obj,(APTR)msg);
175 //case OM_SET: return vgSet(cl,obj,(APTR)msg);
176 case OM_GET: return vgGet(cl,obj,(APTR)msg);
177 case MUIM_Draw: return vgDraw(cl,obj,(APTR)msg);
178 case MUIM_HandleInput: if(is38) return vgHandleInput(cl,obj,(APTR)msg); break;
180 return DoSuperMethodA(cl,obj,(APTR)msg);
182 END_DISPATCHER(vgDispatcher)
184 struct MUI_CustomClass *vgroup_mcc;
186 Static void update_sizes(struct IClass *cl,Object *obj);
188 Static void update_dpi(struct IClass *cl,Object *obj) {
189 DocScrollData *dat=INST_DATA(cl,obj);
190 int dpi=dat->dpi==-1?0x7fffffff:dat->dpi;
191 struct List *list;
192 APTR state;
193 Object *o;
194 static in_update_dpi;
195 if(in_update_dpi)
196 return;
197 ++in_update_dpi;
198 DB(kprintf("update_dpi() dpi=%ld\n",dat->dpi);)
199 get(dat->pageset,MUIA_Group_ChildList,&list);
200 state=list->lh_Head;
201 while(o=NextObject(&state)) {
202 int dpi1;
203 get(o,MYATTR_DocBitmap_DPI,&dpi1);
204 DB(kprintf("o=%lx, dpi=%ld\n",o,dpi1);)
205 if(dpi1>0 && dpi1<dpi)
206 dpi=dpi1;
208 DB(kprintf("-> dpi=%ld\n",dpi);)
209 if(dpi!=dat->dpi) {
210 struct page_info *pages=dat->pages;
211 dat->dpi=dpi;
212 set(dat->pageset,MYATTR_PageSet_DPI,dpi);
213 if(pages) {
214 int k;
215 for(k=0;k<dat->num_pages;++k) {
216 pages[k].width=-1;
217 pages[k].height=-1;
219 update_sizes(cl,obj);
222 --in_update_dpi;
225 Static void calc_sizes(DocScrollData *dat) {
226 int k;
227 int total_height=0,num=0,max_width=1,num2=0;
228 struct page_info *pages=dat->pages;
229 if(!pages)
230 return;
231 get(dat->pageset,MYATTR_PageSet_Columns,&dat->columns);
232 dat->skip=!(dat->columns&1);
233 for(k=-dat->skip;k<dat->num_pages;) {
234 int i;
235 int max_height=0;
236 int total_width=0;
237 for(i=0;i<dat->columns && k<dat->num_pages;++i) {
238 if(k>=0 && pages[k].width>0) {
239 total_width+=pages[k].width;
240 if(pages[k].height>max_height)
241 max_height=pages[k].height;
243 ++k;
245 if(max_height) {
246 total_height+=max_height;
247 ++num;
248 } else
249 ++num2;
250 if(total_width>max_width)
251 max_width=total_width;
253 if(num) {
254 dat->average_height=total_height/num;
255 dat->total_height=total_height+dat->average_height*num2+SPACING*(num+num2-1);
256 } else {
257 dat->average_height=1;
258 dat->total_height=1;
260 dat->average_width=1;
261 dat->total_width=1;
262 dat->max_width=max_width;
263 DB(kprintf("num=%ld, num2=%ld, num_pages=%ld, skip=%ld\n"
264 "total_width=%ld, max_width=%ld, avg_width=%ld\n"
265 "total_height=%ld, max_height=%ld, avg_height=%ld\n",
266 num,num2,dat->num_pages,dat->skip,
267 dat->total_width,dat->max_width,dat->average_width,
268 dat->total_height,dat->max_height,dat->average_height);)
269 set(dat->hscroll,MUIA_Prop_Entries,dat->max_width);
270 set(dat->vscroll,MUIA_Prop_Entries,dat->total_height);
273 Static void update_sizes(struct IClass *cl,Object *obj) {
274 DocScrollData *dat=INST_DATA(cl,obj);
275 BOOL change=FALSE;
276 APTR state;
277 struct List *list;
278 Object *o;
279 //DB(kprintf("update_sizes: num_pages=%ld\n",dat->num_pages);)
280 if(dat->mode==vmContinuous &&
281 (dat->zoom==zoomPage || dat->zoom==zoomWidth))
282 update_dpi(cl,obj);
283 if(!dat->pages)
284 return;
285 get(dat->pageset,MUIA_Group_ChildList,&list);
286 state=list->lh_Head;
287 while(o=NextObject(&state)) {
288 int page,width,height;
289 get(o,MYATTR_DocBitmap_Page,&page);
290 //DB(kprintf("o=%lx, page=%ld\n",o,page);)
291 --page;
292 if(page<dat->num_pages) {
293 get(o,MYATTR_DocBitmap_Width,&width);
294 get(o,MYATTR_DocBitmap_Height,&height);
295 //DB(kprintf("width=%ld, height=%ld\n",width,height);)
296 if(dat->pages[page].width!=width ||
297 dat->pages[page].height!=height) {
298 change=TRUE;
299 dat->pages[page].width=width;
300 dat->pages[page].height=height;
304 if(change)
305 calc_sizes(dat);
309 Static ULONG dsSet(struct IClass *cl,Object *obj,struct opSet *msg) {
310 DocScrollData *dat=INST_DATA(cl,obj);
311 struct TagItem *tags=msg->ops_AttrList;
312 struct TagItem *tag;
313 BOOL no_history=FALSE;
315 while(tag=NextTagItem(&tags)) {
316 switch(tag->ti_Tag) {
317 case MYATTR_DocScroll_NoHistory:
318 no_history=tag->ti_Data;
319 break;
321 case MYATTR_DocScroll_DocChanged:
322 dat->docchanged=(Object *)tag->ti_Data;
323 break;
325 case MYATTR_DocScroll_Document:
326 if(tag->ti_Data!=(LONG)dat->doc) {
327 struct MYS_DocBitmap_CropBox box;
328 ULONG page,zoom,rotate,textaa,fillaa,strokeaa,page1;
329 get((Object*)tag->ti_Data,MYATTR_Document_NumPages,&dat->num_pages);
330 get((Object*)tag->ti_Data,MYATTR_Document_OpenPage,&page);
331 if(!no_history && dat->doc) {
332 const char *name;
333 BPTR dir;
334 get(dat->doc,MYATTR_Document_Dir,&dir);
335 get(dat->doc,MYATTR_Document_Name,&name);
336 DoMethod5(obj,MYM_DocScroll_HistoryPush,dat->page,dir,name);
338 set(obj,MYATTR_DocScroll_Quiet,TRUE);
339 dat->doc=(Object *)tag->ti_Data;
340 DB(kprintf("DocScroll: open page %d\n",page);)
341 page1=GetTagData(MYATTR_DocScroll_Page,-1,msg->ops_AttrList);
342 if(page1!=-1)
343 page=page1;
344 get(dat->doc,MYATTR_Document_OpenZoom,&zoom);
345 get(dat->doc,MYATTR_Document_OpenRotate,&rotate);
346 get(dat->doc,MYATTR_Document_OpenCropBox,&box);
347 #if HAS_AA
348 get(dat->doc,MYATTR_Document_OpenTextAA,&textaa);
349 get(dat->doc,MYATTR_Document_OpenFillAA,&fillaa);
350 get(dat->doc,MYATTR_Document_OpenStrokeAA,&strokeaa);
351 #endif
352 DB(kprintf("DocScroll: set document. openzoom %d openpage %d\n",zoom,page);)
353 dat->page=page;
354 DB(kprintf("DocScroll: set pageset params\n"));
355 SetAttrs(dat->pageset,
356 MYATTR_PageSet_Document,dat->doc,
357 MYATTR_PageSet_Page,page,
358 MYATTR_PageSet_Zoom,zoom,
359 MYATTR_PageSet_Rotate,rotate,
360 MYATTR_PageSet_CropBox,&box,
361 AA(MYATTR_PageSet_TextAA,textaa,)
362 AA(MYATTR_PageSet_FillAA,fillaa,)
363 AA(MYATTR_PageSet_StrokeAA,strokeaa,)
364 TAG_END);
365 DB(kprintf("DocScroll: set self params\n"));
366 SetAttrs(obj,
367 MYATTR_DocScroll_NoHistory,TRUE,
368 MYATTR_DocScroll_Page,page,
369 MYATTR_DocScroll_Zoom,zoom,
370 TAG_END);
371 set(obj,MYATTR_DocScroll_DocChanged,dat->doc);
372 DoMethod2(obj,MYM_DocScroll_ResetData);
373 set(obj,MYATTR_DocScroll_Quiet,FALSE);
375 break;
377 case MYATTR_DocScroll_Page: {
378 int p=tag->ti_Data;
379 if(p==-1)
380 break;
381 if(p<1)
382 p=1;
383 else if(p>dat->num_pages)
384 p=dat->num_pages;
385 if(p!=dat->page) {
386 DB(kprintf("docscroll: set(page,%ld)\n",p);)
387 if(!no_history && dat->doc)
388 DoMethod5(obj,MYM_DocScroll_HistoryPush,dat->page,0,NULL);
389 if(dat->mode==vmContinuous) {
390 int k;
391 int t=0;
392 int q;
393 struct page_info *pages=dat->pages;
394 //set(dat->pageset,MYATTR_PageSet_Page,p);
395 --p;
396 if(dat->pages) {
397 //set(dat->vgroup,MUIA_Virtgroup_Top,0);
398 for(k=-dat->skip;k+dat->columns<p;) {
399 int i,max_height=0;
400 for(i=0;i<dat->columns && k<dat->num_pages;++i) {
401 if(k>=0) {
402 int h=pages[k].height<0 ? dat->average_height : pages[k].height;
403 if(h>max_height)
404 max_height=h;
406 ++k;
408 t+=max_height+SPACING;
410 ++p;
411 dat->page=p;
412 DB(kprintf("set_page(%ld) -> top=%ld\n",dat->page,t);)
413 set(obj,MYATTR_DocScroll_Quiet,TRUE);
414 nnset(dat->vscroll,MUIA_Prop_First,t);
415 nnset(dat->pageset,MYATTR_PageSet_Page,p);
416 set(obj,MYATTR_DocScroll_Quiet,FALSE);
418 } else {
419 dat->page=p;
420 if(dat->mode!=vmSpecial)
421 set(dat->pageset,MYATTR_PageSet_Page,p);
424 break;
427 case MYATTR_DocScroll_ViewMode:
428 if(tag->ti_Data!=dat->mode) {
429 int old_mode=dat->mode;
430 set(obj,MYATTR_DocScroll_Quiet,TRUE);
431 dat->mode=tag->ti_Data;
432 if(dat->mode==vmContinuous) {
433 get(dat->pageset,MYATTR_PageSet_Rows,&dat->orig_rows);
434 set(dat->pageset,MYATTR_PageSet_StripMode,TRUE);
435 DB(kprintf("orig_rows=%ld\n",dat->orig_rows);)
437 #ifndef BROKEN_KILLNOTIFY
438 DoMethod3(dat->vscroll,MUIM_KillNotify,MUIA_Prop_First);
439 DoMethod3(dat->vgroup,MUIM_KillNotify,MUIA_Virtgroup_Top);
440 DoMethod3(dat->vgroup,MUIM_KillNotify,MUIA_Virtgroup_Height);
441 if(dat->mode==vmContinuous) {
442 DoMethod7(dat->vscroll,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,
443 //_app(obj),4,MUIM_Application_PushMethod,
444 obj,1,MYM_DocScroll_PosChanged);
445 } else {
446 DoMethod9(dat->vscroll,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,
447 dat->vgroup,3,MUIM_Set,MUIA_Virtgroup_Top,MUIV_TriggerValue);
448 DoMethod9(dat->vgroup,MUIM_Notify,MUIA_Virtgroup_Top,MUIV_EveryTime,
449 dat->vscroll,3,MUIM_Set,MUIA_Prop_First,MUIV_TriggerValue);
450 DoMethod9(dat->vgroup,MUIM_Notify,MUIA_Virtgroup_Height,MUIV_EveryTime,
451 dat->vscroll,3,MUIM_Set,MUIA_Prop_Entries,MUIV_TriggerValue);
453 #endif
454 DoMethod2(obj,MYM_DocScroll_UpdateState);
455 if(dat->mode==vmContinuous) {
456 int p=dat->page;
457 dat->page=-1;
458 SetAttrs(obj,
459 MYATTR_DocScroll_NoHistory,TRUE,
460 MYATTR_DocScroll_Page,p,
461 TAG_END);
463 if(old_mode==vmContinuous) {
464 DB(kprintf("rows reset to %ld\n",dat->orig_rows);)
465 SetAttrs(dat->pageset,
466 MYATTR_PageSet_Rows,dat->orig_rows,
467 MYATTR_PageSet_StripMode,FALSE,
468 MYATTR_PageSet_YOffset,0,
469 TAG_END);
471 set(obj,MYATTR_DocScroll_Quiet,FALSE);
473 break;
475 case MYATTR_DocScroll_Quiet:
477 * When this attribute is set, no drawing operation is done,
478 * neither by the pageset object, nor by the virtual group that
479 * contains it. Unfortunately, when the position of the
480 * virtual group is changed, the visible area is scrolled
481 * without going through the MUIM_Draw method of the virtual
482 * group. So a 'quiet' mode for the virtual group can not be
483 * implemented by subclassing the MUIC_Virtgroup class.
484 * Instead, we do it in the following way: we put the virtual group
485 * in a page group together with a RectangleObject that has
486 * FillArea=FALSE. Switching to the RectangleObject page prevents
487 * the virtual group from drawing anything.
489 set(dat->pageset,MYATTR_PageSet_Quiet,tag->ti_Data);
490 if(tag->ti_Data) {
491 set(obj,MUIA_Group_ActivePage,1);
492 ++dat->quiet;
493 } else {
494 if(!--dat->quiet)
495 set(obj,MUIA_Group_ActivePage,0);
497 DB(kprintf("docscroll %lx: quiet=%ld\n",obj,dat->quiet);)
498 break;
500 case MYATTR_DocScroll_Zoom:
501 if(dat->zoom!=tag->ti_Data) {
502 DB(kprintf("docscroll: zoom=%ld (was %d)\n",tag->ti_Data,dat->zoom);)
503 dat->zoom=tag->ti_Data;
504 set(obj,MYATTR_DocScroll_Quiet,TRUE);
505 if(dat->zoom==zoomPage) {
506 if(dat->mode!=vmContinuous)
507 set(obj,MYATTR_DocScroll_ViewMode,vmFitPage);
508 } else if(dat->mode==vmFitPage) {
509 set(obj,MYATTR_DocScroll_ViewMode,vmFix);
511 if(dat->zoom==zoomPage || dat->zoom==zoomWidth)
512 dat->dpi=-1;
513 set(dat->pageset,MYATTR_PageSet_Zoom,dat->zoom);
514 DoMethod2(obj,MYM_DocScroll_UpdateState);
515 /*if(dat->mode==vmContinuous &&
516 (dat->zoom==zoomPage || dat->zoom==zoomWidth)) {
517 dat->dpi=-1;
518 set(dat->pageset,MYATTR_PageSet_DPI,dat->dpi);
520 set(obj,MYATTR_DocScroll_Quiet,FALSE);
522 break;
525 if(msg->MethodID==OM_NEW)
526 return 0;
527 else
528 return DoSuperMethodA(cl,obj,(APTR)msg);
531 Static Object *getParent(Object *o) {
532 Object *p;
533 get(o, MUIA_Parent, &p);
534 return p;
537 Static ULONG dsNew(struct IClass *cl,Object *obj,struct opSet *msg) {
538 Object *vscroll,*hscroll,*vgroup,*pageset,*pgroup,*rect,*fgroup;
539 struct TagItem tags[4];
540 struct comm_info *ci;
541 BOOL full_screen;
543 DB(kprintf("new DocScrollObject\n");)
545 pageset=(Object*)GetTagData(MYATTR_DocScroll_Contents,0,msg->ops_AttrList);
546 ci=(struct comm_info *)GetTagData(MYATTR_DocScroll_CommInfo,0,msg->ops_AttrList);
547 full_screen=GetTagData(MYATTR_DocScroll_FullScreen,0,msg->ops_AttrList);
549 if(!pageset || !ci)
550 return 0;
552 vgroup=myVirtgroupObject,
553 //MUIA_FillArea,FALSE,
554 MUIA_Virtgroup_Input,FALSE,
555 Child,pageset,
556 End;
558 tags[0].ti_Tag=MUIA_Group_PageMode;
559 tags[0].ti_Data=TRUE;
560 tags[1].ti_Tag=MUIA_Group_Child;
561 tags[1].ti_Data=(LONG)(pgroup=VGroup,
562 MUIA_Group_Columns,2,
563 MUIA_Group_Spacing,0,
564 Child,fgroup=HGroup,
565 /* put the frame in another group, so that the size
566 of the inner area is the size of vgroup */
567 MUIA_Frame,full_screen?MUIV_Frame_None:MUIV_Frame_Virtual,
568 Child,vgroup,
569 End,
570 Child,vscroll=ScrollbarObject,
571 End,
572 Child,hscroll=ScrollbarObject,
573 MUIA_Group_Horiz,TRUE,
574 End,
575 Child,rect=RectangleObject,
576 End,
577 End);
578 tags[2].ti_Tag=MUIA_Group_Child;
579 tags[2].ti_Data=(LONG)RectangleObject, /* hack for MYATTR_DocScroll_Quiet */
580 MUIA_FillArea,FALSE,
581 End;
582 tags[3].ti_Tag=TAG_MORE;
583 tags[3].ti_Data=(LONG)msg->ops_AttrList;
584 msg->ops_AttrList=tags;
586 if(obj=(Object*)DoSuperMethodA(cl,obj,(APTR)msg)) {
587 DocScrollData* dat=INST_DATA(cl,obj);
588 LONG t;
590 memset(dat,0,sizeof(*dat));
591 dat->comm_info=ci;
592 dat->pageset=pageset;
593 dat->pgroup=pgroup;
594 dat->fgroup=fgroup;
595 dat->vgroup=vgroup;
596 dat->hscroll=hscroll;
597 dat->vscroll=vscroll;
598 dat->rect=rect;
599 dat->mode=-1;
600 dat->zoom=defZoom;
601 dat->dpi=-1;
603 // kiero: use parent as it seems obj is not real parent of these objects. this one should be safe
604 if (getParent(hscroll))
605 DoMethod3(getParent(hscroll),OM_REMMEMBER,hscroll);
606 if (getParent(vscroll))
607 DoMethod3(getParent(vscroll),OM_REMMEMBER,vscroll);
608 if (getParent(rect))
609 DoMethod3(getParent(rect),OM_REMMEMBER,rect);
611 dat->has_hscroll=FALSE;//TRUE;
612 dat->has_vscroll=FALSE;//TRUE;
614 get(dat->pageset,MYATTR_PageSet_Page,&dat->page);
615 get(dat->pageset,MYATTR_PageSet_Rows,&dat->orig_rows);
616 set(dat->pageset,MYATTR_PageSet_VGroup,vgroup);
617 set(obj,MYATTR_DocScroll_ViewMode,vmFix);
618 get(dat->pageset,MYATTR_PageSet_Zoom,&t);
619 DB(kprintf("DocScroll: zoom %d pageset zoom %d\n",dat->zoom,t);)
620 set(obj,MYATTR_DocScroll_Zoom,t);
622 DoMethod9(pageset,MUIM_Notify,MYATTR_PageSet_Page,MUIV_EveryTime,
623 obj,3,MUIM_Set,MYATTR_DocScroll_Page,MUIV_TriggerValue);
624 DoMethod9(pageset,MUIM_Notify,MYATTR_PageSet_DocChanged,MUIV_EveryTime,
625 obj,3,MUIM_Set,MYATTR_DocScroll_Document,MUIV_TriggerValue);
626 //DoMethod7(vscroll,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,
627 // obj,1,MYM_DocScroll_PosChanged);
628 //DoMethod9(pageset,MUIM_Notify,MYATTR_PageSet_Zoom,MUIV_EveryTime,
629 // obj,3,MUIM_Set,MYATTR_DocScroll_Zoom,MUIV_TriggerValue);
630 DoMethod7(pageset,MUIM_Notify,MYATTR_PageSet_Rotate,MUIV_EveryTime,
631 //app,3,MUIM_Application_PushMethod,
632 obj,1,MYM_DocScroll_UpdateState);
633 DoMethod7(pageset,MUIM_Notify,MYATTR_PageSet_Columns,MUIV_EveryTime,
634 //app,3,MUIM_Application_PushMethod,
635 obj,1,MYM_DocScroll_Layout);
636 DoMethod7(pageset,MUIM_Notify,MYATTR_PageSet_Rows,MUIV_EveryTime,
637 //app,3,MUIM_Application_PushMethod,
638 obj,1,MYM_DocScroll_Layout);
639 DoMethod7(pageset,MUIM_Notify,MYATTR_PageSet_Back,TRUE,
640 obj,1,MYM_DocScroll_Backward);
641 /*DoMethod9(vgroup,MUIM_Notify,MUIA_Height,MUIV_EveryTime,
642 vscroll,3,MUIM_Set,MUIA_Prop_Visible,MUIV_TriggerValue);*/
643 DoMethod9(vgroup,MUIM_Notify,MUIA_Virtgroup_Width,MUIV_EveryTime,
644 hscroll,3,MUIM_Set,MUIA_Prop_Entries,MUIV_TriggerValue);
645 DoMethod9(vgroup,MUIM_Notify,MUIA_Virtgroup_Left,MUIV_EveryTime,
646 hscroll,3,MUIM_Set,MUIA_Prop_First,MUIV_TriggerValue);
647 DoMethod9(hscroll,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,
648 vgroup,3,MUIM_Set,MUIA_Virtgroup_Left,MUIV_TriggerValue);
649 /*DoMethod9(vgroup,MUIM_Notify,MUIA_Width,MUIV_EveryTime,
650 hscroll,3,MUIM_Set,MUIA_Prop_Visible,MUIV_TriggerValue);*/
651 #ifdef BROKEN_KILLNOTIFY
652 DoMethod7(vscroll,MUIM_Notify,MUIA_Prop_First,MUIV_EveryTime,
653 //app,4,MUIM_Application_PushMethod,
654 obj,1,MYM_DocScroll_PosChanged);
655 #endif
656 DoMethod7(vgroup,MUIM_Notify,MYATTR_Virtgroup_GeometryChange,MUIV_EveryTime,
657 //app,3,MUIM_Application_PushMethod,
658 obj,1,MYM_DocScroll_UpdateScroll);
659 get(pageset,MYATTR_PageSet_Document,&t);
660 DB(kprintf("doc=%lx\n",t);)
661 if(t)
662 SetAttrs(obj,
663 MYATTR_DocScroll_Document,t,
664 MYATTR_DocScroll_Page,dat->page,
665 TAG_END);
666 dsSet(cl,obj,msg);
669 msg->ops_AttrList=(APTR)tags[3].ti_Data;
671 return (LONG)obj;
674 Static ULONG dsDispose(struct IClass *cl,Object *obj,Msg msg) {
675 DocScrollData *dat=INST_DATA(cl,obj);
676 int n;
677 MyFreeMem(dat->pages);
678 for(n=0;n<dat->histTot;++n) {
679 MyFreeMem(dat->history[n].name);
680 UnLock(dat->history[n].dir);
682 for(n=0;n<numBookmarks;++n) {
683 MyFreeMem(dat->bookmark[n].name);
684 UnLock(dat->bookmark[n].dir);
686 return DoSuperMethodA(cl,obj,msg);
689 Static ULONG dsGet(struct IClass *cl,Object *obj,struct opGet *msg) {
690 DocScrollData *dat=INST_DATA(cl,obj);
691 switch(msg->opg_AttrID) {
692 case MYATTR_DocScroll_ViewMode:
693 *msg->opg_Storage=dat->mode;
694 return TRUE;
695 case MYATTR_DocScroll_DocChanged:
696 *msg->opg_Storage=(LONG)dat->docchanged;
697 return TRUE;
698 case MYATTR_DocScroll_Document:
699 *msg->opg_Storage=(LONG)dat->doc;
700 return TRUE;
701 case MYATTR_DocScroll_Page:
702 *msg->opg_Storage=dat->page;
703 return TRUE;
704 case MYATTR_DocScroll_Zoom:
705 *msg->opg_Storage=dat->zoom;
706 return TRUE;
708 return DoSuperMethodA(cl,obj,(APTR)msg);
711 Static ULONG dsSetup(struct IClass *cl,Object *obj,Msg msg) {
712 DocScrollData *dat=INST_DATA(cl,obj);
713 if(!DoSuperMethodA(cl,obj,msg))
714 return FALSE;
715 //MUI_RequestIDCMP(obj,IDCMP_RAWKEY);
716 dat->ehn.ehn_Priority=0;
717 dat->ehn.ehn_Flags=0;
718 dat->ehn.ehn_Object=obj;
719 dat->ehn.ehn_Class=NULL;
720 dat->ehn.ehn_Events=IDCMP_RAWKEY;
721 DoMethod3(_win(obj),MUIM_Window_AddEventHandler,&dat->ehn);
722 return TRUE;
725 Static ULONG dsCleanup(struct IClass *cl,Object *obj,Msg msg) {
726 DocScrollData *dat=INST_DATA(cl,obj);
727 DoMethod3(_win(obj),MUIM_Window_RemEventHandler,&dat->ehn);
728 //MUI_RejectIDCMP(obj,IDCMP_RAWKEY);
729 return DoSuperMethodA(cl,obj,msg);
732 /*Static ULONG dsAskMinMax(struct IClass *cl,Object *obj,Msg msg) {
733 DocScrollData *dat=INST_DATA(cl,obj);
734 ULONG r=DoSuperMethodA(cl,obj,msg);
735 int w,h;
736 get(dat->vgroup,MUIA_Width,&w);
737 get(dat->vgroup,MUIA_Height,&h);
738 DB(kprintf("askminmax-> %ld/%ld, %ld/%ld\n",w,dat->max_width,h,dat->total_height);)
739 SetAttrs(dat->hscroll,
740 MUIA_Prop_Entries,dat->max_width,
741 MUIA_Prop_Visible,w,
742 TAG_END);
743 SetAttrs(dat->vscroll,
744 MUIA_Prop_Entries,dat->total_height,
745 MUIA_Prop_Visible,h,
746 TAG_END);
747 return r;
750 /*Static ULONG dsDraw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg) {
751 ULONG r=DoSuperMethodA(cl,obj,msg);
752 if(msg->flags&MADF_DRAWOBJECT) {
754 return r;
755 } */
757 Static ULONG dsHandleEvent(struct IClass *cl,Object *obj,struct MUIP_HandleEvent *msg) {
758 DocScrollData *dat=INST_DATA(cl,obj);
759 ULONG rc = 0;
760 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
761 #define _isinobject(x,y) (_between(_mleft(obj),(x),_mright(obj)) && _between(_mtop(obj),(y),_mbottom(obj)))
763 if(msg->imsg) {
765 ULONG mouse_inside = _isinobject(msg->imsg->MouseX, msg->imsg->MouseY);
767 switch(msg->imsg->Class) {
768 case IDCMP_RAWKEY:
769 if(msg->imsg->Code>=0x50 && msg->imsg->Code<=0x59) {
770 /* Function keys */
771 int n=msg->imsg->Code-0x50;
772 if(msg->imsg->Qualifier&IEQUALIFIER_LSHIFT ||
773 msg->imsg->Qualifier&IEQUALIFIER_RSHIFT) {
774 BPTR dir;
775 const char *name;
776 MyFreeMem(dat->bookmark[n].name);
777 UnLock(dat->bookmark[n].dir);
778 get(dat->doc,MYATTR_Document_Dir,&dir);
779 get(dat->doc,MYATTR_Document_Name,&name);
780 dat->bookmark[n].dir=DupLock(dir);
781 CopyStr(&dat->bookmark[n].name,name);
782 dat->bookmark[n].page=dat->page;
783 } else {
784 if(dat->bookmark[n].name) {
785 Object *app,*win,*doc;
786 get(obj,MUIA_ApplicationObject,&app);
787 get(obj,MUIA_WindowObject,&win);
788 doc=getDocument(dat->comm_info,app,win,dat->bookmark[n].dir,dat->bookmark[n].name);
789 if(doc)
790 SetAttrs(obj,
791 MYATTR_DocScroll_Document,doc,
792 MYATTR_DocScroll_Page,dat->bookmark[n].page,
793 TAG_END);
796 } else if (mouse_inside && msg->imsg->Code == RAWKEY_NM_WHEEL_UP) {
797 DoMethod3(obj,MYM_DocScroll_PageUp, 15);
798 } else if (mouse_inside && msg->imsg->Code == RAWKEY_NM_WHEEL_DOWN) {
799 DoMethod3(obj,MYM_DocScroll_PageDown, 15);
800 } else if (mouse_inside && msg->imsg->Code == RAWKEY_NM_WHEEL_LEFT) {
801 int t;
802 get(dat->hscroll,MUIA_Prop_First,&t);
803 set(dat->hscroll,MUIA_Prop_First,t-30);
804 } else if (mouse_inside && msg->imsg->Code == RAWKEY_NM_WHEEL_RIGHT) {
805 int t;
806 get(dat->hscroll,MUIA_Prop_First,&t);
807 set(dat->hscroll,MUIA_Prop_First,t+30);
808 } else {
809 struct InputEvent ie={0};
810 char buf[4];
811 int n;
812 ie.ie_Class=IECLASS_RAWKEY;
813 ie.ie_SubClass=0;
814 ie.ie_Code=msg->imsg->Code;
815 ie.ie_Qualifier=msg->imsg->Qualifier;
816 ie.ie_EventAddress=*(APTR*)msg->imsg->IAddress;
817 n=MapRawKey(&ie,buf,sizeof(buf),NULL);
818 if(n==1) {
819 ULONG prevrc = rc;
820 rc = MUI_EventHandlerRC_Eat; // eat event when we processed the key
822 switch(buf[0]) {
823 case 8: /* BS */
824 DoMethod3(obj,MYM_DocScroll_PageUp, 80);
825 break;
826 case ' ':
827 DoMethod3(obj,MYM_DocScroll_PageDown, 80);
828 break;
829 case 'l':
830 DoMethod2(dat->pageset,MYM_PageSet_RLeft);
831 break ;
832 case 'r':
833 DoMethod2(dat->pageset,MYM_PageSet_RRight);
834 break ;
835 case 'c':
836 DoMethod2(dat->pageset,MYM_PageSet_Crop);
837 break;
838 case 'u':
839 DoMethod2(dat->pageset,MYM_PageSet_UnCrop);
840 break;
841 case '+':
842 if(dat->zoom<maxZoom-1)
843 set(obj,MYATTR_DocScroll_Zoom,dat->zoom+1);
844 break;
845 case '-':
846 if(dat->zoom>minZoom)
847 set(obj,MYATTR_DocScroll_Zoom,dat->zoom-1);
848 break;
849 default:
850 rc = prevrc; // restore event state
854 break;
857 switch(msg->muikey) {
858 case MUIKEY_UP:
859 DoMethod3(obj,MYM_DocScroll_PageUp, 10);
860 rc = MUI_EventHandlerRC_Eat;
861 break;
862 case MUIKEY_DOWN:
863 DoMethod3(obj,MYM_DocScroll_PageDown, 10);
864 rc = MUI_EventHandlerRC_Eat;
865 break;
866 case MUIKEY_LEFT: {
867 int t;
868 get(dat->hscroll,MUIA_Prop_First,&t);
869 set(dat->hscroll,MUIA_Prop_First,t-20);
870 rc = MUI_EventHandlerRC_Eat;
871 break;
873 case MUIKEY_RIGHT: {
874 int t;
875 get(dat->hscroll,MUIA_Prop_First,&t);
876 set(dat->hscroll,MUIA_Prop_First,t+20);
877 rc = MUI_EventHandlerRC_Eat;
878 break;
880 case MUIKEY_PAGEUP:
881 DoMethod3(obj,MYM_DocScroll_PageUp, 80);
882 rc = MUI_EventHandlerRC_Eat;
883 break;
884 case MUIKEY_PAGEDOWN:
885 DoMethod3(obj,MYM_DocScroll_PageDown, 80);
886 rc = MUI_EventHandlerRC_Eat;
887 break;
888 case MUIKEY_TOP:
889 set(obj,MYATTR_DocScroll_Page,1);
890 rc = MUI_EventHandlerRC_Eat;
891 break;
892 case MUIKEY_BOTTOM:
893 set(obj,MYATTR_DocScroll_Page,dat->num_pages);
894 rc = MUI_EventHandlerRC_Eat;
895 break;
896 case MUIKEY_LINESTART:
897 set(dat->hscroll,MUIA_Prop_First,0);
898 rc = MUI_EventHandlerRC_Eat;
899 break;
900 case MUIKEY_LINEEND:
901 set(dat->hscroll,MUIA_Prop_First,0x7fffffff);
902 rc = MUI_EventHandlerRC_Eat;
903 break;
904 case MUIKEY_WORDLEFT: {
905 int f,v;
906 get(dat->hscroll,MUIA_Prop_First,&f);
907 get(dat->hscroll,MUIA_Prop_Visible,&v);
908 set(dat->hscroll,MUIA_Prop_First,f-v+30);
909 rc = MUI_EventHandlerRC_Eat;
910 break;
912 case MUIKEY_WORDRIGHT: {
913 int f,v;
914 get(dat->hscroll,MUIA_Prop_First,&f);
915 get(dat->hscroll,MUIA_Prop_Visible,&v);
916 set(dat->hscroll,MUIA_Prop_First,f+v-30);
917 rc = MUI_EventHandlerRC_Eat;
918 break;
922 #undef _between
923 #undef _isinobject
926 return rc;//DoSuperMethodA(cl,obj,(Msg)msg);
929 Static ULONG dsUpdateScroll(struct IClass *cl,Object *obj) {
930 DocScrollData *dat=INST_DATA(cl,obj);
931 int w,h,w1,h1,w2,h2,w3,h3;
932 static int in_update_scroll;
933 BOOL rem_hscroll,rem_vscroll;
935 if(in_update_scroll>=2 || dat->mode==vmSpecial)
936 return;
937 ++in_update_scroll;
939 DB(kprintf("update_scroll\n");)
941 if(dat->zoom==zoomWidth) {
942 set(obj,MYATTR_DocScroll_Quiet,TRUE);
943 get(dat->vgroup,MUIA_Width,&w);
944 DB(kprintf("zoomWidth(%ld)\n",w);)
945 SetAttrs(dat->pageset,
946 MYATTR_PageSet_Zoom,zoomWidth,
947 MYATTR_PageSet_VisWidth,w,
948 TAG_END);
949 update_dpi(cl,obj);
950 set(obj,MYATTR_DocScroll_Quiet,FALSE);
951 } else if(dat->zoom==zoomPage && dat->mode==vmContinuous) {
952 set(obj,MYATTR_DocScroll_Quiet,TRUE);
953 get(dat->vgroup,MUIA_Width,&w);
954 get(dat->vgroup,MUIA_Height,&h);
955 DB(kprintf("cont. zoomPage(%ld,%ld)\n",w,h);)
956 SetAttrs(dat->pageset,
957 MYATTR_PageSet_Zoom,zoomPage,
958 MYATTR_PageSet_VisWidth,w,
959 MYATTR_PageSet_VisHeight,h,
960 TAG_END);
961 update_dpi(cl,obj);
962 set(obj,MYATTR_DocScroll_Quiet,FALSE);
965 get(obj,MUIA_Width,&w2);
966 get(obj,MUIA_Height,&h2);
967 if(w2==0) {
968 DB(kprintf("not visible\n");)
969 --in_update_scroll;
970 return;
972 get(dat->vgroup,MUIA_Width,&w);
973 get(dat->vgroup,MUIA_Height,&h);
974 get(dat->pgroup,MUIA_Width,&w3);
975 get(dat->pgroup,MUIA_Height,&h3);
976 get(dat->vgroup,MUIA_Virtgroup_Width,&w1);
977 SetAttrs(dat->hscroll,
978 MUIA_Prop_Entries,w1,
979 MUIA_Prop_Visible,w,
980 TAG_END);
982 if(dat->mode==vmFitPage) {
983 rem_hscroll=TRUE;
984 rem_vscroll=TRUE;
985 DB(kprintf("zoomPage(%ld,%ld)\n",w2-w3+w,h2-h3+h);)
986 SetAttrs(dat->pageset,
987 MYATTR_PageSet_VisWidth,w2-(w3-w),
988 MYATTR_PageSet_VisHeight,h2-(h3-h),
989 TAG_END);
990 } else {
991 if(dat->mode==vmContinuous) {
992 update_sizes(cl,obj);
993 SetAttrs(dat->vscroll,
994 MUIA_Prop_Entries,h1=dat->total_height,
995 MUIA_Prop_Visible,h,
996 TAG_END);
997 } else {
998 get(dat->vgroup,MUIA_Virtgroup_Height,&h1);
999 SetAttrs(dat->vscroll,
1000 MUIA_Prop_Entries,h1,
1001 MUIA_Prop_Visible,h,
1002 TAG_END);
1005 DB(kprintf("w=%ld, h=%ld, w1=%ld, h1=%ld, w2=%ld, h2=%ld, w3=%ld, h3=%ld\n",w,h,w1,h1,w2,h2,w3,h3);)
1006 if(w2-(w3-w)>=w1 && h2-(h3-h)>=h1) {
1007 rem_hscroll=TRUE;
1008 rem_vscroll=TRUE;
1009 } else if(w>=w1) {
1010 rem_hscroll=TRUE;
1011 rem_vscroll=FALSE;
1012 } else if(h>=h1) {
1013 rem_hscroll=FALSE;
1014 rem_vscroll=TRUE;
1015 } else {
1016 rem_hscroll=FALSE;
1017 rem_vscroll=FALSE;
1021 if(in_update_scroll>1) {
1022 --in_update_scroll;
1023 return 0;
1026 if(rem_hscroll==dat->has_hscroll || rem_vscroll==dat->has_vscroll) {
1027 Object* g=dat->pgroup;
1028 //set(obj,MYATTR_DocScroll_Quiet,TRUE);
1029 if(DoMethod2(g,MUIM_Group_InitChange)) {
1031 if(rem_hscroll) {
1032 if(dat->has_hscroll) {
1033 DB(kprintf("removing hscroll\n");)
1034 DoMethod3(g,OM_REMMEMBER,dat->hscroll);
1035 if(dat->has_vscroll)
1036 DoMethod3(g,OM_REMMEMBER,dat->rect);
1037 dat->has_hscroll=FALSE;
1039 } else {
1040 if(!dat->has_hscroll) {
1041 DB(kprintf("adding hscroll\n");)
1042 DoMethod3(g,OM_ADDMEMBER,dat->hscroll);
1043 if(dat->has_vscroll)
1044 DoMethod3(g,OM_ADDMEMBER,dat->rect);
1045 dat->has_hscroll=TRUE;
1048 if(rem_vscroll) {
1049 if(dat->has_vscroll) {
1050 DB(kprintf("removing vscroll\n");)
1051 DoMethod3(g,OM_REMMEMBER,dat->vscroll);
1052 if(dat->has_hscroll)
1053 DoMethod3(g,OM_REMMEMBER,dat->rect);
1054 set(g,MUIA_Group_Columns,1);
1055 dat->has_vscroll=FALSE;
1057 } else {
1058 if(!dat->has_vscroll) {
1059 DB(kprintf("adding vscroll\n");)
1060 DoMethod3(g,OM_ADDMEMBER,dat->vscroll);
1061 if(dat->has_hscroll) {
1062 DoMethod3(g,OM_ADDMEMBER,dat->rect);
1063 DoMethod7(g,MUIM_Group_Sort,dat->fgroup,dat->vscroll,dat->hscroll,dat->rect,NULL);
1065 set(g,MUIA_Group_Columns,2);
1066 dat->has_vscroll=TRUE;
1070 DoMethod2(g,MUIM_Group_ExitChange);
1072 //set(obj,MYATTR_DocScroll_Quiet,FALSE);
1074 DB(kprintf("ok\n");)
1075 --in_update_scroll;
1076 return 0;
1079 Static ULONG dsPageDown(struct IClass *cl,Object *obj,struct MYP_DocScroll_PageUpDown* msg) {
1080 DocScrollData *dat=INST_DATA(cl,obj);
1081 LONG f,v,e;
1082 get(dat->vscroll,MUIA_Prop_First,&f);
1083 get(dat->vscroll,MUIA_Prop_Visible,&v);
1084 get(dat->vscroll,MUIA_Prop_Entries,&e);
1085 if(dat->mode==vmContinuous || (dat->mode==vmFix && f+v<e))
1086 set(dat->vscroll,MUIA_Prop_First,f+v*msg->percent/100);
1087 else if (dat->page < dat->num_pages) {
1088 SetAttrs(obj,
1089 MYATTR_DocScroll_Quiet,TRUE,
1090 MYATTR_DocScroll_Page,dat->page+1,
1091 TAG_END);
1092 set(dat->vscroll,MUIA_Prop_First,0);
1093 set(obj,MYATTR_DocScroll_Quiet,FALSE);
1095 return 0;
1098 Static ULONG dsPageUp(struct IClass *cl,Object *obj,struct MYP_DocScroll_PageUpDown* msg) {
1099 DocScrollData *dat=INST_DATA(cl,obj);
1100 LONG f,v;
1101 get(dat->vscroll,MUIA_Prop_First,&f);
1102 get(dat->vscroll,MUIA_Prop_Visible,&v);
1103 if(dat->mode==vmContinuous || (dat->mode==vmFix && f>0))
1104 set(dat->vscroll,MUIA_Prop_First,f-v*msg->percent/100);
1105 else if (dat->page > 1)
1107 LONG e;
1108 get(dat->vscroll,MUIA_Prop_Entries,&e);
1109 SetAttrs(obj,
1110 MYATTR_DocScroll_Quiet,TRUE,
1111 MYATTR_DocScroll_Page,dat->page-1,
1112 TAG_END);
1113 set(dat->vscroll,MUIA_Prop_First,e);
1114 set(obj,MYATTR_DocScroll_Quiet,FALSE);
1116 return 0;
1119 Static ULONG dsPosChanged(struct IClass *cl,Object* obj) {
1120 DocScrollData *dat=INST_DATA(cl,obj);
1121 int top,t=0,k,l,vis_height,bottom,s;
1122 struct page_info *pages=dat->pages;
1123 static int in_pos_changed;
1125 get(dat->vscroll,MUIA_Prop_First,&top);
1126 if(dat->mode!=vmContinuous) {
1127 set(dat->vgroup,MUIA_Virtgroup_Top,top);
1128 return;
1130 if(!pages || in_pos_changed || ((dat->zoom==zoomPage || dat->zoom==zoomWidth) && dat->dpi<=0))
1131 return;
1132 DB(kprintf("pos_changed:\n");)
1133 get(dat->vgroup,MUIA_Height,&vis_height);
1134 DB({int total; int vis;
1135 get(dat->vscroll,MUIA_Prop_Entries,&total);
1136 get(dat->vscroll,MUIA_Prop_Visible,&vis);
1137 kprintf("prop: total=%ld, vis=%ld, top=%ld, vgroup:vis=%ld\n",total,vis,top,vis_height);
1139 if(vis_height==0)
1140 return;
1141 ++in_pos_changed;
1142 for(k=-dat->skip;k<dat->num_pages && t<=top;) {
1143 int i;
1144 int max_height=0;
1145 s=t;
1146 l=k;
1147 for(i=0;i<dat->columns && k<dat->num_pages;++i) {
1148 if(k>=0) {
1149 int h=pages[k].height<=0 ? dat->average_height : pages[k].height;
1150 if(h>max_height)
1151 max_height=h;
1153 ++k;
1155 t+=max_height+SPACING;
1157 ++l;
1158 ++k;
1159 if(t==top)
1160 k=l;
1161 DB(kprintf("->t=%ld, page=%ld, cur=%ld, vis=%ld\n",s,l,k,vis_height+top-s);)
1162 /*if(dat->page!=k) {
1163 DoMethod5(obj,MYM_DocScroll_HistoryPush,dat->page,0,NULL);
1164 dat->page=k;
1166 set(obj,MYATTR_DocScroll_Quiet,TRUE);
1167 DoMethod6(dat->pageset,MYM_PageSet_VStrip,l,vis_height+top-s,s,k);
1168 //set(dat->pageset,MYATTR_PageSet_Page,k);
1169 dat->mode=vmSpecial;
1170 set(obj,MYATTR_DocScroll_Page,k);
1171 dat->mode=vmContinuous;
1172 //set(dat->pageset,MYATTR_PageSet_YOffset,s);
1173 //DB(kprintf("yoffset=%ld\n",s);)
1174 set(dat->vgroup,MUIA_Virtgroup_Top,top-s);
1175 set(obj,MYATTR_DocScroll_Quiet,FALSE);
1176 update_sizes(cl,obj);
1177 DB(kprintf("~pos_changed(%ld):\n",dat->page);)
1178 --in_pos_changed;
1179 return 0;
1182 Static ULONG dsLayout(struct IClass *cl,Object *obj) {
1183 DocScrollData *dat=INST_DATA(cl,obj);
1184 if(dat->mode==vmContinuous) {
1185 calc_sizes(dat);
1186 dsPosChanged(cl,obj);
1188 return 0;
1191 Static ULONG dsResetData(struct IClass *cl,Object *obj) {
1192 DocScrollData *dat=INST_DATA(cl,obj);
1193 dat->dpi=-1;
1194 MyFreeMem(dat->pages);
1195 if(dat->mode==vmContinuous)
1196 dat->pages=MyAllocMem(dat->num_pages*sizeof(*dat->pages));
1197 else
1198 dat->pages=NULL;
1199 if(dat->pages) {
1200 int k,p=dat->page;
1201 struct page_info *pages=dat->pages;
1202 for(k=0;k<dat->num_pages;++k) {
1203 pages[k].width=-1;
1204 pages[k].height=-1;
1206 set(obj,MYATTR_DocScroll_Quiet,TRUE);
1207 update_sizes(cl,obj);
1208 dat->page=-1;
1209 SetAttrs(obj,
1210 MYATTR_DocScroll_NoHistory,TRUE,
1211 MYATTR_DocScroll_Page,p,
1212 TAG_END);
1213 dsPosChanged(cl,obj);
1214 set(obj,MYATTR_DocScroll_Quiet,FALSE);
1216 return 0;
1219 Static ULONG dsUpdateState(struct IClass *cl,Object *obj) {
1220 set(obj,MYATTR_DocScroll_Quiet,TRUE);
1221 dsResetData(cl,obj);
1222 dsLayout(cl,obj);
1223 dsUpdateScroll(cl,obj);
1224 set(obj,MYATTR_DocScroll_Quiet,FALSE);
1225 return 0;
1228 Static ULONG dsHistoryPush(struct IClass *cl,Object *obj,struct MYP_DocScroll_HistoryPush *msg) {
1229 DocScrollData *dat=INST_DATA(cl,obj);
1230 DB(kprintf("historyPush(%ld,%lx,%s)\n",msg->page,msg->dir,msg->name?msg->name:"NULL"));
1231 while(dat->histCur<dat->histTot) {
1232 struct History *h;
1233 --dat->histTot;
1234 h=dat->history+dat->histTot;
1235 MyFreeMem(h->name);
1236 UnLock(h->dir);
1238 if(dat->histCur==historySize) {
1239 MyFreeMem(dat->history->name);
1240 UnLock(dat->history->dir);
1241 memmove(dat->history,dat->history+1,(historySize-1)*sizeof(struct History));
1242 --dat->histCur;
1243 --dat->histTot;
1245 dat->history[dat->histCur].page=msg->page;
1246 dat->history[dat->histCur].dir=DupLock(msg->dir);
1247 dat->history[dat->histCur].name=NULL;
1248 if(msg->name)
1249 CopyStr(&dat->history[dat->histCur].name,msg->name);;
1250 ++dat->histCur;
1251 ++dat->histTot;
1252 return 0;
1255 Static ULONG dsHistory(struct IClass *cl,Object *obj,struct History *h) {
1256 DocScrollData *dat=INST_DATA(cl,obj);
1257 Object *doc=dat->doc;
1258 int p=h->page;
1259 if(h->name) {
1260 const char* name;
1261 BPTR dir;
1262 Object *app,*win;
1263 get(doc,MYATTR_Document_Dir,&dir);
1264 get(doc,MYATTR_Document_Name,&name);
1265 get(obj,MUIA_ApplicationObject,&app);
1266 get(obj,MUIA_WindowObject,&win);
1267 doc=getDocument(dat->comm_info,app,win,h->dir,h->name);
1268 if(!doc)
1269 return 0;
1270 CopyStr(&h->name,name);
1271 UnLock(h->dir);
1272 h->dir=DupLock(dir);
1274 h->page=dat->page;
1275 SetAttrs(obj,
1276 MYATTR_DocScroll_NoHistory,TRUE,
1277 MYATTR_DocScroll_Document,doc,
1278 MYATTR_DocScroll_Page,p,
1279 TAG_END);
1280 return 1;
1283 Static ULONG dsBackward(struct IClass *cl,Object *obj) {
1284 DocScrollData *dat=INST_DATA(cl,obj);
1285 if(dat->histCur>0 && dsHistory(cl,obj,dat->history+dat->histCur-1)) {
1286 --dat->histCur;
1287 return 1;
1289 return 0;
1292 Static ULONG dsForward(struct IClass *cl,Object *obj) {
1293 DocScrollData *dat=INST_DATA(cl,obj);
1294 if(dat->histCur<dat->histTot && dsHistory(cl,obj,dat->history+dat->histCur)) {
1295 ++dat->histCur;
1296 return 1;
1298 return 0;
1301 BEGIN_DISPATCHER(dsDispatcher,cl,obj,msg) {
1302 switch(msg->MethodID) {
1303 case OM_NEW : return dsNew (cl,obj,(APTR)msg);
1304 case OM_DISPOSE : return dsDispose (cl,obj,(APTR)msg);
1305 case OM_SET : return dsSet (cl,obj,(APTR)msg);
1306 case OM_GET : return dsGet (cl,obj,(APTR)msg);
1307 // case MUIM_AskMinMax : return dsAskMinMax (cl,obj,(APTR)msg);
1308 // case MUIM_Draw : return dsDraw (cl,obj,(APTR)msg);
1309 case MUIM_Setup : return dsSetup(cl,obj,(APTR)msg);
1310 case MUIM_Cleanup : return dsCleanup(cl,obj,(APTR)msg);
1311 case MUIM_HandleEvent : return dsHandleEvent(cl,obj,(APTR)msg);
1312 case MYM_DocScroll_PageDown : return dsPageDown(cl,obj,(APTR)msg);
1313 case MYM_DocScroll_PageUp : return dsPageUp(cl,obj,(APTR)msg);
1314 case MYM_DocScroll_PosChanged : return dsPosChanged(cl,obj);
1315 case MYM_DocScroll_Layout : return dsLayout(cl,obj);
1316 case MYM_DocScroll_ResetData : return dsResetData(cl,obj);
1317 case MYM_DocScroll_UpdateScroll : return dsUpdateScroll(cl,obj);
1318 case MYM_DocScroll_UpdateState : return dsUpdateState(cl,obj);
1319 case MYM_DocScroll_HistoryPush : return dsHistoryPush(cl,obj,(APTR)msg);
1320 case MYM_DocScroll_Backward : return dsBackward(cl,obj);
1321 case MYM_DocScroll_Forward : return dsForward(cl,obj);
1323 return DoSuperMethodA(cl,obj,msg);
1325 END_DISPATCHER(dsDispatcher)
1328 struct MUI_CustomClass *docscroll_mcc;
1329 static int count;
1331 BOOL createDocScrollClass(void) {
1332 if(count++==0) {
1333 if(vgroup_mcc=MUI_CreateCustomClass(NULL,MUIC_Virtgroup,NULL,sizeof(VGroupData),(APTR)&vgDispatcher)) {
1334 if(docscroll_mcc=MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(DocScrollData),(APTR)&dsDispatcher))
1335 return TRUE;
1336 MUI_DeleteCustomClass(vgroup_mcc);
1338 count=0;
1339 return FALSE;
1341 return TRUE;
1344 BOOL deleteDocScrollClass(void) {
1345 if(count && --count==0) {
1346 MUI_DeleteCustomClass(docscroll_mcc);
1347 MUI_DeleteCustomClass(vgroup_mcc);
1349 return TRUE;