1
0
mirror of https://frontier.innolan.net/rainlance/amiga-tz.git synced 2025-11-20 12:03:22 +00:00
Files
amiga-tz/timezone.c
2015-06-25 22:28:02 +02:00

483 lines
13 KiB
C

/*
* Copyright (c) 2015 Carsten 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.
*
*/
/**
* @file tzselect.c
* @brief
* Inspired from example at:
* http://thomas-rapp.homepage.t-online.de/examples/lv.c
*
* Retrieved 2015-06-20
*
*/
// --------------------------------------------------------------------------- //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zone.h"
#include "amiga_tz.h"
#include "version.h"
const char *vers = "\0$VER: TimeZone" AMIGA_VERSION;
// --------------------------------------------------------------------------- //
#define GID_LIST 1001
#define GID_STRING 1002
#define GID_TZ 1003
#define GID_SAVE 1010
#define GID_USE 1011
#define GID_CANCEL 1012
#ifndef __amigaos4__
#define NewList(list) ((list)->lh_Head = (struct Node *)&(list)->lh_Tail,(list)->lh_TailPred = (struct Node *)&(list)->lh_Head,(list)->lh_Tail = NULL)
#define GetHead(list) ((list) && (list)->lh_Head && (list)->lh_Head->ln_Succ ? (list)->lh_Head : NULL)
#define GetTail(list) ((list) && (list)->lh_TailPred && (list)->lh_TailPred->ln_Pred ? (list)->lh_TailPred : NULL)
#define GetSucc(node) ((node) && (node)->ln_Succ->ln_Succ ? (node)->ln_Succ : NULL)
#define GetPred(node) ((node) && (node)->ln_Pred->ln_Pred ? (node)->ln_Pred : NULL)
#endif
// --------------------------------------------------------------------------- //
// Globals variables
char *tz = NULL;
struct Library *DOSBase = NULL;
struct Library *UtilityBase = NULL;
struct Library *IntuitionBase = NULL;
struct Library *GadToolsBase = NULL;
struct Screen *screen = NULL;
struct Window *window = NULL;
struct Gadget *glist = NULL;
int gmtoffset = 0;
// Window variables
struct Gadget *lvgad;
struct Gadget *strgad;
struct Gadget *tzgad;
struct List lvlist;
char *tztext = NULL;
// Shared temporary variables
struct Gadget *lastgad;
int width;
int height;
// --------------------------------------------------------------------------- //
void amiga_cleanup();
void amiga_open_lib_error(char *name, int version)
{
fprintf(stderr, OPEN_VER_ERROR, name, version);
fprintf(stderr, REQ_ERROR);
}
int amiga_open_libs()
{
atexit(amiga_cleanup);
if(!(DOSBase = OpenLibrary(DOSLIB_NAME, DOSLIB_REV))) {
amiga_open_lib_error(DOSLIB_NAME, DOSLIB_REV);
return 1;
}
if(!(UtilityBase = OpenLibrary(UTILLIB_NAME, UTILLIB_REV))) {
amiga_open_lib_error(UTILLIB_NAME, UTILLIB_REV);
return 1;
}
if(!(IntuitionBase = OpenLibrary(INTUILIB_NAME, INTUILIB_REV))) {
amiga_open_lib_error(INTUILIB_NAME, INTUILIB_REV);
return 1;
}
if(!(GadToolsBase = OpenLibrary(GADTOOLLIB_NAME, GADTOOLLIB_REV))) {
amiga_open_lib_error(GADTOOLLIB_NAME, GADTOOLLIB_REV);
return 1;
}
if (!(screen = (struct Screen*)LockPubScreen(NULL)))
{
fprintf(stderr, OPEN_ERROR, PUBSCREEN_NAME);
return 1;
}
if (!(lastgad = CreateContext(&glist)))
{
fprintf(stderr, "cannot create gadget objects\n");
return 1;
}
NewList(&lvlist);
return 0;
}
void amiga_cleanup()
{
struct Node *node;
if (window != NULL) {
CloseWindow(window);
window = NULL;
}
while ((node = RemHead(&lvlist))) {
FreeVec(node);
}
if (glist != NULL) {
FreeGadgets (glist);
glist = NULL;
}
if (screen != NULL) {
UnlockPubScreen (NULL, screen);
screen = NULL;
}
if (GadToolsBase != NULL) {
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
if (IntuitionBase != NULL) {
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
if (UtilityBase != NULL) {
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
if (DOSBase != NULL) {
CloseLibrary(DOSBase);
DOSBase = NULL;
}
if (tztext != NULL) {
FreeVec(tztext);
tztext = NULL;
}
if (tz != NULL) {
FreeVec(tz);
tz = NULL;
}
}
// --------------------------------------------------------------------------- //
int amiga_open_window()
{
window = (struct Window*)OpenWindowTags (
NULL,
WA_Title, "Time zone preferences",
WA_Width, width,
WA_Height, height,
WA_Left, (screen->Width - width) / 2,
WA_Top, (screen->Height - height) / 2,
WA_Flags,WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE,
WA_IDCMP,IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_REFRESHWINDOW | BUTTONIDCMP | STRINGIDCMP | LISTVIEWIDCMP,
WA_PubScreen, screen,
WA_Gadgets, glist,
TAG_END
);
return window != NULL ? 0 : 1;
}
void amiga_setup_gui()
{
struct NewGadget ng;
int fontw, fonth;
ng.ng_VisualInfo = GetVisualInfo(screen, TAG_END);
ng.ng_TextAttr = screen->Font;
ng.ng_Flags = 0;
fontw = screen->RastPort.TxWidth;
fonth = screen->RastPort.TxHeight;
width = screen->WBorTop + fonth + 5; /* top of listview */
height = 20 * fonth + 4; /* height of listview */
ng.ng_LeftEdge = screen->WBorLeft + 4;
ng.ng_TopEdge = width + height;
ng.ng_Height = fonth + 6;
ng.ng_Width = (3*16 * fontw + 3*8 + 2*4);
ng.ng_GadgetText = NULL;
ng.ng_GadgetID = GID_STRING;
lastgad = CreateGadget(STRING_KIND,lastgad,&ng,GA_Disabled,TRUE,TAG_END);
strgad = lastgad;
ng.ng_TopEdge = width;
ng.ng_Height += height; /* including string height */
ng.ng_GadgetID = GID_LIST;
lastgad = CreateGadget(LISTVIEW_KIND,lastgad,&ng,GTLV_Labels,&lvlist,GTLV_ShowSelected,lastgad,TAG_END);
lvgad = lastgad;
ng.ng_TopEdge += ng.ng_Height + 4;
ng.ng_Width = 16 * fontw + 8;
ng.ng_Height = fonth + 6;
ng.ng_GadgetText = "";
ng.ng_GadgetID = GID_TZ;
lastgad = CreateGadget(TEXT_KIND, lastgad, &ng, TAG_END);
tzgad = lastgad;
ng.ng_TopEdge += (ng.ng_Height + 4) * 1.5;
ng.ng_LeftEdge = screen->WBorLeft + 4;
ng.ng_GadgetText = "Save";
ng.ng_GadgetID = GID_SAVE;
lastgad = CreateGadget (BUTTON_KIND,lastgad,&ng,TAG_END);
ng.ng_LeftEdge += ng.ng_Width + 4;
ng.ng_GadgetText = "Use";
ng.ng_GadgetID = GID_USE;
lastgad = CreateGadget (BUTTON_KIND,lastgad,&ng,TAG_END);
ng.ng_LeftEdge += ng.ng_Width + 4;
ng.ng_GadgetText = "Cancel";
ng.ng_GadgetID = GID_CANCEL;
lastgad = CreateGadget (BUTTON_KIND,lastgad,&ng,TAG_END);
width = ng.ng_LeftEdge + ng.ng_Width + 4 + screen->WBorRight;
height = ng.ng_TopEdge + ng.ng_Height + 4 + screen->WBorBottom;
}
// --------------------------------------------------------------------------- //
void load_tz()
{
if (tz != NULL) {
FreeVec(tz);
tz = NULL;
}
tz = AllocVec(ENVSIZE, MEMF_ANY | MEMF_CLEAR);
GetVar("TZ", tz, ENVSIZE - 1, GVF_GLOBAL_ONLY);
underscore_remove(tz);
gmtoffset = get_gmtoffset();
}
void set_tz(char *newtz)
{
if (tz != NULL) {
FreeVec(tz);
tz = NULL;
}
tz = AllocVec(strlen(newtz) + 1, MEMF_ANY);
strcpy(tz, newtz);
}
void use_tz()
{
int offset;
if (tz != NULL) {
underscore_add(tz);
SetVar("TZ", tz, strlen(tz) + 1, GVF_GLOBAL_ONLY);
}
}
void save_tz()
{
BPTR file;
if (tz != NULL) {
underscore_add(tz);
if ((file = Open("ENVARC:TZ", MODE_NEWFILE))) {
FPuts(file, tz);
Close(file);
}
}
}
void show_tz()
{
if (tztext != NULL) {
FreeVec(tztext);
}
if (tz != NULL) {
const char *txt1 = "Timezone is set to ";
tztext = AllocVec(strlen(txt1) + strlen(tz) + 1, MEMF_ANY);
strcpy(tztext, txt1);
strcat(tztext, tz);
} else {
const char *deftz = "Timezone is not set";
tztext = AllocVec(strlen(deftz) + 1, MEMF_ANY);
strcpy(tztext, deftz);
}
GT_SetGadgetAttrs(tzgad, window, NULL, GTTX_Text, tztext, TAG_END);
}
// --------------------------------------------------------------------------- //
int cmploc (const void * a, const void * b)
{
struct Location *loca, *locb;
loca = (struct Location*)a;
locb = (struct Location*)b;
return strcmp(loca->tz, locb->tz);
}
void populate_list()
{
unsigned int i;
struct Node *node = NULL;
const unsigned int count = sizeof(locations) / sizeof(struct Location);
qsort(locations, count, sizeof(struct Location), cmploc);
for (i = 0; i < count; i++) {
if ((node = AllocVec(sizeof(struct Node) + strlen(locations[i].tz) + 1, MEMF_CLEAR))) {
node->ln_Name = (STRPTR)(node + 1);
strcpy(node->ln_Name,locations[i].tz);
underscore_remove(node->ln_Name);
AddTail(&lvlist, node);
}
}
}
// --------------------------------------------------------------------------- //
struct Node *get_node (struct List *list,ULONG num)
{
struct Node *node;
ULONG i = 0;
for (node = GetHead(list); node; node = GetSucc(node))
{
if (i == num)
return (node);
i ++;
}
return (NULL);
}
ULONG node_number (struct List *list,struct Node *node_to_find)
{
struct Node *node;
ULONG i = 0;
for (node = GetHead(list); node; node = GetSucc(node))
{
if (node == node_to_find)
return (i);
i ++;
}
return (-1);
}
// --------------------------------------------------------------------------- //
int main (void)
{
BOOL cont;
ULONG num;
ULONG winsig, sigs;
struct Gadget *gad;
struct Node *node = NULL;
struct IntuiMessage *imsg;
if (amiga_open_libs()) {
exit(5);
}
amiga_setup_gui();
load_tz();
show_tz();
populate_list();
if (amiga_open_window()) {
exit(5);
}
GT_RefreshWindow(window, NULL);
GT_SetGadgetAttrs(lvgad, window, NULL, GTLV_Labels, &lvlist, TAG_END);
winsig = 1L << window->UserPort->mp_SigBit;
cont = TRUE;
do {
sigs = Wait(winsig | SIGBREAKF_CTRL_C);
if (sigs & SIGBREAKF_CTRL_C) {
cont = FALSE;
}
if (sigs & winsig) {
while ((imsg = GT_GetIMsg(window->UserPort))) {
switch (imsg->Class) {
case IDCMP_GADGETUP:
gad = (struct Gadget *)imsg->IAddress;
switch (gad->GadgetID) {
case GID_SAVE:
cont = FALSE;
save_tz();
break;
case GID_USE:
cont = FALSE;
use_tz();
break;
case GID_CANCEL:
cont = FALSE;
break;
case GID_LIST:
GT_GetGadgetAttrs(lvgad, window, NULL, GTLV_Selected, &num, TAG_END);
if ((node = get_node(&lvlist, num))) {
set_tz(node->ln_Name);
GT_SetGadgetAttrs (strgad, window, NULL, GTST_String, node->ln_Name, GA_Disabled, FALSE, TAG_END);
ActivateGadget(strgad, window, NULL);
}
break;
}
break;
case IDCMP_VANILLAKEY:
if (imsg->Code == 0x1b) /* Esc */
cont = FALSE;
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(window);
GT_EndRefresh(window, TRUE);
break;
case IDCMP_CLOSEWINDOW:
cont = FALSE;
break;
}
GT_ReplyIMsg(imsg);
}
}
}
while (cont);
amiga_cleanup();
return 0;
}