Fix for a crash which happened when a document couldn't be opened.
[AROS-Contrib.git] / vpdf / mcc / documentview_class.c
blobd5d629ffcc88c8ed52f7c5fc23a2d754fa407adb
1 #if defined(__AROS__)
2 #define MUIMASTER_YES_INLINE_STDARG
3 #include <clib/arossupport_protos.h>
4 #endif
6 #define SYSTEM_PRIVATE 1
8 /// System includes
9 #define AROS_ALMOST_COMPATIBLE
10 #include <proto/muimaster.h>
11 #include <libraries/mui.h>
13 #include <libraries/asl.h>
15 #if !defined(__AROS__)
16 #include <libraries/charsets.h>
17 #endif
19 #include <libraries/locale.h>
20 #include <workbench/workbench.h>
22 #include <proto/exec.h>
23 #include <intuition/intuition.h>
24 #include <graphics/gfx.h>
25 #include <exec/libraries.h>
26 #include <exec/lists.h>
27 #include <proto/graphics.h>
28 #include <proto/intuition.h>
29 #include <proto/icon.h>
30 #include <dos/dos.h>
31 #include <proto/dos.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <math.h>
37 #include <time.h>
39 #include <proto/alib.h>
40 #include <proto/utility.h>
42 #include <proto/dtclass.h>
43 #include <datatypes/pictureclass.h>
44 #include <devices/rawkeycodes.h>
46 #include <libraries/gadtools.h>
48 #if defined(__MORPHOS__)
49 #include <emul/emulregs.h>
50 #include <emul/emulinterface.h>
51 #endif
52 ////
54 #include <private/vapor/vapor.h>
55 #include "util.h"
56 #include "poppler.h"
57 #include "pageview_class.h"
58 #include "documentview_class.h"
59 #include "outlineview_class.h"
60 #include "documentlayout_class.h"
61 #include "thumbnaillist_class.h"
62 #include "renderer_class.h"
63 #include "search_class.h"
64 #include "annotation_class.h"
65 #include "toolbar_class.h"
66 #include "clipboard.h"
68 #include "system/chunky.h"
69 #include "system/gentexture.h"
70 #include "../locale.h"
72 struct Data
74 void *doc;
75 Object *layoutgroup;
76 Object *renderer;
77 Object *sldPage;
78 Object *grpDisplay;
79 Object *grpSearch;
80 Object *grpToolbar;
81 Object *grpOutline;
82 int dragaction;
83 int layoutmode;
84 int renderpriority;
85 char *filename;
86 int rotation;
87 struct MinList **annotationLists; // annotations are loaded on demand
88 struct MUI_EventHandlerNode eh;
92 #define D(x) x
93 #define gFalse 0
94 #define ANNOTLIST_INVALID 0
95 #define ANNOTLIST_EMPTY ((void*)-1)
97 #define ANNOTFLAG_ATTACHED 1
99 static char *outlinenames[] = {"Tree", "Thumbnails", NULL};
101 static Object *buildlayoutobject(int layoutmode, struct Data *data)
103 switch(layoutmode)
105 case MUIV_DocumentView_Layout_Single:
106 return SinglePageLayoutObject,
107 MUIA_DocumentLayout_PDFDocument, data->doc,
108 MUIA_DocumentLayout_Columns, 1,
109 MUIA_DocumentLayout_Rotation, data->rotation,
110 End;
112 case MUIV_DocumentView_Layout_ContinuousSingle:
113 return ContinuousLayoutObject,
114 MUIA_DocumentLayout_PDFDocument, data->doc,
115 MUIA_DocumentLayout_Columns, 1,
116 MUIA_DocumentLayout_Rotation, data->rotation,
117 End;
119 case MUIV_DocumentView_Layout_Facing:
120 return SinglePageLayoutObject,
121 MUIA_DocumentLayout_PDFDocument, data->doc,
122 MUIA_DocumentLayout_Columns, 2,
123 MUIA_DocumentLayout_Rotation, data->rotation,
124 End;
126 case MUIV_DocumentView_Layout_ContinuousFacing:
127 return ContinuousLayoutObject,
128 MUIA_DocumentLayout_PDFDocument, data->doc,
129 MUIA_DocumentLayout_Columns, 2,
130 MUIA_DocumentLayout_Rotation, data->rotation,
131 End;
132 break;
135 return NULL; /* let it hit! */
138 DEFNEW
140 Object *sldPage, *grpOutlines, *grpOutlinesTitles, *grpToolbar;
141 Object *grpDisplay, *grpOutlineTree, *grpNavigation, *balBalance, *grpSearch, *grpOutlineThumbs;
143 obj = DoSuperNew(cl, obj,
144 MUIA_Group_Horiz, FALSE,
145 Child, HGroup,
146 Child, grpDisplay = VGroup, End,
147 Child, balBalance = BalanceObject, End,
148 Child, grpOutlines = VGroup,
149 MUIA_ShowMe, GetTagData(MUIA_DocumentView_Outline, TRUE, INITTAGS),
150 MUIA_Group_PageMode, TRUE,
151 MUIA_Frame, MUIV_Frame_Group,
152 MUIA_Weight, 30,
153 Child, grpOutlinesTitles = MUI_NewObject(MUIC_Title,
154 TAG_DONE),
155 End,
156 End,
157 Child, HGroup,
158 Child, grpNavigation = HGroup,
159 Child, sldPage = SliderObject,
160 MUIA_Slider_Level, 1,
161 MUIA_Numeric_Default, 1,
162 MUIA_Slider_Min,1,
163 MUIA_Slider_Max,100,
164 MUIA_Weight,200,
165 MUIA_Numeric_Format, LOCSTR( MSG_SLIDER_PAGE ),
166 MUIA_CycleChain, TRUE,
167 End,
168 Child, HSpace(5),
169 Child, grpSearch = SearchObject,
170 End,
171 End,
172 End,
173 Child, grpToolbar = ToolbarObject,
174 MUIA_DocumentView_Outline, GetTagData(MUIA_DocumentView_Outline, TRUE, INITTAGS),
175 End,
177 TAG_MORE, INITTAGS);
179 if (obj != NULL)
181 GETDATA;
182 int outlinenum = 0;
183 int i;
185 data->dragaction = MUIV_DocumentView_DragAction_Scroll;
186 data->rotation = MUIV_DocumentLayout_Rotation_None;
187 data->filename = strdup((char*)GetTagData(MUIA_DocumentView_FileName, NULL, INITTAGS));
188 data->renderer = (Object*)GetTagData(MUIA_DocumentView_Renderer, NULL, INITTAGS);
189 data->doc = pdfNew(data->filename);
190 data->layoutmode = GetTagData(MUIA_DocumentView_Layout, MUIV_DocumentView_Layout_Single, INITTAGS);
191 data->renderpriority = GetTagData(MUIA_DocumentView_RenderPriority, MUIV_Renderer_Enqueue_Priority_Normal, INITTAGS);
193 data->sldPage = sldPage;
194 data->grpDisplay = grpDisplay;
195 data->grpToolbar = grpToolbar;
197 if (data->doc == NULL)
199 CoerceMethod(cl, obj, OM_DISPOSE);
200 return 0;
203 data->annotationLists = calloc(pdfGetPagesNum(data->doc), sizeof(struct MinList*));
204 for(i=pdfGetPagesNum(data->doc)-1; i>=0; i--)
205 data->annotationLists[i] = ANNOTLIST_INVALID;
208 /* setup search group */
210 set(grpSearch, MUIA_Search_DocumentView, obj);
212 /* setup pages slider */
214 set(sldPage, MUIA_Slider_Max, pdfGetPagesNum(data->doc));
215 data->layoutgroup = buildlayoutobject(data->layoutmode, data);
216 if (data->layoutgroup != NULL)
218 int scaling = GetTagData(MUIA_DocumentLayout_Scaling, MUIV_DocumentLayout_Scaling_FitPage, INITTAGS);
219 if (scaling == MUIV_DocumentLayout_Scaling_None)
220 scaling = MUIV_DocumentLayout_Scaling_Zoom;
222 set(data->layoutgroup, MUIA_DocumentLayout_Scaling, scaling);
225 DoMethod(grpDisplay, OM_ADDMEMBER, ScrollgroupObject, MUIA_Scrollgroup_Contents, data->layoutgroup, End);
228 Object *outline = OutlineViewObject,
229 MUIA_OutlineView_Document, data->doc,
230 End;
232 if (xget(outline, MUIA_OutlineView_IsEmpty) == FALSE)
234 DoMethod(grpOutlines, OM_ADDMEMBER, outline);
235 DoMethod(grpOutlinesTitles, OM_ADDMEMBER, TextObject, MUIA_Text_Contents, "Tree", End);
236 outlinenum++;
238 else
240 MUI_DisposeObject(outline);
241 outline = NULL;
244 data->grpOutline = grpOutlines;
248 Object *thumbnails = ThumbnailListObject,
249 MUIA_ThumbnailList_PDFDocument, data->doc,
250 MUIA_ThumbnailList_Renderer, data->renderer,
251 End;
253 DoMethod(grpOutlines, OM_ADDMEMBER, thumbnails);
254 if (outlinenum > 0)
255 DoMethod(grpOutlinesTitles, OM_ADDMEMBER, TextObject, MUIA_Text_Contents, "Thumbnails", End);
257 outlinenum++;
260 if (outlinenum == 1)
262 DoMethod(grpOutlines, OM_REMMEMBER, grpOutlinesTitles);
263 MUI_DisposeObject(grpOutlinesTitles);
266 /* attach toolbar to the document view */
268 set(grpToolbar, MUIA_Toolbar_DocumentView, obj);
270 /* */
272 DoMethod(grpOutlines, MUIM_Notify, MUIA_OutlineView_Page, MUIV_EveryTime, sldPage, 3, MUIM_Set, MUIA_Slider_Level, MUIV_TriggerValue);
274 DoMethod(sldPage, MUIM_Notify, MUIA_Slider_Level, MUIV_EveryTime, obj, 3, MUIM_Set, MUIA_DocumentView_Page, MUIV_TriggerValue);
275 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_DocumentLayout_Page, MUIV_EveryTime, sldPage, 3, MUIM_NoNotifySet, MUIA_Slider_Level, MUIV_TriggerValue);
276 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_DocumentLayout_Page, MUIV_EveryTime, obj, 2, MUIM_DocumentView_UpdateAnnotations, MUIV_TriggerValue);
278 /* NOTE: this will add notification for all child objects!! todo: rework so no time/memory is wasted! */
279 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_NeedRefresh, MUIV_EveryTime, obj, 2, MUIM_DocumentView_EnqueueRender, MUIV_TriggerValue);
280 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_RedirectPage, MUIV_EveryTime, obj, 3, MUIM_Set, MUIA_DocumentView_Page, MUIV_TriggerValue);
281 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_RedirectPage, MUIV_EveryTime, data->sldPage, 3, MUIM_NoNotifySet, MUIA_Slider_Level, MUIV_TriggerValue);
285 return (ULONG)obj;
288 DEFDISP
290 GETDATA;
292 if (data->doc != NULL)
293 pdfDelete(data->doc);
295 if (data->filename != NULL)
296 free(data->filename);
298 return DOSUPER;
301 DEFSET
303 GETDATA;
305 FORTAG(INITTAGS)
307 case MUIA_DocumentView_Page:
309 int page = tag->ti_Data;
310 SetAttrs(data->layoutgroup, MUIA_Group_Forward, FALSE, MUIA_DocumentLayout_Page, page, TAG_DONE);
311 break;
314 case MUIA_DocumentView_Layout:
315 DoMethod(obj, MUIM_DocumentView_Layout, tag->ti_Data); /* this will set layoutmode */
316 break;
318 case MUIA_DocumentView_Outline:
319 if (data->grpOutline != NULL)
320 set(data->grpOutline, MUIA_ShowMe, tag->ti_Data);
321 break;
323 case MUIA_DocumentView_DragAction:
324 data->dragaction = tag->ti_Data;
325 break;
329 NEXTTAG
331 return DOSUPER;
334 DEFGET
336 GETDATA;
338 switch (msg->opg_AttrID)
340 case MUIA_DocumentLayout_Zoom:
341 *(ULONG*)msg->opg_Storage = xget(data->layoutgroup, msg->opg_AttrID);
342 return TRUE;
344 case MUIA_DocumentView_PDFDocument:
345 *(ULONG*)msg->opg_Storage = (ULONG)data->doc;
346 return TRUE;
348 case MUIA_DocumentView_Page:
349 *(ULONG*)msg->opg_Storage = (ULONG)xget(data->sldPage, MUIA_Slider_Level);
350 return TRUE;
352 case MUIA_DocumentView_Layout:
353 *(ULONG*)msg->opg_Storage = (ULONG)data->layoutmode;
354 return TRUE;
356 case MUIA_DocumentView_FileName:
357 *(ULONG*)msg->opg_Storage = (ULONG)data->filename;
358 return TRUE;
360 case MUIA_DocumentView_DragAction:
361 *(ULONG*)msg->opg_Storage = (ULONG)data->dragaction;
362 return TRUE;
365 return(DOSUPER);
368 DEFMMETHOD(Setup)
370 GETDATA;
372 data->eh.ehn_Object = obj;
373 data->eh.ehn_Class = cl;
374 data->eh.ehn_Events = IDCMP_RAWKEY;
375 data->eh.ehn_Priority = 100;
376 data->eh.ehn_Flags = MUI_EHF_GUIMODE;
377 DoMethod(_win(obj), MUIM_Window_AddEventHandler, &data->eh);
379 return DOSUPER;
382 DEFMMETHOD(Cleanup)
384 GETDATA;
386 /* remove all pending pages from renderer */
387 D(kprintf("cleanup renderer for view %p\n", data->layoutgroup));
388 DoMethod(data->renderer, MUIM_Renderer_Remove, MUIV_Renderer_Remove_All, data->layoutgroup);
389 D(kprintf(" ..cleanup done\n"));
391 if (data->eh.ehn_Object != NULL)
393 DoMethod(_win(obj), MUIM_Window_RemEventHandler, &data->eh);
394 data->eh.ehn_Object = NULL;
397 return DOSUPER;
402 DEFMMETHOD(DocumentView_EnqueueRender)
404 GETDATA;
405 //kprintf("enqueue with high priority:%d\n", msg->page);
406 DoMethod(data->renderer, MUIM_Renderer_Enqueue, msg->page, data->layoutgroup, data->renderpriority);
408 // rerendered so probably annotations have to be reprocessed. optimize this pass..
409 DoMethod(_app(obj), MUIM_Application_PushMethod, obj,2, MUIM_DocumentView_UpdateAnnotations, msg->page);
412 return 0;
415 DEFMMETHOD(DocumentView_Layout)
417 GETDATA;
418 Object *grpDisplayChild;
419 ULONG zoom = xget(data->layoutgroup, MUIA_DocumentLayout_Zoom);
420 ULONG scaling = xget(data->layoutgroup, MUIA_DocumentLayout_Scaling);
421 LONG page = xget(data->layoutgroup, MUIA_DocumentLayout_Page);
422 LONG pagenum;
424 D(kprintf("cleanup renderer for view %p\n", data->layoutgroup));
425 DoMethod(data->renderer, MUIM_Renderer_Remove, MUIV_Renderer_Remove_All, data->layoutgroup);
426 D(kprintf(" ..cleanup done\n"));
428 grpDisplayChild = (Object*)DoMethod(data->grpDisplay, MUIM_Family_GetChild, MUIV_Family_GetChild_First);
429 DoMethod(data->grpDisplay, MUIM_Group_InitChange);
430 DoMethod(data->grpDisplay, MUIM_Group_Remove, grpDisplayChild);
431 MUI_DisposeObject(grpDisplayChild);
433 /* disposing layout object disposed all annotation objects which are currently attached to pages. mark them as invalid */
435 for(pagenum=1; pagenum<=pdfGetPagesNum(data->doc); pagenum++)
437 struct MinList *l = data->annotationLists[pagenum - 1];
438 if (l != ANNOTLIST_INVALID && l != ANNOTLIST_EMPTY)
440 struct pdfAnnotation *an;
441 ITERATELIST(an, l)
443 an->obj = NULL;
448 data->layoutmode = msg->layout;
449 data->layoutgroup = buildlayoutobject(msg->layout, data);
450 SetAttrs(data->layoutgroup, MUIA_DocumentLayout_Zoom, zoom, MUIA_DocumentLayout_Scaling, scaling, TAG_DONE);
452 DoMethod(data->grpDisplay, OM_ADDMEMBER, ScrollgroupObject, MUIA_Scrollgroup_Contents, data->layoutgroup, End);
453 DoMethod(data->grpDisplay, MUIM_Group_ExitChange);
455 /* NOTE: using pushmethod ensures that object will be properly layed out and focusing on page will work properly. investigate in mui! */
456 #warning investigate!
457 DoMethod(_app(obj), MUIM_Application_PushMethod, data->layoutgroup, 3, MUIM_Set, MUIA_DocumentLayout_Page, page);
458 //set(data->layoutgroup, MUIA_DocumentLayout_Page, page);
460 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_DocumentLayout_Page, MUIV_EveryTime, data->sldPage, 3, MUIM_NoNotifySet, MUIA_Slider_Level, MUIV_TriggerValue);
461 /* NOTE: this will add notification for all child objects!! todo: rework so no time/memory is wasted! */
462 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_NeedRefresh, MUIV_EveryTime, obj, 2, MUIM_DocumentView_EnqueueRender, MUIV_TriggerValue);
463 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_RedirectPage, MUIV_EveryTime, obj, 3, MUIM_Set, MUIA_DocumentView_Page, MUIV_TriggerValue);
464 DoMethod(data->layoutgroup, MUIM_Notify, MUIA_PageView_RedirectPage, MUIV_EveryTime, data->sldPage, 3, MUIM_NoNotifySet, MUIA_Slider_Level, MUIV_TriggerValue);
466 return 0;
469 DEFMMETHOD(DocumentView_FindViewForPage)
471 GETDATA;
472 return DoMethod(data->layoutgroup, MUIM_DocumentLayout_FindViewForPage, msg->page);
475 DEFMMETHOD(HandleEvent)
478 GETDATA;
479 int rc = 0;
481 if (msg->imsg != NULL)
483 switch (msg->imsg->Class)
485 case IDCMP_RAWKEY:
486 if (msg->imsg->Code == RAWKEY_SPACE)
488 set(data->sldPage, MUIA_Slider_Level, xget(data->sldPage, MUIA_Slider_Level) + 1);
489 rc = MUI_EventHandlerRC_Eat;
491 else if (msg->imsg->Code == RAWKEY_BACKSPACE)
493 set(data->sldPage, MUIA_Slider_Level, xget(data->sldPage, MUIA_Slider_Level) - 1);
494 rc = MUI_EventHandlerRC_Eat;
496 break;
501 return rc;
505 DEFMMETHOD(DocumentView_RotateLeft)
507 GETDATA;
508 data->rotation = data->rotation == MUIV_PageView_Rotation_None ? MUIV_PageView_Rotation_270 : data->rotation - 1;
509 SetAttrs(data->layoutgroup, MUIA_DocumentLayout_Rotation, data->rotation, TAG_DONE);
510 return TRUE;
513 DEFMMETHOD(DocumentView_RotateRight)
515 GETDATA;
516 data->rotation = data->rotation == MUIV_PageView_Rotation_270 ? MUIV_PageView_Rotation_None : data->rotation + 1;
517 SetAttrs(data->layoutgroup, MUIA_DocumentLayout_Rotation, data->rotation, TAG_DONE);
518 return TRUE;
521 DEFMMETHOD(DocumentView_UpdateAnnotations)
523 GETDATA;
524 int refpagenum = msg->page;
525 int pagenum;
526 int first = -1;
527 int last;
528 int modified = FALSE;
530 /* for each visible page around the reference one we display annotations objects */
532 for(first = refpagenum; first > 1 && DoMethod(data->layoutgroup, MUIM_DocumentLayout_IsPageVisible, first - 1); first--) {}
533 for(last = first; last < pdfGetPagesNum(data->doc) && DoMethod(data->layoutgroup, MUIM_DocumentLayout_IsPageVisible, last + 1); last++) {}
535 //printf("process annotations...:%d:%d-%d\n", refpagenum, first, last);
537 for(pagenum=first; pagenum<=last; pagenum++)
539 struct MinList *l = data->annotationLists[pagenum - 1];
540 if (l == ANNOTLIST_INVALID)
542 struct MinList *annotList;
544 //printf("fetch annotations for page %d\n", pagenum);
545 annotList = pdfGetAnnotations(data->doc, pagenum);
546 if (annotList == NULL)
547 annotList = ANNOTLIST_EMPTY;
549 data->annotationLists[pagenum - 1] = annotList;
554 for(pagenum = pdfGetPagesNum(data->doc); pagenum >= 1; pagenum--)
556 struct MinList *l = data->annotationLists[pagenum-1];
557 if (l != ANNOTLIST_EMPTY && l != ANNOTLIST_INVALID)
559 struct pdfAnnotation *an;
560 Object *pageview = (Object*)DoMethod(data->layoutgroup, MUIM_DocumentLayout_FindViewForPage, pagenum);
562 if (pagenum < first || pagenum> last)
564 ITERATELIST(an, l)
566 if (an->obj != NULL)
568 //printf(" remove annotation from page %d\n", pagenum);
569 if (!modified)
570 DoMethod(data->layoutgroup, MUIM_Group_InitChange);
571 modified = TRUE;
573 DoMethod(data->layoutgroup, MUIM_Family_Remove, an->obj);
574 DoMethod(pageview, MUIM_PageView_RemoveAnnotation, an->obj);
575 MUI_DisposeObject(an->obj);
576 an->obj = NULL;
580 else
582 ITERATELIST(an, l)
584 if (an->obj == NULL)
586 float coords[4];
587 //printf(" new annotation for page %d\n", pagenum);
588 if (!modified)
589 DoMethod(data->layoutgroup, MUIM_Group_InitChange);
590 modified = TRUE;
592 an->obj = AnnotationObject,
593 MUIA_Annotation_Contents, an->contents,
594 MUIA_Annotation_RefObject, pageview,
595 End;
596 DoMethod(data->layoutgroup, MUIM_Family_AddTail, an->obj);
597 coords[0] = an->x1;
598 coords[1] = an->y1;
599 coords[2] = an->x2;
600 coords[3] = an->y2;
601 DoMethod(pageview, MUIM_PageView_AddAnnotation, an->obj, coords);
608 if (modified)
609 DoMethod(data->layoutgroup, MUIM_Group_ExitChange);
611 return TRUE;
614 DEFMMETHOD(DocumentView_ClearSelection)
616 GETDATA;
617 int pagenum;
619 for(pagenum=1; pagenum<=pdfGetPagesNum(data->doc); pagenum++)
621 Object *pageview = (Object*)DoMethod(data->layoutgroup, MUIM_DocumentLayout_FindViewForPage, pagenum);
622 if (pageview != NULL)
624 DoMethod(pageview, MUIM_PageView_ClearSelection);
629 return TRUE;
632 DEFMMETHOD(DocumentView_SelectionCopy)
634 GETDATA;
635 int pagenum;
637 for(pagenum=1; pagenum<=pdfGetPagesNum(data->doc); pagenum++)
640 Object *pageview = (Object*)DoMethod(data->layoutgroup, MUIM_DocumentLayout_FindViewForPage, pagenum);
641 if (pageview != NULL)
643 struct MUIP_PageView_GetSelection msg;
644 msg.MethodID = MUIM_PageView_GetSelection;
645 if (DoMethodA(pageview, &msg))
647 struct pdfSelectionText *selection = pdfBuildTextForSelection(data->doc, pagenum, msg.region.x1, msg.region.y1, msg.region.x2, msg.region.y2);
648 if (selection != NULL)
650 clipboard_write_text(selection->utf8, CODESET_UTF8);
651 pdfDisposeTextForSelection(data->doc, selection);
653 return TRUE;
659 return FALSE;
662 BEGINMTABLE
663 DECNEW
664 DECSET
665 DECGET
666 DECDISP
667 DECMMETHOD(Cleanup)
668 DECMMETHOD(Setup)
669 DECMMETHOD(HandleEvent)
670 DECMMETHOD(DocumentView_EnqueueRender)
671 DECMMETHOD(DocumentView_Layout)
672 DECMMETHOD(DocumentView_FindViewForPage)
673 DECMMETHOD(DocumentView_RotateRight)
674 DECMMETHOD(DocumentView_RotateLeft)
675 DECMMETHOD(DocumentView_UpdateAnnotations)
676 DECMMETHOD(DocumentView_ClearSelection)
677 DECMMETHOD(DocumentView_SelectionCopy)
679 ENDMTABLE
681 DECSUBCLASS_NC(MUIC_Group, DocumentViewClass)