LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 1 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 1 /********************************************************************** 2 * Locale.c,v 3.9 1994/12/05 22:44:42 lindner Exp 3 * 4 * Paul Lindner, University of Minnesota DCS 5 * 6 * Copyright 1994 by the Regents of the University of Minnesota 7 * see the file "Copyright" in the distribution for conditions of use. 8 ********************************************************************** 9 * MODULE: Locale.c 10 * These routines make using the international messages facilities easier. 11 * 12 * This interface could be applied to methods other than X/Open coding 13 * (VMS etc..) 14 ********************************************************************** 15 * Locale.c,v 16 * Revision 3.9 1994/12/05 22:44:42 lindner 17 * Added VMS code from F. Macrides for specifying the default language 18 * via the GOPHERMSGS_DEFAULT definition in conf.h, for when a series of 19 * languages have been made available by setting the DCL logical 20 * LC_MESSAGES to the * wildcard. 21 * 22 * Added code for specifying the device where shared images of message 23 * files will be found, via the GOPHERMSGS_DEV definition in conf.h. 24 * 25 * Blocked potential ACCVIO's for VMSers who misunderstand how to set up 26 * the messaging and do it wrong. 27 * 28 * Revision 3.8 1994/11/24 08:10:20 lindner 29 * sundry compiler fixes 30 * 31 * Revision 3.7 1994/11/17 06:34:00 lindner 32 * Fixes for VMS internationalization 33 * 34 * Revision 3.6 1994/08/19 16:27:51 lindner 35 * Alan's mega-patch for Locale stuff 36 * 37 * Revision 3.5 1994/07/25 14:00:35 lindner 38 * Add std comments 39 * 40 */ 41 42 #include "Locale.h" 122 123 #ifdef GINTERNATIONAL 124 125 #include "Stdlib.h" 999 #include "String.h" 1516 #include "DAarray.h" 1585 #include "STRstring.h" 1664 #include "fileio.h" 2774 #include 2837 2838 nl_catd Gcatd = (nl_catd) -1; 2839 2840 #ifdef NO_XPGCAT LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 2 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 2841 X /** if we're not using the X/Open message catalogs, we have to keep 2842 X track of the locale **/ 2843 X String *msgLocale = NULL; 2844 #endif /* NO_XPGCAT */ 2845 2846 /*************** DynArray of messages ***************/ 2847 typedef DynArray GtxtArray; 2848 GtxtArray *GtxtMsgs = (GtxtArray *) NULL; 2849 2850 #define GtxtNew STRnew 2851 #define GtxtInit STRinit 2852 #define GtxtCopy STRcpy 2853 #define GtxtDestroy STRdestroy 2854 2855 /*************** Public interfaces ***************/ 2856 2857 char * 2858 Gtxt (defaultString, msgNumber) 2859 char *defaultString; 2860 int msgNumber; 2861 { 2862 1 String *msgString; 2863 1 2864 1 if ( (Gcatd == (nl_catd) -1) ) 2865 1 return defaultString; 2866 1 2867 1 if ( GtxtMsgs != NULL ) { 2868 2 if (DAgetNumitems(GtxtMsgs) < msgNumber) { 2869 3 DAgrow(GtxtMsgs, msgNumber); 2870 3 } 2871 2 msgString = (String *) DAgetEntry(GtxtMsgs, msgNumber - 1); 2872 2 #ifndef NO_XPGCAT 2873 2 if (STRlen(msgString) == 0) { 2874 3 STRset(msgString, 2875 3 catgets(Gcatd, NL_SETD, msgNumber, defaultString)); 2876 3 } 2877 2 #endif 2878 2 if (STRget(msgString) != NULL) 2879 2 return (STRget(msgString)); 2880 2 } 2881 1 2882 1 #ifdef NO_XPGCAT 2883 X return defaultString; 2884 1 #else 2885 1 return (catgets(Gcatd, NL_SETD, msgNumber, defaultString)); 2886 1 #endif 2887 1 } 2888 2889 #ifdef flags 2890 X #undef flags 2891 #endif 2892 2893 nl_catd 2894 Gtxtopen (catname, flags) 2895 char *catname; 2896 int flags; /* not used */ 2897 { LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 3 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 2898 1 #ifdef NO_XPGCAT 2899 X FileIO *fio = NULL; 2900 X char quotechar = '\0'; 2901 X char inputline[1024]; 2902 1 #endif /*NO_XPGCAT*/ 2903 1 2904 1 if (GtxtMsgs != NULL) { 2905 2 DAdestroy(GtxtMsgs); 2906 2 } 2907 1 2908 1 #ifdef NO_XPGCAT 2909 X if (strchr(catname,'/') != NULL) { /* file path name */ 2910 X fio = FIOopenUFS(catname, O_RDONLY, 0); 2911 X } else if ( (msgLocale != NULL) && (STRlen(msgLocale) > 0) ) { 2912 X sprintf(inputline, "%s/%s.msg", LOCALEDIR, STRget(msgLocale)); 2913 X fio = FIOopenUFS(inputline, O_RDONLY, 0); 2914 X } 2915 X 2916 X if (fio != NULL) { 2917 X GtxtMsgs = (GtxtArray *) DAnew(10, GtxtNew, GtxtInit, 2918 X GtxtDestroy, GtxtCopy); 2919 X 2920 X if (GtxtMsgs == NULL) { 2921 X FIOclose(fio); 2922 X Gcatd = -1; 2923 X return Gcatd; 2924 X } 2925 X 2926 X while (FIOreadline(fio, inputline, sizeof(inputline))) { 2927 X if (*inputline == '$') { 2928 X if (strncmp(inputline + 1, "quote ", 6)==0) 2929 X quotechar = *(inputline + 7); 2930 X } else if (isdigit(*inputline)) { 2931 X char *cp, *cp2; 2932 X int msgNumber; 2933 X 2934 X msgNumber = atoi(inputline); 2935 X if (msgNumber != 0) { 2936 X if (quotechar != '\0') { 2937 X cp = strchr(inputline, quotechar); 2938 X if (cp != NULL) { 2939 X cp2 = cp++; 2940 X do { 2941 X cp2 = strchr(cp2 + 1, quotechar); 2942 X } while ((cp2 != NULL) && (*(cp2-1) == '\\')); 2943 X if (cp2 != NULL) 2944 X *cp2 = '\0'; 2945 X } 2946 X } else { 2947 X cp = inputline; 2948 X while (isdigit(*cp)) 2949 X cp++; 2950 X cp++; /* skip exactly one char after number */ 2951 X 2952 X cp2 = cp + strlen(cp); 2953 X if (*cp2 == '\n') /* strip trailing return */ 2954 X *cp2 = '\0'; LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 4 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 2955 X } 2956 X if (cp != NULL) { 2957 X if (DAgetNumitems(GtxtMsgs) < msgNumber) { 2958 X DAgrow(GtxtMsgs, msgNumber); 2959 X } 2960 X STRset((String *) 2961 X DAgetEntry(GtxtMsgs, msgNumber - 1), cp); 2962 X } 2963 X } 2964 X } 2965 X } 2966 X FIOclose(fio); 2967 X Gcatd = 1; /* random positive number */ 2968 X } 2969 X else 2970 X Gcatd = -1; 2971 1 #else 2972 1 Gcatd = catopen(catname, flags); 2973 1 2974 1 if (Gcatd != (nl_catd) -1) { 2975 2 GtxtMsgs = (GtxtArray *) DAnew(10, GtxtNew, GtxtInit, 2976 2 GtxtDestroy, GtxtCopy); 2977 2 } 2978 1 #endif /* NO_XPGCAT */ 2979 1 2980 1 return Gcatd; 2981 1 } 2982 2983 #ifndef VMS 2984 X char * 2985 X Gtxtlocale(type, str) 2986 X int type; 2987 X char *str; 2988 X { 2989 X #ifdef NO_XPGCAT 2990 X # ifdef LC_MESSAGES 2991 X if ( (type == LC_ALL) || (type == LC_MESSAGES) ) { 2992 X # else 2993 X if (type == LC_ALL) { 2994 X # endif 2995 X if (*str == '\0') { /* load from LC_MESSAGES or LANG env var */ 2996 X char *cp; 2997 X 2998 X cp = getenv("LC_MESSAGES"); 2999 X if (cp == NULL) 3000 X cp = getenv("LANG"); 3001 X 3002 X if (cp != NULL) { 3003 X if (msgLocale == NULL) 3004 X msgLocale = STRnew(); 3005 X STRset(msgLocale, str); 3006 X } 3007 X 3008 X } else { 3009 X if (msgLocale == NULL) 3010 X msgLocale = STRnew(); 3011 X STRset(msgLocale, str); LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 5 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 3012 X } 3013 X } 3014 X #endif /* NO_XPGCAT */ 3015 X 3016 X #ifndef NO_LOCALE 3017 X return (setlocale(type,str)); 3018 X #else 3019 X if (msgLocale == NULL) 3020 X return NULL; 3021 X else 3022 X return STRget(msgLocale); 3023 X #endif /* NO_LOCALE */ 3024 X } 3025 X 3026 #else /* VMS */ 3027 3028 #include "[-]conf.h" 3684 #include "GDgopherDir.h" 6229 #include "GSgopherObj.h" 6625 #include 7058 #include 7700 7701 int GTXT_facility=0; 7702 char *GTXT_language; 7703 7704 #ifndef GOPHERMSGS_DEFAULT 7705 X #define GOPHERMSGS_DEFAULT "- none -" 7706 #endif /* GOPHERMSGS_DEFAULT */ 7707 7708 #ifndef GOPHERMSGS_DEV 7709 X #define GOPHERMSGS_DEV "GopherP_Dir:.EXE" 7710 #endif /* GOPHERMSGS_DEV */ 7711 7712 #ifndef VMS_SERVER 7713 extern GopherDirObj *setlocale_LangDir; 7714 #endif 7715 7716 /* 7717 ** Emulate catgets() by securing a VMS message 7718 */ 7719 7720 char * 7721 catgets(junk1, junk2, code, msg_default) 7722 int junk1; 7723 int junk2; 7724 int code; 7725 char *msg_default; 7726 { 7727 1 struct dsc$descriptor_s buf_; 7728 1 static 7729 1 char buf[512]; 7730 1 int i; 7731 1 int x; 7732 1 7733 1 /* Reconfigure code as VMS error condition */ 7734 1 code = (GTXT_facility<<16) + (code << 3) + 3; 7735 1 code |= 0x08008000; LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 6 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 7736 1 7737 1 buf_.dsc$b_dtype = DSC$K_DTYPE_T; 7738 1 buf_.dsc$b_class = DSC$K_CLASS_S; 7739 1 buf_.dsc$a_pointer = buf; 7740 1 buf_.dsc$w_length = sizeof(buf); 7741 1 memset(buf,'\0',sizeof(buf)); 7742 1 i = 0; 7743 1 x = SYS$GETMSG(code, &i, &buf_, 1, 0); 7744 1 if ((x & 1) && (x != SS$_MSGNOTFND)) { 7745 2 buf[i] = '\0'; 7746 2 return(buf); 7747 2 } 7748 1 return(msg_default); 7749 1 } 7750 7751 /* 7752 ** Emulate catopen() by locating and activating a VMS message file 7753 */ 7754 nl_catd 7755 catopen(char *filespec, int junk) 7756 { 7757 1 struct dsc$descriptor_s filespec_; 7758 1 struct dsc$descriptor_s symbol_; 7759 1 unsigned long value; 7760 1 int status; 7761 1 $DESCRIPTOR(image_,GOPHERMSGS_DEV); 7762 1 char *file; 7763 1 char *cp; 7764 1 7765 1 filespec_.dsc$b_dtype = symbol_.dsc$b_dtype = DSC$K_DTYPE_T; 7766 1 filespec_.dsc$b_class = symbol_.dsc$b_class = DSC$K_CLASS_S; 7767 1 if ((cp=strstr(filespec, "GOPHER_MSG")) == NULL) 7768 1 return(SS$_IVLOGNAM); 7769 1 file = (char *)malloc(sizeof(char)*(strlen(cp)+1)); 7770 1 strcpy(file,cp); 7771 1 GTXT_language = strstr(file,"_MSG") + strlen("_MSG"); 7772 1 cp = strrchr(GTXT_language,'.'); 7773 1 if (cp) 7774 1 *cp = '\0'; 7775 1 symbol_.dsc$a_pointer = (char *)malloc(sizeof(char)*(strlen("GOPHER_LANG") 7776 1 +1+strlen(GTXT_language))); 7777 1 strcpy(symbol_.dsc$a_pointer,"GOPHER_LANG"); 7778 1 strcat(symbol_.dsc$a_pointer,GTXT_language); 7779 1 symbol_.dsc$w_length = strlen(symbol_.dsc$a_pointer); 7780 1 filespec_.dsc$a_pointer = file; 7781 1 filespec_.dsc$w_length = strlen(filespec_.dsc$a_pointer); 7782 1 status = LIB$FIND_IMAGE_SYMBOL(&filespec_,&symbol_,&value,&image_); 7783 1 free(symbol_.dsc$a_pointer); 7784 1 free(file); 7785 1 if (status == SS$_NORMAL) { 7786 2 GTXT_facility = value; 7787 2 return( (nl_catd) 1); 7788 2 } 7789 1 else 7790 1 return ( (nl_catd) -1 ); 7791 1 } 7792 LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 7 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 7793 /* 7794 ** This procedure secures the LC_MESSAGES logical or symbol or SYS$LANGUAGE 7795 ** system logical and inserts it into the GopherP_Dir:gopher_msg_%s.exe 7796 ** filespec. If not defined, "*" is inserted, triggering a wildcard search 7797 ** of message files. The filespec is then searched for, and for each 7798 ** matching filespec found, the message number 222 is retrieved and inserted 7799 ** into a menu list. If no menu list entries are retrieved, Gtxt() is 7800 ** disabled, causing the default message to be returned. If only one menu 7801 ** list entry is retrieved, the message file it came from is chosen as the 7802 ** process level message file and Gtxt() is enabled to read it. If more 7803 ** than one menu list entry is retrieved, the menu is offered to the user, 7804 ** and the choice they make is set as the process level message file and 7805 ** Gtxt() is enabled to read it. 7806 */ 7807 7808 #include 10374 #include 10980 10981 void 10982 rsetlocale(int facility) 10983 { 10984 1 Gcatd = (nl_catd) 1; 10985 1 GTXT_facility = facility; 10986 1 if (GtxtMsgs != NULL) 10987 1 DAdestroy(GtxtMsgs); 10988 1 GtxtMsgs = (GtxtArray *) DAnew(10, GtxtNew, GtxtInit, 10989 1 GtxtDestroy, GtxtCopy); 10990 1 } 10991 10992 #ifndef VMS_SERVER 10993 void 10994 setlocale(char *x, char *y) 10995 { 10996 1 int status; 10997 1 int defaultLang = -1; 10998 1 char fname[256], *cp; 10999 1 char command[256]; 11000 1 char iso_language[33]; 11001 1 GopherObj *tmpgs = NULL; 11002 1 static struct 11003 1 dsc$descriptor_s language_ = {0,DSC$K_DTYPE_T, DSC$K_CLASS_S,0}; 11004 1 static struct FAB wild_fab; 11005 1 static struct NAM wild_nam; 11006 1 static char fullname[256]; 11007 1 static char expanded[256]; 11008 1 static char result[256]; 11009 1 11010 1 iso_language[0] = '\0'; 11011 1 11012 1 if (getenv("LC_MESSAGES") != NULL) 11013 1 strcpy(iso_language,getenv("LC_MESSAGES")); 11014 1 else { /* Test SYS$LANGUAGE using LIB$GET_USERS_LANGUAGE() */ 11015 2 language_.dsc$w_length = sizeof(iso_language)-1; 11016 2 language_.dsc$a_pointer = iso_language; 11017 2 if (SS$_NORMAL == (status = LIB$GET_USERS_LANGUAGE(&language_))) 11018 2 iso_language[language_.dsc$w_length] = '\0'; 11019 2 else LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 8 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 11020 2 iso_language[0] = '\0'; 11021 2 } 11022 1 11023 1 while (iso_language[0] != '\0' && 11024 1 iso_language[strlen(iso_language)-1] == ' ') 11025 1 iso_language[strlen(iso_language)-1] = '\0'; 11026 1 11027 1 if (iso_language[0] == '\0') 11028 1 strcpy(iso_language,"*"); 11029 1 11030 1 if ((cp=strchr(GOPHERMSGS_DEV, ':')) != NULL) { 11031 2 strcpy(fname, GOPHERMSGS_DEV); 11032 2 sprintf(cp=strchr(fname, ':'), ":gopher_msg_%s.exe", iso_language); 11033 2 } else { 11034 2 sprintf(fname, "GopherP_Dir:gopher_msg_%s.exe", iso_language); 11035 2 } 11036 1 11037 1 /* Scan for fname; on a hit, activate the image and get menu message */ 11038 1 wild_fab = cc$rms_fab; 11039 1 wild_nam = cc$rms_nam; 11040 1 wild_fab.fab$b_fac = FAB$M_GET; 11041 1 wild_fab.fab$l_fop = FAB$V_NAM; 11042 1 wild_fab.fab$l_nam = &wild_nam; 11043 1 wild_fab.fab$l_dna = fname; 11044 1 wild_fab.fab$b_dns = strlen(wild_fab.fab$l_dna); 11045 1 wild_nam.nam$l_esa = expanded; 11046 1 wild_nam.nam$l_rsa = result; 11047 1 wild_nam.nam$b_ess = wild_nam.nam$b_rss = 255; 11048 1 wild_fab.fab$l_fna = fullname; 11049 1 wild_fab.fab$b_fns = fullname[0] = expanded[0] = result[0] = 0; 11050 1 if ((status = SYS$PARSE(&wild_fab)) != RMS$_NORMAL) 11051 1 return; /* The while loop will hang if wild_fab is invalid */ 11052 1 11053 1 Gcatd = (nl_catd) 1; /* Always try to get the msg here. */ 11054 1 11055 1 while (status!=RMS$_NMF && status!=RMS$_FNF) { 11056 2 if ((( status = SYS$SEARCH(&wild_fab)) &1) != 1) 11057 2 continue; 11058 2 result[wild_nam.nam$b_rsl] = '\0'; 11059 2 if ((nl_catd)1 != catopen(result,0)) 11060 2 continue; 11061 2 strcpy(command,Gtxt("",232)); 11062 2 if (strlen(command)) { /* An available language */ 11063 3 if (setlocale_LangDir == NULL) { 11064 4 setlocale_LangDir = GDnew(32); /* 1st language */ 11065 4 GDsetTitle(setlocale_LangDir,""); 11066 4 } 11067 3 tmpgs = GSnew(); /* Store language menu item */ 11068 3 GSsetTitle(tmpgs, command); 11069 3 strcpy(command+1,result); 11070 3 GSsetType(tmpgs, command[0] = A_LANGUAGE); 11071 3 GSsetPath(tmpgs, command); 11072 3 GSsetHost(tmpgs,"0.0.0.0"); 11073 3 GSsetPort(tmpgs,GTXT_facility); 11074 3 GDaddGS(setlocale_LangDir, tmpgs); 11075 3 GSdestroy(tmpgs); 11076 3 if (strcmp(GTXT_language+1,GOPHERMSGS_DEFAULT)==0) { LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 9 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 11077 4 defaultLang = GDgetNumitems(setlocale_LangDir) - 1; 11078 4 } 11079 3 } 11080 2 } 11081 1 Gcatd = (nl_catd) -1; /* By default, never bother trying a message file */ 11082 1 if (setlocale_LangDir) { 11083 2 /* We have one or more available languages */ 11084 2 if (GDgetNumitems(setlocale_LangDir)==1) { 11085 3 status = 0; /* Only one choice */ 11086 3 rsetlocale(GSgetPort(GDgetEntry(setlocale_LangDir,0))); 11087 3 GDdestroy(setlocale_LangDir); 11088 3 setlocale_LangDir = NULL; 11089 3 } 11090 2 else if (defaultLang != -1) /* No choice for now. */ 11091 2 rsetlocale(GSgetPort(GDgetEntry(setlocale_LangDir,defaultLang))); 11092 2 else { /* Two or more choices. */ 11093 3 status = setlocale_screen(); 11094 3 rsetlocale(GSgetPort(GDgetEntry(setlocale_LangDir,status))); 11095 3 } 11096 2 } 11097 1 } 11098 11099 #else 11100 X 11101 X /* Really chopped down setlocale() for server usage on OpenVMS 11102 X specialized parameters, too: setlocale(pname,lang); 11103 X This allows us to pass the directory where the GopherD.exe file 11104 X resides (by passing the pname pulled off the command line) and 11105 X the default language (specified in the configuration file or 11106 X by default in the user environment variable LC_MESSAGES). 11107 X */ 11108 X void 11109 X setlocale(char *x, char *y) 11110 X { 11111 X int status; 11112 X char fname[256]; 11113 X char exedir[256]; 11114 X 11115 X strcpy(exedir, x); 11116 X if (x = strrchr(exedir,']')) { 11117 X *(x+1) = '\0'; 11118 X strcat(exedir,":"); 11119 X } 11120 X else 11121 X exedir[0] = '\0'; 11122 X sprintf(fname, "%sgopherd_msg_%s.exe", exedir, y); 11123 X if ((nl_catd)1 != catopen(fname,0)) 11124 X Gcatd = (nl_catd) -1; /* By default, never bother trying a message file */ 11125 X rsetlocale(GTXT_facility); 11126 X } 11127 #endif 11128 void 11129 Gtxtlocale(a,b) 11130 char *a, *b; 11131 { 11132 1 setlocale(a,b); 11133 1 } LOCALE 22-SEP-1995 18:31:55 VAX C V3.2-044 Page 10 V1.0 22-SEP-1995 16:08:39 [GOPHER.G2.VMS2_13.OBJECT]LOCALE.C;3 (1) 11134 11135 11136 #endif 11137 11138 #endif /* GINTERNATIONAL */ 11139 Command Line ------------ CC/INCL=([-],[-.OBJECT])/DEFINE=(MULTINET=1,DEBUGGING,__VMS)/DEBUG/NOOPT/OBJ=[.VAX.DBG]/LIS=[.VAX.LIS] LOCALE.C .