Sindbad~EG File Manager
/* M. Beeson, for Mathpert.
Support for different natural-language interfaces
Here are all the functions that deliver natural-language output
modified 6.27.99
Modified set_language 1.13.00
6.17.04 removed conditional 16-bit compilation
*/
/* In mathpert.ini there is a section [Languages] with
entries such as English = english. The left side of =
(or its translation) becomes a menu name of a language.
The right side is the name of the DLL containing the strings
for that language. Each language also has a number; these
are defined in natlang.h as ENGLISH, FRENCH, etc. So long as we
only need to support languages which have a pre-assigned number
we don't need to recompile Mathpert; the new DLL will be dynamically
loaded based on the information in mathpert.ini.
When the program first loads, it looks in the [Startup] key in
mathpert.ini for an entry like SelectedLanguage=French. If one is
found it loads the corresponding DLL. If more than one language is
listed in the [Languages] section, it also adds a Languages menu from
which the language can be dynamically changed.
*/
#include <stdlib.h> /* NULL */
#include <assert.h>
#include <string.h>
#define NATLANG_DLL
#include "export.h"
#include "english.h"
#include "mtext.h" /* MAXLENGTH */
#include "natlang.h" /* ENGLISH, FRENCH, ... */
#include <windows.h> /* LoadLibrary, FreeLibrary, GetProcAddress */
#include "button.h" /* id's for the buttons on the Graph Toolbar */
#include "mp32.h"
/*_________________________________________________________*/
static int language = ENGLISH;
/* This static variable serves the same function as
InitFile.selected_language, which is accessed by
get_selected_language(), but for efficiency is maintained
in natlang.dll, so we don't have to call get_selected_language
every time we want a string. It must therefore be changed
every time InitFile.selected_language is changed. */
static HMODULE hLanguageLib;
typedef const char *( *stringfn)(int);
typedef int (*wordfn)(char *);
typedef const char *(*stringfn2)(int,int);
typedef const char **(*menufn)(int);
static stringfn p_aem;
static stringfn p_pem;
static stringfn p_dem;
static stringfn p_input_error_message;
static stringfn2 p_problemtitle;
static stringfn p_menutitle;
static stringfn p_monthname;
static stringfn p_topicstr;
static stringfn p_menustr;
static stringfn p_english;
static stringfn p_topichelp;
static stringfn p_language_name;
static wordfn p_two_letter_word;
static stringfn2 p_hints;
static menufn p_cmdmenu;
static menufn p_ophelp;
/*_______________________________________________________________________*/
static char *dllname(int n)
/* return the dll name for language number n */
{ switch(n)
{ case ENGLISH: return "english.dll";
case FRENCH: return "french.dll";
case CANADIAN: return "french.dll";
case GERMAN: return "german.dll";
case SPANISH: return "spanish.dll";
case DUTCH: return "dutch.dll";
case SWEDISH: return "swedish.dll";
case PORTUGESE: return "portugese.dll";
case ITALIAN: return "italian.dll";
case RUSSIAN: return "russian.dll";
case JAPANESE: return "japanese.dll";
case CHINESE: return "chinese.dll";
}
return "english.dll";
}
/*_______________________________________________________________________*/
MEXPORT_NATLANG int EXPORT get_separator_char(int n)
/* return the character to use in separating
bignum digits when language number n is selected
*/
{ switch(n)
{ case ENGLISH: return ',';
case FRENCH: return ' ';
case CANADIAN: return ',';
case GERMAN: return '.';
case SPANISH: return '.';
case DUTCH: return '.';
case SWEDISH: return '.';
case PORTUGESE: return '.';
case ITALIAN: return '.';
case RUSSIAN: return '.';
case JAPANESE: return ' ';
case CHINESE: return ' ';
}
return ' ';
}
/*_______________________________________________________________________*/
MEXPORT_NATLANG int EXPORT get_decimalpoint_char(int n)
/* return the character to use in separating
bignum digits when language number n is selected
*/
{ switch(n)
{ case ENGLISH: return '.';
case FRENCH: return ',';
case CANADIAN: return '.';
case GERMAN: return ',';
case SPANISH: return ',';
case DUTCH: return ',';
case SWEDISH: return ',';
case PORTUGESE: return ',';
case ITALIAN: return ',';
case RUSSIAN: return '.';
case JAPANESE: return '.';
case CHINESE: return '.';
}
return ' ';
}
/*_______________________________________________________________________*/
MEXPORT_NATLANG int EXPORT uppercase_in_menus(int n)
/* In English and French, uppercase is used only for the
first character of a menus string, but in German, all
nouns are capitalized, so the menu text must be taken
literally rather than "corrected" for this point of style.
Return 1 if the language with number n allows uppercase,
(i.e. to take the menu strings literally from mathpert.toc),
and return 0 to enforce lowercase except for the first character.
*/
{ switch(n)
{ case ENGLISH: return 0;
case FRENCH: return 0;
case CANADIAN: return 0;
case GERMAN: return 1;
case SPANISH: return 0;
case DUTCH: return 0;
case SWEDISH: return 0;
case PORTUGESE: return 0;
case ITALIAN: return 0;
case RUSSIAN: return 0;
case JAPANESE: return 0;
case CHINESE: return 0;
}
return 0;
}
/*_______________________________________________________________________*/
MEXPORT_NATLANG int EXPORT set_language(int n, char message[128])
/* set the static global variable 'language' to language number n.
load the correct language DLL to supply natural
language strings. If there is an error, write a message into 'message'
and return 1; else return 0.
*/
{ HMODULE oldlib = hLanguageLib; /* save in case new one doesn't exist */
int oldlanguage = language;
language = n;
hLanguageLib = LoadLibrary(dllname(n));
if(hLanguageLib == NULL)
{ hLanguageLib = oldlib;
if(hLanguageLib == NULL)
{ strcpy(message, "File ");
strcat(message, dllname(n));
strcat(message, " not found");
}
else
{ strcpy(message, english(1919)); /* File */
strcat(message, dllname(n));
strcat(message, english(1195)); /* not found */
}
language = oldlanguage;
return 1;
}
if(oldlib)
FreeLibrary(oldlib); /* free the old one because it exports functions
with the same name as the new one */
p_language_name = (stringfn) GetProcAddress(hLanguageLib, "LanguageName");
if(!p_language_name)
goto error;
p_aem = (stringfn) GetProcAddress(hLanguageLib, "aem");
if(!p_aem)
goto error;
p_pem = (stringfn) GetProcAddress(hLanguageLib, "pem");
if(!p_pem)
goto error;
p_dem = (stringfn) GetProcAddress(hLanguageLib, "dem");
if(!p_dem)
goto error;
p_input_error_message = (stringfn) GetProcAddress(hLanguageLib, "input_error_message");
if(!p_input_error_message)
goto error;
p_problemtitle = (stringfn2) GetProcAddress(hLanguageLib, "problemtitle");
if(!p_problemtitle)
goto error;
p_menutitle = (stringfn) GetProcAddress(hLanguageLib, "menutitle");
if(!p_menutitle)
goto error;
p_monthname = (stringfn) GetProcAddress(hLanguageLib, "month");
if(!p_monthname)
goto error;
p_menustr = (stringfn) GetProcAddress(hLanguageLib, "menustring");
if(!p_menustr)
goto error;
p_english = (stringfn) GetProcAddress(hLanguageLib,"LanguageStrings");
if(!p_english)
goto error;
p_topicstr = (stringfn) GetProcAddress(hLanguageLib,"topicstr");
if(!p_topicstr)
goto error;
p_topichelp = (stringfn) GetProcAddress(hLanguageLib,"topichelp");
if(!p_topichelp)
goto error;
p_two_letter_word = (wordfn) GetProcAddress(hLanguageLib, "two_letter_word");
if(!p_two_letter_word)
goto error;
p_hints = (stringfn2) GetProcAddress(hLanguageLib, "hints");
if(!p_hints)
goto error;
p_ophelp = (menufn) GetProcAddress(hLanguageLib, "ophelp");
if(!p_ophelp)
goto error;
p_cmdmenu = (menufn) GetProcAddress(hLanguageLib,"cmdmenu");
if(!p_cmdmenu)
goto error;
return 0;
error:
set_language(oldlanguage,message); /* this resets p_cmdmenu, etc. properly and
calls FreeLibrary(hLanguageLib) */
strcpy(message, english(1919)); /* File */
strcat(message, dllname(n));
strcat(message, english(2315)); /* is not correct. Cannot switch to that language. */
return 1;
}
/*__________________________________________________________________*/
MEXPORT_NATLANG void EXPORT FreeLanguageLib(void)
/* called at the end of WinMain to free the language DLL
that is loaded by set_language */
{
if(hLanguageLib)
FreeLibrary(hLanguageLib);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT english(int n)
{ return p_english(n);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT monthname(int n)
/* n is 0 to 11; return the name of the corresponding month
in the current language. */
{ return p_monthname(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT menutitle(int n)
{ return p_menutitle(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT input_error_message(int n)
{ return p_input_error_message(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT aem(int n)
/* arithmetic error message */
{ return p_aem(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT pem(int n)
/* parser error message */
{ return p_pem(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT dem(int n)
/* deval error message */
{ return p_dem(n);
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT hints(int n, int m)
{ return p_hints(n,m);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char ** EXPORT cmdmenu(int n)
{ return p_cmdmenu(n);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char ** EXPORT ophelp(int n)
{ return p_ophelp(n);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT topichelp(int n)
{ return p_topichelp(n);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT problemtitle(int probtype, int topic)
{ return p_problemtitle(probtype,topic);
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT topicstr(int topic)
{ return p_topicstr(topic);
}
/*__________________________________________________________________*/
MEXPORT_NATLANG int EXPORT language_number(char *language_name)
/* return e.g. ENGLISH when the input is "English" */
{ if(!stricmp(language_name,"English"))
return ENGLISH;
if(!stricmp(language_name,"French"))
return FRENCH;
if(!stricmp(language_name,"Canadian French"))
return CANADIAN;
if(!stricmp(language_name,"German"))
return GERMAN;
if(!stricmp(language_name,"Spanish"))
return SPANISH;
if(!stricmp(language_name,"Dutch"))
return DUTCH;
if(!stricmp(language_name,"Swedish"))
return SWEDISH;
if(!stricmp(language_name,"Portugese"))
return PORTUGESE;
if(!stricmp(language_name,"Italian"))
return ITALIAN;
if(!stricmp(language_name,"Russian"))
return RUSSIAN;
if(!stricmp(language_name,"Japanese"))
return JAPANESE;
if(!stricmp(language_name,"Chinese"))
return CHINESE;
return ENGLISH; /* the default */
}
/*__________________________________________________________________*/
MEXPORT_NATLANG const char *EXPORT language_name(int language_number)
/* Return the name in the currently selected language for
the language with the given number. Example: if the language
is english and language_number is FRENCH, return "French".
If the language is French and language_number is ENGLISH,
return "anglais". These strings are returned in ISO-Latin
character set.
*/
{ return p_language_name(language_number);
}
/*__________________________________________________________________*/
MEXPORT_NATLANG const char *EXPORT menustr(int n)
{ return p_menustr(n);
}
/*__________________________________________________________________*/
MEXPORT_NATLANG int EXPORT two_letter_word(char *buffer)
/* Return 0 if buffer contains a two-letter word needed in
mtext or ophelp. Return 1 otherwise.
*/
{ return p_two_letter_word(buffer);
}
/*__________________________________________________________________*/
static char *tocfile(void)
/* return the name of the translated mathpert.toc */
{ switch(language)
{ case ENGLISH: return "mathpert.toc";
case FRENCH: return "french.toc";
case CANADIAN: return "french.toc";
case GERMAN: return "german.toc";
case SPANISH: return "spanish.toc";
case DUTCH: return "dutch.toc";
case SWEDISH: return "swedish.toc";
case PORTUGESE: return "portugese.toc";
case ITALIAN: return "italian.toc";
case RUSSIAN: return "russian.toc";
case JAPANESE: return "japanese.toc";
case CHINESE: return "chinese.toc";
}
return "mathpert.toc";
}
/*__________________________________________________________________*/
MEXPORT_NATLANG void EXPORT get_tocfile(char ans[32])
/* Supply the name of the translated mathpert.toc */
{ strcpy(ans,tocfile());
return;
}
/*____________________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT english_language_name(int n)
/* Return names of different languages. The input is one of the
language identifiers in natlang.h, such as ENGLISH, FRENCH,...
On illegal input it just returns "English". This one always returns
names in English, which are needed to write into mathpert.ini.
Each different language DLL exports its own language_name function
which is used to build the language menu. These entries must match
the code used in language_number above.
*/
{ switch(n)
{ case ENGLISH: return "English";
case FRENCH: return "French";
case CANADIAN: return "Canadian French";
case GERMAN: return "German";
case SPANISH: return "Spanish";
case DUTCH: return "Dutch";
case SWEDISH: return "Swedish";
case PORTUGESE: return "Portugese";
case ITALIAN: return "Italian";
case RUSSIAN: return "Russian";
case JAPANESE: return "Japanese";
case CHINESE: return "Chinese";
default: return "English";
}
}
/*______________________________________________________________*/
MEXPORT_NATLANG const char * EXPORT ButtonText(int id)
{ if(language == ENGLISH)
return NULL; /* English text is already in the bitmaps */
switch(id)
{ /* First the Speedbar buttons */
case IDC_UNDO: return english(2380); /* Undo */
case IDC_HINT: return english(2381); /* Hint */
case IDC_AUTOSTEP: return english(2382); /* AutoStep */
case IDC_SHOWSTEP: return english(2383); /* ShowStep */
case IDC_AUTOFINISH: return english(2384); /* AutoFinish */
case IDC_FINISHED: return english(2385); /* Finished */
case IDC_SPEEDBARGRAPH: return english(2386); /* Graph */
case IDC_SPEEDBARPREV: return english(2387); /* Prev */
case IDC_SPEEDBARNEW: return english(2388); /* Edit */
case IDC_SPEEDBARNEXT: return english(2389); /* Next */
/* Now for the Graph Toolbar buttons */
case BUTTON_RANGE: return english(2375); /* Range */
case BUTTON_DRAW: return english(2376); /* Redraw */
case BUTTON_NEXT: return english(2377); /* Next */
case BUTTON_PREV: return english(2378); /* Prev */
case BUTTON_NEW: return english(2379); /* Edit */
}
return NULL;
}
/*_____________________________________________________________*/
MEXPORT_NATLANG double EXPORT atof2(char *x)
/* like atof but replaces commas (or other decimalchar) by periods first.
Hence, it can convert text in any language into a double.
*/
{ char decimalchar = get_decimalpoint_char(language);
char buffer[64];
char *marker;
if(decimalchar == '.')
return atof(x);
strncpy(buffer,x,63);
buffer[63] = 0; /* guard against overflow */
marker = buffer;
while(*marker)
{ if(*marker == decimalchar)
*marker = '.';
++marker;
}
return atof(buffer);
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists