/* * 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 #include #include #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; }