564 lines
14 KiB
C
564 lines
14 KiB
C
#include "tzversion.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "zone.h"
|
|
|
|
const char *vers = "\0$VER: TimeZone" AMIGA_VERSION;
|
|
|
|
#define GID_LIST 1001
|
|
#define GID_TZ 1003
|
|
#define GID_USE_TZ 1004
|
|
#define GID_USE_LT 1005
|
|
#define GID_SAVE 1010
|
|
#define GID_USE 1011
|
|
#define GID_CANCEL 1012
|
|
|
|
#ifdef AOS3
|
|
#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 Library *TimezoneBase = NULL;
|
|
struct Screen *screen = NULL;
|
|
struct Window *window = NULL;
|
|
struct Gadget *glist = NULL;
|
|
|
|
// Window variables
|
|
struct Gadget *lvgad;
|
|
struct Gadget *tzgad;
|
|
struct Gadget *usetzgad;
|
|
struct Gadget *useltgad;
|
|
struct List lvlist;
|
|
char *tztext = NULL;
|
|
|
|
// Shared temporary variables
|
|
struct Gadget *lastgad;
|
|
int width;
|
|
int height;
|
|
int startindex;
|
|
|
|
void save_localtime();
|
|
void amiga_cleanup();
|
|
void copy_file(char *fromname, char *toname);
|
|
|
|
void amiga_open_lib_error(char *name, int version)
|
|
{
|
|
FPrintf(Output(), (STRPTR)OPEN_VER_ERROR, name, version);
|
|
}
|
|
|
|
int amiga_open_libs()
|
|
{
|
|
atexit(amiga_cleanup);
|
|
|
|
if(!(DOSBase = OpenLibrary((CONST_STRPTR)DOSLIB_NAME, DOSLIB_REV))) {
|
|
amiga_open_lib_error(DOSLIB_NAME, DOSLIB_REV);
|
|
return 1;
|
|
}
|
|
|
|
if(!(UtilityBase = OpenLibrary((CONST_STRPTR)UTILLIB_NAME, UTILLIB_REV))) {
|
|
amiga_open_lib_error(UTILLIB_NAME, UTILLIB_REV);
|
|
return 1;
|
|
}
|
|
|
|
if(!(IntuitionBase = OpenLibrary((CONST_STRPTR)INTUILIB_NAME, INTUILIB_REV))) {
|
|
amiga_open_lib_error(INTUILIB_NAME, INTUILIB_REV);
|
|
return 1;
|
|
}
|
|
|
|
if(!(GadToolsBase = OpenLibrary((CONST_STRPTR)GADTOOLLIB_NAME, GADTOOLLIB_REV))) {
|
|
amiga_open_lib_error(GADTOOLLIB_NAME, GADTOOLLIB_REV);
|
|
return 1;
|
|
}
|
|
|
|
if(!(TimezoneBase = OpenLibrary((CONST_STRPTR)TIMEZONELIB_NAME, TIMEZONELIB_REV))) {
|
|
amiga_open_lib_error(TIMEZONELIB_NAME, TIMEZONELIB_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 (TimezoneBase != NULL) {
|
|
CloseLibrary(TimezoneBase);
|
|
TimezoneBase = NULL;
|
|
}
|
|
|
|
if (GadToolsBase != NULL) {
|
|
CloseLibrary(GadToolsBase);
|
|
GadToolsBase = NULL;
|
|
}
|
|
|
|
if (IntuitionBase != NULL) {
|
|
CloseLibrary(IntuitionBase);
|
|
IntuitionBase = 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 | 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;
|
|
|
|
ng.ng_LeftEdge = screen->WBorLeft + 4;
|
|
ng.ng_TopEdge = screen->WBorTop + fonth + 5;
|
|
ng.ng_Height = 20 * fonth + 4;
|
|
ng.ng_Width = (3*16 * fontw + 3*8 + 2*4);
|
|
ng.ng_GadgetID = GID_LIST;
|
|
lastgad = CreateGadget(LISTVIEW_KIND, lastgad, &ng, GTLV_Labels, &lvlist, GTLV_ShowSelected, NULL, 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 = NULL;
|
|
ng.ng_GadgetID = GID_TZ;
|
|
lastgad = CreateGadget(TEXT_KIND, lastgad, &ng, TAG_END);
|
|
tzgad = lastgad;
|
|
|
|
ng.ng_TopEdge += ng.ng_Height + 4;
|
|
ng.ng_Flags = PLACETEXT_RIGHT;
|
|
ng.ng_GadgetText = (STRPTR)"Use TZ variable (advanced)";
|
|
ng.ng_GadgetID = GID_USE_TZ;
|
|
lastgad = CreateGadget(CHECKBOX_KIND, lastgad, &ng, TAG_END);
|
|
usetzgad = lastgad;
|
|
|
|
ng.ng_TopEdge += ng.ng_Height + 4;
|
|
ng.ng_LeftEdge = screen->WBorLeft + 4;
|
|
ng.ng_GadgetText = (STRPTR)"Use localtime file";
|
|
ng.ng_GadgetID = GID_USE_LT;
|
|
lastgad = CreateGadget(CHECKBOX_KIND, lastgad, &ng, TAG_END);
|
|
useltgad = lastgad;
|
|
|
|
ng.ng_TopEdge += ng.ng_Height + 6;
|
|
ng.ng_LeftEdge = screen->WBorLeft + 4;
|
|
ng.ng_GadgetText = (STRPTR)"Save";
|
|
ng.ng_GadgetID = GID_SAVE;
|
|
ng.ng_Flags = 0;
|
|
lastgad = CreateGadget (BUTTON_KIND,lastgad,&ng,TAG_END);
|
|
|
|
ng.ng_LeftEdge += ng.ng_Width + 4;
|
|
ng.ng_GadgetText = (STRPTR)"Use";
|
|
ng.ng_GadgetID = GID_USE;
|
|
lastgad = CreateGadget (BUTTON_KIND,lastgad,&ng,TAG_END);
|
|
|
|
ng.ng_LeftEdge += ng.ng_Width + 4;
|
|
ng.ng_GadgetText = (STRPTR)"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);
|
|
if(GetVar((STRPTR)TZVARIABLE, (STRPTR)tz, ENVSIZE - 1, GVF_GLOBAL_ONLY) == -1) {
|
|
FreeVec(tz);
|
|
tz = NULL;
|
|
} else {
|
|
utos(tz);
|
|
}
|
|
}
|
|
|
|
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()
|
|
{
|
|
long checked;
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
if (tz != NULL) {
|
|
stou(tz);
|
|
SetVar((STRPTR)TZVARIABLE, (STRPTR)tz, strlen(tz) + 1, GVF_GLOBAL_ONLY);
|
|
|
|
GT_GetGadgetAttrs(usetzgad, window, NULL, GTCB_Checked, &checked, TAG_END);
|
|
if (checked) {
|
|
SetVar((STRPTR)"TZ", (STRPTR)tz, strlen(tz) + 1, GVF_GLOBAL_ONLY);
|
|
}
|
|
|
|
tzset();
|
|
settimeofday(&tv, NULL);
|
|
}
|
|
}
|
|
|
|
void save_tz()
|
|
{
|
|
char *name;
|
|
long checked;
|
|
BPTR file;
|
|
|
|
if (tz != NULL) {
|
|
stou(tz);
|
|
|
|
name = (char*)AllocVec(7 + strlen(TZVARIABLE) + 1, MEMF_ANY | MEMF_CLEAR);
|
|
strcpy(name, "ENVARC:");
|
|
strcat(name, TZVARIABLE);
|
|
|
|
if ((file = Open((STRPTR)name, MODE_NEWFILE))) {
|
|
FPuts(file, (STRPTR)tz);
|
|
Close(file);
|
|
}
|
|
|
|
FreeVec(name);
|
|
|
|
GT_GetGadgetAttrs(usetzgad, window, NULL, GTCB_Checked, &checked, TAG_END);
|
|
if (checked) {
|
|
SetVar((STRPTR)"TZ", (STRPTR)tz, strlen(tz) + 1, GVF_GLOBAL_ONLY);
|
|
}
|
|
|
|
GT_GetGadgetAttrs(useltgad, window, NULL, GTCB_Checked, &checked, TAG_END);
|
|
if (checked) {
|
|
save_localtime();
|
|
}
|
|
|
|
tzset();
|
|
}
|
|
}
|
|
|
|
void save_localtime()
|
|
{
|
|
char *source, *dest;
|
|
|
|
source = (char*)AllocVec(sizeof(TZDIR) + strlen(tz) + 2 , MEMF_ANY | MEMF_CLEAR);
|
|
strcpy(source, TZDIR);
|
|
strcat(source, "/");
|
|
strcat(source, tz);
|
|
|
|
dest = (char*)AllocVec(sizeof(TZDIR) + sizeof(TZDEFAULT) + 2 , MEMF_ANY | MEMF_CLEAR);
|
|
strcpy(dest, TZDIR);
|
|
strcat(dest, "/");
|
|
strcat(dest, TZDEFAULT);
|
|
|
|
copy_file(source, dest);
|
|
|
|
FreeVec(source);
|
|
FreeVec(dest);
|
|
}
|
|
|
|
void show_tz()
|
|
{
|
|
if (tztext != NULL) {
|
|
FreeVec(tztext);
|
|
}
|
|
|
|
if (*tz != '\0') {
|
|
const char *txt1 = "Time zone is set to ";
|
|
tztext = AllocVec(strlen(txt1) + strlen(tz) + 1, MEMF_ANY);
|
|
strcpy(tztext, txt1);
|
|
strcat(tztext, tz);
|
|
} else {
|
|
const char *deftz = "Time zone 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);
|
|
|
|
startindex = 0;
|
|
for (i = 0; i < count; i++) {
|
|
if ((node = AllocVec(sizeof(struct Node) + strlen(locations[i].tz) + 1, MEMF_CLEAR))) {
|
|
node->ln_Name = (char*)(node + 1);
|
|
strcpy(node->ln_Name,locations[i].tz);
|
|
utos(node->ln_Name);
|
|
AddTail(&lvlist, node);
|
|
|
|
if (!strcmp(tz, node->ln_Name)) {
|
|
startindex = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
int showindex;
|
|
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_SetGadgetAttrs(lvgad, window, NULL, GTLV_Labels, &lvlist, TAG_END);
|
|
|
|
if (startindex != 0) {
|
|
showindex = startindex - 3;
|
|
if (showindex < 0) {
|
|
showindex = 0;
|
|
}
|
|
|
|
GT_SetGadgetAttrs(lvgad, window, NULL, GTLV_Selected, startindex, GTLV_Top, showindex, TAG_END);
|
|
}
|
|
|
|
GT_RefreshWindow(window, NULL);
|
|
|
|
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;
|
|
use_tz();
|
|
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);
|
|
}
|
|
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;
|
|
}
|
|
|
|
void copy_file(char *fromname, char *toname)
|
|
{
|
|
const int bufsize = 512;
|
|
STRPTR buffer;
|
|
LONG s;
|
|
BPTR fromfile, tofile;
|
|
|
|
buffer = (STRPTR)AllocMem(bufsize, MEMF_PUBLIC);
|
|
if (!buffer) {
|
|
return;
|
|
}
|
|
|
|
fromfile = Open((STRPTR)fromname, MODE_OLDFILE);
|
|
if (!fromfile) {
|
|
fprintf(stderr, "Can't read %s\n", fromname);
|
|
FreeMem(buffer, bufsize);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
tofile = Open((STRPTR)toname, MODE_NEWFILE);
|
|
if (!tofile) {
|
|
Close(fromfile);
|
|
FreeMem(buffer, bufsize);
|
|
fprintf(stderr, "Can't create %s\n", toname);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
do {
|
|
Flush(fromfile);
|
|
if ((s = Read(fromfile, buffer, bufsize)) == -1 || Write(tofile, buffer, s) != s)
|
|
{
|
|
break;
|
|
}
|
|
} while (s > 0);
|
|
|
|
FreeMem(buffer, bufsize);
|
|
Close(tofile);
|
|
Close(fromfile);
|
|
}
|