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
4.7.06 changed stricmp to _stricmp
8.14.07 added POLISH to dllname and made dllname exported
5.3.13 radical changes to provide for flat compilation instead of dynamically loaded dlls.
Now all the natural-language strings from all languages will be in natlang.dll (under Windows)
or just compiled into the executable file (on OSX).
*/
/* This is how it formerly worked:
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.
2.13.24 corrected typo in LanguageNames[0]
*/
#ifdef XCODE
#define _stricmp strcasecmp
#endif
#include <stdlib.h> /* NULL */
#include <assert.h>
#include <string.h>
#define NATLANG_DLL
#include "english.h"
#include "mtext.h" /* MAXLENGTH */
#include "natlang.h" /* ENGLISH, FRENCH, ... */
#include "button.h" /* id's for the buttons on the Graph Toolbar and Speedbar */
#include "english1.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. */
/*______________________________________________________________*/
int get_selected_language(void)
{ return language;
}
/*______________________________________________________________*/
typedef const char *( *stringfn)(int);
typedef int (*wordfn)(char *);
typedef const char *(*stringfn2)(int,int);
typedef const char **(*menufn)(int);
static stringfn *StringFunctions;
static menufn *MenuFunctions;
static stringfn p_aem;
static stringfn p_pem;
static stringfn p_dem;
static stringfn p_input_error_message;
static stringfn p_menutitle;
static stringfn p_monthname;
static stringfn p_topicstr;
static stringfn p_subjectstr;
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 stringfn2 p_problemtitle;
static menufn p_cmdmenu;
static menufn p_ophelp;
/* _____________________________________________________________________*/
static stringfn EnglishStringFunctions[] =
{ English_LanguageName,
English_aem,
English_pem,
English_dem,
English_input_error_message,
English_menutitle,
English_month,
English_menustring,
English_LanguageStrings,
English_topicstr,
English_subjectstr,
English_topichelp
};
static menufn EnglishMenuFunctions[] =
{ English_cmdmenu,
English_ophelp
};
/* _____________________________________________________________________*/
static stringfn FrenchStringFunctions[] =
{ French_LanguageName,
French_aem,
French_pem,
French_dem,
French_input_error_message,
French_menutitle,
French_month,
French_menustring,
French_LanguageStrings,
French_topicstr,
French_subjectstr,
French_topichelp
};
static menufn FrenchMenuFunctions[] =
{ French_cmdmenu,
French_ophelp
};
/* _____________________________________________________________________*/
static stringfn DutchStringFunctions[] =
{ Dutch_LanguageName,
Dutch_aem,
Dutch_pem,
Dutch_dem,
Dutch_input_error_message,
Dutch_menutitle,
Dutch_month,
Dutch_menustring,
Dutch_LanguageStrings,
Dutch_topicstr,
Dutch_subjectstr,
Dutch_topichelp
};
static menufn DutchMenuFunctions[] =
{ Dutch_cmdmenu,
Dutch_ophelp
};
/* _____________________________________________________________________*/
static stringfn GermanStringFunctions[] =
{ German_LanguageName,
German_aem,
German_pem,
German_dem,
German_input_error_message,
German_menutitle,
German_month,
German_menustring,
German_LanguageStrings,
German_topicstr,
German_subjectstr,
German_topichelp
};
static menufn GermanMenuFunctions[] =
{ German_cmdmenu,
German_ophelp
};
/* _____________________________________________________________________*/
static stringfn ItalianStringFunctions[] =
{ Italian_LanguageName,
Italian_aem,
Italian_pem,
Italian_dem,
Italian_input_error_message,
Italian_menutitle,
Italian_month,
Italian_menustring,
Italian_LanguageStrings,
Italian_topicstr,
Italian_subjectstr,
Italian_topichelp
};
static menufn ItalianMenuFunctions[] =
{ Italian_cmdmenu,
Italian_ophelp
};
/* _____________________________________________________________________*/
static stringfn SpanishStringFunctions[] =
{ Spanish_LanguageName,
Spanish_aem,
Spanish_pem,
Spanish_dem,
Spanish_input_error_message,
Spanish_menutitle,
Spanish_month,
Spanish_menustring,
Spanish_LanguageStrings,
Spanish_topicstr,
Spanish_subjectstr,
Spanish_topichelp
};
static menufn SpanishMenuFunctions[] =
{ Spanish_cmdmenu,
Spanish_ophelp
};
/* _____________________________________________________________________*/
static stringfn ChineseStringFunctions[] =
{ Chinese_LanguageName,
Chinese_aem,
Chinese_pem,
Chinese_dem,
Chinese_input_error_message,
Chinese_menutitle,
Chinese_month,
Chinese_menustring,
Chinese_LanguageStrings,
Chinese_topicstr,
Chinese_subjectstr,
Chinese_topichelp
};
static menufn ChineseMenuFunctions[] =
{ Chinese_cmdmenu,
Chinese_ophelp
};
static int LanguageNumbers[] =
{ ENGLISH, FRENCH, CANADIAN, GERMAN, SPANISH, DUTCH, SWEDISH,
PORTUGUESE,ITALIAN,RUSSIAN,JAPANESE,CHINESE,POLISH};
static char *LanguageNames[] =
{ "English",
"French",
"Canadian",
"German",
"Spanish",
"Dutch",
"Swedish",
"Portugese",
"Italian",
"Russian",
"Japanese",
"Chinese",
"Polish"
};
/*_______________________________________________________________________*/
char *LanguageName(int n)
/* return the name of language number n */
{ switch(n)
{ case ENGLISH: return "English";
case FRENCH: return "French";
case CANADIAN: return "Canadian";
case GERMAN: return "German";
case SPANISH: return "Spanish";
case DUTCH: return "Dutch";
case SWEDISH: return "Swedish";
case PORTUGUESE: return "Portugese";
case ITALIAN: return "Italian";
case RUSSIAN: return "Russian";
case JAPANESE: return "Japanese";
case CHINESE: return "Chinese";
case POLISH: return "Polish";
}
return "";
}
/*_______________________________________________________________________*/
int 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 PORTUGUESE: return '.';
case ITALIAN: return '.';
case RUSSIAN: return '.';
case JAPANESE: return ' ';
case CHINESE: return ' ';
}
return ' ';
}
/*_______________________________________________________________________*/
int 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 PORTUGUESE: return ',';
case ITALIAN: return ',';
case RUSSIAN: return '.';
case JAPANESE: return '.';
case CHINESE: return '.';
}
return ' ';
}
/*_______________________________________________________________________*/
int 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 PORTUGUESE: return 0;
case ITALIAN: return 0;
case RUSSIAN: return 0;
case JAPANESE: return 0;
case CHINESE: return 0;
}
return 0;
}
/*_______________________________________________________________________*/
void set_language(int n)
/* Set the static global variable 'language' to language number n.
Switch the language function pointers.
*/
{ language = n;
switch(n)
{ case ENGLISH:
StringFunctions = EnglishStringFunctions;
MenuFunctions = EnglishMenuFunctions;
p_two_letter_word = English_two_letter_word;
p_hints = English_hints;
p_problemtitle = English_problemtitle;
break;
case GERMAN:
StringFunctions = GermanStringFunctions;
MenuFunctions = GermanMenuFunctions;
p_two_letter_word = German_two_letter_word;
p_hints = German_hints;
p_problemtitle = German_problemtitle;
break;
case FRENCH:
StringFunctions = FrenchStringFunctions;
MenuFunctions = FrenchMenuFunctions;
p_two_letter_word = French_two_letter_word;
p_hints = French_hints;
p_problemtitle = French_problemtitle;
break;
case ITALIAN:
StringFunctions = ItalianStringFunctions;
MenuFunctions = ItalianMenuFunctions;
p_two_letter_word = Italian_two_letter_word;
p_hints = Italian_hints;
p_problemtitle = Italian_problemtitle;
break;
case SPANISH:
StringFunctions = SpanishStringFunctions;
MenuFunctions = SpanishMenuFunctions;
p_two_letter_word = Spanish_two_letter_word;
p_hints = Spanish_hints;
p_problemtitle = Spanish_problemtitle;
break;
case DUTCH:
StringFunctions = DutchStringFunctions;
MenuFunctions = DutchMenuFunctions;
p_two_letter_word = Dutch_two_letter_word;
p_hints = Dutch_hints;
p_problemtitle = Dutch_problemtitle;
break;
case CHINESE:
StringFunctions = ChineseStringFunctions;
MenuFunctions = ChineseMenuFunctions;
p_two_letter_word = Chinese_two_letter_word;
p_hints = Chinese_hints;
p_problemtitle = Chinese_problemtitle;
break;
/* additional languages can be added here */
}
p_language_name = StringFunctions[0];
p_aem = StringFunctions[1];
p_pem = StringFunctions[2];
p_dem = StringFunctions[3];
p_input_error_message = StringFunctions[4];
p_menutitle = StringFunctions[5];
p_monthname = StringFunctions[6];
p_menustr = StringFunctions[7];
p_english = StringFunctions[8];
p_topicstr = StringFunctions[9];
p_subjectstr = StringFunctions[10];
p_topichelp = StringFunctions[11];
p_cmdmenu = MenuFunctions[0];
p_ophelp = MenuFunctions[1];
}
/*____________________________________________________________________*/
int get_language_number(char *x)
/* If the input is "french", return FRENCH, etc. */
{ int k;
int n = sizeof(LanguageNames)/sizeof(char *);
for(k=0;k<n;k++)
{ if(! _stricmp(x,LanguageNames[k]))
return LanguageNumbers[k];
}
return ENGLISH; // the requested language isn't supported
}
/*____________________________________________________________________*/
const char * english(int n)
{ return p_english(n);
}
/*______________________________________________________________*/
const char * monthname(int n)
/* n is 0 to 11; return the name of the corresponding month
in the current language. */
{ return p_monthname(n);
}
/*____________________________________________________________________*/
const char * menutitle(int n)
{ return p_menutitle(n);
}
/*____________________________________________________________________*/
const char * input_error_message(int n)
{ return p_input_error_message(n);
}
/*____________________________________________________________________*/
const char * aem(int n)
/* arithmetic error message */
{ return p_aem(n);
}
/*____________________________________________________________________*/
const char * pem(int n)
/* parser error message */
{ return p_pem(n);
}
/*____________________________________________________________________*/
const char * dem(int n)
/* deval error message */
{ return p_dem(n);
}
/*____________________________________________________________________*/
const char * hints(int n, int m)
{ return p_hints(n,m);
}
/*______________________________________________________________*/
const char ** cmdmenu(int n)
{ return p_cmdmenu(n);
}
/*______________________________________________________________*/
const char ** ophelp(int n)
{ return p_ophelp(n);
}
/*______________________________________________________________*/
const char * topichelp(int n)
{ return p_topichelp(n);
}
/*______________________________________________________________*/
const char * problemtitle(int probtype, int topic)
{ return p_problemtitle(probtype,topic);
}
/*______________________________________________________________*/
const char * topicstr(int topic)
{ return p_topicstr(topic);
}
/*______________________________________________________________*/
const char * subjectstr(int topic)
{ return p_subjectstr(topic);
}
/*__________________________________________________________________*/
const char *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 UTF-8.
*/
{ return p_language_name(language_number);
}
/*__________________________________________________________________*/
const char *menustr(int n)
{ return p_menustr(n);
}
/*__________________________________________________________________*/
int 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);
}
/*____________________________________________________________________*/
const char * 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 PORTUGUESE: return "Portugese";
case ITALIAN: return "Italian";
case RUSSIAN: return "Russian";
case JAPANESE: return "Japanese";
case CHINESE: return "Chinese";
default: return "English";
}
}
/*______________________________________________________________*/
const char * 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;
}
/*_____________________________________________________________*/
double 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