home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / screen / shdwmstr.lha / source / config / prefs.c < prev    next >
C/C++ Source or Header  |  1991-12-29  |  14KB  |  447 lines

  1. /*
  2.  * startup code for preferences programs.
  3.  *
  4.  * Copyright (c) 1991, Mike Meyer
  5.  * All Rights Reserved
  6.  *
  7.  * See the file "ShadowMaster:Distribution"  for information on distribution.
  8.  *
  9.  * ===build instructions
  10.  * % lc prefs ; output= prefs.o input= prefs.c
  11.  * ===endbuild
  12.  */
  13.  
  14. #include <dos.h>
  15. #include <string.h>
  16.  
  17. #include <exec/types.h>
  18. #include <exec/execbase.h>
  19. #include <utility/tagitem.h>
  20. #include <dos/dos.h>
  21. #include <dos/dosextens.h>
  22. #include <intuition/intuition.h>
  23. #include <graphics/gfx.h>
  24. #include <libraries/gadtools.h>
  25. #include <libraries/asl.h>
  26. #include <workbench/startup.h>
  27. #include <workbench/workbench.h>
  28. #include <proto/exec.h>
  29. #include <proto/dos.h>
  30. #include <proto/intuition.h>
  31. #include <proto/graphics.h>
  32. #include <proto/gadtools.h>
  33. #include <proto/asl.h>
  34. #include <proto/icon.h>
  35. #include <clib/alib_stdio_protos.h>
  36.  
  37. /* User supplied values */
  38. extern int windowheight ;        /* Height to open the window to */
  39. extern int windowwidth ;        /* Width to open the window to */
  40. extern char *basename ;            /* env:basename/appname.prefs */
  41. extern char *appname ;            /* is the default prefs file */
  42. extern char *errname ;            /* error reports look like errname: text */
  43.  
  44. /* User functions */
  45. extern int SaveFile(char *) ;        /* Save current preferences to named file */
  46. extern int LoadFile(char *) ;        /* Load preferences from named file */
  47. extern int Undo(void) ;            /* Undo last action */
  48. extern int Defaults(void) ;        /* Reset to defaults */
  49. extern int UserGadgets(struct Gadget *,    /* Add user gadgets to window */
  50.         struct NewGadget *) ;
  51. extern void CleanUp(int) ;        /* Cleans up before exit */
  52.  
  53. /* My functions, supplied here */
  54. static int OpenFile(void) ;
  55. static int SaveAs(void) ;
  56. static int Quit(void) ;
  57. static int gQuit(struct Gadget *, UWORD) ;
  58. static int LastSaved(void) ;
  59. static int Icons(void) ;
  60. static int Use(struct Gadget *, UWORD) ;
  61. static int Save(struct Gadget *, UWORD) ;
  62. static int Restore(void) ;
  63. static void SaveIcon(char *) ;
  64. void dowbmessage(char *) ;
  65.  
  66. /* Static data for the world */
  67. static int icons = TRUE ;        /* Create icons on save? */
  68. static char save[FMSIZE] ;        /* envarc: file name */
  69. static char use[FMSIZE] ;        /* env: file name */
  70. static char *edit ;            /* File we were invoked on */
  71. struct Window *window = NULL ;        /* So I can set the wait pointer for it */
  72.  
  73. /* Library bases we allow the user to access */
  74. struct ExecBase        *SysBase = NULL ;
  75. struct DosLibrary    *DOSBase = NULL ;
  76. struct IntuitionBase    *IntuitionBase = NULL ;
  77. struct GfxBase        *GfxBase = NULL ;
  78. struct Library        *GadToolsBase = NULL ;
  79. struct Library        *AslBase = NULL ;
  80. struct Library        *IconBase = NULL ;
  81.  
  82. /* Initialization data */
  83. static struct TextAttr        topaz_8 = { "topaz.font", 8, 0, 0 } ;/* Blame this on GadTools */
  84.  
  85. static struct NewMenu pref_menu[] = {
  86.     { NM_TITLE, "Project",        0,   0, 0, 0},
  87.     { NM_ITEM,  "Open...",        "O", 0, 0, (APTR) &OpenFile},
  88.     { NM_ITEM,  "Save As...",    "A", 0, 0, (APTR) &SaveAs},
  89.     { NM_ITEM,  NM_BARLABEL,    0,   0, 0, 0},
  90.     { NM_ITEM,  "Quit",        "Q", 0, 0, (APTR) &Quit},
  91.  
  92.     { NM_TITLE, "Edit",        0,   0, 0, 0},
  93.     { NM_ITEM,  "Reset to Default", "D", 0, 0, (APTR) &Defaults},
  94.     { NM_ITEM,  "Last Saved",    "L", 0, 0, (APTR) &LastSaved},
  95.     { NM_ITEM,  "Restore",        "R", 0, 0, (APTR) &Restore},
  96.     { NM_ITEM,  "Undo",        "U", 0, 0, (APTR) &Undo},
  97.  
  98.     { NM_TITLE, "Options",        0,   0, 0, 0},
  99.     { NM_ITEM,  "Create Icons?",    0,   CHECKIT|MENUTOGGLE|CHECKED, 0,
  100.                                 (APTR) &Icons},
  101.     { NM_END,   0,            0,   0, 0, 0}
  102.     } ;
  103.  
  104. #define TEMPLATE "FROM,EDIT/S,USE/S,SAVE/S,PUBSCREEN/K"
  105. static enum {FROM_POS, EDIT_POS, USE_POS, SAVE_POS, SCREEN_POS} ;
  106.  
  107. #define done(x, m) do {mess = m; status = x; goto out; } while (0)
  108. static int __saveds
  109. start(void) {
  110.     int            status = RETURN_OK, (*menufunc)(void),
  111.                 (*gadfunc)(struct Gadget *, UWORD), i,
  112.                 action_use = FALSE, action_save = FALSE ;
  113.     char            *mess = NULL, *tool ;
  114.     long            opts[5] = {&use[0], 1, 0, 0, 0} ;
  115.     WORD            iconic[] = {0, 0, 200, 11} ;
  116.     BPTR            olddir = NULL ;
  117.     struct Menu        *menu = NULL ;
  118.     struct MenuItem        *menuitem = NULL ;
  119.     USHORT            menunumber ;
  120.     struct Screen        *pubsc = NULL ;
  121.     struct RDArgs        *args = NULL ;
  122.     struct TextFont        *font = NULL ;
  123.     struct IntuiMessage    *bounce, in ;
  124.     struct Gadget        *gadget_crap = NULL, *gadtools_turd, *ingad ;
  125.     struct NewGadget    no_good ;
  126.     struct WBStartup    *wbmessage = NULL ;
  127.     struct WBArg        *wbargs ;
  128.     struct DiskObject    *my_icon ;
  129.  
  130.     /* Open the libraries */
  131.     SysBase = *((struct ExecBase **) 4);
  132.     if (!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  133.         done(RETURN_FAIL, "You need 2.04 or later") ;
  134.     if (!(IntuitionBase = (struct IntuitionBase *)
  135.         OpenLibrary("intuition.library", 37)))
  136.             done(RETURN_FAIL, "Can't open intuition.library") ;
  137.     if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 37)))
  138.         done(RETURN_FAIL, "Can't open graphics.library") ;
  139.     if (!(GadToolsBase = OpenLibrary("gadtools.library", 37)))
  140.         done(RETURN_FAIL, "Can't open gadtools.library") ;
  141.     if (!(AslBase = OpenLibrary("asl.library", 37)))
  142.         done(RETURN_FAIL, "Can't open asl.library") ;
  143.     if (!(IconBase = OpenLibrary("icon.library", 37)))
  144.         done(RETURN_FAIL, "Can't open icon.library") ;
  145.  
  146.     /* Make file names that we edit */
  147.     sprintf(save, "envarc:%s/%s.prefs", basename, appname) ;
  148.     sprintf(use, "env:%s/%s.prefs", basename, appname) ;
  149.  
  150.     /* Argument processing, if needed */
  151.     if (((struct Process *) SysBase->ThisTask)->pr_CLI) {    /* do CLI args */
  152.         if (!(args = ReadArgs(TEMPLATE, opts, NULL)))
  153.             done(RETURN_ERROR, "Invalid arguments") ;
  154.         edit = (char *) opts[FROM_POS] ;
  155.         action_use = opts[USE_POS] ;
  156.         action_save = opts[SAVE_POS] ;
  157.         }
  158.     else {    /* Do WB args */
  159.         edit = use ;        /* To make sure we have *something* */
  160.         WaitPort(&((struct Process *) SysBase->ThisTask)->pr_MsgPort) ;
  161.         wbmessage = (struct WBStartup *)
  162.             GetMsg(&((struct Process *) SysBase->ThisTask)->pr_MsgPort) ;
  163.         wbargs = wbmessage->sm_ArgList ;
  164.         i = wbmessage->sm_NumArgs ;
  165.         olddir = CurrentDir(wbargs->wa_Lock) ;
  166.         while (i-- > 0) {
  167.             CurrentDir(wbargs->wa_Lock) ;
  168.             if (my_icon = GetDiskObjectNew(wbargs->wa_Name)) {
  169.                 if (my_icon->do_Type == WBPROJECT)
  170.                     edit = wbargs->wa_Name ;
  171.                 if (tool = FindToolType(my_icon->do_ToolTypes, "ACTION"))
  172.                     if (!stricmp(tool, "use")) {
  173.                         action_use = TRUE ;
  174.                         i = 0 ;
  175.                         }
  176.                     else if (!stricmp(tool, "save")) {
  177.                         action_save = TRUE ;
  178.                         i = 0 ;
  179.                         }
  180.                     else if (!stricmp(tool, "edit")) i = 0 ;
  181.                 FreeDiskObject(my_icon) ;
  182.                 }
  183.             wbargs += 1 ;
  184.             }
  185.         }
  186.         
  187.     /* Load up file we want to work on, and run it */
  188.     if (!LoadFile(edit)) Defaults() ;
  189.     if (action_save) {
  190.         Save(NULL, 0) ;
  191.         done(RETURN_OK, NULL) ;
  192.         }
  193.     if (action_use) {
  194.         Use(NULL, 0) ;
  195.         done(RETURN_OK, NULL) ;
  196.         }
  197.  
  198.     /* Otherwise, we're editing, so open the bloody window... */
  199.  
  200.     if (!(pubsc = LockPubScreen((char *) opts[SCREEN_POS])))
  201.         done(RETURN_ERROR, "Can't lock requested public screen") ;
  202.     if (!(no_good.ng_VisualInfo = GetVisualInfoA(pubsc, NULL)))
  203.         done(RETURN_FAIL, "internal error: VISINFO") ;
  204.     if (!(font = OpenFont(&topaz_8)))
  205.         done(RETURN_FAIL, "Can't open topaz font") ;
  206.     if (!(menu = CreateMenusA(pref_menu, NULL)))
  207.         done(RETURN_FAIL, "Internal error: MENUS") ;
  208.     if (!LayoutMenusA(menu, no_good.ng_VisualInfo, NULL))
  209.         done(RETURN_FAIL, "Internal error: LAYOUT") ;
  210.  
  211.     /* Set up the unchanging no good gadget stuff */
  212.     if (!(gadtools_turd = CreateContext(&gadget_crap)))
  213.         done(RETURN_FAIL, "Internal error: CONTEXT") ;
  214.     no_good.ng_TextAttr = &topaz_8 ;
  215.     no_good.ng_Flags = no_good.ng_GadgetID = 0 ;
  216.     no_good.ng_Height = 12 ;
  217.     no_good.ng_Width = 67 ;
  218.     no_good.ng_TopEdge = pubsc->WBorTop + pubsc->Font->ta_YSize + windowheight - 13 ;
  219.  
  220.     /* standard cancel gadget */
  221.     no_good.ng_LeftEdge = windowwidth - 87 ;
  222.     no_good.ng_GadgetText = "Cancel" ;
  223.     no_good.ng_UserData = (APTR) &gQuit ;
  224.     if (!(gadtools_turd = CreateGadgetA(BUTTON_KIND, gadtools_turd, &no_good, NULL)))
  225.         done(RETURN_FAIL, "internal error: CANCEL") ;
  226.  
  227.     /* standard use gadget */
  228.     no_good.ng_LeftEdge = (windowwidth - no_good.ng_Width) / 2 ;
  229.     no_good.ng_GadgetText = "Use" ;
  230.     no_good.ng_UserData = (APTR) &Use ;
  231.     if (!(gadtools_turd = CreateGadgetA(BUTTON_KIND, gadtools_turd, &no_good, NULL)))
  232.         done(RETURN_FAIL, "internal error: USE") ;
  233.  
  234.     /* standard save gadget */
  235.     no_good.ng_LeftEdge = 13 ;
  236.     no_good.ng_GadgetText = "Save" ;
  237.     no_good.ng_UserData = (APTR) &Save ;
  238.     if (!(gadtools_turd = CreateGadgetA(BUTTON_KIND, gadtools_turd, &no_good, NULL)))
  239.         done(RETURN_FAIL, "internal error: SAVE") ;
  240.  
  241.     /* The users gadgets (if any) */
  242.     if (!UserGadgets(gadtools_turd, &no_good))
  243.         done(RETURN_FAIL, "internal error: GADGETS") ;
  244.  
  245.     if (!(window = OpenWindowTags(NULL,
  246.             WA_Left, 0, WA_InnerWidth, windowwidth,
  247.             WA_Top, 11, WA_InnerHeight, windowheight, WA_AutoAdjust, 1,
  248.             WA_Title, "ScreenSaver Preferences",
  249.             WA_DragBar, 1, WA_Zoom, iconic, WA_DepthGadget, 1,
  250.             WA_Gadgets, gadget_crap,
  251.             WA_IDCMP, LISTVIEWIDCMP|IDCMP_MENUPICK,
  252.             WA_PubScreen, pubsc, WA_PubScreenFallBack, 1,
  253.             TAG_DONE, 0)))
  254.         done(RETURN_FAIL, "Can't open window") ;
  255.  
  256.     SetMenuStrip(window, menu) ;
  257.     GT_RefreshWindow(window, NULL) ;
  258.  
  259.     FOREVER {
  260.         WaitPort(window->UserPort) ;
  261.         while (bounce = GT_GetIMsg(window->UserPort)) {
  262.             in = *bounce ;
  263.             GT_ReplyIMsg(bounce) ;
  264.             switch (in.Class) {
  265.                 case IDCMP_GADGETUP:
  266.                     ingad = (struct Gadget *) in.IAddress ;
  267.                     gadfunc = (int (*)()) ingad->UserData ;
  268.                     if (gadfunc(ingad, in.Code))
  269.                         done(RETURN_OK, NULL) ;
  270.                     break ;
  271.                 case IDCMP_MENUPICK:
  272.                     menunumber = in.Code ;
  273.                     while (menunumber != MENUNULL) {
  274.                         menuitem = ItemAddress(menu, menunumber) ;
  275.                         menufunc = (int (*)()) GTMENUITEM_USERDATA(menuitem) ;
  276.                         if (menufunc()) done(RETURN_OK, NULL) ;
  277.                         menunumber = menuitem->NextSelect ;
  278.                         }
  279.                     break ;
  280.  
  281.                 case IDCMP_REFRESHWINDOW:
  282.                     GT_BeginRefresh(window);
  283.                     GT_EndRefresh(window, TRUE);
  284.                     break ;
  285.                 }
  286.             }
  287.         }
  288.  
  289. out:
  290.     if (mess && DOSBase) {
  291.         if (wbmessage && IntuitionBase) dowbmessage(mess) ;
  292.         else {
  293.             PutStr(errname) ;
  294.             PutStr(": ") ;
  295.             PutStr(mess) ;
  296.             PutStr("\n") ;
  297.             }
  298.         }
  299.             
  300.     if (window) {
  301.         ClearMenuStrip(window) ;
  302.         CloseWindow(window) ;
  303.         }
  304.     if (gadget_crap) FreeGadgets(gadget_crap) ;
  305.     if (pubsc) UnlockPubScreen(NULL, pubsc) ;
  306.     if (no_good.ng_VisualInfo) FreeVisualInfo(no_good.ng_VisualInfo) ;
  307.     if (font) CloseFont(font) ;
  308.     if (menu) FreeMenus(menu) ;
  309.     if (args) FreeArgs(args) ;
  310.     if (olddir) CurrentDir(olddir) ;
  311.     if (IconBase) CloseLibrary(IconBase) ;
  312.     if (AslBase) CloseLibrary(AslBase) ;
  313.     if (GfxBase) CloseLibrary((struct Library *) GfxBase) ;
  314.     if (GadToolsBase) CloseLibrary(GadToolsBase) ;
  315.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase) ;
  316.     if (wbmessage) {
  317.         Forbid() ;
  318.         ReplyMsg((struct Message *) wbmessage) ;
  319.         }
  320.     if (DOSBase) CloseLibrary((struct Library *) DOSBase) ;
  321.     return status ;
  322.     }
  323.  
  324. /* The functions that actually *do* things */
  325. /* Note: an exit that *doesn't* change env:... must go through here */
  326. static int
  327. Quit(void) {
  328.     CleanUp(FALSE) ;
  329.     return 1 ;
  330.     }
  331. static int gQuit(struct Gadget *g, UWORD code) { return Quit(); }
  332.  
  333. static int
  334. LastSaved(void) {
  335.     if (!LoadFile(save)) dowbmessage("Could not load saved file") ;
  336.     return 0 ;
  337.     }
  338.  
  339. static int
  340. Icons(void) {
  341.     icons = !icons ;    /* Tacky, but so is the menu facility */
  342.     return 0 ;
  343.     }
  344.  
  345. /* Note: an exit that changes env:... must go through herre! */
  346. static int
  347. Use(struct Gadget *g, UWORD code) {
  348.     if (!SaveFile(use)) {
  349.         dowbmessage("Could not save file in env:") ;
  350.         return 0 ;
  351.         }
  352.     CleanUp(TRUE) ;
  353.     return 1 ;
  354.     }
  355.  
  356. static int
  357. Save(struct Gadget *g, UWORD code) {
  358.     if (!SaveFile(save)) {
  359.         dowbmessage("Could not save file in envarc:") ;
  360.         return 0 ;
  361.         }
  362.     return Use(g, code) ;
  363.     }
  364.  
  365. static int
  366. Restore(void) {
  367.     if (!LoadFile(edit)) dowbmessage("Could not reload file") ;
  368.     return 0 ;
  369.     }
  370.  
  371. /* 2.0 Busy Pointer data From of Steve Tibbett's PointerX */
  372. USHORT __chip BusyPointerData[] = {
  373.         0x0000,0x0000,
  374.         0x0400,0x07C0,0x0000,0x07C0,0x0100,0x0380,0x0000,0x07E0,
  375.         0x07C0,0x1FF8,0x1FF0,0x3FEC,0x3FF8,0x7FDE,0x3FF8,0x7FBE,
  376.         0x7FFC,0xFF7F,0x7EFC,0xFFFF,0x7FFC,0xFFFF,0x3FF8,0x7FFE,
  377.         0x3FF8,0x7FFE,0x1FF0,0x3FFC,0x07C0,0x1FF8,0x0000,0x07E0,
  378.         0x0000,0x0000,
  379.         } ;
  380.  
  381. static char *
  382. GetFileName(char *prompt, int flags) {
  383.     struct FileRequester    *my_req = NULL ;
  384.     char filename[FNSIZE], hail[FMSIZE], *out = NULL ;
  385.     static char dirname[FMSIZE] ;
  386.  
  387.     sprintf(filename, "%s.prefs", appname) ;
  388.     sprintf(dirname, "envarc:%s", basename) ;
  389.     sprintf(hail, "%s %s preferences", prompt, appname) ;
  390.  
  391.     if (!(my_req = AllocAslRequestTags(ASL_FileRequest,
  392.             ASL_TopEdge, 11, ASL_LeftEdge, 0, ASL_Window, window,
  393.             ASL_Dir, dirname, ASL_File, filename, ASL_FuncFlags, flags,
  394.             ASL_Hail, hail, TAG_DONE, 0)))
  395.         return NULL ;
  396.  
  397.     SetPointer(window, BusyPointerData, 16, 16, -6, 0) ;
  398.     if (RequestFile(my_req)) {
  399.         strcpy(dirname, my_req->rf_Dir) ;
  400.         AddPart(dirname, my_req->rf_File, FMSIZE) ;
  401.         out = dirname ;
  402.         }
  403.     ClearPointer(window) ;
  404.     FreeAslRequest(my_req) ;
  405.             
  406.     return out ;
  407.     }
  408.  
  409. static int
  410. SaveAs(void) {
  411.     struct DiskObject *deficon ;
  412.     char defname[FMSIZE] ;
  413.     char *file = GetFileName("Save", FILF_SAVE) ;
  414.  
  415.     if (!file) return 0 ;
  416.     if (!SaveFile(file)) dowbmessage("Could not open file") ;
  417.     else if (icons) {
  418.         sprintf(defname, "env:%s/%s", basename, appname) ;
  419.         /* If there is no default icon, we don't create them */
  420.         if (deficon = GetDiskObjectNew(defname)) {
  421.             PutDiskObject(file, deficon) ;
  422.             FreeDiskObject(deficon) ;
  423.             }
  424.         }
  425.     return 0 ;
  426.     }
  427.  
  428. static int
  429. OpenFile(void) {
  430.     char *file = GetFileName("Load", 0) ;
  431.     if (!file) return 0 ;
  432.     if (!LoadFile(file)) dowbmessage("Could not open file") ;
  433.     return 0 ;
  434.     }
  435.  
  436. void
  437. dowbmessage(char *message) {
  438.     struct EasyStruct req ;
  439.  
  440.     req.es_StructSize = sizeof(req) ;
  441.     req.es_Flags = 0 ;
  442.     req.es_Title = errname ;
  443.     req.es_TextFormat = message ;
  444.     req.es_GadgetFormat = "Okay" ;
  445.     EasyRequestArgs(window, &req, NULL, NULL) ;
  446.     }
  447.