DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/misc/messages.cpp
00001 /*
00002  *  Copyright (C) 2002-2020  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include "dosbox.h"
00024 #include "cross.h"
00025 #include "support.h"
00026 #include "setup.h"
00027 #include "control.h"
00028 #include <list>
00029 #include <string>
00030 using namespace std;
00031 
00032 
00033 
00034 #define LINE_IN_MAXLEN 2048
00035 
00036 struct MessageBlock {
00037         string name;
00038         string val;
00039         MessageBlock(const char* _name, const char* _val):
00040         name(_name),val(_val){}
00041 };
00042 
00043 static list<MessageBlock> Lang;
00044 typedef list<MessageBlock>::iterator itmb;
00045 
00046 void MSG_Add(const char * _name, const char* _val) {
00047         /* Find the message */
00048         for(itmb tel=Lang.begin();tel!=Lang.end();++tel) {
00049                 if((*tel).name==_name) { 
00050 //                      LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages
00051                         return;
00052                 }
00053         }
00054         /* if the message doesn't exist add it */
00055         Lang.push_back(MessageBlock(_name,_val));
00056 }
00057 
00058 void MSG_Replace(const char * _name, const char* _val) {
00059         /* Find the message */
00060         for(itmb tel=Lang.begin();tel!=Lang.end();++tel) {
00061                 if((*tel).name==_name) { 
00062                         Lang.erase(tel);
00063                         break;
00064                 }
00065         }
00066         /* Even if the message doesn't exist add it */
00067         Lang.push_back(MessageBlock(_name,_val));
00068 }
00069 
00070 void LoadMessageFile(const char * fname) {
00071         if (!fname) return;
00072         if(*fname=='\0') return;//empty string=no languagefile
00073 
00074         LOG(LOG_MISC,LOG_DEBUG)("Loading message file %s",fname);
00075 
00076         FILE * mfile=fopen(fname,"rt");
00077         /* This should never happen and since other modules depend on this use a normal printf */
00078         if (!mfile) {
00079                 E_Exit("MSG:Can't load messages: %s",fname);
00080         }
00081         char linein[LINE_IN_MAXLEN];
00082         char name[LINE_IN_MAXLEN];
00083         char string[LINE_IN_MAXLEN*10];
00084         /* Start out with empty strings */
00085         name[0]=0;string[0]=0;
00086         while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) {
00087                 /* Parse the read line */
00088                 /* First remove characters 10 and 13 from the line */
00089                 char * parser=linein;
00090                 char * writer=linein;
00091 
00092                 while (*parser) {
00093                         if (*parser != 10 && *parser != 13)
00094                                 *writer++ = *parser;
00095 
00096                         parser++;
00097                 }
00098                 *writer=0;
00099 
00100                 /* New string name */
00101                 if (linein[0]==':') {
00102                         string[0]=0;
00103                         strcpy(name,linein+1);
00104                 /* End of string marker */
00105                 } else if (linein[0]=='.') {
00106                         /* Replace/Add the string to the internal languagefile */
00107                         /* Remove last newline (marker is \n.\n) */
00108                         size_t ll = strlen(string);
00109                         if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.
00110                         MSG_Replace(name,string);
00111                 } else {
00112                 /* Normal string to be added */
00113                         strcat(string,linein);
00114                         strcat(string,"\n");
00115                 }
00116         }
00117         fclose(mfile);
00118 }
00119 
00120 const char * MSG_Get(char const * msg) {
00121         for(itmb tel=Lang.begin();tel!=Lang.end();++tel){
00122                 if((*tel).name==msg)
00123                 {
00124                         return  (*tel).val.c_str();
00125                 }
00126         }
00127         return msg;
00128 }
00129 
00130 
00131 bool MSG_Write(const char * location) {
00132         FILE* out=fopen(location,"w+t");
00133         if(out==NULL) return false;//maybe an error?
00134         for(itmb tel=Lang.begin();tel!=Lang.end();++tel){
00135                 fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str());
00136         }
00137         fclose(out);
00138         return true;
00139 }
00140 
00141 void MSG_Init() {
00142         Section_prop *section=static_cast<Section_prop *>(control->GetSection("dosbox"));
00143 
00144         if (control->opt_lang != "") {
00145                 LoadMessageFile(control->opt_lang.c_str());
00146         }
00147         else {
00148                 Prop_path* pathprop = section->Get_path("language");
00149                 if (pathprop != NULL) LoadMessageFile(pathprop->realpath.c_str());
00150         }
00151 }