Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / utilities / MultiView / main.c
blobe965e6a7dbb91f9e860e2b7683ffab7c5c68c923
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*********************************************************************************************/
8 #include "global.h"
10 #include <stdlib.h> /* for exit() */
11 #include <stdio.h>
12 #include <string.h>
14 #include "compilerspecific.h"
15 #include "debug.h"
16 #include "arossupport.h"
18 extern struct NewMenu nm[];
19 extern struct NewMenu nmpict[];
20 extern struct NewMenu nmtext[];
22 /*********************************************************************************************/
24 /* Many datatype classes seem to rely on OM_NOTIFY calls coming back to the datatype object
25 as OM_UPDATE :-\ */
27 #define BACK_CONNECTION 1
29 /*********************************************************************************************/
31 #define ARG_TEMPLATE "FILE,CLIPBOARD/S,CLIPUNIT/K/N,SCREEN/S,PUBSCREEN/K,REQUESTER/S," \
32 "BOOKMARK/S,FONTNAME/K,FONTSIZE/K/N,BACKDROP/S,WINDOW/S," \
33 "PORTNAME/K,IMMEDIATE/S,REPEAT/S,PRTUNIT/K/N"
35 #define ARG_FILE 0
36 #define ARG_CLIPBOARD 1
37 #define ARG_CLIPUNIT 2
38 #define ARG_SCREEN 3
39 #define ARG_PUBSCREEN 4
40 #define ARG_REQUESTER 5
41 #define ARG_BOOKMARK 6
42 #define ARG_FONTNAME 7
43 #define ARG_FONTSIZE 8
44 #define ARG_BACKDROP 9
45 #define ARG_WINDOW 10
46 #define ARG_PORTNAME 11
47 #define ARG_IMMEDIATE 12
48 #define ARG_REPEAT 13
49 #define ARG_PRTUNIT 14
51 #define NUM_ARGS 15
53 /*********************************************************************************************/
55 static struct libinfo
57 APTR var;
58 STRPTR name;
59 WORD version;
60 } libtable[] =
62 {&IntuitionBase , "intuition.library" , 39 },
63 {&GfxBase , "graphics.library" , 39 },
64 {&GadToolsBase , "gadtools.library" , 39 },
65 {&LayersBase , "layers.library" , 39 },
66 {&UtilityBase , "utility.library" , 39 },
67 {&KeymapBase , "keymap.library" , 39 },
68 {&DataTypesBase , "datatypes.library" , 39 },
69 {&DiskfontBase , "diskfont.library" , 39 },
70 {NULL }
73 static struct TextAttr textattr;
74 static struct TextFont *font;
75 static struct RDArgs *myargs;
76 static IPTR args[NUM_ARGS];
77 static UBYTE fontname[256];
78 static WORD winwidth, winheight;
79 static WORD sizeimagewidth, sizeimageheight;
80 static BOOL model_has_members;
82 /*********************************************************************************************/
84 static void CloseLibs(void);
85 static void KillFont(void);
86 static void FreeArguments(void);
87 static void KillICObjects(void);
88 static void FreeVisual(void);
89 static void KillGadgets(void);
90 static void CloseDTO(void);
91 static void KillWindow(void);
92 static void ScrollTo(UWORD dir, UWORD quali);
93 static void FitToWindow(void);
95 /*********************************************************************************************/
97 void OutputMessage(CONST_STRPTR msg)
99 struct EasyStruct es;
101 if (msg)
103 if ( IntuitionBase && !((struct Process *)FindTask(NULL))->pr_CLI )
105 es.es_StructSize = sizeof(es);
106 es.es_Flags = 0;
107 es.es_Title = "MultiView";
108 es.es_TextFormat = msg;
109 es.es_GadgetFormat = MSG(MSG_OK);
111 EasyRequestArgs(win, &es, NULL, NULL);
113 else
115 printf("MultiView: %s\n", msg);
120 /*********************************************************************************************/
122 void Cleanup(CONST_STRPTR msg)
124 OutputMessage(msg);
126 KillWindow();
127 KillMenus();
128 KillGadgets();
129 FreeVisual();
130 CloseDTO();
131 KillICObjects();
132 KillFont();
133 FreeArguments();
135 if (cd != NULL) CurrentDir(cd); /* restore current directory */
137 CloseLibs();
138 CleanupLocale();
140 exit(prog_exitcode);
144 /*********************************************************************************************/
146 static void OpenLibs(void)
148 struct libinfo *li;
150 for(li = libtable; li->var; li++)
152 if (!((*(struct Library **)li->var) = OpenLibrary(li->name, li->version)))
154 sprintf(s, MSG(MSG_CANT_OPEN_LIB), li->name, li->version);
155 Cleanup(s);
161 /*********************************************************************************************/
163 static void CloseLibs(void)
165 struct libinfo *li;
167 for(li = libtable; li->var; li++)
169 if (*(struct Library **)li->var) CloseLibrary((*(struct Library **)li->var));
173 /*********************************************************************************************/
175 static void LoadFont(void)
177 font = OpenDiskFont(&textattr);
178 if (!font)
180 textattr.ta_Name = "topaz.font";
181 textattr.ta_YSize = 8;
182 textattr.ta_Style = 0;
183 textattr.ta_Flags = 0;
185 font = OpenFont(&textattr);
189 /*********************************************************************************************/
191 static void KillFont(void)
193 if (font) CloseFont(font);
196 /*********************************************************************************************/
198 static void InitDefaults(void)
200 struct TextFont *defaultfont = GfxBase->DefaultFont;
202 /* This might be a bit problematic depending on how default system font
203 switching through Font prefs program works and if then the previous
204 default system font is closed or not. So this is very likely only safe
205 when in such a case the previous font is not closed (means -> the font
206 will remain in memory in any case)
208 ClipView example program on Amiga Dev CD also does it like this. So ... */
210 textattr.ta_Name = defaultfont->tf_Message.mn_Node.ln_Name;
211 textattr.ta_YSize = defaultfont->tf_YSize;
212 textattr.ta_Style = defaultfont->tf_Style;
213 textattr.ta_Flags = defaultfont->tf_Flags;
216 /*********************************************************************************************/
218 static void GetArguments(void)
221 if (!(myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
223 Fault(IoErr(), 0, s, 256);
224 Cleanup(s);
227 filename = (STRPTR)args[ARG_FILE];
228 if (!filename && !args[ARG_CLIPBOARD])
230 filename = GetFileName(MSG_ASL_OPEN_TITLE);
231 if (!filename) Cleanup(NULL);
234 if (args[ARG_FONTNAME])
236 strncpy(fontname, (char *)args[ARG_FONTNAME], 255 - 5);
237 if (!strstr(fontname, ".font")) strcat(fontname, ".font");
239 textattr.ta_Name = fontname;
242 if (args[ARG_FONTSIZE])
244 textattr.ta_YSize = *(LONG *)args[ARG_FONTSIZE];
249 /*********************************************************************************************/
251 static void FreeArguments(void)
253 if (myargs) FreeArgs(myargs);
256 /*********************************************************************************************/
258 static void MakeICObjects(void)
260 static const struct TagItem dto_to_vert_map[] =
262 {DTA_TopVert , PGA_Top },
263 {DTA_VisibleVert , PGA_Visible },
264 {DTA_TotalVert , PGA_Total },
265 {TAG_DONE }
267 static const struct TagItem dto_to_horiz_map[] =
269 {DTA_TopHoriz , PGA_Top },
270 {DTA_VisibleHoriz , PGA_Visible },
271 {DTA_TotalHoriz , PGA_Total },
272 {TAG_DONE }
274 static const struct TagItem vert_to_dto_map[] =
276 {PGA_Top , DTA_TopVert },
277 {TAG_DONE }
279 static const struct TagItem horiz_to_dto_map[] =
281 {PGA_Top , DTA_TopHoriz },
282 {TAG_DONE }
285 model_obj = NewObject(NULL, MODELCLASS, ICA_TARGET, ICTARGET_IDCMP,
286 TAG_DONE);
287 dto_to_vert_ic_obj = NewObject(NULL, ICCLASS, ICA_MAP, (IPTR)dto_to_vert_map,
288 TAG_DONE);
289 dto_to_horiz_ic_obj = NewObject(NULL, ICCLASS, ICA_MAP, (IPTR)dto_to_horiz_map,
290 TAG_DONE);
291 vert_to_dto_ic_obj = NewObject(NULL, ICCLASS, ICA_MAP, (IPTR)vert_to_dto_map,
292 TAG_DONE);
293 horiz_to_dto_ic_obj = NewObject(NULL, ICCLASS, ICA_MAP, (IPTR)horiz_to_dto_map,
294 TAG_DONE);
295 #if BACK_CONNECTION
296 model_to_dto_ic_obj = NewObject(NULL, ICCLASS, TAG_DONE);
297 #endif
299 if (!model_obj ||
300 !dto_to_vert_ic_obj ||
301 !dto_to_horiz_ic_obj ||
302 !vert_to_dto_ic_obj ||
303 !horiz_to_dto_ic_obj
304 #if BACK_CONNECTION
305 || !model_to_dto_ic_obj
306 #endif
309 Cleanup(MSG(MSG_CANT_CREATE_IC));
312 DoMethod(model_obj, OM_ADDMEMBER, (IPTR) dto_to_vert_ic_obj);
313 DoMethod(model_obj, OM_ADDMEMBER, (IPTR) dto_to_horiz_ic_obj);
314 #if BACK_CONNECTION
315 DoMethod(model_obj, OM_ADDMEMBER, (IPTR) model_to_dto_ic_obj);
316 #endif
318 model_has_members = TRUE;
322 /*********************************************************************************************/
324 static void KillICObjects(void)
326 if (!model_has_members)
328 if (dto_to_vert_ic_obj) DisposeObject(dto_to_vert_ic_obj);
329 if (dto_to_horiz_ic_obj) DisposeObject(dto_to_horiz_ic_obj);
330 #if BACK_CONNECTION
331 if (model_to_dto_ic_obj) DisposeObject(model_to_dto_ic_obj);
332 #endif
335 if (model_obj) DisposeObject(model_obj);
336 if (vert_to_dto_ic_obj) DisposeObject(vert_to_dto_ic_obj);
337 if (horiz_to_dto_ic_obj) DisposeObject(horiz_to_dto_ic_obj);
340 /*********************************************************************************************/
342 static void GetVisual(void)
344 scr = LockPubScreen(NULL);
345 if (!scr) Cleanup(MSG(MSG_CANT_LOCK_SCR));
347 dri = GetScreenDrawInfo(scr);
348 if (!dri) Cleanup(MSG(MSG_CANT_GET_DRI));
350 vi = GetVisualInfoA(scr, NULL);
351 if (!vi) Cleanup(MSG(MSG_CANT_GET_VI));
354 /*********************************************************************************************/
356 static void FreeVisual(void)
358 if (vi) FreeVisualInfo(vi);
359 if (dri) FreeScreenDrawInfo(scr, dri);
360 if (scr) UnlockPubScreen(NULL, scr);
363 /*********************************************************************************************/
365 static void MakeGadgets(void)
367 static WORD img2which[] =
369 UPIMAGE,
370 DOWNIMAGE,
371 LEFTIMAGE,
372 RIGHTIMAGE,
373 SIZEIMAGE
376 IPTR imagew[NUM_IMAGES], imageh[NUM_IMAGES];
377 WORD v_offset, h_offset, btop, i;
379 for(i = 0; i < NUM_IMAGES; i++)
381 img[i] = NewObject(NULL, SYSICLASS, SYSIA_DrawInfo , (IPTR)( dri ),
382 SYSIA_Which , (IPTR)( img2which[i] ),
383 TAG_DONE);
385 if (!img[i]) Cleanup(MSG(MSG_CANT_CREATE_SYSIMAGE));
387 GetAttr(IA_Width,(Object *)img[i],&imagew[i]);
388 GetAttr(IA_Height,(Object *)img[i],&imageh[i]);
391 sizeimagewidth = imagew[IMG_SIZE];
392 sizeimageheight = imageh[IMG_SIZE];
394 btop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;
396 v_offset = imagew[IMG_DOWNARROW] / 4;
397 h_offset = imageh[IMG_LEFTARROW] / 4;
399 gad[GAD_UPARROW] = NewObject(NULL, BUTTONGCLASS,
400 GA_Image , (IPTR)( img[IMG_UPARROW] ),
401 GA_RelRight , (IPTR)( -imagew[IMG_UPARROW] + 1 ),
402 GA_RelBottom , (IPTR)( -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ),
403 GA_ID , (IPTR)( GAD_UPARROW ),
404 GA_RightBorder , (IPTR)TRUE,
405 GA_Immediate , (IPTR)TRUE,
406 GA_RelVerify , (IPTR)TRUE,
407 TAG_DONE);
409 gad[GAD_DOWNARROW] = NewObject(NULL, BUTTONGCLASS,
410 GA_Image , (IPTR)( img[IMG_DOWNARROW] ),
411 GA_RelRight , (IPTR)( -imagew[IMG_UPARROW] + 1 ),
412 GA_RelBottom , (IPTR)( -imageh[IMG_UPARROW] - imageh[IMG_SIZE] + 1 ),
413 GA_ID , (IPTR)( GAD_DOWNARROW ),
414 GA_RightBorder , (IPTR)TRUE,
415 GA_Previous , (IPTR)( gad[GAD_UPARROW] ),
416 GA_Immediate , (IPTR)TRUE,
417 GA_RelVerify , (IPTR)TRUE,
418 TAG_DONE);
420 gad[GAD_VERTSCROLL] = NewObject(NULL, PROPGCLASS,
421 GA_Top , (IPTR)( btop + 1 ),
422 GA_RelRight , (IPTR)( -imagew[IMG_DOWNARROW] + v_offset + 1 ),
423 GA_Width , (IPTR)( imagew[IMG_DOWNARROW] - v_offset * 2 ),
424 GA_RelHeight , (IPTR)( -imageh[IMG_DOWNARROW] - imageh[IMG_UPARROW] - imageh[IMG_SIZE] - btop -2 ),
425 GA_ID , (IPTR)( GAD_VERTSCROLL ),
426 GA_Previous , (IPTR)( gad[GAD_DOWNARROW] ),
427 GA_RightBorder , (IPTR)TRUE,
428 GA_RelVerify , (IPTR)TRUE,
429 GA_Immediate , (IPTR)TRUE,
430 PGA_NewLook , (IPTR)TRUE,
431 PGA_Borderless , (IPTR)TRUE,
432 PGA_Total , (IPTR)100,
433 PGA_Visible , (IPTR)100,
434 PGA_Freedom , (IPTR)FREEVERT,
435 PGA_NotifyBehaviour , (IPTR)PG_BEHAVIOUR_NICE,
436 TAG_DONE);
438 gad[GAD_RIGHTARROW] = NewObject(NULL, BUTTONGCLASS,
439 GA_Image , (IPTR)( img[IMG_RIGHTARROW] ),
440 GA_RelRight , (IPTR)( -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] + 1 ),
441 GA_RelBottom , (IPTR)( -imageh[IMG_RIGHTARROW] + 1 ),
442 GA_ID , (IPTR)( GAD_RIGHTARROW ),
443 GA_BottomBorder , (IPTR)TRUE,
444 GA_Previous , (IPTR)( gad[GAD_VERTSCROLL] ),
445 GA_Immediate , (IPTR)TRUE,
446 GA_RelVerify , (IPTR)TRUE,
447 TAG_DONE);
449 gad[GAD_LEFTARROW] = NewObject(NULL, BUTTONGCLASS,
450 GA_Image , (IPTR)( img[IMG_LEFTARROW] ),
451 GA_RelRight , (IPTR)( -imagew[IMG_SIZE] - imagew[IMG_RIGHTARROW] - imagew[IMG_LEFTARROW] + 1 ),
452 GA_RelBottom , (IPTR)( -imageh[IMG_RIGHTARROW] + 1 ),
453 GA_ID , (IPTR)( GAD_LEFTARROW ),
454 GA_BottomBorder , (IPTR)TRUE,
455 GA_Previous , (IPTR)( gad[GAD_RIGHTARROW] ),
456 GA_Immediate , (IPTR)TRUE,
457 GA_RelVerify , (IPTR)TRUE,
458 TAG_DONE);
460 gad[GAD_HORIZSCROLL] = NewObject(NULL, PROPGCLASS,
461 GA_Left , (IPTR)( scr->WBorLeft ),
462 GA_RelBottom , (IPTR)( -imageh[IMG_LEFTARROW] + h_offset + 1 ),
463 GA_RelWidth , (IPTR)( -imagew[IMG_LEFTARROW] - imagew[IMG_RIGHTARROW] - imagew[IMG_SIZE] - scr->WBorRight - 2 ),
464 GA_Height , (IPTR)( imageh[IMG_LEFTARROW] - (h_offset * 2) ),
465 GA_ID , (IPTR)( GAD_HORIZSCROLL ),
466 GA_Previous , (IPTR)( gad[GAD_LEFTARROW] ),
467 GA_BottomBorder , (IPTR)TRUE,
468 GA_RelVerify , (IPTR)TRUE,
469 GA_Immediate , (IPTR)TRUE,
470 PGA_NewLook , (IPTR)TRUE,
471 PGA_Borderless , (IPTR)TRUE,
472 PGA_Total , (IPTR)100,
473 PGA_Visible , (IPTR)100,
474 PGA_Freedom , (IPTR)FREEHORIZ,
475 PGA_NotifyBehaviour , (IPTR)PG_BEHAVIOUR_NICE,
476 TAG_DONE);
478 for(i = 0;i < NUM_GADGETS;i++)
480 if (!gad[i]) Cleanup(MSG(MSG_CANT_CREATE_GADGET));
483 SetAttrs(gad[GAD_VERTSCROLL] , ICA_TARGET, (IPTR)vert_to_dto_ic_obj, TAG_DONE);
484 SetAttrs(gad[GAD_HORIZSCROLL], ICA_TARGET, (IPTR)horiz_to_dto_ic_obj, TAG_DONE);
485 SetAttrs(dto_to_vert_ic_obj , ICA_TARGET, (IPTR)gad[GAD_VERTSCROLL], TAG_DONE);
486 SetAttrs(dto_to_horiz_ic_obj , ICA_TARGET, (IPTR)gad[GAD_HORIZSCROLL], TAG_DONE);
489 /*********************************************************************************************/
491 static void KillGadgets(void)
493 WORD i;
495 for(i = 0; i < NUM_GADGETS;i++)
497 if (win) RemoveGadget(win, (struct Gadget *)gad[i]);
498 if (gad[i]) DisposeObject(gad[i]);
499 gad[i] = 0;
502 for(i = 0; i < NUM_IMAGES;i++)
504 if (img[i]) DisposeObject(img[i]);
505 img[i] = NULL;
509 /*********************************************************************************************/
511 void AddDTOToWin(void)
513 EraseRect(win->RPort, win->BorderLeft,
514 win->BorderTop,
515 win->Width - 1 - win->BorderRight,
516 win->Height - 1 - win->BorderBottom);
518 SetDTAttrs (dto, NULL, NULL, GA_Left , win->BorderLeft + 2 ,
519 GA_Top , win->BorderTop + 2 ,
520 GA_RelWidth , - win->BorderLeft - win->BorderRight - 4 ,
521 GA_RelHeight , - win->BorderTop - win->BorderBottom - 4 ,
522 TAG_DONE);
524 AddDTObject(win, NULL, dto, -1);
525 // RefreshDTObjects(dto, win, NULL, NULL); needed ?
529 /*********************************************************************************************/
531 static void OpenDTO(void)
533 struct DTMethod *triggermethods;
534 ULONG *methods;
535 STRPTR objname = NULL;
536 IPTR val;
537 struct DataType *dt;
539 old_dto = dto;
543 if (!old_dto && args[ARG_CLIPBOARD])
545 APTR clipunit = 0;
547 if (args[ARG_CLIPUNIT]) clipunit = *(APTR *)args[ARG_CLIPUNIT];
549 D(bug("MultiView: calling NewDTObject\n"));
551 dto = NewDTObject(clipunit, ICA_TARGET , (IPTR)model_obj,
552 GA_ID , 1000 ,
553 DTA_SourceType, DTST_CLIPBOARD ,
554 DTA_TextAttr , (IPTR)&textattr,
555 TAG_DONE);
557 D(bug("MultiView: NewDTObject returned %x\n", dto));
559 else
561 dto = NewDTObject(filename, ICA_TARGET , (IPTR)model_obj,
562 GA_ID , 1000 ,
563 DTA_TextAttr , (IPTR)&textattr,
564 TAG_DONE);
567 if (!dto)
569 ULONG errnum = IoErr();
571 if (errnum == DTERROR_UNKNOWN_DATATYPE)
573 BPTR lock = Lock(filename,ACCESS_READ);
574 if (lock)
576 struct DataType *dtn;
577 if ((dtn = ObtainDataTypeA(DTST_FILE, lock, NULL)))
579 if (!Stricmp(dtn->dtn_Header->dth_Name, "directory"))
581 /* file is a directory and no directory.datatype is installed */
582 strncpy(filenamebuffer, (filename ? filename : (STRPTR)""), 298);
583 filenamebuffer[298]=0;
585 if (strlen(filenamebuffer) &&
586 filenamebuffer[strlen(filenamebuffer)-1] != ':' &&
587 filenamebuffer[strlen(filenamebuffer)-1] != '/')
589 strcat(filenamebuffer,"/");
592 filename = GetFileName(MSG_ASL_OPEN_TITLE);
593 if (filename) continue;
595 ReleaseDataType(dtn);
597 UnLock(lock);
601 if (errnum >= DTERROR_UNKNOWN_DATATYPE)
602 sprintf(s, GetDTString(errnum), filename);
603 else
604 Fault(errnum, 0, s, 256);
606 if (!old_dto) Cleanup(s);
607 dto = old_dto;
608 return;
610 } while (!dto);
612 strncpy(filenamebuffer, (filename ? filename : (STRPTR)""), 299);
614 SetAttrs(vert_to_dto_ic_obj, ICA_TARGET, (IPTR)dto, TAG_DONE);
615 SetAttrs(horiz_to_dto_ic_obj, ICA_TARGET, (IPTR)dto, TAG_DONE);
616 #if BACK_CONNECTION
617 SetAttrs(model_to_dto_ic_obj, ICA_TARGET, (IPTR)dto, TAG_DONE);
618 #endif
620 val = 0;
621 GetDTAttrs(dto, DTA_NominalHoriz, (IPTR)&val, TAG_DONE);
622 pdt_origwidth = winwidth = (WORD)val;
623 GetDTAttrs(dto, DTA_NominalVert , (IPTR)&val, TAG_DONE);
624 pdt_origheight = winheight = (WORD)val;
625 pdt_zoom = 1;
626 pdt_fit_win = FALSE;
627 pdt_keep_aspect = FALSE;
630 * Add 4 Pixels for border around DataType-Object
631 * See AddDTOToWin() for details
633 if(winwidth)
635 winwidth += 4;
638 if(winheight)
640 winheight += 4;
643 GetDTAttrs(dto, DTA_ObjName, (IPTR)&objname, TAG_DONE);
644 strncpy(objnamebuffer, objname ? objname : filenamebuffer, 299);
646 dt = NULL;
647 dto_subclass_gid = 0;
648 if (GetDTAttrs(dto, DTA_DataType, (IPTR)&dt, TAG_DONE))
650 if (dt)
652 dto_subclass_gid = dt->dtn_Header->dth_GroupID;
656 dto_supports_write = FALSE;
657 dto_supports_write_iff = FALSE;
658 dto_supports_print = FALSE;
659 dto_supports_copy = FALSE;
660 dto_supports_selectall = FALSE;
661 dto_supports_clearselected = FALSE;
663 if (DoWriteMethod(NULL, DTWM_RAW)) dto_supports_write = TRUE; /* probe raw saving */
664 if ((methods = GetDTMethods(dto)))
666 if (FindMethod(methods, DTM_WRITE)) dto_supports_write_iff = TRUE;
667 if (FindMethod(methods, DTM_PRINT)) dto_supports_print = TRUE;
668 if (FindMethod(methods, DTM_COPY)) dto_supports_copy = TRUE;
669 if (FindMethod(methods, DTM_SELECT)) dto_supports_selectall = TRUE;
670 if (FindMethod(methods, DTM_CLEARSELECTED)) dto_supports_clearselected = TRUE;
673 dto_supports_activate_field = FALSE;
674 dto_supports_next_field = FALSE;
675 dto_supports_prev_field = FALSE;
676 dto_supports_retrace = FALSE;
677 dto_supports_browse_next = FALSE;
678 dto_supports_browse_prev = FALSE;
679 dto_supports_search = FALSE;
680 dto_supports_search_next = FALSE;
681 dto_supports_search_prev = FALSE;
683 if ((triggermethods = (struct DTMethod *)GetDTTriggerMethods(dto)))
685 if (FindTriggerMethod(triggermethods, NULL, STM_ACTIVATE_FIELD)) dto_supports_activate_field = TRUE;
686 if (FindTriggerMethod(triggermethods, NULL, STM_NEXT_FIELD)) dto_supports_next_field = TRUE;
687 if (FindTriggerMethod(triggermethods, NULL, STM_PREV_FIELD)) dto_supports_prev_field = TRUE;
688 if (FindTriggerMethod(triggermethods, NULL, STM_RETRACE)) dto_supports_retrace = TRUE;
689 if (FindTriggerMethod(triggermethods, NULL, STM_BROWSE_NEXT)) dto_supports_browse_next = TRUE;
690 if (FindTriggerMethod(triggermethods, NULL, STM_BROWSE_PREV)) dto_supports_browse_prev = TRUE;
691 if (FindTriggerMethod(triggermethods, NULL, STM_SEARCH)) dto_supports_search = TRUE;
692 if (FindTriggerMethod(triggermethods, NULL, STM_SEARCH_NEXT)) dto_supports_search_next = TRUE;
693 if (FindTriggerMethod(triggermethods, NULL, STM_SEARCH_PREV)) dto_supports_search_prev = TRUE;
696 D(bug("\nMultiview: Found Methods:%s%s%s%s%s%s\n",
697 dto_supports_write ? " DTM_WRITE->RAW" : "",
698 dto_supports_write_iff ? " DTM_WRITE->IFF" : "",
699 dto_supports_print ? " DTM_PRINT" : "",
700 dto_supports_copy ? " DTM_COPY" : "",
701 dto_supports_selectall ? " DTM_SELECT" : "",
702 dto_supports_clearselected ? " DTM_CLEARSELECTED" : ""));
704 D(bug("Multiview: Found Triggers:%s%s%s%s%s%s%s\n\n",
705 dto_supports_activate_field ? " STM_ACTIVATE_FIELD" : "",
706 dto_supports_next_field ? " STM_NEXT_FIELD" : "",
707 dto_supports_prev_field ? " STM_PREV_FIELD" : "",
708 dto_supports_retrace ? " STM_RETRACE" : "",
709 dto_supports_browse_next ? " STM_BROWSE_NEXT" : "",
710 dto_supports_browse_prev ? " STM_BROWSE_PREV" : "",
711 dto_supports_search ? " STM_SEARCH" : "",
712 dto_supports_search_next ? " STM_SEARCH_NEXT" : "",
713 dto_supports_search_prev ? " STM_SEARCH_PREV" : ""));
715 if (old_dto)
717 if (win) RemoveDTObject(win, old_dto);
718 DisposeDTObject(old_dto);
720 if (win)
722 AddDTOToWin();
723 SetWindowTitles(win, objnamebuffer, (UBYTE *)~0);
724 SetMenuFlags();
730 /*********************************************************************************************/
732 static void CloseDTO(void)
734 if (dto)
736 if (win) RemoveDTObject(win, dto);
737 DisposeDTObject(dto);
738 dto = NULL;
742 /*********************************************************************************************/
744 static void MakeWindow(void)
746 WORD minwidth, minheight;
748 if (!winwidth) winwidth = scr->Width;
749 if (!winheight) winheight = scr->Height - scr->BarHeight - 1 -
750 scr->WBorTop - scr->Font->ta_YSize - 1 - sizeimageheight;
752 minwidth = (winwidth < 50) ? winwidth : 50;
753 minheight = (winheight < 50) ? winheight : 50;
755 win = OpenWindowTags(0, WA_PubScreen , (IPTR)scr ,
756 WA_Title , (IPTR)objnamebuffer ,
757 WA_CloseGadget , TRUE ,
758 WA_DepthGadget , TRUE ,
759 WA_DragBar , TRUE ,
760 WA_SizeGadget , TRUE ,
761 WA_Activate , TRUE ,
762 WA_SimpleRefresh , TRUE ,
763 WA_NoCareRefresh , TRUE ,
764 WA_NewLookMenus , TRUE ,
765 WA_Left , 0 ,
766 WA_Top , scr->BarHeight + 1 ,
767 WA_InnerWidth , winwidth ,
768 WA_InnerHeight , winheight ,
769 WA_AutoAdjust , TRUE ,
770 WA_MinWidth , minwidth ,
771 WA_MinHeight , minheight ,
772 WA_MaxWidth , 16383 ,
773 WA_MaxHeight , 16383 ,
774 WA_Gadgets , (IPTR)gad[GAD_UPARROW],
775 WA_IDCMP , IDCMP_CLOSEWINDOW |
776 IDCMP_GADGETUP |
777 IDCMP_GADGETDOWN |
778 IDCMP_MOUSEMOVE |
779 IDCMP_VANILLAKEY |
780 IDCMP_RAWKEY |
781 IDCMP_IDCMPUPDATE |
782 IDCMP_MENUPICK |
783 IDCMP_NEWSIZE |
784 IDCMP_INTUITICKS ,
785 TAG_DONE);
787 if (!win) Cleanup(MSG(MSG_CANT_CREATE_WIN));
789 AddDTOToWin();
791 SetMenuStrip(win, menus);
794 /*********************************************************************************************/
796 static void KillWindow(void)
798 if (win)
800 if (dto) RemoveDTObject(win, dto);
801 if (menus) ClearMenuStrip(win);
802 CloseWindow(win);
803 win = NULL;
805 winwidth = winheight = 0;
809 /*********************************************************************************************/
811 static void ScrollTo(UWORD dir, UWORD quali)
813 IPTR val;
814 LONG oldtop, top, total, visible, delta = 1;
815 BOOL horiz;
816 BOOL inc;
818 #ifdef __AROS__
819 switch(dir)
821 case RAWKEY_NM_WHEEL_UP:
822 dir = CURSORUP;
823 delta = 3;
824 break;
826 case RAWKEY_NM_WHEEL_DOWN:
827 dir = CURSORDOWN;
828 delta = 3;
829 break;
831 case RAWKEY_NM_WHEEL_LEFT:
832 dir = CURSORLEFT;
833 delta = 3;
834 break;
836 case RAWKEY_NM_WHEEL_RIGHT:
837 dir = CURSORRIGHT;
838 delta = 3;
839 break;
841 #endif
843 if ((dir == CURSORUP) || (dir == CURSORDOWN))
845 horiz = FALSE;
846 if (dir == CURSORUP) inc = FALSE; else inc = TRUE;
848 GetDTAttrs(dto, DTA_TopVert, (IPTR)&val, TAG_DONE);
849 top = (LONG)val;
850 GetDTAttrs(dto, DTA_TotalVert, (IPTR)&val, TAG_DONE);
851 total = (LONG)val;
852 GetDTAttrs(dto, DTA_VisibleVert, (IPTR)&val, TAG_DONE);
853 visible = (LONG)val;
855 else
857 horiz = TRUE;
858 if (dir == CURSORLEFT) inc = FALSE; else inc = TRUE;
860 GetDTAttrs(dto, DTA_TopHoriz, (IPTR)&val, TAG_DONE);
861 top = (LONG)val;
862 GetDTAttrs(dto, DTA_TotalHoriz, (IPTR)&val, TAG_DONE);
863 total = (LONG)val;
864 GetDTAttrs(dto, DTA_VisibleHoriz, (IPTR)&val, TAG_DONE);
865 visible = (LONG)val;
869 oldtop = top;
870 if (quali & (IEQUALIFIER_LALT | IEQUALIFIER_RALT | IEQUALIFIER_CONTROL))
872 if (inc) top = total; else top = 0;
874 else
875 if (quali & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
877 if (inc) top += visible - 1; else top -= visible - 1;
879 else
881 if (inc) top += delta; else top -= delta;
884 if (top + visible > total) top = total - visible;
885 if (top < 0) top = 0;
887 if (top != oldtop)
889 struct Gadget *g;
891 if (horiz)
893 g = (struct Gadget *)gad[GAD_HORIZSCROLL];
895 else
897 g = (struct Gadget *)gad[GAD_VERTSCROLL];
900 SetGadgetAttrs(g, win, NULL, PGA_Top, top,
901 TAG_DONE);
903 #ifdef __MORPHOS__
904 /* Looks like setting PGA_Top on Amiga does not cause OM_NOTIFIEs
905 to be sent (to dto). Or something like that. */
907 SetDTAttrs(dto, win, NULL, (horiz ? DTA_TopHoriz : DTA_TopVert), top, TAG_DONE);
908 #endif
910 } /* if (top != oldtop) */
914 /*********************************************************************************************/
916 static void FitToWindow(void)
918 if( pdt_fit_win )
920 int x, y;
922 x = win->Width - (win->BorderLeft + win->BorderRight + 4);
923 y = win->Height - (win->BorderTop + win->BorderBottom + 4);
924 D(bug("=> width %ld height %ld\n", x, y));
925 DoScaleMethod(x, y, pdt_keep_aspect);
926 // DoLayout(TRUE); seems to be done by intuition ?
930 /*********************************************************************************************/
932 static void HandleAll(void)
934 struct IntuiMessage *msg;
935 const struct TagItem *tstate, *tags;
936 struct TagItem *tag;
937 struct MenuItem *item;
938 struct Gadget *activearrowgad = NULL;
939 WORD arrowticker = 0, activearrowkind = 0;
940 IPTR tidata;
941 UWORD men;
942 BOOL quitme = FALSE;
943 const STRPTR not_supported = "Sorry, not supported yet\n";
945 while (!quitme)
947 WaitPort(win->UserPort);
948 while((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
950 // D(if (msg->Class!=IDCMP_INTUITICKS) bug(" Msg Class %08lx\n", (long)msg->Class));
951 switch (msg->Class)
953 case IDCMP_CLOSEWINDOW:
954 quitme = TRUE;
955 break;
957 case IDCMP_VANILLAKEY:
958 // D(bug("Vanillakey %d\n", (int)msg->Code));
959 switch(msg->Code)
961 case 27: /* ESC */
962 quitme = TRUE;
963 break;
965 case 13: /* RETURN */
966 if (dto_supports_activate_field) DoTrigger(STM_ACTIVATE_FIELD);
967 else if (dto_supports_search) DoTrigger(STM_SEARCH);
968 RefreshDTObjects (dto, win, NULL, (IPTR) NULL);
969 break;
971 case 9: /* TAB */
972 if (dto_supports_next_field) DoTrigger(STM_NEXT_FIELD);
973 else if (dto_supports_search_next) DoTrigger(STM_SEARCH_NEXT);
974 break;
976 case 8: /* Backspace */
977 if (dto_supports_retrace) DoTrigger(STM_RETRACE);
978 break;
980 case '>':
981 if (dto_supports_browse_next) DoTrigger(STM_BROWSE_NEXT);
982 break;
984 case '<':
985 if (dto_supports_browse_prev) DoTrigger(STM_BROWSE_PREV);
986 break;
988 } /* switch(msg->Code) */
989 break;
991 case IDCMP_RAWKEY:
992 switch(msg->Code)
994 #ifdef __AROS__
995 case RAWKEY_NM_WHEEL_UP:
996 case RAWKEY_NM_WHEEL_DOWN:
997 case RAWKEY_NM_WHEEL_LEFT:
998 case RAWKEY_NM_WHEEL_RIGHT:
999 #endif
1000 case CURSORUP:
1001 case CURSORDOWN:
1002 case CURSORRIGHT:
1003 case CURSORLEFT:
1004 ScrollTo(msg->Code, msg->Qualifier);
1005 break;
1007 #ifdef __AROS__
1008 case RAWKEY_HOME: /* HOME */
1009 ScrollTo(CURSORUP, IEQUALIFIER_LALT);
1010 break;
1012 case RAWKEY_END: /* END */
1013 ScrollTo(CURSORDOWN, IEQUALIFIER_LALT);
1014 break;
1016 case RAWKEY_PAGEUP: /* PAGE UP */
1017 ScrollTo(CURSORUP, IEQUALIFIER_LSHIFT);
1018 break;
1020 case RAWKEY_PAGEDOWN: /* PAGE DOWN */
1021 ScrollTo(CURSORDOWN, IEQUALIFIER_LSHIFT);
1022 break;
1023 #endif
1025 case 0x42: /* SHIFT TAB? */
1026 if (msg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
1028 if (dto_supports_prev_field) DoTrigger(STM_PREV_FIELD);
1029 else if (dto_supports_search_prev) DoTrigger(STM_SEARCH_PREV);
1031 break;
1033 } /* switch(msg->Code) */
1034 break;
1036 case IDCMP_GADGETDOWN:
1037 arrowticker = 3;
1038 activearrowgad = (struct Gadget *)msg->IAddress;
1039 switch(activearrowgad->GadgetID)
1041 case GAD_UPARROW:
1042 activearrowkind = CURSORUP;
1043 ScrollTo(CURSORUP, 0);
1044 break;
1046 case GAD_DOWNARROW:
1047 activearrowkind = CURSORDOWN;
1048 ScrollTo(CURSORDOWN, 0);
1049 break;
1051 case GAD_LEFTARROW:
1052 activearrowkind = CURSORLEFT;
1053 ScrollTo(CURSORLEFT, 0);
1054 break;
1056 case GAD_RIGHTARROW:
1057 activearrowkind = CURSORRIGHT;
1058 ScrollTo(CURSORRIGHT, 0);
1059 break;
1061 default:
1062 activearrowkind = 0;
1063 break;
1066 break;
1068 case IDCMP_INTUITICKS:
1069 if (activearrowkind)
1071 if (arrowticker)
1073 arrowticker--;
1075 else if (activearrowgad->Flags & GFLG_SELECTED)
1077 ScrollTo(activearrowkind, 0);
1080 break;
1082 case IDCMP_GADGETUP:
1083 switch(((struct Gadget *)msg->IAddress)->GadgetID)
1085 case GAD_UPARROW:
1086 case GAD_DOWNARROW:
1087 case GAD_LEFTARROW:
1088 case GAD_RIGHTARROW:
1089 activearrowkind = 0;
1090 break;
1092 break;
1094 case IDCMP_MENUPICK:
1095 men = msg->Code;
1096 // D(bug(" * MV: men %08lx\n", (long)men));
1097 while(men != MENUNULL)
1099 if ((item = ItemAddress(menus, men)))
1101 // D(bug(" * MV: item %08lx menus %08lx\n", (long)item, (long)menus));
1102 switch((ULONG)GTMENUITEM_USERDATA(item))
1104 case MSG_MEN_PROJECT_OPEN:
1105 filename = GetFileName(MSG_ASL_OPEN_TITLE);
1106 if (filename) OpenDTO();
1107 break;
1109 case MSG_MEN_PROJECT_SAVEAS:
1110 filename = GetFileName(MSG_ASL_SAVE_TITLE);
1111 if (filename) DoWriteMethod(filename, DTWM_RAW);
1112 break;
1114 case MSG_MEN_PROJECT_SAVEAS_IFF:
1115 filename = GetFileName(MSG_ASL_SAVE_TITLE);
1116 if (filename) DoWriteMethod(filename, DTWM_IFF);
1117 break;
1119 case MSG_MEN_PROJECT_PRINT:
1120 OutputMessage(not_supported);
1121 break;
1123 case MSG_MEN_PROJECT_ABOUT:
1124 About();
1125 break;
1127 case MSG_MEN_PROJECT_QUIT:
1128 quitme = TRUE;
1129 break;
1131 case MSG_MEN_EDIT_MARK:
1132 #if defined(__AROS__) && !defined(__MORPHOS__)
1133 if (StartDragSelect(dto))
1134 #else
1136 struct DTSpecialInfo *si;
1139 ** ClipView example on AmigaDev CD does just the following.
1140 ** None of the checks AROS datatypes.library/StartDragSelect()
1141 ** does.
1144 si = (struct DTSpecialInfo *)(((struct Gadget *)dto)->SpecialInfo);
1145 si->si_Flags |= DTSIF_DRAGSELECT;
1147 #endif
1149 #warning TODO: change mouse pointer to crosshair
1151 break;
1153 case MSG_MEN_EDIT_COPY:
1155 struct dtGeneral dtg;
1157 dtg.MethodID = DTM_COPY;
1158 dtg.dtg_GInfo = NULL;
1160 DoDTMethodA(dto, win, NULL, (Msg)&dtg);
1162 break;
1164 case MSG_MEN_EDIT_SELECTALL:
1165 OutputMessage(not_supported);
1166 break;
1168 case MSG_MEN_EDIT_CLEARSELECTED:
1170 struct dtGeneral dtg;
1172 dtg.MethodID = DTM_CLEARSELECTED;
1173 dtg.dtg_GInfo = NULL;
1175 DoDTMethodA(dto, win, NULL, (Msg)&dtg);
1177 break;
1179 case MSG_MEN_WINDOW_SEPSCREEN:
1180 OutputMessage(not_supported);
1181 break;
1183 case MSG_MEN_WINDOW_MINIMIZE:
1184 OutputMessage(not_supported);
1185 break;
1187 case MSG_MEN_WINDOW_NORMAL:
1188 OutputMessage(not_supported);
1189 break;
1191 case MSG_MEN_WINDOW_MAXIMIZE:
1192 OutputMessage(not_supported);
1193 break;
1195 case MSG_MEN_SETTINGS_SAVEDEF:
1196 OutputMessage(not_supported);
1197 break;
1199 case MSG_MEN_PICT_ZOOM_IN:
1200 pdt_zoom++;
1201 if (pdt_zoom == -1 ) pdt_zoom = 1;
1202 DoZoom(pdt_zoom);
1203 break;
1205 case MSG_MEN_PICT_ZOOM_OUT:
1206 pdt_zoom--;
1207 if (pdt_zoom == 0 ) pdt_zoom = -2;
1208 DoZoom(pdt_zoom);
1209 break;
1211 case MSG_MEN_PICT_RESET:
1212 pdt_zoom = 1;
1213 DoZoom(pdt_zoom);
1214 break;
1216 case MSG_MEN_PICT_FIT_WIN:
1217 pdt_fit_win = (item->Flags & CHECKED) ? TRUE : FALSE;
1218 FitToWindow();
1219 DoLayout(TRUE);
1220 break;
1222 case MSG_MEN_PICT_KEEP_ASPECT:
1223 pdt_keep_aspect = (item->Flags & CHECKED) ? TRUE : FALSE;
1224 FitToWindow();
1225 DoLayout(TRUE);
1226 break;
1228 case MSG_MEN_PICT_FORCE_MAP:
1229 SetDTAttrs (dto, NULL, NULL,
1230 PDTA_DestMode, (item->Flags & CHECKED) ? FALSE : TRUE,
1231 TAG_DONE);
1232 DoLayout(TRUE);
1233 break;
1235 case MSG_MEN_PICT_DITHER:
1236 SetDTAttrs (dto, NULL, NULL,
1237 PDTA_DitherQuality, (item->Flags & CHECKED) ? 4 : 0,
1238 TAG_DONE);
1239 DoLayout(TRUE);
1240 break;
1242 case MSG_MEN_TEXT_WORDWRAP:
1243 if (item->Flags & CHECKED)
1244 D(bug("wordwrap enabled\n"));
1245 else
1246 D(bug("wordwrap disabled\n"));
1247 SetDTAttrs (dto, NULL, NULL,
1248 TDTA_WordWrap, (item->Flags & CHECKED) ? TRUE : FALSE,
1249 TAG_DONE);
1250 DoLayout(TRUE);
1251 break;
1253 case MSG_MEN_TEXT_SEARCH:
1254 if (dto_supports_search) DoTrigger(STM_SEARCH);
1255 break;
1257 case MSG_MEN_TEXT_SEARCH_PREV:
1258 if (dto_supports_search_prev) DoTrigger(STM_SEARCH_PREV);
1259 break;
1261 case MSG_MEN_TEXT_SEARCH_NEXT:
1262 if (dto_supports_search_next) DoTrigger(STM_SEARCH_NEXT);
1263 break;
1265 } /* switch(GTMENUITEM_USERDATA(item)) */
1267 men = item->NextSelect;
1269 else
1271 men = MENUNULL;
1274 } /* while(men != MENUNULL) */
1275 break;
1277 case IDCMP_NEWSIZE:
1278 D(bug("IDCMP NEWSIZE\n"));
1279 FitToWindow();
1280 break;
1282 case IDCMP_IDCMPUPDATE:
1283 tstate = tags = (const struct TagItem *) msg->IAddress;
1284 while ((tag = NextTagItem(&tstate)) != NULL)
1286 tidata = tag->ti_Data;
1287 // D(bug("IDCMP UPDATE %08lx %08lx\n", (long)tag->ti_Tag, (long)tag->ti_Data));
1288 switch (tag->ti_Tag)
1290 /* Change in busy state */
1291 case DTA_Busy:
1292 if (tidata)
1293 SetWindowPointer (win, WA_BusyPointer, TRUE, TAG_DONE);
1294 else
1295 SetWindowPointer (win, WA_Pointer, (IPTR) NULL, TAG_DONE);
1296 break;
1298 case DTA_Title:
1299 SetWindowTitles(win, (UBYTE *)tidata, (UBYTE *)~0);
1300 break;
1302 /* Error message */
1303 case DTA_ErrorLevel:
1304 /* if (tidata)
1306 errnum = GetTagData (DTA_ErrorNumber, NULL, tags);
1307 PrintErrorMsg (errnum, (STRPTR) options[OPT_NAME]);
1309 break;
1311 /* Time to refresh */
1312 case DTA_Sync:
1313 /* Refresh the DataType object */
1314 D(bug("Multiview: DTA_SYNC\n"));
1315 RefreshDTObjects (dto, win, NULL, (IPTR) NULL);
1316 break;
1318 } /* switch (tag->ti_Tag) */
1320 } /* while ((tag = NextTagItem ((const struct TagItem **)&tstate))) */
1321 break;
1323 } /* switch (msg->Class) */
1325 ReplyMsg((struct Message *)msg);
1327 } /* while((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
1329 } /* while (!quitme) */
1332 /*********************************************************************************************/
1334 int main(int argc, char **argv)
1336 InitLocale("System/Utilities/MultiView.catalog", 1);
1337 InitMenus(nm);
1338 InitMenus(nmpict);
1339 InitMenus(nmtext);
1340 OpenLibs();
1341 InitDefaults();
1343 if (argc == 0)
1345 struct WBStartup *startup = (struct WBStartup *) argv;
1347 if (startup->sm_NumArgs >= 2)
1349 /* FIXME: all arguments but the first are ignored */
1350 cd = CurrentDir(startup->sm_ArgList[1].wa_Lock);
1351 filename = startup->sm_ArgList[1].wa_Name;
1353 else
1355 filename = GetFileName(MSG_ASL_OPEN_TITLE);
1356 if (!filename) Cleanup(NULL);
1359 else
1361 GetArguments();
1364 LoadFont();
1365 MakeICObjects();
1366 OpenDTO();
1367 GetVisual();
1368 MakeGadgets();
1369 menus = MakeMenus(nm);
1370 pictmenus = MakeMenus(nmpict);
1371 textmenus = MakeMenus(nmtext);
1372 SetMenuFlags();
1373 MakeWindow();
1374 HandleAll();
1375 Cleanup(NULL);
1377 return 0;
1380 /*********************************************************************************************/