Skip to content

Commit

Permalink
重写安装脚本;调整仓库目录结构;更新键道码表;调整 o 和 ; 引导符号。
Browse files Browse the repository at this point in the history
  • Loading branch information
tswwe committed Nov 17, 2024
1 parent 57a36e1 commit 2a84648
Show file tree
Hide file tree
Showing 95 changed files with 2,801 additions and 982 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
app-win/yong/
app-win/nsis/*.exe
app-win/test/
55 changes: 55 additions & 0 deletions app-win/nsis/IniGetSectionNames.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
!include LogicLib.nsh
!ifndef NSIS_CHAR_SIZE
!define NSIS_CHAR_SIZE 1
!endif

!define IniGetSectionNames "!insertmacro IniGetSectionNames "
!define IniGetSectionNames_StopEnum 'StrCpy $3 "$\n"'
!define /math _IniGetSectionNames_MAXCCH 0xffff - 1 ; Should be plenty

!macro IniGetSectionNames _INI _FUNCNAME
!insertmacro _LOGICLIB_TEMP
GetFunctionAddress $_LOGICLIB_TEMP "${_FUNCNAME}"
Push "${_INI}"
Push $_LOGICLIB_TEMP
Call IniGetSectionNames
!macroend

Function IniGetSectionNames
Exch $1 ; enumfunc
Push $0 ; str
Push $2 ; mem & tmp
Push $3 ; len
Exch 4 ; .ini on top of stack
System::Call '*(&t${_IniGetSectionNames_MAXCCH})i.r2'
System::Call 'kernel32::GetPrivateProfileSectionNames(ir2r0,i${_IniGetSectionNames_MAXCCH},ts)'
Push $2
loop:
System::Call 'kernel32::lstrlen(t)(i$0)i.r3' ; (t) is here to trigger A/W detection
StrCmp $3 0 done
System::Call '*$0(&t${NSIS_MAX_STRLEN}.r2)'
IntOp $3 $3 + 1
!if ${NSIS_CHAR_SIZE} > 1
IntOp $3 $3 * ${NSIS_CHAR_SIZE}
!endif
IntOp $0 $0 + $3
Push $0 ; Save
Push $1 ; Save
Push $2
Call $1
Pop $1
Pop $0
!ifdef IniGetSectionNames_StopEnum
${If} $3 == "$\n"
System::Call '*$0(&i${NSIS_CHAR_SIZE} 0)'
${EndIf}
!endif
Goto loop
done:
Pop $2
System::Free $2
Pop $2
Pop $0
Pop $1
Pop $3
FunctionEnd
File renamed without changes.
157 changes: 157 additions & 0 deletions app-win/nsis/xxxk.nsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# 引入文件
!include "MUI2.nsh"
!include "LogicLib.nsh"
!include "xxxkFuncBase.nsh"

# 声明常量
!define XXXK_NAME_CN "小小星空"
!define XXXK_NAME_EN "xxxk"
!define XXXK_VER "2.0.0.0"
!define XXXK_VER_DATE "20241117"
!define XXXK_URL_HOME "https://xkinput.github.io/xxxk-help"
!define XXXK_URL_DOWNLOAD "http://xxxk.ysepan.com"
!define XXXK_REG_ROOT "HKLM"
!define XXXK_REG_MAIN "Software\Microsoft\Windows\CurrentVersion\Uninstall" # 注意由于 NSIS 创建的安装包为 32 位,"Software\Microsoft" 会被重定向为 "Software\Wow6432Node\Microsoft"
!define XXXK_DIR_APP_WIN ".."
!define XXXK_DIR_DATA_BASE "..\..\data-base"
!define XXXK_DIR_DATA_SCHEMA "..\..\data-schema"

# 设定安装程序属性
RequestExecutionLevel highest
SetCompressor /SOLID lzma
InstallDir "$LOCALAPPDATA\${XXXK_NAME_EN}"
OutFile "${XXXK_NAME_CN}-v${XXXK_VER}-build${XXXK_VER_DATE}.exe"
Name "${XXXK_NAME_CN}" # 修改变量 $(^Name)。影响欢迎页的有关文本
VIProductVersion "${XXXK_VER}" # 安装包的文件属性 > 详细信息 > 安装文件版本号
VIAddVersionKey ProductVersion "${XXXK_VER}" # 安装包的文件属性 > 详细信息 > 产品版本号
VIAddVersionKey ProductName "${XXXK_NAME_CN}" # 安装包的文件属性 > 详细信息 > 产品名称

# 声明页面

!define MUI_ICON "${XXXK_DIR_DATA_BASE}\skin\favicon.ico" # 安装程序的图标

!define MUI_ABORTWARNING # 用户关闭安装程序前弹出警告

!insertmacro MUI_PAGE_WELCOME

!insertmacro MUI_PAGE_LICENSE "${XXXK_DIR_DATA_BASE}\README.txt"

!insertmacro MUI_PAGE_COMPONENTS

!define MUI_DIRECTORYPAGE_VARIABLE $INSTDIR # 绑定变量到目录选择页
!insertmacro MUI_PAGE_DIRECTORY

!insertmacro MUI_PAGE_INSTFILES

!define MUI_FINISHPAGE_RUN $INSTDIR\yong.bat
!define MUI_FINISHPAGE_RUN_TEXT "运行输入法主程序"

!define MUI_FINISHPAGE_TEXT "要以 TSF 模式(需安装了 TSF 模块)运行输入法,\
$\n请在一个新的可键入文本的窗口中切换至 Yong 输入法键盘,\
$\n再运行输入法主程序。"
!define MUI_FINISHPAGE_LINK '阅读在线文档'
!define MUI_FINISHPAGE_LINK_LOCATION "${XXXK_URL_HOME}/#/install?id=启动"
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_LANGUAGE "SimpChinese"

# 显式区段(选框)
Section /o "标准安装(需管理员身份)" optStandard
AddSize 23810 # KB
SectionEnd
Section /o "便携安装" optPortable
AddSize 23113 # KB
SectionEnd

!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${optStandard} "为所有用户安装输入法主程序和 TSF 模块。$\n$\nTSF 模块能够把小小输入法注册到系统键盘,获得系统原生输入法级别的体验,但必须以管理员身份运行安装包。"
!insertmacro MUI_DESCRIPTION_TEXT ${optPortable} "仅释放主程序和星空方案,不写入注册表、不添加开始菜单、不注册 TSF 模块。$\n$\n仅适合想初步体验或者安装到U盘的用户。"
!insertmacro MUI_FUNCTION_DESCRIPTION_END

# 隐式区段(必发)

!include "xxxkFuncChkInstDir.nsh"
!include "xxxkFuncKillYong.nsh"
!include "xxxkFuncAppFiles.nsh"
!include "xxxkFuncYongIni.nsh"
!include "xxxkFuncAppReg.nsh"
!include "xxxkFuncAppStartMenu.nsh"
!include "xxxkFuncTsf.nsh"
!include "xxxkFuncUninstaller.nsh"

Section "-Main"

Call xxxkFuncChkInstDir # 检查 $INSTDIR 和有关注册表项

Call xxxkFuncKillYong # 退出正在运行的主程序

Call xxxkFuncAppFiles # 释放或删除 app-win, data-base, data-schema 里的有关文件到 $INSTDIR

Call xxxkFuncYongIni # 酌情恢复或删除 yong.ini 里的设置

${IfNot} ${SectionIsSelected} ${optPortable}
Call xxxkFuncAppReg # 创建或删除注册表项
Call xxxkFuncAppStartMenu # 创建或删除开始菜单
Call xxxkFuncTsf # 释放或删除 app-win/tsf 里的文件,以及注册或注销 TSF 模块
${EndIf}

Call xxxkFuncUninstaller # 创建卸载程序

SectionEnd

# 回调函数

Function xxxkSubFuncInitCheckbox
Push "$R0" # 是否为管理员账户
${xxxkUserIsAdmin} $R0
${If} $R0 == "1"
SectionSetFlags ${optStandard} ${SF_SELECTED}
SectionSetFlags ${optPortable} 0
${Else}
SectionSetFlags ${optStandard} ${SF_RO}
SectionSetFlags ${optPortable} ${SF_SELECTED}|${SF_RO}
${EndIf}
Pop $R0
FunctionEnd

Function xxxkSubFuncInitInstDir
${If} ${SectionIsSelected} ${optPortable}
SetShellVarContext current
StrCpy $INSTDIR "$LOCALAPPDATA\${XXXK_NAME_EN}"
${Else}
ClearErrors
ReadRegStr $INSTDIR "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}" "InstallLocation" # 尝试从已有注册表项(注意 "Software\Microsoft" 会被重定向为 "Software\Wow6432Node\Microsoft")中读取安装路径,并赋值给变量 $INSTDIR
${IfThen} ${Errors} ${|} StrCpy $INSTDIR "$PROGRAMFILES\${XXXK_NAME_EN}" ${|}
${EndIf}
FunctionEnd

Function .onInit

Call xxxkSubFuncInitCheckbox
Call xxxkSubFuncInitInstDir

FunctionEnd

Function .onSelChange # 发生变化的区段索引存储在 $0 中

${If} $0 == ${optPortable}

${If} ${SectionIsSelected} ${optPortable}
${xxxkSetSectionState} ${optStandard} ${SF_SELECTED} "0"
${Else}
${xxxkSetSectionState} ${optPortable} ${SF_SELECTED} "1"
${EndIf}

${ElseIf} $0 == ${optStandard}

${If} ${SectionIsSelected} ${optStandard}
${xxxkSetSectionState} ${optPortable} ${SF_SELECTED} "0"
${Else}
${xxxkSetSectionState} ${optStandard} ${SF_SELECTED} "1"
${EndIf}

${EndIf}

Call xxxkSubFuncInitInstDir

FunctionEnd
128 changes: 128 additions & 0 deletions app-win/nsis/xxxkFuncAppFiles.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
!include "LogicLib.nsh"
!include "xxxkFuncBase.nsh"
#!define XXXK_DIR_APP_WIN ".."
#!define XXXK_DIR_DATA_BASE "..\..\data-base"
#!define XXXK_VER "1.0.6.0"
#!define XXXK_VER_DATE "20240415"
#!define XXXK_DIR_DATA_SCHEMA "..\..\data-schema"

Function xxxkFuncAppFiles

# 一、释放 app-win 里的文件(除了 tsf)

# 1. 释放输入法主程序和功能模块(64位版):app-win\yong\w64 → $INSTDIR\w64
SetOutPath "$INSTDIR\w64"
File "${XXXK_DIR_APP_WIN}\yong\w64\libcloud.so"
File "${XXXK_DIR_APP_WIN}\yong\w64\libgbk.so"
File "${XXXK_DIR_APP_WIN}\yong\w64\libl.dll"
File "${XXXK_DIR_APP_WIN}\yong\w64\libmb.so"
File "${XXXK_DIR_APP_WIN}\yong\w64\yong.exe"
File "${XXXK_DIR_APP_WIN}\yong\w64\yong-config.exe"
File "${XXXK_DIR_APP_WIN}\yong\w64\yong-vim.exe"

# 2. 释放输入法主程序和功能模块(32位版)以及有关的资源文件:app-win\yong → $INSTDIR
SetOutPath "$INSTDIR"
File "${XXXK_DIR_APP_WIN}\yong\libcloud.so"
File "${XXXK_DIR_APP_WIN}\yong\libgbk.so"
File "${XXXK_DIR_APP_WIN}\yong\libl.dll"
File "${XXXK_DIR_APP_WIN}\yong\libmb.so"
File "${XXXK_DIR_APP_WIN}\yong\yong.exe"
File "${XXXK_DIR_APP_WIN}\yong\yong-config.exe"
File "${XXXK_DIR_APP_WIN}\yong\yong-vim.exe"
File "${XXXK_DIR_APP_WIN}\yong\class.txt"
File "${XXXK_DIR_APP_WIN}\yong\normal.txt"

# 二、释放 data-base 里的文件

# 3. 释放 xxxk 定制的有关资源文件:data-base → $INSTDIR
SetOutPath "$INSTDIR"
File "${XXXK_DIR_DATA_BASE}\bd.txt"
File "${XXXK_DIR_DATA_BASE}\bihua.bin"
File "${XXXK_DIR_DATA_BASE}\crab.txt"
File "${XXXK_DIR_DATA_BASE}\keyboard.ini"
File "${XXXK_DIR_DATA_BASE}\layout.txt"
File "${XXXK_DIR_DATA_BASE}\menu.ini"
WriteINIStr $INSTDIR\menu.ini "about" "exec" "$$MSG(v${XXXK_VER}-Build${XXXK_VER_DATE})"
File "${XXXK_DIR_DATA_BASE}\README.txt"
File "${XXXK_DIR_DATA_BASE}\urls.txt"
File "${XXXK_DIR_DATA_BASE}\yong.ini"
File "${XXXK_DIR_DATA_BASE}\xxxkCustomizableKeys.ini"
File "${XXXK_DIR_DATA_BASE}\yong.bat"
File "${XXXK_DIR_DATA_BASE}\yong-config.bat"

# 4. 释放 xxxk 定制的皮肤、托盘和图标文件:data-base\skin → $INSTDIR\skin
SetOutPath "$INSTDIR\skin"
File "${XXXK_DIR_DATA_BASE}\skin\*.*" # 只打包文件,因此调试用的皮肤目录不会被打包

# 5. 释放 xxxk 定制的文档:data-base\doc → $INSTDIR\doc
SetOutPath "$INSTDIR\doc"
File /r "${XXXK_DIR_DATA_BASE}\doc\*.*" # 打包所有子文件和子目录

# 6. 释放 xxxk 定制的工具:data-base\tools → $INSTDIR\tools
SetOutPath "$INSTDIR\tools"
File /r "${XXXK_DIR_DATA_BASE}\tools\*.*" # 打包所有子文件和子目录

# 7. 释放 xxxk 定制的码表:data-base\mb → $INSTDIR\mb data-base\entry → $INSTDIR\entry
SetOutPath "$INSTDIR\mb"
File /r "${XXXK_DIR_DATA_BASE}\mb\*.*" # 打包所有子文件和子目录
SetOutPath "$INSTDIR\entry"
File /r "${XXXK_DIR_DATA_BASE}\entry\*.*" # 打包所有子文件和子目录

# 三、释放 data-schema 里的文件

# 8. 释放码表:data-schema\方案名 → $INSTDIR
SetOutPath "$INSTDIR"
File /r "${XXXK_DIR_DATA_SCHEMA}\xkjd6\*.*" # 打包所有子文件和子目录
File /r "${XXXK_DIR_DATA_SCHEMA}\xklb\*.*" # 打包所有子文件和子目录
File /r "${XXXK_DIR_DATA_SCHEMA}\xkxb\*.*" # 打包所有子文件和子目录
File /r "${XXXK_DIR_DATA_SCHEMA}\xkyb\*.*" # 打包所有子文件和子目录

FunctionEnd

Function un.xxxkFuncAppFiles

# 删除在程序目录下创建的输入法主程序的快捷方式(历史遗留)
Delete "$INSTDIR\*.lnk"

# 8.7. 删除码表
${xxxkRMDir} "$INSTDIR\mb" # RMDir /r "$INSTDIR\mb"
${xxxkRMDir} "$INSTDIR\entry" # RMDir /r "$INSTDIR\entry"

# 6. 删除工具
${xxxkRMDir} "$INSTDIR\tools" # RMDir /r "$INSTDIR\tools"

# 5. 删除文档
${xxxkRMDir} "$INSTDIR\doc" # RMDir /r "$INSTDIR\doc"

# 4. 删除皮肤、托盘和图标文件
${xxxkRMDir} "$INSTDIR\skin" # RMDir /r "$INSTDIR\skin"

# 3. 删除 xxxk 定制的有关资源文件
Delete "$INSTDIR\bd.txt"
Delete "$INSTDIR\bihua.bin"
Delete "$INSTDIR\crab.txt"
Delete "$INSTDIR\keyboard.ini"
Delete "$INSTDIR\layout.txt"
Delete "$INSTDIR\menu.ini"
Delete "$INSTDIR\README.txt"
Delete "$INSTDIR\urls.txt"
Delete "$INSTDIR\yong.ini"
Delete "$INSTDIR\xxxkCustomizableKeys.ini"
Delete "$INSTDIR\yong.bat"
Delete "$INSTDIR\yong-config.bat"

# 2. 删除输入法主程序和功能模块(32位版)以及有关的资源文件
Delete "$INSTDIR\libcloud.so"
Delete "$INSTDIR\libgbk.so"
Delete "$INSTDIR\libl.dll"
Delete "$INSTDIR\libmb.so"
Delete "$INSTDIR\yong.exe"
Delete "$INSTDIR\yong-config.exe"
Delete "$INSTDIR\yong-vim.exe"
Delete "$INSTDIR\class.txt"
Delete "$INSTDIR\normal.txt"

# 1. 删除输入法主程序和功能模块(64位版)
${xxxkRMDir} "$INSTDIR\w64" # RMDir /r "$INSTDIR\w64"

FunctionEnd
21 changes: 21 additions & 0 deletions app-win/nsis/xxxkFuncAppReg.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
!include "LogicLib.nsh"
#!define XXXK_REG_ROOT "HKLM"
#!define XXXK_NAME_EN "xxxk"
#!define XXXK_VER "1.0.6.0"
#!define XXXK_REG_MAIN "Software\Microsoft\Windows\CurrentVersion\Uninstall" # 注意由于 NSIS 创建的安装包为 32 位,"Software\Microsoft" 会被重定向为 "Software\Wow6432Node\Microsoft"

Function xxxkFuncAppReg

WriteRegStr "HKCU" "Control Panel\Desktop" "LowLevelHooksTimeout" 0x000003E8 # 修复注册表
WriteRegStr "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}" "DisplayName" "$(^Name)"
WriteRegStr "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}" "UninstallString" "$INSTDIR\uninstall.exe"
WriteRegStr "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}" "DisplayVersion" "${XXXK_VER}"
WriteRegStr "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}" "InstallLocation" "$INSTDIR"

FunctionEnd

Function un.xxxkFuncAppReg # 删除注册表项

DeleteRegKey "${XXXK_REG_ROOT}" "${XXXK_REG_MAIN}\${XXXK_NAME_EN}"

FunctionEnd
Loading

0 comments on commit 2a84648

Please sign in to comment.