From bb60e32aaaed6f86bdde9159daae3098f40bd2cb Mon Sep 17 00:00:00 2001 From: kichik Date: Sun, 29 Sep 2002 20:25:15 +0000 Subject: [PATCH] Added user defined multilingual strings. Define using LangString [un.]name lang_id string, use with $(name). Can't be used inside other strings. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@1214 212acab6-be3b-0410-9dea-997c60f758d6 --- Examples/languages.nsi | 65 +++++++------ Source/build.cpp | 83 +++++++++------- Source/build.h | 3 + Source/exehead/Ui.c | 57 +++++------ Source/exehead/exec.c | 26 ++--- Source/exehead/fileform.c | 7 +- Source/exehead/fileform.h | 30 +----- Source/exehead/ui.h | 4 +- Source/lang.cpp | 198 ++++++++++++++++++++++++-------------- Source/lang.h | 3 + Source/script.cpp | 87 ++++++++--------- Source/strlist.h | 13 +++ Source/tokens.cpp | 1 + Source/tokens.h | 3 +- 14 files changed, 325 insertions(+), 255 deletions(-) diff --git a/Examples/languages.nsi b/Examples/languages.nsi index 5f7a594a..b9461b62 100644 --- a/Examples/languages.nsi +++ b/Examples/languages.nsi @@ -23,6 +23,8 @@ LoadLanguageFile "${NSISDIR}\Contrib\Language files\TradChinese.nlf" Name "Traditional Chinese" LoadLanguageFile "${NSISDIR}\Contrib\Language files\SimpChinese.nlf" Name "Simplified Chinese" +LoadLanguageFile "${NSISDIR}\Contrib\Language files\Slovak.nlf" +Name Slovak ; The language can be the last used language like above, but it can be defined using /LANG ComponentText /LANG=${LANG_ENGLISH} "English component page" @@ -35,14 +37,38 @@ ComponentText /LANG=${LANG_SPANISH} "Spanish component page" ComponentText /LANG=${LANG_SWEDISH} "Swedish component page" ComponentText /LANG=${LANG_TRADCHINESE} "Traditional Chinese component page" ComponentText /LANG=${LANG_SIMPCHINESE} "Simplified Chinese component page" +ComponentText /LANG=${LANG_SLOVAK} "Slovak component page" + +LangString Sec1Name ${LANG_ENGLISH} "!English section #1" +LangString Sec1Name ${LANG_DUTCH} "!Dutch section #1" +LangString Sec1Name ${LANG_FRENCH} "!French section #1" +LangString Sec1Name ${LANG_GERMAN} "!German section #1" +LangString Sec1Name ${LANG_KOREAN} "!Korean section #1" +LangString Sec1Name ${LANG_RUSSIAN} "!Russian section #1" +LangString Sec1Name ${LANG_SPANISH} "!Spanish section #1" +LangString Sec1Name ${LANG_SWEDISH} "!Swedish section #1" +LangString Sec1Name ${LANG_TRADCHINESE} "!Trandional Chinese section #1" +LangString Sec1Name ${LANG_SIMPCHINESE} "!Simplified Chinese section #1" +LangString Sec1Name ${LANG_SLOVAK} "!Slovak section #1" + +LangString Message ${LANG_ENGLISH} "English message" +LangString Message ${LANG_DUTCH} "Dutch message" +LangString Message ${LANG_FRENCH} "French message" +LangString Message ${LANG_GERMAN} "German message" +LangString Message ${LANG_KOREAN} "Korean message" +LangString Message ${LANG_RUSSIAN} "Russian message" +LangString Message ${LANG_SPANISH} "Spanish message" +LangString Message ${LANG_SWEDISH} "Swedish message" +LangString Message ${LANG_TRADCHINESE} "Trandional Chinese message" +LangString Message ${LANG_SIMPCHINESE} "Simplified Chinese message" +LangString Message ${LANG_SLOVAK} "Slovak message" ; scetion names will be given in .onInit to match the language choosen by the user -Section " " sec1 - ; $0 is already set from .onInit - MessageBox MB_OK "$0 section" +Section $(Sec1Name) sec1 + MessageBox MB_OK $(Message) SectionEnd -Section " " sec2 +Section "Section number two" StrCmp $LANGUAGE ${LANG_ENGLISH} 0 +2 MessageBox MB_OK "Installing English stuff" StrCmp $LANGUAGE ${LANG_DUTCH} 0 +2 @@ -63,6 +89,8 @@ Section " " sec2 MessageBox MB_OK "Installing Traditional Chinese stuff" StrCmp $LANGUAGE ${LANG_SIMPCHINESE} 0 +2 MessageBox MB_OK "Installing Simplified Chinese stuff" + StrCmp $LANGUAGE ${LANG_SLOVAK} 0 +2 + MessageBox MB_OK "Installing Slovak stuff" SectionEnd Function .onInit @@ -86,35 +114,12 @@ Function .onInit Push "Traditional Chinese" Push ${LANG_SIMPCHINESE} Push "Simplified Chinese" - Push 10 ; 10 is the number of languages + Push ${LANG_SLOVAK} + Push Slovak + Push 11 ; 11 is the number of languages LangDLL::LangDialog "Installer Language" "Please select the language of the installer" Pop $LANGUAGE StrCmp $LANGUAGE "cancel" 0 +2 Abort - - StrCmp $LANGUAGE ${LANG_ENGLISH} 0 +2 - StrCpy $0 "English" - StrCmp $LANGUAGE ${LANG_DUTCH} 0 +2 - StrCpy $0 "Dutch" - StrCmp $LANGUAGE ${LANG_FRENCH} 0 +2 - StrCpy $0 "French" - StrCmp $LANGUAGE ${LANG_GERMAN} 0 +2 - StrCpy $0 "German" - StrCmp $LANGUAGE ${LANG_KOREAN} 0 +2 - StrCpy $0 "Korean" - StrCmp $LANGUAGE ${LANG_RUSSIAN} 0 +2 - StrCpy $0 "Russian" - StrCmp $LANGUAGE ${LANG_SPANISH} 0 +2 - StrCpy $0 "Spanish" - StrCmp $LANGUAGE ${LANG_SWEDISH} 0 +2 - StrCpy $0 "Swedish" - StrCmp $LANGUAGE ${LANG_TRADCHINESE} 0 +2 - StrCpy $0 "Traditional Chinese" - StrCmp $LANGUAGE ${LANG_SIMPCHINESE} 0 +2 - StrCpy $0 "Simplified Chinese" - - ; Set the section name to something localized - SectionSetText ${sec1} "!$0 section #1" - SectionSetText ${sec2} "$0 section #2" FunctionEnd \ No newline at end of file diff --git a/Source/build.cpp b/Source/build.cpp index c6cb5463..90654499 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -209,6 +209,7 @@ CEXEBuild::CEXEBuild() cur_datablock=&build_datablock; cur_functions=&build_functions; cur_labels=&build_labels; + cur_userlangstrings=&build_userlangstrings; subsection_open_cnt=0; build_cursection_isfunc=0; @@ -229,13 +230,6 @@ CEXEBuild::CEXEBuild() build_header.no_custom_instmode_flag=0; #endif build_header.num_sections=0; - /* Useless - build_header.space_avail_id=0; - build_header.space_req_id=0; - build_header.dir_subtext_id=0; - build_header.com_subtext1_id=0; - build_header.com_subtext2_id=0; - build_header.common.intro_text_id=0;*/ build_header.common.num_entries=0; #ifdef NSIS_CONFIG_SILENT_SUPPORT build_header.common.silent_install=0; @@ -251,9 +245,6 @@ CEXEBuild::CEXEBuild() uninstall_size=-1; memset(&build_uninst,-1,sizeof(build_uninst)); - /* Useless - build_uninst.uninst_subtext_id=0; - build_uninst.common.intro_text_id=0;*/ build_uninst.common.lb_bg=RGB(0,0,0); build_uninst.common.lb_fg=RGB(0,255,0); build_uninst.common.num_entries=0; @@ -267,6 +258,12 @@ CEXEBuild::CEXEBuild() uninstaller_writes_used=0; + build_strlist.add("",0); + ubuild_strlist.add("",0); + build_header.install_directory_ptr=0; + build_header.install_reg_key_ptr=0; + memset(build_header.install_types_ptr,0,sizeof(build_header.install_types_ptr)); + // Changed by Amir Szekely 11th July 2002 // Changed to fit the new format in which uninstaller icons are saved m_unicon_data=(unsigned char *)malloc(unicondata_size+3*sizeof(DWORD)); @@ -399,9 +396,18 @@ int CEXEBuild::preprocess_string(char *out, const char *in) int CEXEBuild::add_string_main(const char *string, int process) // returns offset (in string block) { - if (!*string) return -1; + if (!*string) return 0; if (!process) return build_strlist.add(string,2); + if (*string == '$' && *(string+1) == '(') { + char *cp = strdup(string+2); + strchr(cp, ')')[0] = 0; + int idx; + if (cur_userlangstrings->find(cp, 0, &idx) < 0) idx = -1; + free(cp); + if (idx >= 0) return -(idx+1); + } + char buf[4096]; preprocess_string(buf,string); return build_strlist.add(buf,2); @@ -409,9 +415,18 @@ int CEXEBuild::add_string_main(const char *string, int process) // returns offse int CEXEBuild::add_string_uninst(const char *string, int process) // returns offset (in string block) { - if (!*string) return -1; + if (!*string) return 0; if (!process) return ubuild_strlist.add(string,2); + if (*string == '$' && *(string+1) == '(') { + char *cp = strdup(string+2); + strchr(cp, ')')[0] = 0; + int idx; + if (cur_userlangstrings->find(cp, 0, &idx) < 0) idx = -1; + free(cp); + if (idx >= 0) return -(idx+1); + } + char buf[4096]; preprocess_string(buf,string); return ubuild_strlist.add(buf,2); @@ -996,7 +1011,7 @@ int CEXEBuild::resolve_coderefs(const char *str) for (x = sec->code; x < sec->code+sec->code_size; x ++) { char fname[1024]; - if (sec->name_ptr>=0) wsprintf(fname,"section \"%s\" (%d)",build_strlist.get()+sec->name_ptr,cnt); + if (sec->name_ptr) wsprintf(fname,"section \"%s\" (%d)",build_strlist.get()+sec->name_ptr,cnt); else wsprintf(fname,"unnamed section (%d)",cnt); if (resolve_instruction(fname,str,w+x,x,sec->code,sec->code+sec->code_size)) return 1; } @@ -1073,6 +1088,7 @@ int CEXEBuild::write_output(void) ERROR_MSG("Error: invalid script: no sections specified\n"); return PS_ERROR; } + } #ifdef NSIS_CONFIG_PLUGIN_SUPPORT // Added by Amir Szekely 9th August 2002 @@ -1083,19 +1099,6 @@ int CEXEBuild::write_output(void) // Added by Amir Szekely 3rd August 2002 if (WriteStringTables() == PS_ERROR) return PS_ERROR; -/*#ifdef NSIS_CONFIG_COMPONENTPAGE - if (build_header.componenttext_ptr < 0 && - ns > 1 -#ifdef NSIS_CONFIG_SILENT_SUPPORT - && !build_header.common.silent_install -#endif - ) - { - build_header.componenttext_ptr=-1; - } -#endif*/ - } - if (!build_entries.getlen()) { ERROR_MSG("Error: invalid script: no entries specified\n"); @@ -1427,7 +1430,7 @@ int CEXEBuild::write_output(void) int req=0; for (x = 1; x < ns; x ++) { - if (s[x].name_ptr == -1 || s[x].default_state & DFS_RO) req++; + if (!s[x].name_ptr || s[x].default_state & DFS_RO) req++; } INFO_MSG("Install: %d section%s",ns,ns==1?"":"s"); if (req) @@ -1787,14 +1790,22 @@ void CEXEBuild::set_uninstall_mode(int un) if (un != uninstall_mode) { uninstall_mode=un; - if (un) cur_datablock=&ubuild_datablock; - else cur_datablock=&build_datablock; - if (un) cur_entries=&ubuild_entries; - else cur_entries=&build_entries; - if (un) cur_functions=&ubuild_functions; - else cur_functions=&build_functions; - if (un) cur_labels=&ubuild_labels; - else cur_labels=&build_labels; + if (un) + { + cur_datablock=&ubuild_datablock; + cur_entries=&ubuild_entries; + cur_functions=&ubuild_functions; + cur_labels=&ubuild_labels; + cur_userlangstrings=&ubuild_userlangstrings; + } + else + { + cur_datablock=&build_datablock; + cur_entries=&build_entries; + cur_functions=&build_functions; + cur_labels=&build_labels; + cur_userlangstrings=&build_userlangstrings; + } SWAP(db_opt_save_u,db_opt_save,int); SWAP(db_comp_save_u,db_comp_save,int); @@ -1915,7 +1926,7 @@ again: // StrCmp $PLUGINSDIR "" ent.which=EW_STRCMP; ent.offsets[0]=add_string("$PLUGINSDIR"); - ent.offsets[1]=add_string(""); + ent.offsets[1]=0; ent.offsets[2]=0; ent.offsets[3]=ns_label.add("Initialize_____Plugins_done",0); ret=add_entry(&ent); diff --git a/Source/build.h b/Source/build.h index 68cbc5a6..a1b296be 100644 --- a/Source/build.h +++ b/Source/build.h @@ -134,8 +134,10 @@ class CEXEBuild { void set_uninstall_mode(int un); // lang.cpp by Amir Szekely 3rd August 2002 + StringTable *GetTable(LANGID &lang); int SetString(char *string, int id, int process, WORD lang=0); int SetString(char *string, int id, int process, StringTable *table); + int SetUserString(char *name, LANGID lang, char *string); int WriteStringTables(); void FillDefaultsIfNeeded(StringTable *table, NLF *nlf=0); #define IsNotSet(s) _IsNotSet(string_tables.size()?&(string_tables[0]->s):0) @@ -196,6 +198,7 @@ class CEXEBuild { GrowBuf build_labels, ubuild_labels, *cur_labels; StringList build_strlist,ubuild_strlist; GrowBuf build_langtables, ubuild_langtables; + StringList build_userlangstrings, ubuild_userlangstrings, *cur_userlangstrings; MMapBuf build_datablock, ubuild_datablock; // use GrowBuf here instead of MMapBuf if you want IGrowBuf *cur_datablock; diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index a0ffb4d4..f6faca12 100644 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -42,10 +42,10 @@ HICON g_hIcon; static char gDontFookWithFocus = 0; // Added by Amir Szekely 3rd August 2002 -common_strings *common_strings_tables; +char *language_tables; common_strings *cur_common_strings_table; -char *install_strings_tables; // installer_strings/uninstall_strings depending on installer type -char *cur_install_strings_table; +char *cur_install_strings_table; // installer_strings/uninstall_strings depending on installer type +int *cur_user_strings_table; int g_quit_flag; // set when Quit has been called (meaning bail out ASAP) @@ -252,26 +252,32 @@ static void NSISCALL set_language() int i; LANGID lang_mask=~(LANGID)0; LANGID lang=myatoi(state_language); + char *language_table=0; lang_again: for (i = 0; i < lang_num; i++) { - if (!((lang ^ common_strings_tables[i].lang_id) & lang_mask)) { - cur_common_strings_table=common_strings_tables+i; + language_table=language_tables+i*g_inst_cmnheader->language_table_size; + if (!((lang ^ *(LANGID*)language_table) & lang_mask)) { + cur_common_strings_table=(common_strings*)(language_table+sizeof(LANGID)); + cur_install_strings_table=(void*)(cur_common_strings_table+1); #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT if (g_is_uninstaller) - (uninstall_strings *)cur_install_strings_table=(uninstall_strings *)install_strings_tables+i; + cur_user_strings_table=(int*)((uninstall_strings*)cur_install_strings_table+1); else #endif - (installer_strings *)cur_install_strings_table=(installer_strings *)install_strings_tables+i; + cur_user_strings_table=(int*)((installer_strings*)cur_install_strings_table+1); break; } } - if ((i == lang_num) && (lang_mask == ~(LANGID)0)) { - lang_mask=0x3ff; // primary lang + if (i == lang_num) { + if (lang_mask == ~(LANGID)0) + lang_mask=0x3ff; // primary lang + else // we already tried once and we still don't have a language table + lang_mask=0; // first lang goto lang_again; } - myitoa(state_language, cur_common_strings_table->lang_id); + myitoa(state_language, *(LANGID*)language_table); SendMessage(m_bgwnd, WM_SETTEXT, 0, (LPARAM)process_string_from_lang(g_caption,LANGID_CAPTION)); } @@ -290,7 +296,7 @@ int NSISCALL ui_doinstall(void) #endif if (!is_valid_instpath(state_install_directory)) { - if (g_inst_header->install_reg_key_ptr>=0) + if (g_inst_header->install_reg_key_ptr) { myRegGetStr((HKEY)g_inst_header->install_reg_rootkey, GetStringFromStringTab(g_inst_header->install_reg_key_ptr), @@ -347,10 +353,7 @@ int NSISCALL ui_doinstall(void) { extern char *g_db_strtab; lang_num=g_inst_cmnheader->str_tables_num; - cur_common_strings_table=common_strings_tables= - (common_strings*)(g_db_strtab+g_inst_cmnheader->num_string_bytes); - cur_install_strings_table=install_strings_tables= - (char*)((unsigned long)common_strings_tables+lang_num*sizeof(common_strings)); + language_tables=(void*)(g_db_strtab+g_inst_cmnheader->num_string_bytes); myitoa(state_language, GetUserDefaultLangID()); set_language(); @@ -492,19 +495,19 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT if (g_is_uninstaller) { - islp = (LANG_UNINST_TEXT>=0); + islp = (LANG_UNINST_TEXT>0); iscp++; } else #endif//NSIS_CONFIG_UNINSTALL_SUPPORT { #ifdef NSIS_CONFIG_LICENSEPAGE - islp = (LANG_LICENSE_DATA>=0); + islp = (LANG_LICENSE_DATA>0); #endif//NSIS_CONFIG_LICENSEPAGE #ifdef NSIS_CONFIG_COMPONENTPAGE - iscp = (LANG_COMP_TEXT>=0); + iscp = (LANG_COMP_TEXT>0); #endif//NSIS_CONFIG_COMPONENTPAGE - ispotentiallydp = (LANG_DIR_TEXT>=0); + ispotentiallydp = (LANG_DIR_TEXT>0); if (ispotentiallydp && !((g_inst_cmnheader->misc_flags&2) && is_valid_instpath(state_install_directory) @@ -859,7 +862,7 @@ static BOOL CALLBACK DirProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar // Added by Amir Szekely 24th July 2002 // Allows 'SpaceTexts none' - if (LANG_SPACE_REQ >= 0) { + if (LANG_SPACE_REQ) { inttosizestr(total,mystrcpy(s,STR(LANG_SPACE_REQ))); SetUITextNT(IDC_SPACEREQUIRED,s); if (available != -1) @@ -979,14 +982,14 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar DeleteObject(hBMcheck1); - if (g_inst_header->install_types_ptr[0]<0) + if (!g_inst_header->install_types_ptr[0]) { ShowWindow(hwndCombo1,SW_HIDE); } else { for (m_num_insttypes = 0; m_num_insttypes < NSIS_MAX_INST_TYPES && - g_inst_header->install_types_ptr[m_num_insttypes]>=0; m_num_insttypes ++) + g_inst_header->install_types_ptr[m_num_insttypes]; m_num_insttypes ++) { SendMessage(hwndCombo1,CB_ADDSTRING,0,(LPARAM)GetStringFromStringTab(g_inst_header->install_types_ptr[m_num_insttypes])); } @@ -998,7 +1001,7 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar for (x = 0; x < num_sections; x ++) { - if (g_inst_section[x].name_ptr>=0) + if (g_inst_section[x].name_ptr) { TVINSERTSTRUCT tv; tv.hParent=Par; @@ -1038,7 +1041,7 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar tv.item.pszText++; tv.item.mask|=TVIF_CHILDREN; tv.item.cChildren=1; - if (g_inst_section[x].name_ptr>=0 && g_inst_section[x].expand) + if (g_inst_section[x].name_ptr && g_inst_section[x].expand) tv.item.state|=TVIS_EXPANDED; Par = hTreeItems[x] = TreeView_InsertItem(hwndTree1,&tv); doLines=1; @@ -1074,7 +1077,7 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar int x=wParam; int ns=lParam; - if (g_inst_section[x].name_ptr>=0 && ns >= 0) + if (g_inst_section[x].name_ptr && ns >= 0) { TVITEM tv; tv.hItem=hTreeItems[x]; @@ -1200,7 +1203,7 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar HTREEITEM *ht=hTreeItems; while (x--) { - if (t->name_ptr>=0 && !(t->default_state & DFS_RO)) + if (t->name_ptr && !(t->default_state & DFS_RO)) { TVITEM tv; int l=1; @@ -1248,7 +1251,7 @@ static BOOL CALLBACK SelProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar ShowWindow(GetUIItem(IDC_TEXT2),c); } - if (LANG_SPACE_REQ >= 0) { + if (LANG_SPACE_REQ) { int x,total; char s[128]; for (total=x=0; x < num_sections; x ++) diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 3cd348ac..0576dd54 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -569,7 +569,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) char *p=var0; char *buf0=process_string_fromparm_tobuf(0x01); *p=0; - if (parm2 < 0 || newlen) + if (!parm2 || newlen) { l=mystrlen(buf0); @@ -737,7 +737,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) v=(int)FindWindowEx((HWND)b3,(HWND)b4,buf0[0]?buf0:NULL,buf1[0]?buf1:NULL); } - if (parm0>=0) + if (parm0) myitoa(var0,v); } return 0; @@ -928,7 +928,13 @@ static int NSISCALL ExecuteEntry(entry *entry_) if (funke) { exec_errorflag--; - if (parm2<0) + if (parm2) + { + char *buf2=process_string_fromparm_tobuf(0x22); + update_status_text(buf2,buf0); + funke(); + } + else { void (*func)(HWND,int,char*,void*); func=(void*)funke; @@ -939,12 +945,6 @@ static int NSISCALL ExecuteEntry(entry *entry_) NULL); #endif } - else - { - char *buf2=process_string_fromparm_tobuf(0x22); - update_status_text(buf2,buf0); - funke(); - } } else { @@ -1107,11 +1107,11 @@ static int NSISCALL ExecuteEntry(entry *entry_) mystrcpy(buf1,""); mystrcpy(buf2,buf1); #endif - if (parm1>=0) + if (parm1) { sec=process_string_fromparm_tobuf(0x11); } - if (parm2>=0) + if (parm2) { ent=process_string_fromparm_tobuf(0x22); } @@ -1142,7 +1142,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) int rootkey=parm0; char *buf3=process_string_fromparm_tobuf(0x31); exec_errorflag++; - if (parm2 != -1) + if (parm2) { HKEY hKey; if (RegOpenKeyEx((HKEY)rootkey,buf3,0,KEY_ALL_ACCESS,&hKey) == ERROR_SUCCESS) @@ -1486,7 +1486,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) if (g_SectionHack) { int a; - for (a = 0; a < x; a ++) if (g_inst_section[a].name_ptr>=0) z++; + for (a = 0; a < x; a ++) if (g_inst_section[a].name_ptr) z++; } if (parm1==0) //set text diff --git a/Source/exehead/fileform.c b/Source/exehead/fileform.c index f9e4addd..75430253 100644 --- a/Source/exehead/fileform.c +++ b/Source/exehead/fileform.c @@ -115,8 +115,11 @@ const char * NSISCALL loadHeaders(void) const char * NSISCALL GetStringFromStringTab(int offs) { - if (offs < 0) return ""; - return g_db_strtab+offs; + /*if (offs < 0) { + wsprintf(ps_tmpbuf, "my first user madasd %d->%d which should be %d\n%d", offs, cur_user_strings_table[-(offs+1)], cur_user_strings_table[0], LANG_COMP_TEXT); + my_MessageBox(ps_tmpbuf, MB_OK); + }*/ + return g_db_strtab+(offs < 0 ? cur_user_strings_table[-(offs+1)] : offs); } #define IBUFSIZE 16384 diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index af6565b9..882784e2 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -15,6 +15,7 @@ // uninstall_header (~116 bytes) // entries (24 bytes each) // string table +// language tables // datablock // (hdrinfo+datablock is at least 512 bytes if CRC enabled) // CRC (optional - 4 bytes) @@ -273,16 +274,13 @@ typedef struct int output_dir; int create_dir; int copy_details; - - // Note - should be at the end (everything before here should be just ints) - WORD lang_id; - } common_strings; // Settings common to both installers and uninstallers typedef struct { int str_tables_num; // number of strings tables in array + int language_table_size; // size of each language table int num_entries; // total number of entries int num_string_bytes; // total number of bytes taken by strings @@ -311,12 +309,6 @@ typedef struct #endif//NSIS_CONFIG_SILENT_SUPPORT // additional flags char misc_flags; // auto_close=&1, no_show_dirpage=&2, no_show_icon&4, no_rootdir&8; - - // Added by Amir Szekely 6th August 2002 - // Adds the ability to make the inner text show up in a dialog item in the outer dialog. - /* Useless - WORD intro_text_id;*/ - } common_header; // Strings specific to installers @@ -388,18 +380,6 @@ typedef struct int code_onSelChange; #endif//NSIS_CONFIG_COMPONENTPAGE #endif//NSIS_SUPPORT_CODECALLBACKS - - // Added by Amir Szekely 6th August 2002 - // Adds the ability to make the inner text show up in a dialog item in the outer dialog. - /* - Useless - - WORD space_avail_id; - WORD space_req_id; - WORD dir_subtext_id; - WORD com_subtext1_id; - WORD com_subtext2_id;*/ - } header; // Strings specific to uninstallers @@ -419,12 +399,6 @@ typedef struct int code; int code_size; - - // Added by Amir Szekely 6th August 2002 - // Adds the ability to make the inner text show up in a dialog item in the outer dialog. - /* Useless - WORD uninst_subtext_id;*/ - } uninstall_header; typedef struct diff --git a/Source/exehead/ui.h b/Source/exehead/ui.h index 90d00042..c7f434a9 100644 --- a/Source/exehead/ui.h +++ b/Source/exehead/ui.h @@ -4,8 +4,10 @@ #include "lang.h" // Added by Amir Szekely 3rd August 2002 +extern char *language_tables; extern common_strings *cur_common_strings_table; -extern char *cur_install_strings_table; // installer_strings/uninstall_strings depending on installer type +extern char *cur_install_strings_table; // installer_strings/uninstall_strings depending on installer type +extern int *cur_user_strings_table; int NSISCALL ui_doinstall(void); void NSISCALL update_status_text_from_lang(langid_t id, const char *text2); diff --git a/Source/lang.cpp b/Source/lang.cpp index 1400e79b..118c9200 100644 --- a/Source/lang.cpp +++ b/Source/lang.cpp @@ -67,27 +67,33 @@ extern char *english_strings[] = { "Copy Details To Clipboard" }; -int CEXEBuild::SetString(char *string, int id, int process, LANGID lang/*=0*/) { +StringTable* CEXEBuild::GetTable(LANGID &lang) { lang=lang?lang:last_used_lang; last_used_lang=lang; StringTable *table = 0; for (int i = 0; i < string_tables.size(); i++) { - if (lang == string_tables[i]->common.lang_id) { + if (lang == string_tables[i]->lang_id) { table = string_tables[i]; break; } } if (!table) { - table = (StringTable*)malloc(sizeof(StringTable)); + table = new StringTable; if (!table) { ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n",sizeof(StringTable)); - return PS_ERROR; + return 0; } - memset(table, -1, sizeof(StringTable)); - table->common.lang_id = table->ucommon.lang_id = lang; + memset(table, 0, sizeof(StringTable)-sizeof(GrowBuf)*2); + table->lang_id = table->lang_id = lang; string_tables.push_back(table); } + return table; +} + +int CEXEBuild::SetString(char *string, int id, int process, LANGID lang/*=0*/) { + StringTable *table = GetTable(lang); + if (!table) return PS_ERROR; return SetString(string, id, process, table); } @@ -178,55 +184,103 @@ int CEXEBuild::SetString(char *string, int id, int process, StringTable *table) return PS_OK; } +int CEXEBuild::SetUserString(char *name, LANGID lang, char *string) { + StringTable *table = GetTable(lang); + if (!table) return PS_ERROR; + + GrowBuf *user_strings; + StringList *user_strings_list; + bool uninst; + if (!(uninst = !strnicmp(name,"un.",3))) { + name += 3; + user_strings=&table->user_strings; + user_strings_list=&build_userlangstrings; + } + else { + user_strings=&table->user_ustrings; + user_strings_list=&ubuild_userlangstrings; + } + + int idx; + if (user_strings_list->find(name, 0, &idx) < 0) { + user_strings_list->add(name, 0); + user_strings_list->find(name, 0, &idx); + } + + user_strings->resize((idx+1)*sizeof(int)); + ((int*)user_strings->get())[idx] = uninst ? add_string_uninst(string,1) : add_string_main(string,1); + + for (int j = 0; j < string_tables.size(); j++) { + if (j == idx) continue; + if (uninst) { + if (string_tables[j]->user_ustrings.getlen() < (idx+1)*sizeof(int)) { + string_tables[j]->user_ustrings.resize((idx+1)*sizeof(int)); + ((int*)string_tables[j]->user_ustrings.get())[idx] = 0; + } + } + else { + if (string_tables[j]->user_strings.getlen() < (idx+1)*sizeof(int)) { + string_tables[j]->user_strings.resize((idx+1)*sizeof(int)); + ((int*)string_tables[j]->user_strings.get())[idx] = 0; + } + } + } + + return PS_OK; +} + bool CEXEBuild::_IsSet(int *str, WORD lang) { if (!str) return false; lang = lang?lang:build_nlfs.size()?build_nlfs[build_nlfs.size()-1]->GetLang():0; - lang = lang?lang:string_tables.size()?string_tables[0]->common.lang_id:1033; // Default is English (1033) + lang = lang?lang:string_tables.size()?string_tables[0]->lang_id:1033; // Default is English (1033) int i; for (i = 0; i < string_tables.size(); i++) { - if (lang == string_tables[i]->common.lang_id) { + if (lang == string_tables[i]->lang_id) { break; } } if (i == string_tables.size()) return false; - if (*(int*)(int(str)-int(string_tables[0])+int(string_tables[i]))>=0) return true; + if (*(int*)(int(str)-int(string_tables[0])+int(string_tables[i]))) return true; return false; } int CEXEBuild::WriteStringTables() { int i; + SCRIPT_MSG("Generating language tables... "); + // If we have no tables (user didn't set any string and didn't load any NLF) create the default one - if (string_tables.size() == 0) { - StringTable *table = (StringTable*)malloc(sizeof(StringTable)); - if (!table) { - ERROR_MSG("Internal compiler error #12345: malloc(%d) failed\n",sizeof(StringTable)); - return PS_ERROR; - } - memset(table, -1, sizeof(StringTable)); - table->common.lang_id=table->ucommon.lang_id=1033; // English - string_tables.push_back(table); - } + LANGID lang = 1033; + StringTable *table = GetTable(lang); + if (!table) return PS_ERROR; // Fill tables with defaults (if needed) and with instruction strings int st_num = string_tables.size(); for (i = 0; i < st_num; i++) FillDefaultsIfNeeded(string_tables[i]); - // Add string tables into datablock - for (i = 0; i < st_num; i++) + // Add string tables into their datablock + for (i = 0; i < st_num; i++) { + build_langtables.add(&string_tables[i]->lang_id, sizeof(LANGID)); build_langtables.add(&string_tables[i]->common, sizeof(common_strings)); - build_header.common.str_tables_num = st_num; - - for (i = 0; i < st_num; i++) build_langtables.add(&string_tables[i]->installer, sizeof(installer_strings)); + if (build_userlangstrings.getnum()) + build_langtables.add(string_tables[i]->user_strings.get(), string_tables[i]->user_strings.getlen()); + } + build_header.common.str_tables_num = st_num; + build_header.common.language_table_size = sizeof(LANGID) + sizeof(common_strings) + sizeof(installer_strings) + (build_userlangstrings.getnum() * sizeof(int)); - for (i = 0; i < st_num; i++) + for (i = 0; i < st_num; i++) { + ubuild_langtables.add(&string_tables[i]->lang_id, sizeof(LANGID)); ubuild_langtables.add(&string_tables[i]->ucommon, sizeof(common_strings)); - build_uninst.common.str_tables_num = st_num; - - for (i = 0; i < st_num; i++) ubuild_langtables.add(&string_tables[i]->uninstall, sizeof(uninstall_strings)); + if (ubuild_userlangstrings.getnum()) + ubuild_langtables.add(string_tables[i]->user_ustrings.get(), string_tables[i]->user_ustrings.getlen()); + } + build_uninst.common.str_tables_num = st_num; + build_uninst.common.language_table_size = sizeof(LANGID) + sizeof(common_strings) + sizeof(uninstall_strings) + (ubuild_userlangstrings.getnum() * sizeof(int)); + + SCRIPT_MSG("Done!\n"); return PS_OK; } @@ -234,7 +288,7 @@ int CEXEBuild::WriteStringTables() { void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { if (!nlf) { for (int i = 0; i < build_nlfs.size(); i++) { - if (build_nlfs[i]->GetLang() == table->common.lang_id) { + if (build_nlfs[i]->GetLang() == table->lang_id) { nlf = build_nlfs[i]; break; } @@ -245,7 +299,7 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { #ifdef NSIS_CONFIG_COMPONENTPAGE // if component page, do component strings: - if (table->installer.componenttext>=0) + if (table->installer.componenttext) { int x; int iscp=0; @@ -256,29 +310,29 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { } if (iscp) { - if (table->installer.custom<0) table->installer.custom=add_string_main(str(NLF_COMP_CUSTOM),0); - if (table->common.subcaptions[1]<0) + if (!table->installer.custom) table->installer.custom=add_string_main(str(NLF_COMP_CUSTOM),0); + if (!table->common.subcaptions[1]) table->common.subcaptions[1]=add_string_main(str(NLF_SUBCAPTION_OPTIONS)); - if (build_header.install_types_ptr[0] < 0) + if (!build_header.install_types_ptr[0]) { - if (table->installer.componentsubtext[1]<0) + if (!table->installer.componentsubtext[1]) table->installer.componentsubtext[1]=add_string_main(str(NLF_COMP_SUBTEXT1_NO_INST_TYPES),0); } else { - if (table->installer.componentsubtext[0]<0) + if (!table->installer.componentsubtext[0]) table->installer.componentsubtext[0]=add_string_main(str(NLF_COMP_SUBTEXT1),0); - if (build_header.no_custom_instmode_flag!=1 && table->installer.componentsubtext[1]<0) + if (build_header.no_custom_instmode_flag!=1 && !table->installer.componentsubtext[1]) table->installer.componentsubtext[1]=add_string_main(str(NLF_COMP_SUBTEXT2),0); } } - else table->installer.componenttext=-1; + else table->installer.componenttext=0; } #endif static bool nameWarned = false; - if (table->common.name < 0) + if (!table->common.name) { if (!nameWarned) { warning("Name command not specified. Assuming default."); @@ -290,69 +344,69 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { #ifdef NSIS_CONFIG_VISIBLE_SUPPORT #ifdef NSIS_CONFIG_LICENSEPAGE - if (table->installer.licensedata<0 || table->installer.licensetext<0) + if (!table->installer.licensedata || !table->installer.licensetext) { - table->installer.licensedata=-1; - table->installer.licensetext=-1; + table->installer.licensedata=0; + table->installer.licensetext=0; } - if (table->installer.licensedata>=0) + if (table->installer.licensedata) { - if (table->common.subcaptions[0]<0) + if (!table->common.subcaptions[0]) table->common.subcaptions[0]=add_string_main(str(NLF_SUBCAPTION_LICENSE)); - if (table->installer.licensebutton<0) + if (!table->installer.licensebutton) table->installer.licensebutton=add_string_main(str(NLF_BTN_LICENSE),0); } #endif //NSIS_CONFIG_LICENSEPAGE - if (table->installer.text >= 0) + if (table->installer.text) { - if (table->installer.dirsubtext<0) + if (!table->installer.dirsubtext) { char buf[2048]; wsprintf(buf,str(NLF_DIR_SUBTEXT),build_strlist.get()+table->common.name); table->installer.dirsubtext=add_string_main(buf,0); } - if (table->common.subcaptions[2]<0) + if (!table->common.subcaptions[2]) table->common.subcaptions[2]=add_string_main(str(NLF_SUBCAPTION_DIR)); - if (table->installer.browse<0) table->installer.browse=add_string_main(str(NLF_BTN_BROWSE),0); - if (table->installer.spaceavailable<0 && !no_space_texts) table->installer.spaceavailable=add_string_main(str(NLF_SPACE_AVAIL),0); + if (!table->installer.browse) table->installer.browse=add_string_main(str(NLF_BTN_BROWSE),0); + if (!table->installer.spaceavailable && !no_space_texts) table->installer.spaceavailable=add_string_main(str(NLF_SPACE_AVAIL),0); } - if (table->installer.text >= 0 + if (table->installer.text #ifdef NSIS_CONFIG_COMPONENTPAGE - || table->installer.componenttext>=0 + || table->installer.componenttext #endif ) { // Changed by Amir Szekely 22nd July 2002 // Adds the ability to disable space texts - if (table->installer.spacerequired<0 && !no_space_texts) table->installer.spacerequired=add_string_main(str(NLF_SPACE_REQ),0); - if (table->installer.nextbutton<0) table->installer.nextbutton=add_string_main(str(NLF_BTN_NEXT),0); - if (table->installer.installbutton<0) table->installer.installbutton=add_string_main(str(NLF_BTN_INSTALL),0); + if (!table->installer.spacerequired && !no_space_texts) table->installer.spacerequired=add_string_main(str(NLF_SPACE_REQ),0); + if (!table->installer.nextbutton) table->installer.nextbutton=add_string_main(str(NLF_BTN_NEXT),0); + if (!table->installer.installbutton) table->installer.installbutton=add_string_main(str(NLF_BTN_INSTALL),0); } - if (table->common.subcaptions[3]<0) + if (!table->common.subcaptions[3]) table->common.subcaptions[3]=add_string_main(str(NLF_SUBCAPTION_INSTFILES)); - if (table->common.subcaptions[4]<0) + if (!table->common.subcaptions[4]) table->common.subcaptions[4]=add_string_main(str(NLF_USUBCAPTION_COMPLETED)); - if (table->common.branding<0) + if (!table->common.branding) { char buf[256]; wsprintf(buf,str(NLF_BRANDING),NSIS_VERSION); table->common.branding=add_string_main(buf,0); } - if (table->installer.backbutton<0) table->installer.backbutton=add_string_main(str(NLF_BTN_BACK),0); - if (table->common.cancelbutton<0) table->common.cancelbutton=add_string_main(str(NLF_BTN_CANCEL),0); - if (table->common.showdetailsbutton<0) table->common.showdetailsbutton=add_string_main(str(NLF_BTN_DETAILS),0); + if (!table->installer.backbutton) table->installer.backbutton=add_string_main(str(NLF_BTN_BACK),0); + if (!table->common.cancelbutton) table->common.cancelbutton=add_string_main(str(NLF_BTN_CANCEL),0); + if (!table->common.showdetailsbutton) table->common.showdetailsbutton=add_string_main(str(NLF_BTN_DETAILS),0); - if (table->common.closebutton<0) table->common.closebutton=add_string_main(str(NLF_BTN_CLOSE),0); - if (table->common.completed<0) table->common.completed=add_string_main(str(NLF_COMPLETED),0); + if (!table->common.closebutton) table->common.closebutton=add_string_main(str(NLF_BTN_CLOSE),0); + if (!table->common.completed) table->common.completed=add_string_main(str(NLF_COMPLETED),0); #endif #ifdef NSIS_SUPPORT_FILE - if (m_inst_fileused && table->common.fileerrtext<0) + if (m_inst_fileused && !table->common.fileerrtext) { table->common.fileerrtext=add_string_main(str(NLF_FILE_ERROR)); } @@ -362,15 +416,15 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { if (ubuild_entries.getlen()) { if (uninstaller_writes_used) { - if (table->uninstall.uninstalltext2<0) + if (!table->uninstall.uninstalltext2) table->uninstall.uninstalltext2=add_string_uninst(str(NLF_UNINST_SUBTEXT),0); - if (table->ucommon.subcaptions[0]<0) + if (!table->ucommon.subcaptions[0]) table->ucommon.subcaptions[0]=add_string_uninst(str(NLF_USUBCAPTION_CONFIRM)); - if (table->ucommon.subcaptions[1]<0) + if (!table->ucommon.subcaptions[1]) table->ucommon.subcaptions[1]=add_string_uninst(str(NLF_USUBCAPTION_INSTFILES)); - if (table->ucommon.subcaptions[2]<0) + if (!table->ucommon.subcaptions[2]) table->ucommon.subcaptions[2]=add_string_uninst(str(NLF_USUBCAPTION_COMPLETED)); - if (table->ucommon.caption < 0) + if (!table->ucommon.caption) { char buf[1024]; wsprintf(buf,str(NLF_UCAPTION),ubuild_strlist.get()+table->ucommon.name); @@ -382,12 +436,12 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { table->ucommon.closebutton=add_string_uninst(build_strlist.get() + table->common.closebutton,0); table->ucommon.completed=add_string_uninst(build_strlist.get() + table->common.completed,0); - if (table->uninstall.uninstbutton<0) table->uninstall.uninstbutton=add_string_uninst(str(NLF_BTN_UNINSTALL),0); + if (!table->uninstall.uninstbutton) table->uninstall.uninstbutton=add_string_uninst(str(NLF_BTN_UNINSTALL),0); } } #ifdef NSIS_SUPPORT_FILE - if (m_uninst_fileused && table->ucommon.fileerrtext<0) + if (m_uninst_fileused && !table->ucommon.fileerrtext) { table->ucommon.fileerrtext=add_string_uninst(build_strlist.get() + table->common.fileerrtext); } @@ -395,7 +449,7 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { #endif - if (table->common.caption < 0) + if (!table->common.caption) { char buf[1024]; wsprintf(buf,str(NLF_CAPTION),build_strlist.get()+table->common.name); @@ -467,7 +521,7 @@ void CEXEBuild::FillDefaultsIfNeeded(StringTable *table, NLF *nlf/*=0*/) { bool CEXEBuild::_IsNotSet(int *str) { if (!str) return true; for (int i = 0; i < string_tables.size(); i++) { - if (*(int*)(int(str)-int(string_tables[0])+int(string_tables[i])) >= 0) { + if (*(int*)(int(str)-int(string_tables[0])+int(string_tables[i]))) { return false; } } diff --git a/Source/lang.h b/Source/lang.h index f9f73da5..ad676e9f 100644 --- a/Source/lang.h +++ b/Source/lang.h @@ -8,10 +8,13 @@ using namespace std; struct StringTable { + LANGID lang_id; common_strings common; common_strings ucommon; installer_strings installer; uninstall_strings uninstall; + GrowBuf user_strings; + GrowBuf user_ustrings; }; #define NLF_VERSION 2 diff --git a/Source/script.cpp b/Source/script.cpp index 12225b17..f749eda9 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -531,6 +531,14 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char return PS_OK; // header flags /////////////////////////////////////////////////////////////////////////////// + case TOK_LANGSTRING: + SCRIPT_MSG("LangString: \"%s\" %s \"%s\"\n", line.gettoken_str(1), line.gettoken_str(2), line.gettoken_str(3)); + if (SetUserString(line.gettoken_str(1), line.gettoken_int(2), line.gettoken_str(3)) != PS_OK) + { + ERROR_MSG("Error: LangString: can't add user string!\n"); + return PS_ERROR; + } + return make_sure_not_in_secorfunc(line.gettoken_str(0)); case TOK_NAME: { int a = 1; @@ -659,7 +667,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char else if (line.gettoken_str(1)[0]=='/') PRINTHELP() else { - for (x = 0; x < NSIS_MAX_INST_TYPES && build_header.install_types_ptr[x]>=0; x ++); + for (x = 0; x < NSIS_MAX_INST_TYPES && build_header.install_types_ptr[x]; x ++); if (x==NSIS_MAX_INST_TYPES) { ERROR_MSG("InstType: no more than %d install types allowed. %d specified\n",NSIS_MAX_INST_TYPES,NSIS_MAX_INST_TYPES+1); @@ -786,7 +794,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char SCRIPT_MSG("OutFile: \"%s\"\n",build_output_filename); return make_sure_not_in_secorfunc(line.gettoken_str(0)); case TOK_INSTDIR: - if (build_header.install_directory_ptr >= 0) + if (build_header.install_directory_ptr) { warning("%s: specified multiple times. wasting space (%s:%d)",line.gettoken_str(0),curfilename,linecnt); } @@ -795,7 +803,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char return make_sure_not_in_secorfunc(line.gettoken_str(0)); case TOK_INSTALLDIRREGKEY: // InstallDirRegKey { - if (build_header.install_reg_key_ptr>= 0) + if (build_header.install_reg_key_ptr) { warning("%s: specified multiple times, wasting space (%s:%d)",line.gettoken_str(0),curfilename,linecnt); } @@ -1398,17 +1406,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char return PS_ERROR; } build_nlfs.push_back(newNLF); - for (i = 0; i < string_tables.size(); i++) { - if (newNLF->GetLang() == string_tables[i]->common.lang_id) { - break; - } - } - if (i == string_tables.size()) { - StringTable *table = (StringTable*)malloc(sizeof(StringTable)); - memset(table, -1, sizeof(StringTable)); - table->common.lang_id=table->ucommon.lang_id=newNLF->GetLang(); - string_tables.push_back(table); - } + LANGID lang = newNLF->GetLang(); + GetTable(lang); last_used_lang=newNLF->GetLang(); // define LANG_LangName as "####" (lang id) // for example ${LANG_ENGLISH} = 1033 @@ -1607,7 +1606,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[0]=add_string_main(line.gettoken_str(1)); ent.offsets[1]=0; // uninstall section 0 ent.offsets[2]=0; - if (ent.offsets[0]<0) PRINTHELP() + if (!ent.offsets[0]) PRINTHELP() SCRIPT_MSG("WriteUninstaller: \"%s\"\n",line.gettoken_str(1)); return add_entry(&ent); #else//!NSIS_CONFIG_UNINSTALL_SUPPORT @@ -2084,13 +2083,13 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char } if (a+1 != line.getnumtokens()) PRINTHELP(); ent.offsets[1]=add_string(line.gettoken_str(a)); - if (ent.offsets[1]<0) PRINTHELP() - ent.offsets[2]=-1; + if (!ent.offsets[1]) PRINTHELP() + ent.offsets[2]=0; } else // register { ent.offsets[1] = add_string(line.gettoken_str(2)); - if (ent.offsets[1]<0) ent.offsets[1]=add_string("DllRegisterServer"); + if (!ent.offsets[1]) ent.offsets[1]=add_string("DllRegisterServer"); ent.offsets[2]=add_string("Registering: "); } @@ -2613,7 +2612,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char return add_entry(&ent); case TOK_SETDETAILSPRINT: ent.which=EW_UPDATETEXT; - ent.offsets[0] = -1; + ent.offsets[0] = 0; ent.offsets[1] = line.gettoken_enum(1,"none\0listonly\0textonly\0both\0"); if (ent.offsets[1] < 0) PRINTHELP() if (!ent.offsets[1]) ent.offsets[1]=4; @@ -2662,8 +2661,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.which=EW_GETFUNCTIONADDR; ent.offsets[0]=line.gettoken_enum(1,usrvars); ent.offsets[1]=ns_func.add(line.gettoken_str(2),0); - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; if (ent.offsets[0] < 0) PRINTHELP() SCRIPT_MSG("GetFunctionAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); return add_entry(&ent); @@ -2671,8 +2670,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.which=EW_GETLABELADDR; ent.offsets[0]=line.gettoken_enum(1,usrvars); if (ent.offsets[0] < 0 || process_jump(line,2,&ent.offsets[1])) PRINTHELP() - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; SCRIPT_MSG("GetLabelAddress: %s %s",line.gettoken_str(1),line.gettoken_str(2)); return add_entry(&ent); case TOK_GETCURRENTADDR: @@ -2684,8 +2683,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[1]=add_string(buf); } if (ent.offsets[0] < 0) PRINTHELP() - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; SCRIPT_MSG("GetCurrentAddress: %s %s",line.gettoken_str(1)); return add_entry(&ent); case TOK_STRCMP: @@ -2729,16 +2728,16 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[0]=line.gettoken_enum(2,usrvars); wsprintf(buf,"%u",high); ent.offsets[1]=add_string(buf); - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; if (ent.offsets[0]<0) PRINTHELP() add_entry(&ent); ent.offsets[0]=line.gettoken_enum(3,usrvars); wsprintf(buf,"%u",low); ent.offsets[1]=add_string(buf); - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; if (ent.offsets[0]<0) PRINTHELP() SCRIPT_MSG("GetDLLVersionLocal: %s (%u,%u)->(%s,%s)\n", line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); @@ -2771,16 +2770,16 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[0]=line.gettoken_enum(2,usrvars); wsprintf(buf,"%u",high); ent.offsets[1]=add_string(buf); - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; if (ent.offsets[0]<0) PRINTHELP() add_entry(&ent); ent.offsets[0]=line.gettoken_enum(3,usrvars); wsprintf(buf,"%u",low); ent.offsets[1]=add_string(buf); - ent.offsets[2]=-1; - ent.offsets[3]=-1; + ent.offsets[2]=0; + ent.offsets[3]=0; if (ent.offsets[0]<0) PRINTHELP() SCRIPT_MSG("GetFileTimeLocal: %s (%u,%u)->(%s,%s)\n", line.gettoken_str(1),high,low,line.gettoken_str(2),line.gettoken_str(3)); @@ -2811,8 +2810,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char vname=line.gettoken_str(3); ent.offsets[1]=add_string(vname); // value name } - else ent.offsets[1]=-1; - ent.offsets[2]=-1; + else ent.offsets[1]=0; + ent.offsets[2]=0; ent.offsets[3]=add_string(line.gettoken_str(1)); SCRIPT_MSG("DeleteINI%s: [%s] %s in %s\n",vname?"Str":"Sec", line.gettoken_str(2),vname,line.gettoken_str(1)); @@ -2958,7 +2957,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[0]=line.gettoken_enum(1,usrvars); int k=line.gettoken_enum(2,rootkeys[0]); if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); - if (ent.offsets[0] < 0 || k == -1) PRINTHELP() + if (!ent.offsets[0] || k == -1) PRINTHELP() ent.offsets[1]=(int)rootkey_tab[k]; ent.offsets[2]=add_string(line.gettoken_str(3)); ent.offsets[3]=add_string(line.gettoken_str(4)); @@ -2991,7 +2990,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.which=EW_DELREG; ent.offsets[0]=(int)rootkey_tab[k]; ent.offsets[1]=add_string(line.gettoken_str(a+1)); - ent.offsets[2]=(which_token==TOK_DELETEREGKEY)?-1:add_string(line.gettoken_str(a+2)); + ent.offsets[2]=(which_token==TOK_DELETEREGKEY)?0:add_string(line.gettoken_str(a+2)); if (line.gettoken_str(a+1)[0] == '\\') warning("%s: registry path name begins with \'\\\', may cause problems (%s:%d)",line.gettoken_str(0),curfilename,linecnt); if (which_token==TOK_DELETEREGKEY) SCRIPT_MSG("DeleteRegKey: %s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1)); @@ -3075,7 +3074,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[0]=line.gettoken_enum(1,usrvars); int k=line.gettoken_enum(2,rootkeys[0]); if (k == -1) k=line.gettoken_enum(2,rootkeys[1]); - if (ent.offsets[0] < 0 || k == -1) PRINTHELP() + if (!ent.offsets[0] || k == -1) PRINTHELP() ent.offsets[1]=(int)rootkey_tab[k]; ent.offsets[2]=add_string(line.gettoken_str(3)); ent.offsets[3]=add_string(line.gettoken_str(4)); @@ -3463,8 +3462,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.offsets[1]=add_string(line.gettoken_str(2)); SCRIPT_MSG("CreateFont: output=%s \"%s\"",line.gettoken_str(1),line.gettoken_str(2)); { - int height=-1; - int weight=-1; + int height=0; + int weight=0; int flags=0; for (int i = 3; i < line.getnumtokens(); i++) { char *tok=line.gettoken_str(i); @@ -3487,11 +3486,11 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char } } else { - if (height==-1) { + if (!height) { SCRIPT_MSG(" height=%s",tok); height=add_string(tok); } - else if (weight==-1) { + else if (!weight) { SCRIPT_MSG(" weight=%s",tok); weight=add_string(tok); } @@ -3501,8 +3500,6 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char } } } - if (height==-1) height=add_string("0"); - if (weight==-1) weight=add_string("0"); ent.offsets[2]=height; ent.offsets[3]=weight; ent.offsets[4]=flags; @@ -3588,7 +3585,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char ent.which=EW_REGISTERDLL; ent.offsets[0]=add_string(tempDLL);; ent.offsets[1]=add_string(command); - ent.offsets[2]=-1; + ent.offsets[2]=0; ent.offsets[3]=nounload; ret=add_entry(&ent); if (ret != PS_OK) return ret; diff --git a/Source/strlist.h b/Source/strlist.h index e4782f8d..dababe69 100644 --- a/Source/strlist.h +++ b/Source/strlist.h @@ -139,6 +139,19 @@ public: return -1; } + int getnum() { + char *s=(char*)gr.get(); + int ml=gr.getlen(); + int offs=0; + int idx=0; + while (offs < ml) + { + offs+=strlen(s+offs)+1; + idx++; + } + return idx; + } + char *get() { return (char*)gr.get(); } int getlen() { return gr.getlen(); } private: diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 0148afda..bc498461 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -92,6 +92,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_INTFMT,"IntFmt",3,0,"$(user_var: output) format_string input"}, {TOK_ISWINDOW,"IsWindow",2,1,"hwnd jump_if_window [jump_if_not_window]"}, {TOK_GOTO,"Goto",1,0,"label"}, +{TOK_LANGSTRING,"LangString",3,0,"name lang_id string"}, {TOK_LICENSEDATA,"LicenseData",1,1,"[/LANG=lang_id] local_file_that_has_license_text.txt"}, {TOK_LICENSETEXT,"LicenseText",1,2,"[/LANG=lang_id] license_page_description [license_button_text]"}, {TOK_LICENSEBKCOLOR,"LicenseBkColor",1,0,"background_color"}, diff --git a/Source/tokens.h b/Source/tokens.h index f3c163be..c4189734 100644 --- a/Source/tokens.h +++ b/Source/tokens.h @@ -40,7 +40,6 @@ enum TOK_INSTPROGRESSFLAGS, TOK_XPSTYLE, TOK_CHANGEUI, - // useless - TOK_USEOUTERUIITEM, TOK_ADDBRANDINGIMAGE, TOK_SETFONT, TOK_SETCOMPRESSOR, @@ -53,6 +52,8 @@ enum TOK_INSTBUTTONTEXT, TOK_SPACETEXTS, TOK_COMPLETEDTEXT, + + TOK_LANGSTRING, // system "preprocessor"ish tokens TOK_P_IFDEF,