AmiTimeKeeper/win_main.c

370 lines
8.7 KiB
C

/*-
* Copyright (c) 2017-2021 Carsten Sonne Larsen <cs@innolan.net>
* 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;
}
}