comparison src/win32/libc_interface.c @ 13333:b04212d6b115

[gaim-migrate @ 15703] win32 TZ name to abbreviation conversion. This make the behavior consistent across platforms. committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Mon, 27 Feb 2006 08:49:14 +0000
parents 33bef17125c2
children 0f708ed02902
comparison
equal deleted inserted replaced
13332:97545c71d208 13333:b04212d6b115
1 /* 1 /*
2 * gaim 2 * gaim
3 *
4 * File: libc_interface.c
5 * Date: October 14, 2002
6 * Description: libc interface for Windows api
7 * 3 *
8 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com> 4 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
9 * 5 *
10 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
39 #else 35 #else
40 #define g_remove remove 36 #define g_remove remove
41 #define g_rename rename 37 #define g_rename rename
42 #define g_stat stat 38 #define g_stat stat
43 #endif 39 #endif
44 /*
45 * PROTOS
46 */
47
48 /*
49 * LOCALS
50 */
51 40
52 static char errbuf[1024]; 41 static char errbuf[1024];
53
54 /*
55 * CODE
56 */
57 42
58 /* helpers */ 43 /* helpers */
59 static int wgaim_is_socket( int fd ) { 44 static int wgaim_is_socket( int fd ) {
60 int optval; 45 int optval;
61 unsigned int optlen = sizeof(int); 46 unsigned int optlen = sizeof(int);
434 if(resultp && tmptm) 419 if(resultp && tmptm)
435 return memcpy(resultp, tmptm, sizeof(struct tm)); 420 return memcpy(resultp, tmptm, sizeof(struct tm));
436 else 421 else
437 return NULL; 422 return NULL;
438 } 423 }
424
425 /*
426 * Used by gaim_utf8_strftime() by way of gaim_internal_strftime()
427 * in src/util.c
428 *
429 * Code derived from PostgreSQL src/timezone/pgtz.c:
430 * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
431 */
432
433 /*
434 PostgreSQL Database Management System
435 (formerly known as Postgres, then as Postgres95)
436
437 Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
438
439 Portions Copyright (c) 1994, The Regents of the University of California
440
441 Permission to use, copy, modify, and distribute this software and its
442 documentation for any purpose, without fee, and without a written agreement
443 is hereby granted, provided that the above copyright notice and this
444 paragraph and the following two paragraphs appear in all copies.
445
446 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
447 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
448 LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
449 DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
450 POSSIBILITY OF SUCH DAMAGE.
451
452 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
453 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
454 AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
455 ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
456 PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
457
458 */
459 static const struct
460 {
461 const char *wstd; /* Windows name of standard timezone */
462 const char *wdst; /* Windows name of daylight timezone */
463 const char *ustd; /* Unix name of standard timezone */
464 const char *udst; /* Unix name of daylight timezone */
465 } win32_tzmap[] =
466 {
467 /*
468 * This list was built from the contents of the registry at
469 * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
470 * on Windows XP Professional SP1
471 */
472 {
473 "Afghanistan Standard Time", "Afghanistan Daylight Time",
474 "AFT", "AFT"
475 },
476 {
477 "Alaskan Standard Time", "Alaskan Daylight Time",
478 "AKST", "AKDT"
479 },
480 {
481 "Arab Standard Time", "Arab Daylight Time",
482 "AST", "AST"
483 },
484 {
485 "Arabian Standard Time", "Arabian Daylight Time",
486 "GST", "GST"
487 },
488 {
489 "Arabic Standard Time", "Arabic Daylight Time",
490 "AST", "ADT"
491 },
492 {
493 "Atlantic Standard Time", "Atlantic Daylight Time",
494 "AST", "ADT"
495 },
496 {
497 "AUS Central Standard Time", "AUS Central Daylight Time",
498 "CST", "CST"
499 },
500 {
501 "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
502 "EST", "EST"
503 },
504 {
505 "Azores Standard Time", "Azores Daylight Time",
506 "AZOT", "AZOST"
507 },
508 {
509 "Canada Central Standard Time", "Canada Central Daylight Time",
510 "CST", "MDT"
511 },
512 {
513 "Cape Verde Standard Time", "Cape Verde Daylight Time",
514 "CVT", "CVST"
515 },
516 {
517 "Caucasus Standard Time", "Caucasus Daylight Time",
518 "AZT", "AZST"
519 },
520 {
521 "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
522 "CST", "CST"
523 },
524 {
525 "Central America Standard Time", "Central America Daylight Time",
526 "CST", "CDT"
527 },
528 {
529 "Central Asia Standard Time", "Central Asia Daylight Time",
530 "BDT", "BDT"
531 },
532 {
533 "Central Europe Standard Time", "Central Europe Daylight Time",
534 "CET", "CEST"
535 },
536 {
537 "Central European Standard Time", "Central European Daylight Time",
538 "CET", "CEST"
539 },
540 {
541 "Central Pacific Standard Time", "Central Pacific Daylight Time",
542 "NCT", "NCST"
543 },
544 {
545 "Central Standard Time", "Central Daylight Time",
546 "CST", "CDT"
547 },
548 {
549 "China Standard Time", "China Daylight Time",
550 "HKT", "HKST"
551 },
552 {
553 "Dateline Standard Time", "Dateline Daylight Time",
554 "GMT+12", "GMT+12"
555 },
556 {
557 "E. Africa Standard Time", "E. Africa Daylight Time",
558 "EAT", "EAT"
559 },
560 {
561 "E. Australia Standard Time", "E. Australia Daylight Time",
562 "EST", "EST"
563 },
564 {
565 "E. Europe Standard Time", "E. Europe Daylight Time",
566 "EET", "EEST"
567 },
568 {
569 "E. South America Standard Time", "E. South America Daylight Time",
570 "BRT", "BRST"
571 },
572 {
573 "Eastern Standard Time", "Eastern Daylight Time",
574 "EST", "EDT"
575 },
576 {
577 "Egypt Standard Time", "Egypt Daylight Time",
578 "EET", "EEST"
579 },
580 {
581 "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
582 "YEKT", "YEKST"
583 },
584 {
585 "Fiji Standard Time", "Fiji Daylight Time",
586 "FJT", "FJST"
587 },
588 {
589 "FLE Standard Time", "FLE Daylight Time",
590 "EET", "EEST"
591 },
592 {
593 "GMT Standard Time", "GMT Daylight Time",
594 "GMT", "IST"
595 },
596 {
597 "Greenland Standard Time", "Greenland Daylight Time",
598 "WGT", "WGST"
599 },
600 {
601 "Greenwich Standard Time", "Greenwich Daylight Time",
602 "WET", "WEST"
603 },
604 {
605 "GTB Standard Time", "GTB Daylight Time",
606 "EET", "EEST"
607 },
608 {
609 "Hawaiian Standard Time", "Hawaiian Daylight Time",
610 "HST", "HPT"
611 },
612 {
613 "India Standard Time", "India Daylight Time",
614 "IST", "IST"
615 },
616 {
617 "Iran Standard Time", "Iran Daylight Time",
618 "IRST", "IRDT"
619 },
620 {
621 "Jerusalem Standard Time", "Jerusalem Daylight Time",
622 "IST", "IDT"
623 },
624 {
625 "Korea Standard Time", "Korea Daylight Time",
626 "KST", "KDT"
627 },
628 {
629 "Mexico Standard Time", "Mexico Daylight Time",
630 "CST", "CDT"
631 },
632 {
633 "Mexico Standard Time", "Mexico Daylight Time",
634 "BOT", "BOST"
635 },
636 {
637 "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
638 "GST", "GST"
639 },
640 {
641 "Mountain Standard Time", "Mountain Daylight Time",
642 "MST", "MDT"
643 },
644 {
645 "Myanmar Standard Time", "Myanmar Daylight Time",
646 "MMT", "MMT"
647 },
648 {
649 "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
650 "ALMT", "ALMST"
651 },
652 {
653 "Nepal Standard Time", "Nepal Daylight Time",
654 "NPT", "NPT"
655 },
656 {
657 "New Zealand Standard Time", "New Zealand Daylight Time",
658 "NZST", "NZDT"
659 },
660 {
661 "Newfoundland Standard Time", "Newfoundland Daylight Time",
662 "NST", "NDT"
663 },
664 {
665 "North Asia East Standard Time", "North Asia East Daylight Time",
666 "IRKT", "IRKST"
667 },
668 {
669 "North Asia Standard Time", "North Asia Daylight Time",
670 "KRAT", "KRAST"
671 },
672 {
673 "Pacific SA Standard Time", "Pacific SA Daylight Time",
674 "CLT", "CLST"
675 },
676 {
677 "Pacific Standard Time", "Pacific Daylight Time",
678 "PST", "PDT"
679 },
680 {
681 "Romance Standard Time", "Romance Daylight Time",
682 "CET", "CEST"
683 },
684 {
685 "Russian Standard Time", "Russian Daylight Time",
686 "MSK", "MSD"
687 },
688 {
689 "SA Eastern Standard Time", "SA Eastern Daylight Time",
690 "ART", "ARST"
691 },
692 {
693 "SA Pacific Standard Time", "SA Pacific Daylight Time",
694 "COT", "COST"
695 },
696 {
697 "SA Western Standard Time", "SA Western Daylight Time",
698 "VET", "VET"
699 },
700 {
701 "Samoa Standard Time", "Samoa Daylight Time",
702 "SST", "NDT"
703 },
704 {
705 "SE Asia Standard Time", "SE Asia Daylight Time",
706 "ICT", "ICT"
707 },
708 {
709 "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
710 "MYT", "MALST"
711 },
712 {
713 "South Africa Standard Time", "South Africa Daylight Time",
714 "CAT", "CAT"
715 },
716 {
717 "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
718 "LKT", "IST"
719 },
720 {
721 "Taipei Standard Time", "Taipei Daylight Time",
722 "CST", "CDT"
723 },
724 {
725 "Tasmania Standard Time", "Tasmania Daylight Time",
726 "EST", "EST"
727 },
728 {
729 "Tokyo Standard Time", "Tokyo Daylight Time",
730 "JST", "JDT"
731 },
732 {
733 "Tonga Standard Time", "Tonga Daylight Time",
734 "TOT", "TOST"
735 },
736 {
737 "US Eastern Standard Time", "US Eastern Daylight Time",
738 "EST", "EDT"
739 },
740 {
741 "US Mountain Standard Time", "US Mountain Daylight Time",
742 "MST", "MDT"
743 },
744 {
745 "Vladivostok Standard Time", "Vladivostok Daylight Time",
746 "VLAT", "VLAST"
747 },
748 {
749 "W. Australia Standard Time", "W. Australia Daylight Time",
750 "WST", "WST"
751 },
752
753 /* Not mapped in PostgreSQL.
754 *
755 * I mapped this based on the following information... -- rlaager
756 * $ cd /usr/share/zoneinfo/Africa
757 * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
758 * +0100 CET Algiers
759 * +0100 WAT Bangui
760 * +0100 WAT Brazzaville
761 * +0100 CET Ceuta
762 * +0100 WAT Douala
763 * +0100 WAT Kinshasa
764 * +0100 WAT Lagos
765 * +0100 WAT Libreville
766 * +0100 WAT Luanda
767 * +0100 WAT Malabo
768 * +0100 WAT Ndjamena
769 * +0100 WAT Niamey
770 * +0100 WAT Porto-Novo
771 * +0100 CET Tunis
772 **/
773 {
774 "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
775 "WAT", "WAT"
776 },
777
778 {
779 "W. Europe Standard Time", "W. Europe Daylight Time",
780 "CET", "CEST"
781 },
782 {
783 "West Asia Standard Time", "West Asia Daylight Time",
784 "PKT", "PKST"
785 },
786 {
787 "West Pacific Standard Time", "West Pacific Daylight Time",
788 "ChST", "ChST"
789 },
790 {
791 "Yakutsk Standard Time", "Yakutsk Daylight Time",
792 "YAKT", "YAKST"
793 },
794 {
795 NULL, NULL,
796 NULL, NULL
797 }
798 };
799
800 const char *
801 wgaim_get_timezone_abbreviation(const struct tm *tm)
802 {
803 int i;
804 char tzname[128];
805 char localtzname[256];
806 HKEY rootKey;
807 int idx;
808
809 if (!tm)
810 {
811 gaim_debug_warning("wgaim", "could not determine current date/time: localtime failed");
812 return NULL;
813 }
814
815 memset(tzname, 0, sizeof(tzname));
816 strftime(tzname, sizeof(tzname) - 1, "%Z", tm);
817
818 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
819 {
820 if (strcmp(tzname, win32_tzmap[i].wstd) == 0)
821 {
822 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"",
823 win32_tzmap[i].ustd, tzname);
824 return win32_tzmap[i].ustd;
825 }
826 if (strcmp(tzname, win32_tzmap[i].wdst) == 0)
827 {
828 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"",
829 win32_tzmap[i].udst, tzname);
830 return win32_tzmap[i].udst;
831 }
832 }
833
834 /*
835 * Localized Windows versions return localized names for the timezone.
836 * Scan the registry to find the English name, and then try matching
837 * against our table again.
838 */
839 memset(localtzname, 0, sizeof(localtzname));
840 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
841 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
842 0,
843 KEY_READ,
844 &rootKey) != ERROR_SUCCESS)
845 {
846 gaim_debug_warning("wgaim", "could not open registry key to identify Windows timezone: %i", (int) GetLastError());
847 return NULL;
848 }
849
850 for (idx = 0;; idx++)
851 {
852 char keyname[256];
853 char zonename[256];
854 DWORD namesize;
855 FILETIME lastwrite;
856 HKEY key;
857 LONG r;
858
859 memset(keyname, 0, sizeof(keyname));
860 namesize = sizeof(keyname);
861 if ((r = RegEnumKeyEx(rootKey,
862 idx,
863 keyname,
864 &namesize,
865 NULL,
866 NULL,
867 NULL,
868 &lastwrite)) != ERROR_SUCCESS)
869 {
870 if (r == ERROR_NO_MORE_ITEMS)
871 break;
872 gaim_debug_warning("wgaim", "could not enumerate registry subkeys to identify Windows timezone: %i", (int) r);
873 break;
874 }
875
876 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
877 {
878 gaim_debug_warning("wgaim", "could not open registry subkey to identify Windows timezone: %i", (int) r);
879 break;
880 }
881
882 memset(zonename, 0, sizeof(zonename));
883 namesize = sizeof(zonename);
884 if ((r = RegQueryValueEx(key, "Std", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
885 {
886 gaim_debug_warning("wgaim", "could not query value for 'std' to identify Windows timezone: %i", (int) r);
887 RegCloseKey(key);
888 break;
889 }
890 if (strcmp(tzname, zonename) == 0)
891 {
892 /* Matched zone */
893 strcpy(localtzname, keyname);
894 RegCloseKey(key);
895 break;
896 }
897 memset(zonename, 0, sizeof(zonename));
898 namesize = sizeof(zonename);
899 if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
900 {
901 gaim_debug_warning("wgaim", "could not query value for 'dlt' to identify Windows timezone: %i", (int) r);
902 RegCloseKey(key);
903 break;
904 }
905 if (strcmp(tzname, zonename) == 0)
906 {
907 /* Matched DST zone */
908 strcpy(localtzname, keyname);
909 RegCloseKey(key);
910 break;
911 }
912
913 RegCloseKey(key);
914 }
915
916 RegCloseKey(rootKey);
917
918 if (localtzname[0])
919 {
920 /* Found a localized name, so scan for that one too */
921 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
922 {
923 if (strcmp(localtzname, win32_tzmap[i].wstd) == 0)
924 {
925 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")",
926 win32_tzmap[i].ustd, tzname, localtzname);
927 return win32_tzmap[i].ustd;
928 }
929 if (strcmp(localtzname, win32_tzmap[i].wdst) == 0)
930 {
931 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")",
932 win32_tzmap[i].udst, tzname, localtzname);
933 return win32_tzmap[i].udst;
934 }
935 }
936 }
937
938 gaim_debug_warning("wgaim", "could not find a match for Windows timezone \"%s\"", tzname);
939 return "";
940 }