/*- * Copyright (c) 2017-2021 Carsten Sonne Larsen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "config.h" #include "global.h" #include "message.h" #include "setting.h" #include "timer.h" #include "conv.h" #include "sync.h" #include "text.h" #include "mem.h" #include "win.h" #include "logmod.h" #undef MODULENAME #define MODULENAME "Window" #define WINPROCNAME APP_SHORT_NAME " Window" #ifndef GADTOOLSNAME #define GADTOOLSNAME "gadtools.library" #endif static void SettingsProc(void); static void MsgLoop(void); static void HandleGadgetUp(struct Gadget *); volatile bool WindowProcRunning = false; struct AppSettings *WindowSettings = NULL; struct AppSettingWindow SettingWindow; static APTR OrgWindowPtr = NULL; void ShowSettingWindow(void) { bool running; struct Task *task = NULL; if (GadToolsBase == NULL) { LogWarn(GADTOOLSNAME " is not present"); LogNotice("Settings window cannot open"); return; } #if defined(AROS) LogWarn("Settings window dos not work in AROS with " APP_TITLE_VERSION); return; #endif Forbid(); running = WindowProcRunning; if (!WindowProcRunning) { task = (struct Task *)CreateNewProcTags( NP_Entry, (IPTR)SettingsProc, NP_Name, (IPTR)WINPROCNAME, NP_StackSize, 64 * 1024, TAG_DONE); WindowProcRunning = (task != NULL); } Permit(); if (running) { LogDebug(Text2P, "Setting process", TextAlreadyRunning); SendWindowMessage(ATK_SHOW); } else if (task != NULL) { LogDebug("Created setting process"); } else { LogError("Failed to create setting process"); } } static bool InitWindow(void) { bool success; LogInfo(TextInitComponent, "settings window"); SettingWindow.Screen = NULL; SettingWindow.Window = NULL; SettingWindow.GadgetList = NULL; SettingWindow.VisualInfo = NULL; SettingWindow.PriorityText = NULL; SettingWindow.ThresholdText = NULL; SettingWindow.TimezoneText = NULL; SettingWindow.Width = 0; SettingWindow.Height = 0; SettingWindow.Gadgets = NULL; success = CreateMessagePort(MSGPORT_WINDOW); if (!success) { return false; } SettingWindow.Screen = LockPubScreen(NULL); if (!SettingWindow.Screen) { return false; } SettingWindow.VisualInfo = GetVisualInfo(SettingWindow.Screen, NULL); if (SettingWindow.VisualInfo == NULL) { return false; } SettingWindow.PriorityText = AllocStringSafe(15); SettingWindow.TimezoneText = AllocStringSafe(TIMEZONE_TEXT_LEN); SettingWindow.ThresholdText = AllocStringSafe(MAXLONGLONGCHARSIZE); if (SettingWindow.PriorityText == NULL || SettingWindow.TimezoneText == NULL || SettingWindow.ThresholdText == NULL) { return false; } LongToStr(Settings->Priority, SettingWindow.PriorityText); LongLongToStr(Settings->Threshold, SettingWindow.ThresholdText); GetTimezoneText(SettingWindow.TimezoneText, Settings->TimeZoneDisplay); return true; } static void DestroyWindow(void) { LogTrace("Clean up"); DestroyMessagePort(MSGPORT_WINDOW); if (SettingWindow.Window != NULL) { struct Message *msg; while ((msg = GetMsg(SettingWindow.Window->UserPort))) ReplyMsg(msg); Forbid(); struct Process *proc = (struct Process *)FindTask(NULL); proc->pr_WindowPtr = OrgWindowPtr; Permit(); CloseWindow(SettingWindow.Window); SettingWindow.Window = NULL; } if (SettingWindow.GadgetList != NULL) { FreeGadgets(SettingWindow.GadgetList); SettingWindow.GadgetList = NULL; } if (SettingWindow.VisualInfo != NULL) { FreeVisualInfo(SettingWindow.VisualInfo); SettingWindow.VisualInfo = NULL; } if (SettingWindow.Screen != NULL) { UnlockPubScreen(NULL, SettingWindow.Screen); SettingWindow.Screen = NULL; } FreeSettings(WindowSettings); WindowSettings = NULL; FreeMemSafe(SettingWindow.Gadgets); FreeMemSafe(SettingWindow.PriorityText); FreeMemSafe(SettingWindow.ThresholdText); FreeMemSafe(SettingWindow.TimezoneText); SettingWindow.Gadgets = NULL; SettingWindow.PriorityText = NULL; SettingWindow.ThresholdText = NULL; SettingWindow.TimezoneText = NULL; } static bool CreateWindow(void) { long w = SettingWindow.Screen->WBorLeft + SettingWindow.Screen->WBorRight + SettingWindow.Width + 38; // Why is this 38? long h = SettingWindow.Height + 8 + SettingWindow.Screen->WBorBottom; struct Window *x = OpenWindowTags(NULL, WA_Width, w, WA_Height, h, WA_Left, (SettingWindow.Screen->Width - w) / 2, WA_Top, (SettingWindow.Screen->Height - h) / 2, WA_PubScreen, (IPTR)SettingWindow.Screen, WA_Title, (IPTR)APP_LONG_NAME, WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_MENUPICK, WA_Gadgets, (IPTR)SettingWindow.GadgetList, TAG_END); SettingWindow.Window = x; if (!x) { return false; } Forbid(); struct Process *proc = (struct Process *)FindTask(NULL); OrgWindowPtr = proc->pr_WindowPtr; proc->pr_WindowPtr = x; Permit(); return true; } static void InitWindowSettings() { if (WindowSettings != NULL) { FreeSettings(WindowSettings); } WindowSettings = CopySettings(Settings); } static void SettingsProc(void) { if (!InitWindow() || !CreateGadgets() || !CreateWindow()) { DestroyWindow(); WindowProcRunning = false; return; } InitWindowSettings(); ShowLastSync((struct timeval *)&LastSync); MsgLoop(); SendMessageWait(MSGPORT_BROKER, ATK_UNDO); DestroyWindow(); WindowProcRunning = false; } static void MsgLoop(void) { bool loop = true; ULONG procPortSigMask = GetPortSignalMask(MSGPORT_WINDOW); ULONG windowSigMask = (1 << SettingWindow.Window->UserPort->mp_SigBit); ULONG sigMask = procPortSigMask | windowSigMask; GT_RefreshWindow(SettingWindow.Window, NULL); do { ULONG sigrcvd = Wait(sigMask); if (sigrcvd & windowSigMask) { struct IntuiMessage *msg; while ((msg = GT_GetIMsg(SettingWindow.Window->UserPort))) { switch (msg->Class) { case IDCMP_REFRESHWINDOW: GT_BeginRefresh(SettingWindow.Window); GT_EndRefresh(SettingWindow.Window, TRUE); break; case IDCMP_GADGETUP: HandleGadgetUp((struct Gadget *)msg->IAddress); break; case IDCMP_VANILLAKEY: if (msg->Code == 0x1b) { loop = false; } break; case IDCMP_CLOSEWINDOW: loop = false; break; } GT_ReplyIMsg(msg); } } if (sigrcvd & procPortSigMask) { struct ApplicationMesage *msg; while ((msg = (struct ApplicationMesage *)GetNewMessage(MSGPORT_WINDOW))) { long msgId = msg->MsgId; ReplyMsg((struct Message *)msg); switch (msgId) { case ATK_SHUTDOWN: loop = false; break; case ATK_LASTSYNC: ShowLastSync((struct timeval *)&LastSync); break; case ATK_TZ_CHANGED: ShowNewTimezone(); break; case ATK_SHOW: WindowToFront(SettingWindow.Window); break; default: break; } } } } while (loop); } static void HandleGadgetUp(struct Gadget *gadget) { switch (gadget->GadgetID) { case GID_SERVER: ReadUiServer(); break; case GID_PORT: ReadUiPort(); break; case GID_INTERVAL: ReadUiInterval(); break; case GID_TIMEOUT: ReadUiTimeout(); break; case GID_THRESHOLD: ReadUiThreshold(); break; case GID_PRIORITY: ReadUiCxPriority(); break; case GID_SAVE: UseSettings(); InitWindowSettings(); SendBrokerMessage(ATK_STORE); break; case GID_USE: UseSettings(); InitWindowSettings(); SendBrokerMessage(ATK_APPLY); break; case GID_CANCEL: SendBrokerMessage(ATK_UNDO); break; default: break; } }