mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
fix(font): install correctly on Windows
This commit is contained in:
parent
c301864021
commit
265790659c
|
@ -1,34 +1,37 @@
|
||||||
// Derived from https://github.com/Crosse/font-install
|
|
||||||
// Copyright 2020 Seth Wright <seth@crosse.org>
|
|
||||||
package font
|
package font
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FontsDir denotes the path to the user's fonts directory on Linux.
|
// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-addfontresourcea
|
||||||
// Windows doesn't have the concept of a permanent, per-user collection
|
var FontsDir = filepath.Join(os.Getenv("WINDIR"), "Fonts")
|
||||||
// of fonts, meaning that all fonts are stored in the system-level fonts
|
|
||||||
// directory, which is %WINDIR%\Fonts by default.
|
const (
|
||||||
var FontsDir = path.Join(os.Getenv("WINDIR"), "Fonts")
|
WM_FONTCHANGE = 0x001D // nolint:revive
|
||||||
|
HWND_BROADCAST = 0xFFFF // nolint:revive
|
||||||
|
)
|
||||||
|
|
||||||
func install(font *Font) (err error) {
|
func install(font *Font) (err error) {
|
||||||
// To install a font on Windows:
|
// To install a font on Windows:
|
||||||
// - Copy the file to the fonts directory
|
// - Copy the file to the fonts directory
|
||||||
// - Create a registry entry for the font
|
// - Add registry entry
|
||||||
fullPath := path.Join(FontsDir, font.FileName)
|
// - Call AddFontResourceW to set the font
|
||||||
|
// - Notify other applications that the fonts have changed
|
||||||
err = ioutil.WriteFile(fullPath, font.Data, 0644) //nolint:gosec
|
fullPath := filepath.Join(FontsDir, font.FileName)
|
||||||
|
err = os.WriteFile(fullPath, font.Data, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, write metadata about the font to the registry.
|
// Add registry entry
|
||||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts`, registry.WRITE)
|
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts`, registry.WRITE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If this fails, remove the font file as well.
|
// If this fails, remove the font file as well.
|
||||||
|
@ -40,12 +43,8 @@ func install(font *Font) (err error) {
|
||||||
}
|
}
|
||||||
defer k.Close()
|
defer k.Close()
|
||||||
|
|
||||||
// Apparently it's "ok" to mark an OpenType font as "TrueType",
|
name := fmt.Sprintf("%v (TrueType)", font.Name)
|
||||||
// and since this tool only supports True- and OpenType fonts,
|
if err = k.SetStringValue(name, font.FileName); err != nil {
|
||||||
// this should be Okay(tm).
|
|
||||||
// Besides, Windows does it, so why can't I?
|
|
||||||
valueName := fmt.Sprintf("%v (TrueType)", font.FileName)
|
|
||||||
if err = k.SetStringValue(font.Name, valueName); err != nil {
|
|
||||||
// If this fails, remove the font file as well.
|
// If this fails, remove the font file as well.
|
||||||
if nexterr := os.Remove(fullPath); nexterr != nil {
|
if nexterr := os.Remove(fullPath); nexterr != nil {
|
||||||
return nexterr
|
return nexterr
|
||||||
|
@ -54,5 +53,26 @@ func install(font *Font) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdi32 := syscall.NewLazyDLL("gdi32.dll")
|
||||||
|
proc := gdi32.NewProc("AddFontResourceW")
|
||||||
|
|
||||||
|
fontPtr, err := syscall.UTF16PtrFromString(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, _ := proc.Call(uintptr(unsafe.Pointer(fontPtr)))
|
||||||
|
if ret == 0 {
|
||||||
|
return errors.New("unable to add font resource")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify other applications that the fonts have changed
|
||||||
|
user32 := syscall.NewLazyDLL("user32.dll")
|
||||||
|
procSendMessageW := user32.NewProc("SendMessageW")
|
||||||
|
_, _, e1 := syscall.SyscallN(procSendMessageW.Addr(), uintptr(HWND_BROADCAST), uintptr(WM_FONTCHANGE), 0, 0)
|
||||||
|
if e1 != 0 {
|
||||||
|
return errors.New("unable to broadcast font change")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue