mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 10:22:12 +02:00
+81
-281
@@ -61,12 +61,19 @@ jobs:
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-22.04
|
||||
linux-hosts:
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: ubuntu-22.04
|
||||
- arch: aarch64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
outputs:
|
||||
ffversion: ${{ steps.ffversion.outputs.ffversion }}
|
||||
steps:
|
||||
@@ -83,25 +90,27 @@ jobs:
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libchafa-dev directx-headers-dev rpm ninja-build
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
if: matrix.arch == 'amd64'
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
@@ -126,71 +135,19 @@ jobs:
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
runs-on: ubuntu-22.04-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
|
||||
|
||||
- name: install linuxbrew packages
|
||||
- name: polyfill glibc
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ matrix.arch }} -O polyfill-glibc
|
||||
chmod +x polyfill-glibc
|
||||
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
|
||||
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
|
||||
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
|
||||
cpack
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-aarch64
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7l:
|
||||
@@ -212,11 +169,11 @@ jobs:
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
|
||||
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
|
||||
dpkg -i *.deb
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get update && apt-get install -y ca-certificates gpg curl
|
||||
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
|
||||
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
|
||||
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -252,7 +209,7 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -268,12 +225,18 @@ jobs:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-24.04
|
||||
linux-vms:
|
||||
name: Linux-${{ matrix.arch }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: riscv64
|
||||
- arch: ppc64le
|
||||
- arch: s390x
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
@@ -282,47 +245,12 @@ jobs:
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-riscv64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-ppc64le:
|
||||
name: Linux-ppc64le
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ppc64le
|
||||
arch: ${{ matrix.arch }}
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -335,42 +263,7 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-ppc64le
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-s390x:
|
||||
name: Linux-s390x
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: s390x
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-s390x
|
||||
name: fastfetch-linux-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
@@ -411,12 +304,19 @@ jobs:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-amd64:
|
||||
name: macOS-amd64
|
||||
runs-on: macos-13
|
||||
macos-hosts:
|
||||
name: macOS-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: macos-15-intel
|
||||
- arch: aarch64
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
@@ -455,54 +355,7 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-aarch64:
|
||||
name: macOS-aarch64
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-aarch64
|
||||
name: fastfetch-macos-${{ matrix.arch }}
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
@@ -718,12 +571,25 @@ jobs:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
windows-hosts:
|
||||
name: Windows-${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runs-on: windows-latest
|
||||
msystem: CLANG64
|
||||
msystem-lower: clang64
|
||||
msys-arch: x86_64
|
||||
- arch: aarch64
|
||||
runs-on: windows-11-arm
|
||||
msystem: CLANGARM64
|
||||
msystem-lower: clangarm64
|
||||
msys-arch: aarch64
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
@@ -734,21 +600,21 @@ jobs:
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
msystem: ${{ matrix.msystem }}
|
||||
update: true
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt mingw-w64-clang-x86_64-imagemagick
|
||||
install: git mingw-w64-clang-${{ matrix.msys-arch }}-7zip mingw-w64-clang-${{ matrix.msys-arch }}-cmake mingw-w64-clang-${{ matrix.msys-arch }}-clang mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-loader mingw-w64-clang-${{ matrix.msys-arch }}-vulkan-headers mingw-w64-clang-${{ matrix.msys-arch }}-opencl-icd mingw-w64-clang-${{ matrix.msys-arch }}-opencl-headers mingw-w64-clang-${{ matrix.msys-arch }}-cppwinrt mingw-w64-clang-${{ matrix.msys-arch }}-imagemagick mingw-w64-clang-${{ matrix.msys-arch }}-chafa
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
run: env PKG_CONFIG_PATH=/${{ matrix.msystem-lower }}/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
|
||||
run: cp /${{ matrix.msystem-lower }}/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -769,101 +635,35 @@ jobs:
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ matrix.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
|
||||
windows-aarch64:
|
||||
name: Windows-aarch64
|
||||
runs-on: windows-11-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANGARM64
|
||||
update: true
|
||||
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-aarch64
|
||||
path: ./fastfetch-windows-aarch64.*
|
||||
name: fastfetch-windows-${{ matrix.arch }}
|
||||
path: ./fastfetch-windows-${{ matrix.arch }}.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-hosts
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- linux-s390x
|
||||
- linux-vms
|
||||
- musl-amd64
|
||||
- macos-amd64
|
||||
- macos-aarch64
|
||||
- macos-hosts
|
||||
- freebsd-amd64
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- haiku-amd64
|
||||
- windows-amd64
|
||||
- windows-aarch64
|
||||
- windows-hosts
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
# 2.53.0
|
||||
|
||||
Changes:
|
||||
* JSON property `length` in `Separator` module has been renamed to `times` for clarity (Separator)
|
||||
|
||||
Features:
|
||||
* Adds IPv6 type selection (#1459, LocalIP)
|
||||
* For example: `{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`
|
||||
* Adds more ARM CPU part IDs (CPU, Linux)
|
||||
* Improves Ghostty font config parsing with fallback font detection (#1967, TerminalFont)
|
||||
* Replaces statx(2) call with syscall(2) for better compatibility (Disk, Linux)
|
||||
* Allows array input for disk folder and filesystem options (Disk)
|
||||
* For example: `{ "type": "disk", "folders": ["/", "/home"] }`
|
||||
* Adds support for ignoring input devices by name prefix (#1950, Keyboard / Mouse / Gamepad)
|
||||
* For example: `{ "type": "keyboard", "ignores": ["Apple ", "Corsair "] }`
|
||||
* Adds support for (B)SSID detection on macOS Tahoe (Wifi, macOS)
|
||||
* Please don't expect it to work on later macOS versions
|
||||
* Improves Ubuntu flavor detection (#1975, OS, Linux)
|
||||
* Refines ARMv8.4-A detection to require LSE2 (CPU, Windows)
|
||||
* Detects the latest Dimensity & Snapdragon SoC names (CPU, Android)
|
||||
|
||||
Bugfixes:
|
||||
* Handles zero temperature data (#1960, CPU, Windows)
|
||||
* Fixes `dlopen libzfs.so failed` error on Proxmox 9 (#1973, Zpool, Linux)
|
||||
|
||||
Logos:
|
||||
* Removes Starry Linux
|
||||
* Adds TempleOS
|
||||
* Updates ObsidianOS
|
||||
|
||||
# 2.52.0
|
||||
|
||||
Changes:
|
||||
|
||||
+2
-9
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.52.0
|
||||
VERSION 2.53.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -1304,10 +1304,7 @@ endif()
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(wcwidth HAVE_WCWIDTH)
|
||||
if(NOT HAVE_WCWIDTH)
|
||||
list(APPEND LIBFASTFETCH_SRC src/3rdparty/mk_wcwidch/wcwidth.c)
|
||||
endif()
|
||||
if(LINUX)
|
||||
check_function_exists(statx HAVE_STATX)
|
||||
list(APPEND LIBFASTFETCH_SRC src/util/wcwidth.c)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
@@ -1424,10 +1421,6 @@ if(FreeBSD OR OpenBSD OR NetBSD)
|
||||
unset(CMAKE_REQUIRED_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
if(HAVE_STATX)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_STATX)
|
||||
endif()
|
||||
|
||||
if(HAVE_WCWIDTH)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH)
|
||||
endif()
|
||||
|
||||
Vendored
+6
@@ -1,3 +1,9 @@
|
||||
fastfetch (2.52.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.52.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 05 Sep 2025 14:59:44 +0800
|
||||
|
||||
fastfetch (2.51.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.51.0
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libelf-dev, libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.51.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.52.0_source.buildinfo universe/utils optional
|
||||
|
||||
+104
-9
@@ -2307,17 +2307,60 @@
|
||||
"const": "disk"
|
||||
},
|
||||
"folders": {
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options"
|
||||
"description": "A list of folder paths for the disk output\nDefault: auto detection using mount-points\nThis option overrides other `show*` options",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to get disk usage from",
|
||||
"default": "/"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of folder paths to get disk usage from",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"hideFolders": {
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output",
|
||||
"description": "A list of folder paths to hide from the disk output",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon (semicolon on Windows) separated list of folder paths to hide from the disk output"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of folder paths to hide from the disk output",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
],
|
||||
"default": "/efi:/boot:/boot/efi:/boot/firmware"
|
||||
},
|
||||
"hideFS": {
|
||||
"type": "string",
|
||||
"description": "A colon separated file systems to hide from the disk output"
|
||||
"description": "A list of file systems to hide from the disk output",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "A colon separated list of file systems to hide from the disk output"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"description": "An array of file systems to hide from the disk output",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"showRegular": {
|
||||
"type": "boolean",
|
||||
@@ -2593,6 +2636,15 @@
|
||||
"const": "gamepad",
|
||||
"description": "List connected gamepads"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
@@ -2852,6 +2904,15 @@
|
||||
"const": "keyboard",
|
||||
"description": "List (connected) keyboards"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -2920,7 +2981,32 @@
|
||||
},
|
||||
"showIpv6": {
|
||||
"description": "Show IPv6 addresses",
|
||||
"type": "boolean",
|
||||
"oneOf": [
|
||||
{
|
||||
"const": true,
|
||||
"description": "Show the most useful IPv6 addresses"
|
||||
},
|
||||
{
|
||||
"const": false,
|
||||
"description": "Do not show IPv6 addresses"
|
||||
},
|
||||
{
|
||||
"const": "gua",
|
||||
"description": "Show only global unicast IPv6 addresses (2000::/3)"
|
||||
},
|
||||
{
|
||||
"const": "ula",
|
||||
"description": "Show only unique local IPv6 addresses (fc00::/7)"
|
||||
},
|
||||
{
|
||||
"const": "lla",
|
||||
"description": "Show only link-local IPv6 addresses (fe80::/10)"
|
||||
},
|
||||
{
|
||||
"const": "unknown",
|
||||
"description": "Show only IPv6 addresses that are not gua, ula or lla"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
},
|
||||
"showSpeed": {
|
||||
@@ -3150,6 +3236,15 @@
|
||||
"const": "mouse",
|
||||
"description": "List connected mouses"
|
||||
},
|
||||
"ignores": {
|
||||
"type": "array",
|
||||
"description": "An array of case-insensitive device name prefixes to ignore",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -3687,8 +3782,8 @@
|
||||
"description": "Set the color of the separator line",
|
||||
"$ref": "#/$defs/outputColor"
|
||||
},
|
||||
"length": {
|
||||
"description": "Set the length of the separator line, or 0 to auto-detect",
|
||||
"times": {
|
||||
"description": "Set the times of separator string to repeat, or 0 to auto-detect",
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #1887
|
||||
{
|
||||
"$schema": "file:///Users/carter/fastfetch/doc/json_schema.json",
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": null,
|
||||
"display": {
|
||||
"constants": [
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": null,
|
||||
"display": {
|
||||
"key": {
|
||||
"type": "both",
|
||||
"paddingLeft": 6,
|
||||
"width": 17
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "|---------------------: {#1}Hardware{#} : ---------------------|"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"keyColor": "green",
|
||||
"type": "host"
|
||||
},
|
||||
{
|
||||
"keyColor": "green",
|
||||
"type": "cpu"
|
||||
},
|
||||
{
|
||||
"keyColor": "yellow",
|
||||
"type": "memory"
|
||||
},
|
||||
{
|
||||
"keyColor": "yellow",
|
||||
"type": "swap"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"keyIcon": "",
|
||||
"key": "Disks"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": " ",
|
||||
"format": " [{mountpoint}] - {size-used} / {size-total} ({size-percentage})"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "title",
|
||||
"format": "|-------------------------------------------------------|\u001b[40D: {#1}{user-name} @ {host-name}{#} :"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "os",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"keyColor": "red",
|
||||
"key": "Pkgs"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "Term",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "|---------------------: {#1}Software{#} : ---------------------|"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"symbol": "circle",
|
||||
"paddingLeft": 8
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"home": "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c",
|
||||
"license": "MIT compatible (embed in source)",
|
||||
"version": "2007-05-26 (Unicode 5.0)",
|
||||
"author": "Markus Kuhn",
|
||||
"modified": "CarterLi"
|
||||
}
|
||||
Vendored
-314
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* This is an implementation of wcwidth() and wcswidth() (defined in
|
||||
* IEEE Std 1002.1-2001) for Unicode.
|
||||
*
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
|
||||
*
|
||||
* In fixed-width output devices, Latin characters all occupy a single
|
||||
* "cell" position of equal width, whereas ideographic CJK characters
|
||||
* occupy two such cells. Interoperability between terminal-line
|
||||
* applications and (teletype-style) character terminals using the
|
||||
* UTF-8 encoding requires agreement on which character should advance
|
||||
* the cursor by how many cell positions. No established formal
|
||||
* standards exist at present on which Unicode character shall occupy
|
||||
* how many cell positions on character terminals. These routines are
|
||||
* a first attempt of defining such behavior based on simple rules
|
||||
* applied to data provided by the Unicode Consortium.
|
||||
*
|
||||
* For some graphical characters, the Unicode standard explicitly
|
||||
* defines a character-cell width via the definition of the East Asian
|
||||
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
|
||||
* In all these cases, there is no ambiguity about which width a
|
||||
* terminal shall use. For characters in the East Asian Ambiguous (A)
|
||||
* class, the width choice depends purely on a preference of backward
|
||||
* compatibility with either historic CJK or Western practice.
|
||||
* Choosing single-width for these characters is easy to justify as
|
||||
* the appropriate long-term solution, as the CJK practice of
|
||||
* displaying these characters as double-width comes from historic
|
||||
* implementation simplicity (8-bit encoded characters were displayed
|
||||
* single-width and 16-bit ones double-width, even for Greek,
|
||||
* Cyrillic, etc.) and not any typographic considerations.
|
||||
*
|
||||
* Much less clear is the choice of width for the Not East Asian
|
||||
* (Neutral) class. Existing practice does not dictate a width for any
|
||||
* of these characters. It would nevertheless make sense
|
||||
* typographically to allocate two character cells to characters such
|
||||
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
|
||||
* represented adequately with a single-width glyph. The following
|
||||
* routines at present merely assign a single-cell width to all
|
||||
* neutral characters, in the interest of simplicity. This is not
|
||||
* entirely satisfactory and should be reconsidered before
|
||||
* establishing a formal standard in this area. At the moment, the
|
||||
* decision which Not East Asian (Neutral) characters should be
|
||||
* represented by double-width glyphs cannot yet be answered by
|
||||
* applying a simple rule from the Unicode database content. Setting
|
||||
* up a proper standard for the behavior of UTF-8 character terminals
|
||||
* will require a careful analysis not only of each Unicode character,
|
||||
* but also of each presentation form, something the author of these
|
||||
* routines has avoided to do so far.
|
||||
*
|
||||
* http://www.unicode.org/unicode/reports/tr11/
|
||||
*
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* for any purpose and without fee is hereby granted. The author
|
||||
* disclaims all warranties with regard to this software.
|
||||
*
|
||||
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
*/
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
struct interval {
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
/* auxiliary function for binary search in interval table */
|
||||
static int bisearch(wchar_t ucs, const struct interval *table, int max) {
|
||||
int min = 0;
|
||||
int mid;
|
||||
|
||||
if (ucs < table[0].first || ucs > table[max].last)
|
||||
return 0;
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if (ucs > table[mid].last)
|
||||
min = mid + 1;
|
||||
else if (ucs < table[mid].first)
|
||||
max = mid - 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The following two functions define the column width of an ISO 10646
|
||||
* character as follows:
|
||||
*
|
||||
* - The null character (U+0000) has a column width of 0.
|
||||
*
|
||||
* - Other C0/C1 control characters and DEL will lead to a return
|
||||
* value of -1.
|
||||
*
|
||||
* - Non-spacing and enclosing combining characters (general
|
||||
* category code Mn or Me in the Unicode database) have a
|
||||
* column width of 0.
|
||||
*
|
||||
* - SOFT HYPHEN (U+00AD) has a column width of 1.
|
||||
*
|
||||
* - Other format characters (general category code Cf in the Unicode
|
||||
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
|
||||
*
|
||||
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
|
||||
* have a column width of 0.
|
||||
*
|
||||
* - Spacing characters in the East Asian Wide (W) or East Asian
|
||||
* Full-width (F) category as defined in Unicode Technical
|
||||
* Report #11 have a column width of 2.
|
||||
*
|
||||
* - All remaining characters (including all printable
|
||||
* ISO 8859-1 and WGL4 characters, Unicode control characters,
|
||||
* etc.) have a column width of 1.
|
||||
*
|
||||
* This implementation assumes that wchar_t characters are encoded
|
||||
* in ISO 10646.
|
||||
*/
|
||||
|
||||
int mk_wcwidth(wchar_t ucs)
|
||||
{
|
||||
/* sorted list of non-overlapping intervals of non-spacing characters */
|
||||
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
|
||||
static const struct interval combining[] = {
|
||||
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
|
||||
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
|
||||
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
|
||||
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
|
||||
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
|
||||
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
|
||||
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
|
||||
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
|
||||
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
|
||||
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
|
||||
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
|
||||
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
|
||||
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
|
||||
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
|
||||
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
|
||||
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
|
||||
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
|
||||
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
|
||||
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
|
||||
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
|
||||
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
|
||||
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
|
||||
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
|
||||
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
|
||||
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
|
||||
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
|
||||
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
|
||||
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
|
||||
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
|
||||
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
|
||||
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
|
||||
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
|
||||
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
|
||||
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
|
||||
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
|
||||
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
|
||||
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
|
||||
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
|
||||
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
|
||||
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
|
||||
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
|
||||
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
|
||||
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
|
||||
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
|
||||
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
|
||||
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
|
||||
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
|
||||
{ 0xE0100, 0xE01EF }
|
||||
};
|
||||
|
||||
/* test for 8-bit control characters */
|
||||
if (ucs == 0)
|
||||
return 0;
|
||||
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
|
||||
return -1;
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, combining,
|
||||
sizeof(combining) / sizeof(struct interval) - 1))
|
||||
return 0;
|
||||
|
||||
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||
|
||||
return 1 +
|
||||
(ucs >= 0x1100 &&
|
||||
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||
ucs == 0x2329 || ucs == 0x232a ||
|
||||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
|
||||
ucs != 0x303f) || /* CJK ... Yi */
|
||||
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
|
||||
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
|
||||
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
|
||||
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
|
||||
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
|
||||
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
|
||||
|
||||
#ifndef _WIN32 // sizeof(wchar_t) == 2
|
||||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
|
||||
(ucs >= 0x30000 && ucs <= 0x3fffd) ||
|
||||
#endif
|
||||
0
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
int mk_wcswidth(const wchar_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are the same as mk_wcwidth() and
|
||||
* mk_wcswidth(), except that spacing characters in the East Asian
|
||||
* Ambiguous (A) category as defined in Unicode Technical Report #11
|
||||
* have a column width of 2. This variant might be useful for users of
|
||||
* CJK legacy encodings who want to migrate to UCS without changing
|
||||
* the traditional terminal character-width behaviour. It is not
|
||||
* otherwise recommended for general use.
|
||||
*/
|
||||
int mk_wcwidth_cjk(wchar_t ucs)
|
||||
{
|
||||
/* sorted list of non-overlapping intervals of East Asian Ambiguous
|
||||
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
|
||||
static const struct interval ambiguous[] = {
|
||||
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
|
||||
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
|
||||
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
|
||||
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
|
||||
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
|
||||
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
|
||||
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
|
||||
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
|
||||
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
|
||||
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
|
||||
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
|
||||
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
|
||||
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
|
||||
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
|
||||
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
|
||||
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
|
||||
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
|
||||
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
|
||||
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
|
||||
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
|
||||
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
|
||||
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
|
||||
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
|
||||
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
|
||||
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
|
||||
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
|
||||
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
|
||||
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
|
||||
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
|
||||
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
|
||||
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
|
||||
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
|
||||
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
|
||||
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
|
||||
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
|
||||
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
|
||||
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
|
||||
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
|
||||
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
|
||||
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
|
||||
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
|
||||
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
|
||||
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
|
||||
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
|
||||
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
|
||||
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
|
||||
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
|
||||
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
|
||||
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
|
||||
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
|
||||
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
|
||||
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
|
||||
};
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, ambiguous,
|
||||
sizeof(ambiguous) / sizeof(struct interval) - 1))
|
||||
return 2;
|
||||
|
||||
return mk_wcwidth(ucs);
|
||||
}
|
||||
|
||||
|
||||
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ridiculousfish/widecharwidth",
|
||||
"license": "Public domain",
|
||||
"version": "Unicode 17",
|
||||
"author": "ridiculousfish"
|
||||
}
|
||||
+1590
File diff suppressed because it is too large
Load Diff
+13
-20
@@ -71,42 +71,35 @@ bool ffParseModuleOptions(const char* key, const char* value)
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME, ':'))
|
||||
ffPrepareCPUUsage();
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
|
||||
ffInitDiskIOOptions(&options);
|
||||
ffPrepareDiskIO(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
|
||||
ffInitNetIOOptions(&options);
|
||||
ffPrepareNetIO(&options);
|
||||
}
|
||||
|
||||
if(instance.config.general.multithreading)
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME, ':'))
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
|
||||
ffInitPublicIpOptions(&options);
|
||||
ffPreparePublicIp(&options);
|
||||
}
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
if(ffStrbufSeparatedContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME, ':'))
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
|
||||
ffInitWeatherOptions(&options);
|
||||
ffPrepareWeather(&options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-63
@@ -132,35 +132,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
#ifdef __linux__
|
||||
#include "common/io/io.h"
|
||||
#include <elf.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifndef HWCAP2_SME
|
||||
#define HWCAP2_SME (1UL << 23)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2
|
||||
#define HWCAP2_SME2 (1UL << 37)
|
||||
#endif
|
||||
#ifndef HWCAP2_CSSC
|
||||
#define HWCAP2_CSSC (1UL << 34)
|
||||
#endif
|
||||
#ifndef HWCAP2_SME2P1
|
||||
#define HWCAP2_SME2P1 (1UL << 38)
|
||||
#endif
|
||||
#ifndef HWCAP2_MOPS
|
||||
#define HWCAP2_MOPS (1UL << 43)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E4M3
|
||||
#define HWCAP2_F8E4M3 (1UL << 55)
|
||||
#endif
|
||||
#ifndef HWCAP2_F8E5M2
|
||||
#define HWCAP2_F8E5M2 (1UL << 56)
|
||||
#endif
|
||||
#ifndef HWCAP_CMPBR
|
||||
#define HWCAP_CMPBR (1UL << 33)
|
||||
#endif
|
||||
#ifndef HWCAP_FPRCVT
|
||||
#define HWCAP_FPRCVT (1UL << 34)
|
||||
#endif
|
||||
// #include <asm/hwcap.h>
|
||||
|
||||
void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
@@ -188,69 +160,69 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
cpu->march = "unknown";
|
||||
|
||||
// ARMv8-A
|
||||
bool has_fp = (hwcap & HWCAP_FP) != 0;
|
||||
bool has_asimd = (hwcap & HWCAP_ASIMD) != 0;
|
||||
bool has_fp = (hwcap & (1 << 0) /* HWCAP_FP */) != 0;
|
||||
bool has_asimd = (hwcap & (1 << 1) /* HWCAP_ASIMD */) != 0;
|
||||
|
||||
// ARMv8.1-A
|
||||
bool has_atomics = (hwcap & HWCAP_ATOMICS) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & HWCAP_CRC32) != 0; // optional from v8.0
|
||||
bool has_asimdrdm = (hwcap & HWCAP_ASIMDRDM) != 0; // optional from v8.0
|
||||
bool has_atomics = (hwcap & (1 << 8) /* HWCAP_ATOMICS */) != 0; // optional from v8.0
|
||||
bool has_crc32 = (hwcap & (1 << 7) /* HWCAP_CRC32 */) != 0; // optional from v8.0
|
||||
bool has_asimdrdm = (hwcap & (1 << 12) /* HWCAP_ASIMDRDM */) != 0; // optional from v8.0
|
||||
|
||||
// ARMv8.2-A
|
||||
bool has_fphp = (hwcap & HWCAP_FPHP) != 0; // optional
|
||||
bool has_dcpop = (hwcap & HWCAP_DCPOP) != 0; // DC CVAP, optional from v8.1
|
||||
bool has_fphp = (hwcap & (1 << 9) /* HWCAP_FPHP */) != 0; // optional
|
||||
bool has_dcpop = (hwcap & (1 << 16) /* HWCAP_DCPOP */) != 0; // DC CVAP, optional from v8.1
|
||||
|
||||
// ARMv8.3-A
|
||||
bool has_paca = (hwcap & HWCAP_PACA) != 0; // optional from v8.2
|
||||
bool has_lrcpc = (hwcap & HWCAP_LRCPC) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & HWCAP_FCMA) != 0; // optional from v8.2
|
||||
bool has_jscvt = (hwcap & HWCAP_JSCVT) != 0; // optional from v8.2
|
||||
bool has_paca = (hwcap & (1 << 30) /* HWCAP_PACA */) != 0; // optional from v8.2
|
||||
bool has_lrcpc = (hwcap & (1 << 15) /* HWCAP_LRCPC */) != 0; // optional from v8.2
|
||||
bool has_fcma = (hwcap & (1 << 14) /* HWCAP_FCMA */) != 0; // optional from v8.2
|
||||
bool has_jscvt = (hwcap & (1 << 13) /* HWCAP_JSCVT */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.4-A
|
||||
bool has_dit = (hwcap & HWCAP_DIT) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & HWCAP_FLAGM) != 0; // optional from v8.1
|
||||
bool has_ilrcpc = (hwcap & HWCAP_ILRCPC) != 0; // optional from v8.2
|
||||
bool has_dit = (hwcap & (1 << 24) /* HWCAP_DIT */) != 0; // optional from v8.3
|
||||
bool has_flagm = (hwcap & (1 << 27) /* HWCAP_FLAGM */) != 0; // optional from v8.1
|
||||
bool has_ilrcpc = (hwcap & (1 << 26) /* HWCAP_ILRCPC */) != 0; // optional from v8.2
|
||||
|
||||
// ARMv8.5-A
|
||||
bool has_bti = (hwcap2 & HWCAP2_BTI) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & HWCAP_SB) != 0; // optional from v8.0
|
||||
bool has_dcpodp = (hwcap2 & HWCAP2_DCPODP) != 0; // optional from v8.1
|
||||
bool has_flagm2 = (hwcap2 & HWCAP2_FLAGM2) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & HWCAP2_FRINT) != 0; // optional from v8.4
|
||||
bool has_bti = (hwcap2 & (1 << 17) /* HWCAP2_BTI */) != 0; // optional from v8.4
|
||||
bool has_sb = (hwcap & (1 << 29) /* HWCAP_SB */) != 0; // optional from v8.0
|
||||
bool has_dcpodp = (hwcap2 & (1 << 0) /* HWCAP2_DCPODP */) != 0; // optional from v8.1
|
||||
bool has_flagm2 = (hwcap2 & (1 << 7) /* HWCAP2_FLAGM2 */) != 0; // optional from v8.4
|
||||
bool has_frint = (hwcap2 & (1 << 8) /* HWCAP2_FRINT */) != 0; // optional from v8.4
|
||||
|
||||
// ARMv9.0-A
|
||||
bool has_sve2 = (hwcap2 & HWCAP2_SVE2) != 0;
|
||||
bool has_sve2 = (hwcap2 & (1 << 1) /* HWCAP2_SVE2 */) != 0;
|
||||
|
||||
// ARMv9.1-A
|
||||
// ARMv8.6-A
|
||||
bool has_bf16 = (hwcap2 & HWCAP2_BF16) != 0; // optional from v8.2
|
||||
bool has_i8mm = (hwcap2 & HWCAP2_I8MM) != 0; // optional from v8.1
|
||||
bool has_bf16 = (hwcap2 & (1 << 14) /* HWCAP2_BF16 */) != 0; // optional from v8.2
|
||||
bool has_i8mm = (hwcap2 & (1 << 13) /* HWCAP2_I8MM */) != 0; // optional from v8.1
|
||||
|
||||
// ARMv8.7-A
|
||||
bool has_afp = (hwcap2 & HWCAP2_AFP) != 0; // optional from v8.6
|
||||
bool has_afp = (hwcap2 & (1 << 20) /* HWCAP2_AFP */) != 0; // optional from v8.6
|
||||
|
||||
// ARMv9.2-A
|
||||
bool has_sme = (hwcap2 & HWCAP2_SME) != 0;
|
||||
bool has_sme = (hwcap2 & (1 << 23) /* HWCAP2_SME */) != 0;
|
||||
|
||||
// ARMv9.3-A
|
||||
bool has_sme2 = (hwcap2 & HWCAP2_SME2) != 0; // optional from v9.2
|
||||
bool has_sme2 = (hwcap2 & (1UL << 37) /* HWCAP2_SME2 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv8.8-A
|
||||
bool has_mops = (hwcap2 & HWCAP2_MOPS) != 0; // optional from v8.7
|
||||
bool has_mops = (hwcap2 & (1UL << 43) /* HWCAP2_MOPS */) != 0; // optional from v8.7
|
||||
|
||||
// ARMv8.9-A
|
||||
bool has_cssc = (hwcap2 & HWCAP2_CSSC) != 0; // optional from v8.7
|
||||
bool has_cssc = (hwcap2 & (1UL << 34) /* HWCAP2_CSSC */) != 0; // optional from v8.7
|
||||
|
||||
// ARMv9.4-A
|
||||
bool has_sme2p1 = (hwcap2 & HWCAP2_SME2P1) != 0; // optional from v9.2
|
||||
bool has_sme2p1 = (hwcap2 & (1UL << 38) /* HWCAP2_SME2P1 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv9.5-A
|
||||
bool has_f8e4m3 = (hwcap2 & HWCAP2_F8E4M3) != 0; // optional from v9.2
|
||||
bool has_f8e5m2 = (hwcap2 & HWCAP2_F8E5M2) != 0; // optional from v9.2
|
||||
bool has_f8e4m3 = (hwcap2 & (1UL << 55) /* HWCAP2_F8E4M3 */) != 0; // optional from v9.2
|
||||
bool has_f8e5m2 = (hwcap2 & (1UL << 56) /* HWCAP2_F8E5M2 */) != 0; // optional from v9.2
|
||||
|
||||
// ARMv9.6-A
|
||||
bool has_cmpbr = (hwcap & HWCAP_CMPBR) != 0; // optional from v9.5
|
||||
bool has_fprcvt = (hwcap & HWCAP_FPRCVT) != 0; // optional from v9.5
|
||||
bool has_cmpbr = (hwcap & (1UL << 33) /* HWCAP_CMPBR */) != 0; // optional from v9.5
|
||||
bool has_fprcvt = (hwcap & (1UL << 34) /* HWCAP_FPRCVT */) != 0; // optional from v9.5
|
||||
|
||||
if (has_sve2 || has_sme) {
|
||||
// ARMv9
|
||||
@@ -457,7 +429,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
|
||||
// ARMv8.4-A
|
||||
// My CPU (Apple M1 Pro in VM) does support LSE2, but Windows doesn't detect it for some reason
|
||||
// bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_lse2 = IsProcessorFeaturePresent(PF_ARM_LSE2_AVAILABLE); // Large System Extensions version 2, optional from v8.2
|
||||
bool has_dp = IsProcessorFeaturePresent(PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE); // DotProd, optional from v8.1 (*)
|
||||
|
||||
// ARMv9.0-A
|
||||
@@ -503,7 +475,7 @@ void ffCPUDetectByCpuid(FFCPUResult* cpu)
|
||||
cpu->march = "ARMv8.7-A";
|
||||
} else if (has_i8mm && has_bf16) {
|
||||
cpu->march = "ARMv8.6-A";
|
||||
} else if (has_dp) {
|
||||
} else if (has_dp && has_lse2) {
|
||||
cpu->march = "ARMv8.4-A";
|
||||
} else if (has_lrcpc && has_jscvt) {
|
||||
cpu->march = "ARMv8.3-A";
|
||||
|
||||
@@ -112,8 +112,12 @@ static const char* armPartId2name(uint32_t partId)
|
||||
case 0xd87: return "Cortex-A725";
|
||||
case 0xd88: return "Cortex-A520AE";
|
||||
case 0xd89: return "Cortex-A720AE";
|
||||
case 0xd8a: return "C1-Nano";
|
||||
case 0xd8b: return "C1-Pro";
|
||||
case 0xd8c: return "C1-Ultra";
|
||||
case 0xd8e: return "Neoverse-N3";
|
||||
case 0xd8f: return "Cortex-A320";
|
||||
case 0xd90: return "C1-Premium";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -213,6 +217,7 @@ static const char* nvidiaPartId2name(uint32_t partId)
|
||||
case 0x000: return "Denver";
|
||||
case 0x003: return "Denver 2";
|
||||
case 0x004: return "Carmel";
|
||||
case 0x010: return "Olympus";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,8 @@ static void detectQualcomm(FFCPUResult* cpu)
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 8845: name = "8 Gen 5"; break; // ?
|
||||
case 8850: name = "8 Elite Gen 5"; break;
|
||||
case 8735: name = "8s Gen 4"; break;
|
||||
case 8750: name = "8 Elite"; break;
|
||||
case 8635: name = "8s Gen 3"; break;
|
||||
@@ -192,6 +194,7 @@ static void detectMediaTek(FFCPUResult* cpu)
|
||||
|
||||
switch (code) // The SOC code of MTK Dimensity series is full of mess
|
||||
{
|
||||
case 6993: name = "9500"; break;
|
||||
case 6991: name = "9400"; break;
|
||||
case 6989:
|
||||
case 8796: name = "9300"; break;
|
||||
|
||||
@@ -102,12 +102,16 @@ const char* detectThermalTemp(double* result)
|
||||
if (pCounterData->dwDataSize == sizeof(int32_t))
|
||||
{
|
||||
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
|
||||
int32_t value = *(int32_t*)(pCounterData + 1);
|
||||
if (value == 0)
|
||||
return "Temperature data is zero";
|
||||
|
||||
switch (pCounterIds[iCounter]) {
|
||||
case 0: // Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) - 273;
|
||||
*result = value - 273;
|
||||
break;
|
||||
case 3: // High Precision Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) / 10.0 - 273;
|
||||
*result = value / 10.0 - 273;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -238,7 +242,8 @@ static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
if (ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL))
|
||||
ffStrbufTrimRightSpace(&cpu->vendor);
|
||||
|
||||
if (cpu->coresLogical == 0)
|
||||
{
|
||||
|
||||
@@ -1,30 +1,5 @@
|
||||
#include "disk.h"
|
||||
|
||||
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char separator = ';';
|
||||
#else
|
||||
const char separator = ':';
|
||||
#endif
|
||||
|
||||
uint32_t mountpointLength = (uint32_t) strlen(mountpoint);
|
||||
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < folders->length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(folders, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == mountpointLength && memcmp(folders->chars + startIndex, mountpoint, mountpointLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int compareDisks(const FFDisk* disk1, const FFDisk* disk2)
|
||||
{
|
||||
return ffStrbufComp(&disk1->mountpoint, &disk2->mountpoint);
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include "fastfetch.h"
|
||||
#include "modules/disk/option.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FF_DISK_FOLDER_SEPARATOR ';'
|
||||
#else
|
||||
#define FF_DISK_FOLDER_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
typedef struct FFDisk
|
||||
{
|
||||
FFstrbuf mountFrom;
|
||||
@@ -29,4 +35,3 @@ typedef struct FFDisk
|
||||
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks /* list of FFDisk */);
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks);
|
||||
bool ffDiskMatchMountpoint(FFstrbuf* folders, const char* mountpoint);
|
||||
|
||||
@@ -145,7 +145,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if(__builtin_expect(options->folders.length > 0, 0))
|
||||
{
|
||||
if(!ffDiskMatchMountpoint(&options->folders, fs->f_mntonname))
|
||||
if(!ffStrbufSeparatedContainS(&options->folders, fs->f_mntonname, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs") && !ffStrEquals(fs->f_fstypename, "fusefs.sshfs"))
|
||||
|
||||
@@ -23,7 +23,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, path.Path()))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, path.Path(), FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#ifdef STATX_BTIME
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef __USE_LARGEFILE64
|
||||
#define stat stat64
|
||||
#define statvfs statvfs64
|
||||
@@ -263,9 +267,9 @@ static void detectStats(FFDisk* disk)
|
||||
}
|
||||
|
||||
disk->createTime = 0;
|
||||
#ifdef FF_HAVE_STATX
|
||||
#ifdef SYS_statx
|
||||
struct statx stx;
|
||||
if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME))
|
||||
if (syscall(SYS_statx, 0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec > 685065600 /*birth of Linux*/)
|
||||
disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000));
|
||||
#endif
|
||||
|
||||
@@ -287,7 +291,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if (__builtin_expect(options->folders.length > 0, false))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, device->mnt_dir))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, device->mnt_dir, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(device))
|
||||
|
||||
@@ -113,7 +113,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, device.mnt_mountp))
|
||||
if (!ffStrbufSeparatedContainS(&options->folders, device.mnt_mountp, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(!isPhysicalDevice(&device))
|
||||
|
||||
@@ -47,7 +47,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
if (__builtin_expect((long) options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(&options->folders, buffer.chars))
|
||||
if (!ffStrbufSeparatedContain(&options->folders, &buffer, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
}
|
||||
else if(driveType == DRIVE_NO_ROOT_DIR)
|
||||
|
||||
@@ -3,6 +3,19 @@
|
||||
#include "fastfetch.h"
|
||||
#include "modules/localip/option.h"
|
||||
|
||||
#ifndef IN6_IS_ADDR_GLOBAL
|
||||
#define IN6_IS_ADDR_GLOBAL(a) \
|
||||
((((const uint32_t *) (a))[0] & htonl(0x70000000)) == htonl(0x20000000))
|
||||
#endif
|
||||
#ifndef IN6_IS_ADDR_UNIQUE_LOCAL
|
||||
#define IN6_IS_ADDR_UNIQUE_LOCAL(a) \
|
||||
((((const uint32_t *) (a))[0] & htonl(0xfe000000)) == htonl(0xfc000000))
|
||||
#endif
|
||||
#ifndef IN6_IS_ADDR_LINKLOCAL
|
||||
#define IN6_IS_ADDR_LINKLOCAL(a) \
|
||||
((((const uint32_t *) (a))[0] & htonl(0xffc00000)) == htonl(0xfe800000))
|
||||
#endif
|
||||
|
||||
typedef struct FFLocalIpResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
|
||||
@@ -111,47 +111,32 @@ static const FFLocalIpNIFlag niFlagOptions[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFIPv6Type
|
||||
{
|
||||
FF_IPV6_Other,
|
||||
FF_IPV6_GUA = 0b0001,
|
||||
FF_IPV6_GUA_SECONDARY = 0b0101,
|
||||
FF_IPV6_ULA = 0b0010,
|
||||
FF_IPV6_ULA_SECONDARY = 0b0110,
|
||||
FF_IPV6_TYPE_MASK = 0b0011,
|
||||
FF_IPV6_SECONDARY_FLAG = 0b1100,
|
||||
FF_IPV6_PREFERRED = UINT8_MAX,
|
||||
} FFIPv6Type;
|
||||
|
||||
static FFIPv6Type getIpType(struct ifaddrs* ifa)
|
||||
static FFLocalIpIpv6Type getIpv6Type(struct ifaddrs* ifa)
|
||||
{
|
||||
struct sockaddr_in6* addr = (struct sockaddr_in6*) ifa->ifa_addr;
|
||||
|
||||
FF_DEBUG("Checking IPv6 type for interface %s", ifa->ifa_name);
|
||||
|
||||
#ifndef IN6_IS_ADDR_GLOBAL
|
||||
#define IN6_IS_ADDR_GLOBAL(a) \
|
||||
((((const uint32_t *) (a))[0] & htonl(0x70000000)) == htonl(0x20000000))
|
||||
#endif
|
||||
#ifndef IN6_IS_ADDR_UNIQUE_LOCAL
|
||||
#define IN6_IS_ADDR_UNIQUE_LOCAL(a) \
|
||||
((((const uint32_t *) (a))[0] & htonl(0xfe000000)) == htonl(0xfc000000))
|
||||
#endif
|
||||
FFIPv6Type result = FF_IPV6_Other;
|
||||
FFLocalIpIpv6Type result = FF_LOCALIP_IPV6_TYPE_NONE;
|
||||
if (IN6_IS_ADDR_GLOBAL(&addr->sin6_addr))
|
||||
{
|
||||
result = FF_IPV6_GUA;
|
||||
result = FF_LOCALIP_IPV6_TYPE_GUA_BIT;
|
||||
FF_DEBUG("Interface %s has Global Unicast Address", ifa->ifa_name);
|
||||
}
|
||||
else if (IN6_IS_ADDR_UNIQUE_LOCAL(&addr->sin6_addr))
|
||||
{
|
||||
result = FF_IPV6_ULA;
|
||||
result = FF_LOCALIP_IPV6_TYPE_ULA_BIT;
|
||||
FF_DEBUG("Interface %s has Unique Local Address", ifa->ifa_name);
|
||||
}
|
||||
else if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
|
||||
{
|
||||
result = FF_LOCALIP_IPV6_TYPE_LLA_BIT;
|
||||
FF_DEBUG("Interface %s has Link-Local Address", ifa->ifa_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Interface %s has other IPv6 address type", ifa->ifa_name);
|
||||
return FF_IPV6_Other;
|
||||
FF_DEBUG("Interface %s has unknown IPv6 address type", ifa->ifa_name);
|
||||
return FF_LOCALIP_IPV6_TYPE_UNKNOWN_BIT;
|
||||
}
|
||||
|
||||
#ifdef SIOCGIFAFLAG_IN6
|
||||
@@ -178,13 +163,13 @@ static FFIPv6Type getIpType(struct ifaddrs* ifa)
|
||||
|
||||
#ifdef IN6_IFF_PREFER_SOURCE
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_PREFER_SOURCE)
|
||||
return FF_IPV6_PREFERRED;
|
||||
result |= FF_LOCALIP_IPV6_TYPE_PREFERRED_BIT;
|
||||
#endif
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY | IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED
|
||||
#ifdef IN6_IFF_OPTIMISTIC
|
||||
| IN6_IFF_OPTIMISTIC
|
||||
#endif
|
||||
)) result |= FF_IPV6_SECONDARY_FLAG;
|
||||
)) result |= FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT;
|
||||
return result;
|
||||
#elif __linux__
|
||||
static FFlist addresses = {};
|
||||
@@ -220,13 +205,13 @@ static FFIPv6Type getIpType(struct ifaddrs* ifa)
|
||||
if (memcmp(&addr->sin6_addr, entry, sizeof(struct in6_addr)) == 0)
|
||||
return result;
|
||||
}
|
||||
result |= FF_IPV6_SECONDARY_FLAG;
|
||||
result |= FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT;
|
||||
return result;
|
||||
#elif __sun
|
||||
if (ifa->ifa_flags & IFF_PREFERRED)
|
||||
return FF_IPV6_PREFERRED;
|
||||
result |= FF_LOCALIP_IPV6_TYPE_PREFERRED_BIT;
|
||||
if (ifa->ifa_flags & (IFF_DEPRECATED | IFF_TEMPORARY | IFF_DUPLICATE))
|
||||
result |= FF_IPV6_SECONDARY_FLAG;
|
||||
result |= FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT;
|
||||
return result;
|
||||
#else
|
||||
return result;
|
||||
@@ -509,46 +494,65 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT))
|
||||
if (options->ipv6Type == FF_LOCALIP_IPV6_TYPE_AUTO)
|
||||
{
|
||||
struct ifaddrs* selected = NULL;
|
||||
struct ifaddrs* secondary = NULL;
|
||||
|
||||
FF_LIST_FOR_EACH(struct ifaddrs*, pifa, adapter->ipv6)
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT))
|
||||
{
|
||||
FFIPv6Type type = getIpType(*pifa);
|
||||
if (type == FF_IPV6_PREFERRED)
|
||||
struct ifaddrs* selected = NULL;
|
||||
struct ifaddrs* secondary = NULL;
|
||||
|
||||
FF_LIST_FOR_EACH(struct ifaddrs*, pifa, adapter->ipv6)
|
||||
{
|
||||
selected = *pifa;
|
||||
FF_DEBUG("Found preferred IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
break;
|
||||
FFLocalIpIpv6Type type = getIpv6Type(*pifa);
|
||||
if (type & FF_LOCALIP_IPV6_TYPE_PREFERRED_BIT)
|
||||
{
|
||||
selected = *pifa;
|
||||
FF_DEBUG("Found preferred IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
break;
|
||||
}
|
||||
else if ((type & FF_LOCALIP_IPV6_TYPE_GUA_BIT) && !(type & FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT) && !selected)
|
||||
{
|
||||
selected = *pifa;
|
||||
FF_DEBUG("Found GUA IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
}
|
||||
else if ((type & FF_LOCALIP_IPV6_TYPE_ULA_BIT) && !(type & FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT) && !secondary)
|
||||
{
|
||||
secondary = *pifa;
|
||||
FF_DEBUG("Found ULA IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
}
|
||||
}
|
||||
else if (type == FF_IPV6_GUA && !selected)
|
||||
if (!selected) selected = secondary;
|
||||
|
||||
if (selected)
|
||||
appendIpv6(options, &item->ipv6, selected);
|
||||
else if (adapter->ipv6.length > 0)
|
||||
{
|
||||
selected = *pifa;
|
||||
FF_DEBUG("Found GUA IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
}
|
||||
else if (type == FF_IPV6_ULA && !secondary)
|
||||
{
|
||||
secondary = *pifa;
|
||||
FF_DEBUG("Found ULA IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
appendIpv6(options, &item->ipv6, *FF_LIST_GET(struct ifaddrs*, adapter->ipv6, 0));
|
||||
FF_DEBUG("Using first IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
}
|
||||
}
|
||||
if (!selected) selected = secondary;
|
||||
|
||||
if (selected)
|
||||
appendIpv6(options, &item->ipv6, selected);
|
||||
else if (adapter->ipv6.length > 0)
|
||||
else
|
||||
{
|
||||
appendIpv6(options, &item->ipv6, *FF_LIST_GET(struct ifaddrs*, adapter->ipv6, 0));
|
||||
FF_DEBUG("Using first IPv6 address for interface %s", adapter->mac->ifa_name);
|
||||
FF_DEBUG("Adding all IPv6 addresses for interface %s", adapter->mac->ifa_name);
|
||||
FF_LIST_FOR_EACH(struct ifaddrs*, pifa, adapter->ipv6)
|
||||
appendIpv6(options, &item->ipv6, *pifa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Adding all IPv6 addresses for interface %s", adapter->mac->ifa_name);
|
||||
FF_LIST_FOR_EACH(struct ifaddrs*, pifa, adapter->ipv6)
|
||||
appendIpv6(options, &item->ipv6, *pifa);
|
||||
{
|
||||
FFLocalIpIpv6Type type = getIpv6Type(*pifa);
|
||||
if (type & options->ipv6Type)
|
||||
{
|
||||
if ((options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT) || !(type & FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT))
|
||||
{
|
||||
appendIpv6(options, &item->ipv6, *pifa);
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mac:
|
||||
|
||||
@@ -140,13 +140,24 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
|
||||
for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next)
|
||||
{
|
||||
FF_DEBUG("Processing unicast address: family=%d, DadState=%d",
|
||||
ifa->Address.lpSockaddr->sa_family, ifa->DadState);
|
||||
FF_DEBUG("Processing unicast address: prefix origin=%d, suffix origin=%d, family=%d, DadState=%d",
|
||||
ifa->PrefixOrigin, ifa->SuffixOrigin, ifa->Address.lpSockaddr->sa_family, ifa->DadState);
|
||||
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT) && ifa->DadState != IpDadStatePreferred)
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT))
|
||||
{
|
||||
FF_DEBUG("Skipping address (DadState=%d, not preferred)", ifa->DadState);
|
||||
continue;
|
||||
if (ifa->DadState != IpDadStatePreferred)
|
||||
{
|
||||
FF_DEBUG("Skipping address (not preferred)");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ifa->SuffixOrigin == IpSuffixOriginRandom)
|
||||
{
|
||||
FF_DEBUG("Skipping temporary address (random suffix)");
|
||||
continue;
|
||||
}
|
||||
|
||||
// MIB_UNICASTIPADDRESS_ROW::SkipAsSource
|
||||
}
|
||||
|
||||
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
|
||||
@@ -192,6 +203,20 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
continue;
|
||||
}
|
||||
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
|
||||
FFLocalIpIpv6Type ipv6Type = FF_LOCALIP_IPV6_TYPE_NONE;
|
||||
if (IN6_IS_ADDR_GLOBAL(&ipv6->sin6_addr)) ipv6Type |= FF_LOCALIP_IPV6_TYPE_GUA_BIT;
|
||||
else if (IN6_IS_ADDR_UNIQUE_LOCAL(&ipv6->sin6_addr)) ipv6Type |= FF_LOCALIP_IPV6_TYPE_ULA_BIT;
|
||||
else if (IN6_IS_ADDR_LINKLOCAL(&ipv6->sin6_addr)) ipv6Type |= FF_LOCALIP_IPV6_TYPE_LLA_BIT;
|
||||
else ipv6Type |= FF_LOCALIP_IPV6_TYPE_UNKNOWN_BIT;
|
||||
|
||||
if (!(options->ipv6Type & ipv6Type))
|
||||
{
|
||||
FF_DEBUG("Skipping IPv6 address (doesn't match requested type 0x%X)", options->ipv6Type);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isDefaultRoute = ((options->showType & FF_LOCALIP_TYPE_IPV6_BIT) && ffNetifGetDefaultRouteV6()->ifIndex == adapter->IfIndex);
|
||||
if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRoute)
|
||||
{
|
||||
@@ -199,7 +224,6 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
continue;
|
||||
}
|
||||
|
||||
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN + 6];
|
||||
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
typedef struct WGLData
|
||||
{
|
||||
FFOpenGLResult* result;
|
||||
const char* error;
|
||||
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(wglMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(wglCreateContext)
|
||||
@@ -18,82 +15,77 @@ typedef struct WGLData
|
||||
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
|
||||
|
||||
static const char* wglHandleContext(WGLData* wglData, HDC hdc, HGLRC context)
|
||||
static const char* wglHandleContext(WGLData* wglData, FFOpenGLResult* result, HDC hdc, HGLRC context)
|
||||
{
|
||||
if(wglData->ffwglMakeCurrent(hdc, context) == FALSE)
|
||||
return "wglMakeCurrent() failed";
|
||||
ffOpenGLHandleResult(wglData->result, wglData->ffglGetString);
|
||||
ffStrbufSetStatic(&wglData->result->library, "WGL 1.0");
|
||||
ffOpenGLHandleResult(result, wglData->ffglGetString);
|
||||
ffStrbufSetStatic(&result->library, "WGL 1.0");
|
||||
if(wglData->ffwglMakeCurrent(NULL, NULL) == FALSE)
|
||||
return "wglMakeCurrent(NULL, NULL) failed";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* wglHandlePixelFormat(WGLData* wglData, HWND hWnd)
|
||||
static const char* wglHandlePixelFormat(WGLData* wglData, FFOpenGLResult* result, HWND hWnd)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(pfd),
|
||||
1,
|
||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
|
||||
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
|
||||
32, // Colordepth of the framebuffer.
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
24, // Number of bits for the depthbuffer
|
||||
8, // Number of bits for the stencilbuffer
|
||||
0, // Number of Aux buffers in the framebuffer.
|
||||
PFD_MAIN_PLANE,
|
||||
0,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
HDC hdc = GetDC(hWnd);
|
||||
|
||||
if(SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd) == FALSE)
|
||||
if(hdc == NULL)
|
||||
return "GetDC() failed";
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd = {
|
||||
.nSize = sizeof(PIXELFORMATDESCRIPTOR),
|
||||
.nVersion = 1,
|
||||
.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||
.iPixelType = PFD_TYPE_RGBA,
|
||||
.cColorBits = 32,
|
||||
.cDepthBits = 24,
|
||||
.iLayerType = PFD_MAIN_PLANE
|
||||
};
|
||||
int pixelFormat = ChoosePixelFormat(hdc, &pfd);
|
||||
if(pixelFormat == 0)
|
||||
{
|
||||
ReleaseDC(hWnd, hdc);
|
||||
return "ChoosePixelFormat() failed";
|
||||
}
|
||||
|
||||
if(SetPixelFormat(hdc, pixelFormat, &pfd) == FALSE)
|
||||
{
|
||||
ReleaseDC(hWnd, hdc);
|
||||
return "SetPixelFormat() failed";
|
||||
}
|
||||
|
||||
HGLRC context = wglData->ffwglCreateContext(hdc);
|
||||
if(context == NULL)
|
||||
{
|
||||
ReleaseDC(hWnd, hdc);
|
||||
return "wglCreateContext() failed";
|
||||
}
|
||||
|
||||
const char* error = wglHandleContext(wglData, hdc, context);
|
||||
const char* error = wglHandleContext(wglData, result, hdc, context);
|
||||
wglData->ffwglDeleteContext(context);
|
||||
|
||||
return error;
|
||||
}
|
||||
ReleaseDC(hWnd, hdc);
|
||||
|
||||
static LRESULT CALLBACK wglHandleWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(message)
|
||||
{
|
||||
case WM_CREATE: {
|
||||
WGLData* wglData = (WGLData*)((CREATESTRUCT*)lParam)->lpCreateParams;
|
||||
wglData->error = wglHandlePixelFormat(wglData, hWnd);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* wglDetectOpenGL(FFOpenGLResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(opengl32, "dlopen opengl32" FF_LIBRARY_EXTENSION " failed", "opengl32" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
WGLData data = { .result = result };
|
||||
WGLData data = {};
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, wglDeleteContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opengl32, data, glGetString);
|
||||
|
||||
MSG msg = {0};
|
||||
HINSTANCE hInstance = GetModuleHandleW(NULL);
|
||||
|
||||
WNDCLASSW wc = {
|
||||
.lpfnWndProc = wglHandleWndProc,
|
||||
.hInstance = NULL,
|
||||
.lpfnWndProc = DefWindowProcW,
|
||||
.hInstance = hInstance,
|
||||
.hbrBackground = (HBRUSH)COLOR_BACKGROUND,
|
||||
.lpszClassName = L"ogl_version_check",
|
||||
.style = CS_OWNDC,
|
||||
@@ -101,12 +93,16 @@ static const char* wglDetectOpenGL(FFOpenGLResult* result)
|
||||
if(!RegisterClassW(&wc))
|
||||
return "RegisterClassW() failed";
|
||||
|
||||
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, NULL, NULL, NULL, &data);
|
||||
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, NULL, NULL, hInstance, NULL);
|
||||
if(!hWnd)
|
||||
return "CreateWindowW() failed";
|
||||
|
||||
while(GetMessageW(&msg, hWnd, 0, 0) > 0)
|
||||
DispatchMessage(&msg);
|
||||
const char* error = wglHandlePixelFormat(&data, result, hWnd);
|
||||
|
||||
return data.error;
|
||||
DestroyWindow(hWnd);
|
||||
UnregisterClassW(wc.lpszClassName, hInstance);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -61,10 +61,6 @@ FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result)
|
||||
|
||||
FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
|
||||
{
|
||||
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
|
||||
if(!ffStrSet(xdgConfigDirs))
|
||||
return;
|
||||
|
||||
if (detectArmbianVersion(result))
|
||||
return;
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "Linux Lite "))
|
||||
@@ -104,6 +100,10 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
|
||||
return;
|
||||
}
|
||||
|
||||
const char* xdgConfigDirs = getenv("XDG_CONFIG_DIRS");
|
||||
if(!ffStrSet(xdgConfigDirs))
|
||||
return;
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
|
||||
{
|
||||
ffStrbufSetStatic(&result->name, "Kubuntu");
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "common/properties.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static void detectAlacritty(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
@@ -48,29 +50,72 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont)
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
}
|
||||
|
||||
static void detectGhostty(FFTerminalFontResult* terminalFont)
|
||||
static void detectGhostty(const FFstrbuf* exe, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_DEBUG("detectGhostty: start");
|
||||
FF_STRBUF_AUTO_DESTROY configPath = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontNameFallback = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
|
||||
FFpropquery fontQueryToml[] = {
|
||||
{"font-family =", &fontName},
|
||||
{"font-size =", &fontSize},
|
||||
};
|
||||
// Try ghostty +show-config first
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
exe->chars,
|
||||
"+show-config",
|
||||
NULL,
|
||||
});
|
||||
if(error != NULL)
|
||||
{
|
||||
FF_DEBUG("`ghostty +show-config` failed: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
ffParsePropFileConfigValues("com.mitchellh.ghostty/config", 2, fontQueryToml);
|
||||
#endif
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &buffer))
|
||||
{
|
||||
if (!fontName.length || !fontNameFallback.length)
|
||||
{
|
||||
if (ffStrStartsWith(line, "font-family = ")) {
|
||||
FF_DEBUG("found %s", line);
|
||||
ffStrbufSetNS(
|
||||
!fontName.length ? &fontName : &fontNameFallback,
|
||||
(uint32_t) (len - strlen("font-family = ")),
|
||||
line + strlen("font-family = "));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!fontSize.length)
|
||||
{
|
||||
if (ffStrStartsWith(line, "font-size = ")) {
|
||||
FF_DEBUG("found fallback %s", line);
|
||||
ffStrbufSetNS(
|
||||
&fontSize,
|
||||
(uint32_t) (len - strlen("font-size = ")),
|
||||
line + strlen("font-size = "));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffParsePropFileConfigValues("ghostty/config", 2, fontQueryToml);
|
||||
|
||||
if(fontName.length == 0)
|
||||
if (fontName.length == 0) {
|
||||
ffStrbufAppendS(&fontName, "JetBrainsMono Nerd Font");
|
||||
FF_DEBUG("using default family='%s'", fontName.chars);
|
||||
}
|
||||
|
||||
if(fontSize.length == 0)
|
||||
if (fontSize.length == 0) {
|
||||
ffStrbufAppendS(&fontSize, "13");
|
||||
FF_DEBUG("using default size='%s'", fontSize.chars);
|
||||
}
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
if (fontNameFallback.length > 0) {
|
||||
FF_DEBUG("applying fallback family='%s'", fontNameFallback.chars);
|
||||
ffFontInitValues(&terminalFont->fallback, fontNameFallback.chars, NULL);
|
||||
}
|
||||
FF_DEBUG("result family='%s' size='%s'%s", fontName.chars, fontSize.chars, fontNameFallback.length ? " (with fallback)" : "");
|
||||
FF_DEBUG("detectGhostty: end");
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void detectTTY(FFTerminalFontResult* terminalFont)
|
||||
@@ -279,7 +324,7 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour"))
|
||||
detectContour(&terminal->exe, terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty"))
|
||||
detectGhostty(terminalFont);
|
||||
detectGhostty(&terminal->exe, terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "rio"))
|
||||
detectRio(terminalFont);
|
||||
|
||||
|
||||
+10
-240
@@ -9,227 +9,11 @@ static inline double rssiToSignalQuality(int rssi)
|
||||
return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
|
||||
}
|
||||
|
||||
static bool queryIpconfig(const char* ifName, FFstrbuf* result)
|
||||
{
|
||||
if (@available(macOS 15.6, *))
|
||||
{
|
||||
// ipconfig reports <redacted> too
|
||||
return false;
|
||||
}
|
||||
@interface CWNetworkProfile()
|
||||
@property(readonly, retain, nullable) NSArray<NSDictionary *> *bssidList;
|
||||
@end
|
||||
|
||||
return ffProcessAppendStdOut(result, (char* const[]) {
|
||||
"/usr/sbin/ipconfig",
|
||||
"getsummary",
|
||||
(char* const) ifName,
|
||||
NULL
|
||||
}) == NULL;
|
||||
}
|
||||
|
||||
static bool getWifiInfoByIpconfig(FFstrbuf* ipconfig, const char* prefix, FFstrbuf* result)
|
||||
{
|
||||
// `ipconfig getsummary <interface>` returns a string like this:
|
||||
// <dictionary> {
|
||||
// BSSID : <redacted>
|
||||
// IPv4 : <array> {
|
||||
// ...
|
||||
// }
|
||||
// IPv6 : <array> {
|
||||
// ...
|
||||
// }
|
||||
// InterfaceType : WiFi
|
||||
// LinkStatusActive : TRUE
|
||||
// NetworkID : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
// SSID : XXXXXX
|
||||
// Security : WPA2_PSK
|
||||
// }
|
||||
|
||||
const char* start = memmem(ipconfig->chars, ipconfig->length, prefix, strlen(prefix));
|
||||
if (!start) return false;
|
||||
start += strlen(prefix);
|
||||
const char* end = strchr(start, '\n');
|
||||
if (!end) return false;
|
||||
ffStrbufSetNS(result, (uint32_t) (end - start), start);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* detectByWdutil(FFlist* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY wdutil = ffStrbufCreate();
|
||||
|
||||
if (geteuid() != 0)
|
||||
return "wdutil requires root privileges to run";
|
||||
|
||||
bool ok = ffProcessAppendStdOut(&wdutil, (char* const[]) {
|
||||
"/usr/bin/wdutil",
|
||||
"info",
|
||||
NULL
|
||||
}) == NULL;
|
||||
if (!ok) return "Failed to run wdutil info command";
|
||||
|
||||
// ...
|
||||
// ————————————————————————————————————————————————————————————————————
|
||||
// WIFI
|
||||
// ————————————————————————————————————————————————————————————————————
|
||||
// <WIFI INFO>
|
||||
// ————————————————————————————————————————————————————————————————————
|
||||
// ...
|
||||
|
||||
{
|
||||
// Remove unrelated lines
|
||||
uint32_t start = ffStrbufFirstIndexS(&wdutil, "\nWIFI\n");
|
||||
if (start >= wdutil.length)
|
||||
return "wdutil info command did not return WIFI section (1)";
|
||||
|
||||
start += 6; // Skip "\nWIFI\n"
|
||||
start = ffStrbufNextIndexC(&wdutil, start, '\n');
|
||||
if (start >= wdutil.length)
|
||||
return "wdutil info command did not return WIFI section (2)";
|
||||
start++;
|
||||
|
||||
uint32_t end = ffStrbufNextIndexS(&wdutil, start, "\n——————————");
|
||||
|
||||
ffStrbufSubstr(&wdutil, start, end);
|
||||
}
|
||||
|
||||
|
||||
// `wdutil info <interface>` returns a string like this:
|
||||
// MAC Address : xx:xx:xx:xx:xx:xx (hw=xx:xx:xx:xx:xx:xx)
|
||||
// Interface Name : en0
|
||||
// Power : On [On]
|
||||
// Op Mode : STA
|
||||
// SSID : XXX-XXX
|
||||
// BSSID : xx:xx:xx:xx:xx:xx
|
||||
// RSSI : -58 dBm
|
||||
// CCA : 29 %
|
||||
// Noise : -96 dBm
|
||||
// Tx Rate : 173.0 Mbps
|
||||
// Security : WPA2 Enterprise
|
||||
// 802.1X Mode : User
|
||||
// 802.1X Supplicant : Authenticated
|
||||
// PHY Mode : 11ac
|
||||
// MCS Index : 8
|
||||
// Guard Interval : 400
|
||||
// NSS : 2
|
||||
// Channel : 5g165/20
|
||||
// Country Code : CN
|
||||
// Scan Cache Count : 28
|
||||
// NetworkServiceID : XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
||||
// IPv4 Config Method : DHCP
|
||||
// IPv4 Address : xx.xx.xx.xx
|
||||
// IPv4 Router : xx.xx.xx.x
|
||||
// IPv6 Config Method : Automatic
|
||||
// IPv6 Address : xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
|
||||
// IPv6 Router : None
|
||||
// DNS : xxx.xxx.xxx.xxx
|
||||
// : xxx.xxx.xxx.xxx
|
||||
// BTC Mode : Off
|
||||
// Desense :
|
||||
// Chain Ack : []
|
||||
// BTC Profile 2.4GHz : Disabled
|
||||
// BTC Profile 5GHz : Disabled
|
||||
// Sniffer Supported : YES
|
||||
// Supports 6e : No
|
||||
// Supported Channels : 2g1/20,2g2/20,2g3/20,2g4/20,2g5/20,2g6/20,2g7/20,2g8/20,2g9/20,2g10/20,2g11/20,2g12/20,2g13/20,5g36/20,5g40/20,5g44/20,5g48/20,5g52/20,5g56/20,5g60/20,5g64/20,5g149/20,5g153/20,5g157/20,5g161/20,5g165/20,5g36/40,5g40/40,5g44/40,5g48/40,5g52/40,5g56/40,5g60/40,5g64/40,5g149/40,5g153/40,5g157/40,5g161/40,5g36/80,5g40/80,5g44/80,5g48/80,5g52/80,5g56/80,5g60/80,5g64/80,5g149/80,5g153/80,5g157/80,5g161/80
|
||||
|
||||
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
|
||||
ffStrbufInit(&item->inf.description);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = -DBL_MAX;
|
||||
item->conn.rxRate = -DBL_MAX;
|
||||
item->conn.txRate = -DBL_MAX;
|
||||
item->conn.channel = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &wdutil))
|
||||
{
|
||||
const char* key = line + 4; // Skip " "
|
||||
const char* value = key + strlen("MAC Address : ");
|
||||
switch (key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3])
|
||||
{
|
||||
case 'Inte': // Interface Name
|
||||
ffStrbufAppendS(&item->inf.description, value);
|
||||
break;
|
||||
case 'Powe': // Power
|
||||
if (ffStrStartsWith(value, "On "))
|
||||
ffStrbufSetStatic(&item->inf.status, "Power On");
|
||||
else
|
||||
ffStrbufSetStatic(&item->inf.status, "Power Off");
|
||||
break;
|
||||
case 'SSID': // SSID
|
||||
ffStrbufAppendS(&item->conn.ssid, value);
|
||||
break;
|
||||
case 'BSSI': // BSSID
|
||||
if (ffStrEquals(value, "None") && ffStrbufEqualS(&item->conn.ssid, "None"))
|
||||
{
|
||||
ffStrbufSetStatic(&item->conn.status, "Inactive");
|
||||
ffStrbufClear(&item->conn.ssid); // None
|
||||
return NULL;
|
||||
}
|
||||
ffStrbufSetStatic(&item->conn.status, "Active");
|
||||
ffStrbufAppendS(&item->conn.bssid, value);
|
||||
break;
|
||||
case 'RSSI': // RSSI
|
||||
item->conn.signalQuality = rssiToSignalQuality((int) strtol(value, NULL, 10));
|
||||
break;
|
||||
case 'Tx R': // Tx Rate
|
||||
item->conn.txRate = strtod(value, NULL);
|
||||
break;
|
||||
case 'Secu': // Security
|
||||
if (ffStrEquals(value, "None"))
|
||||
ffStrbufSetStatic(&item->conn.security, "Insecure");
|
||||
else
|
||||
ffStrbufAppendS(&item->conn.security, value);
|
||||
break;
|
||||
case 'PHY ': // PHY Mode
|
||||
if (ffStrEquals(value, "None"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "none");
|
||||
else if (ffStrEquals(value, "11a"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
else if (ffStrEquals(value, "11b"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
else if (ffStrEquals(value, "11g"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
else if (ffStrEquals(value, "11n"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
else if (ffStrEquals(value, "11ac"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
else if (ffStrEquals(value, "11ax"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
else if (ffStrEquals(value, "11be"))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)");
|
||||
else
|
||||
ffStrbufAppendS(&item->conn.protocol, value);
|
||||
break;
|
||||
case 'Chan': // Channel
|
||||
{
|
||||
int band, channel;
|
||||
if (sscanf(value, "%dg%d", &band, &channel) == 2)
|
||||
{
|
||||
item->conn.channel = (uint16_t) channel;
|
||||
switch (band)
|
||||
{
|
||||
case 2: item->conn.frequency = 2400; break;
|
||||
case 5: item->conn.frequency = 5400; break;
|
||||
case 6: item->conn.frequency = 6400; break;
|
||||
default: item->conn.frequency = 0; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByCoreWlan(FFlist* result)
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
NSArray<CWInterface*>* interfaces = CWWiFiClient.sharedWiFiClient.interfaces;
|
||||
if (!interfaces)
|
||||
@@ -262,17 +46,19 @@ static const char* detectByCoreWlan(FFlist* result)
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY ipconfig = ffStrbufCreate();
|
||||
|
||||
CWNetworkProfile* networkProfile = inf.configuration.networkProfiles.firstObject;
|
||||
|
||||
if (inf.ssid) // https://developer.apple.com/forums/thread/732431
|
||||
ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
|
||||
else if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
|
||||
getWifiInfoByIpconfig(&ipconfig, "\n SSID : ", &item->conn.ssid);
|
||||
else if (networkProfile.ssid)
|
||||
ffStrbufSetStatic(&item->conn.ssid, inf.configuration.networkProfiles.firstObject.ssid.UTF8String);
|
||||
else
|
||||
ffStrbufSetStatic(&item->conn.ssid, "<redacted>"); // https://developer.apple.com/forums/thread/732431
|
||||
|
||||
if (inf.bssid)
|
||||
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
|
||||
else if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
|
||||
getWifiInfoByIpconfig(&ipconfig, "\n BSSID : ", &item->conn.bssid);
|
||||
else if (networkProfile.bssidList)
|
||||
ffStrbufSetStatic(&item->conn.bssid, [networkProfile.bssidList.firstObject[@"BSSID"] UTF8String]);
|
||||
else
|
||||
ffStrbufSetStatic(&item->conn.bssid, "<redacted>");
|
||||
|
||||
@@ -360,11 +146,6 @@ static const char* detectByCoreWlan(FFlist* result)
|
||||
case 15 /*kCWSecurityOWETransition*/:
|
||||
ffStrbufSetStatic(&item->conn.security, "OWE Transition");
|
||||
break;
|
||||
case kCWSecurityUnknown:
|
||||
// Sonoma?
|
||||
if (ipconfig.length || (queryIpconfig(item->inf.description.chars, &ipconfig)))
|
||||
getWifiInfoByIpconfig(&ipconfig, "\n Security : ", &item->conn.security);
|
||||
break;
|
||||
default:
|
||||
ffStrbufAppendF(&item->conn.security, "Unknown (%ld)", inf.security);
|
||||
break;
|
||||
@@ -382,14 +163,3 @@ static const char* detectByCoreWlan(FFlist* result)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
if (@available(macOS 15.6, *))
|
||||
{
|
||||
if (detectByWdutil(result) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return detectByCoreWlan(result);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ static int enumZpoolCallback(zpool_handle_t* zpool, void* param)
|
||||
|
||||
const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libzfs, "dlopen libzfs" FF_LIBRARY_EXTENSION " failed", "libzfs" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(libzfs, "dlopen libzfs" FF_LIBRARY_EXTENSION " failed", "libzfs" FF_LIBRARY_EXTENSION, 6);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init);
|
||||
|
||||
libzfs_handle_t* handle = fflibzfs_init();
|
||||
|
||||
@@ -749,7 +749,12 @@ static void run(FFdata* data)
|
||||
if (useJsonConfig)
|
||||
ffPrintJsonConfig(true /* prepare */, instance.state.resultDoc);
|
||||
else
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
|
||||
ffPrepareCommandOption(data);
|
||||
}
|
||||
|
||||
ffStart();
|
||||
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
$1-`$2
|
||||
.$1o+`$2
|
||||
`o$1oo/$2
|
||||
`+o$1ooo:$2
|
||||
`+oo$1oooo:$2
|
||||
-+oo$1oooo+:$2
|
||||
`/:-:+$1+oooo+:$2
|
||||
`/++++/$1+++++++:$2
|
||||
`/++++++$1++++++++:$2
|
||||
`/+++oooo$1ooooooooo/`$2
|
||||
./ooosssso$1++osssssso+`$2
|
||||
.oossssso-`$1```/ossssss+`$2
|
||||
-osssssso. $1 :ssssssso.$2
|
||||
:osssssss/ $1 osssso+++.$2
|
||||
/ossssssss/ $1 +ssssooo/-$2
|
||||
`/ossssso+/:- $1 -:/+osssso+-$2
|
||||
`+sso+:-` $1 `.-/+oso:$2
|
||||
`++:. $1 `-/+/$2
|
||||
.` $1 `/$2
|
||||
$2 *+++++++#
|
||||
$2#*******###$3 @
|
||||
$2#*******###$3 @
|
||||
$2#*******###$3 @ @
|
||||
$2#*******##%$3 @
|
||||
$3@@@@@@@@@ @ @ @
|
||||
@ @ @ @ @
|
||||
@ @ @ @ @
|
||||
@ @ @ @
|
||||
@ @ @ @ @
|
||||
@ @ @@@@@@@@@
|
||||
@$1#*******##%$3
|
||||
@$1 ##########%$3
|
||||
@$1 ##########%$3
|
||||
@$1 ##########%
|
||||
########%
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
*/
|
||||
*,*,*(
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
*,*,*,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
(*,*,*,*,*,*,*,*,*,*,*,*,*,
|
||||
,,,,,,,,,,,,,,,,
|
||||
&*,*,*#@@*,*,*,
|
||||
@@ -0,0 +1,20 @@
|
||||
$1aooooo$2,
|
||||
$1aooooo$2``
|
||||
$1aooooo$2``
|
||||
$3(((((( $1aooooo$2``$3((((((
|
||||
$1oooo$3@@ @C@*;,./k@@ @@ @$1oooo$2
|
||||
$1oooooo$3@@ @@@@@@@@ @@k$1oooooo$2``
|
||||
$1oooooooo$3\@ @/@@ @@$1ooooooooo$2``
|
||||
`````````$3'*@*/'$2````````````
|
||||
$3@@@( $1aooooo$2`` $3@@@@
|
||||
@@ @ $1aooooo$2`` $3@ @@
|
||||
@@@ $1aooooo$2`` $3@@@,
|
||||
@@ $1aooooo$2`` $3 @@
|
||||
@ $1aooooo$2`` $3 (@
|
||||
$1aooooo$2``
|
||||
$1aooooo$2``
|
||||
$1aooooo$2``
|
||||
$1aooooo$2``
|
||||
$1aooooo$2``
|
||||
```````
|
||||
`````
|
||||
+11
-10
@@ -3408,6 +3408,7 @@ static const FFlogo O[] = {
|
||||
.colors = {
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_LIGHT_BLUE,
|
||||
},
|
||||
},
|
||||
// OmniOS
|
||||
@@ -4615,16 +4616,6 @@ static const FFlogo S[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Starry
|
||||
{
|
||||
.names = {"Starry"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_STARRY,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_GREEN,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// StockLinux
|
||||
{
|
||||
.names = {"Stock Linux"},
|
||||
@@ -4778,6 +4769,16 @@ static const FFlogo T[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// TempleOS
|
||||
{
|
||||
.names = {"TempleOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_TEMPLEOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_CYAN,
|
||||
},
|
||||
},
|
||||
// TileOS
|
||||
{
|
||||
.names = {"TileOS"},
|
||||
|
||||
+31
-5
@@ -203,10 +203,10 @@ bool ffPrintDisk(FFDiskOptions* options)
|
||||
if(__builtin_expect(options->folders.length == 0, 1) && (disk->type & ~options->showTypes))
|
||||
continue;
|
||||
|
||||
if (options->hideFolders.length && ffDiskMatchMountpoint(&options->hideFolders, disk->mountpoint.chars))
|
||||
if (options->hideFolders.length && ffStrbufSeparatedContain(&options->hideFolders, &disk->mountpoint, FF_DISK_FOLDER_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (options->hideFS.length && ffStrbufMatchSeparated(&disk->filesystem, &options->hideFS, ':'))
|
||||
if (options->hideFS.length && ffStrbufSeparatedContain(&options->hideFS, &disk->filesystem, ':'))
|
||||
continue;
|
||||
|
||||
printDisk(options, disk, ++index);
|
||||
@@ -223,6 +223,32 @@ bool ffPrintDisk(FFDiskOptions* options)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool setSeparatedList(FFstrbuf* strbuf, yyjson_val* val, char separator)
|
||||
{
|
||||
if (yyjson_is_str(val))
|
||||
{
|
||||
ffStrbufSetJsonVal(strbuf, val);
|
||||
return true;
|
||||
}
|
||||
if (yyjson_is_arr(val))
|
||||
{
|
||||
ffStrbufClear(strbuf);
|
||||
yyjson_val *elem;
|
||||
size_t eidx, emax;
|
||||
yyjson_arr_foreach(val, eidx, emax, elem)
|
||||
{
|
||||
if (yyjson_is_str(elem))
|
||||
{
|
||||
if (strbuf->length > 0)
|
||||
ffStrbufAppendC(strbuf, separator);
|
||||
ffStrbufAppendJsonVal(strbuf, elem);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module)
|
||||
{
|
||||
yyjson_val *key, *val;
|
||||
@@ -234,19 +260,19 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module)
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "folders"))
|
||||
{
|
||||
ffStrbufSetJsonVal(&options->folders, val);
|
||||
setSeparatedList(&options->folders, val, FF_DISK_FOLDER_SEPARATOR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "hideFolders"))
|
||||
{
|
||||
ffStrbufSetJsonVal(&options->hideFolders, val);
|
||||
setSeparatedList(&options->hideFolders, val, FF_DISK_FOLDER_SEPARATOR);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "hideFS"))
|
||||
{
|
||||
ffStrbufSetJsonVal(&options->hideFS, val);
|
||||
setSeparatedList(&options->hideFS, val, ':');
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,15 +68,48 @@ bool ffPrintGamepad(FFGamepadOptions* options)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t index = 0;
|
||||
FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFGamepadDevice*));
|
||||
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
|
||||
{
|
||||
printDevice(options, device, result.length > 1 ? ++index : 0);
|
||||
ffStrbufDestroy(&device->serial);
|
||||
ffStrbufDestroy(&device->name);
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!ignored)
|
||||
{
|
||||
FFGamepadDevice** ptr = ffListAdd(&filtered);
|
||||
*ptr = device;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
bool ret = true;
|
||||
if(!filtered.length)
|
||||
{
|
||||
ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t index = 0;
|
||||
FF_LIST_FOR_EACH(FFGamepadDevice*, pdevice, filtered)
|
||||
{
|
||||
FFGamepadDevice* device = *pdevice;
|
||||
printDevice(options, device, filtered.length > 1 ? ++index : 0);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
|
||||
{
|
||||
ffStrbufDestroy(&device->serial);
|
||||
ffStrbufDestroy(&device->name);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module)
|
||||
@@ -88,6 +121,21 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "ignores"))
|
||||
{
|
||||
yyjson_val *elem;
|
||||
size_t eidx, emax;
|
||||
yyjson_arr_foreach(val, eidx, emax, elem)
|
||||
{
|
||||
if (yyjson_is_str(elem))
|
||||
{
|
||||
FFstrbuf* strbuf = ffListAdd(&options->ignores);
|
||||
ffStrbufInitJsonVal(strbuf, elem);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffPercentParseJsonObject(key, val, &options->percent))
|
||||
continue;
|
||||
|
||||
@@ -99,6 +147,12 @@ void ffGenerateGamepadJsonConfig(FFGamepadOptions* options, yyjson_mut_doc* doc,
|
||||
{
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
|
||||
|
||||
if (options->ignores.length > 0)
|
||||
{
|
||||
yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores");
|
||||
FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores)
|
||||
yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length));
|
||||
}
|
||||
ffPercentGenerateJsonConfig(doc, module, options->percent);
|
||||
}
|
||||
|
||||
@@ -120,6 +174,17 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
|
||||
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
|
||||
@@ -134,12 +199,18 @@ bool ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
|
||||
void ffInitGamepadOptions(FFGamepadOptions* options)
|
||||
{
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
|
||||
ffListInit(&options->ignores, sizeof(FFstrbuf));
|
||||
options->percent = (FFPercentageModuleConfig) { 50, 20, 0 };
|
||||
}
|
||||
|
||||
void ffDestroyGamepadOptions(FFGamepadOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&options->ignores);
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffGamepadModuleInfo = {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/option.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFGamepadOptions
|
||||
{
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFlist ignores; // List of FFstrbuf
|
||||
FFPercentageModuleConfig percent;
|
||||
} FFGamepadOptions;
|
||||
|
||||
|
||||
@@ -39,15 +39,44 @@ bool ffPrintKeyboard(FFKeyboardOptions* options)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t index = 0;
|
||||
FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFKeyboardDevice*));
|
||||
FF_LIST_FOR_EACH(FFKeyboardDevice, device, result)
|
||||
{
|
||||
printDevice(options, device, result.length > 1 ? ++index : 0);
|
||||
ffStrbufDestroy(&device->serial);
|
||||
ffStrbufDestroy(&device->name);
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!ignored)
|
||||
{
|
||||
FFKeyboardDevice** ptr = ffListAdd(&filtered);
|
||||
*ptr = device;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
bool ret = true;
|
||||
if(!filtered.length)
|
||||
{
|
||||
ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t index = 0;
|
||||
FF_LIST_FOR_EACH(FFKeyboardDevice*, pdevice, filtered)
|
||||
{
|
||||
FFKeyboardDevice* device = *pdevice;
|
||||
printDevice(options, device, filtered.length > 1 ? ++index : 0);
|
||||
ffStrbufDestroy(&device->serial);
|
||||
ffStrbufDestroy(&device->name);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module)
|
||||
@@ -59,6 +88,21 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "ignores"))
|
||||
{
|
||||
yyjson_val *elem;
|
||||
size_t eidx, emax;
|
||||
yyjson_arr_foreach(val, eidx, emax, elem)
|
||||
{
|
||||
if (yyjson_is_str(elem))
|
||||
{
|
||||
FFstrbuf* strbuf = ffListAdd(&options->ignores);
|
||||
ffStrbufInitJsonVal(strbuf, elem);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
@@ -66,6 +110,13 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module)
|
||||
void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
|
||||
|
||||
if (options->ignores.length > 0)
|
||||
{
|
||||
yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores");
|
||||
FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores)
|
||||
yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length));
|
||||
}
|
||||
}
|
||||
|
||||
bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
@@ -86,6 +137,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
|
||||
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFKeyboardDevice, device, result)
|
||||
@@ -100,11 +162,17 @@ bool ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yy
|
||||
void ffInitKeyboardOptions(FFKeyboardOptions* options)
|
||||
{
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
|
||||
ffListInit(&options->ignores, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
void ffDestroyKeyboardOptions(FFKeyboardOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&options->ignores);
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffKeyboardModuleInfo = {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/option.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFKeyboardOptions
|
||||
{
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFlist ignores; // List of FFstrbuf
|
||||
} FFKeyboardOptions;
|
||||
|
||||
static_assert(sizeof(FFKeyboardOptions) <= FF_OPTION_MAX_SIZE, "FFKeyboardOptions size exceeds maximum allowed size");
|
||||
|
||||
@@ -198,10 +198,33 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module)
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "showIpv6"))
|
||||
{
|
||||
if (yyjson_get_bool(val))
|
||||
options->showType |= FF_LOCALIP_TYPE_IPV6_BIT;
|
||||
else
|
||||
options->showType &= ~FF_LOCALIP_TYPE_IPV6_BIT;
|
||||
if (yyjson_is_bool(val))
|
||||
{
|
||||
options->ipv6Type = FF_LOCALIP_IPV6_TYPE_AUTO;
|
||||
if (unsafe_yyjson_get_bool(val))
|
||||
options->showType |= FF_LOCALIP_TYPE_IPV6_BIT;
|
||||
else
|
||||
options->showType &= ~FF_LOCALIP_TYPE_IPV6_BIT;
|
||||
}
|
||||
else if (yyjson_is_str(val))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_LOCALIP_IPV6_TYPE_AUTO },
|
||||
{ "gua", FF_LOCALIP_IPV6_TYPE_GUA_BIT },
|
||||
{ "ula", FF_LOCALIP_IPV6_TYPE_ULA_BIT },
|
||||
{ "lla", FF_LOCALIP_IPV6_TYPE_LLA_BIT },
|
||||
{ "unknown", FF_LOCALIP_IPV6_TYPE_UNKNOWN_BIT },
|
||||
{},
|
||||
});
|
||||
if (error)
|
||||
ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error);
|
||||
else
|
||||
{
|
||||
options->showType |= FF_LOCALIP_TYPE_IPV6_BIT;
|
||||
options->ipv6Type = (FFLocalIpIpv6Type) value;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -302,7 +325,21 @@ void ffGenerateLocalIpJsonConfig(FFLocalIpOptions* options, yyjson_mut_doc* doc,
|
||||
|
||||
yyjson_mut_obj_add_bool(doc, module, "showIpv4", !!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT));
|
||||
|
||||
yyjson_mut_obj_add_bool(doc, module, "showIpv6", !!(options->showType & FF_LOCALIP_TYPE_IPV6_BIT));
|
||||
if (options->ipv6Type == FF_LOCALIP_IPV6_TYPE_AUTO)
|
||||
yyjson_mut_obj_add_bool(doc, module, "showIpv6", !!(options->showType & FF_LOCALIP_TYPE_IPV6_BIT));
|
||||
else
|
||||
{
|
||||
const char* str = NULL;
|
||||
switch (options->ipv6Type)
|
||||
{
|
||||
case FF_LOCALIP_IPV6_TYPE_GUA_BIT: str = "gua"; break;
|
||||
case FF_LOCALIP_IPV6_TYPE_ULA_BIT: str = "ula"; break;
|
||||
case FF_LOCALIP_IPV6_TYPE_LLA_BIT: str = "lla"; break;
|
||||
case FF_LOCALIP_IPV6_TYPE_UNKNOWN_BIT: str = "unknown"; break;
|
||||
default: str = "auto"; break;
|
||||
}
|
||||
yyjson_mut_obj_add_str(doc, module, "showIpv6", str);
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_bool(doc, module, "showMac", !!(options->showType & FF_LOCALIP_TYPE_MAC_BIT));
|
||||
|
||||
@@ -385,6 +422,7 @@ void ffInitLocalIpOptions(FFLocalIpOptions* options)
|
||||
| FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT
|
||||
#endif
|
||||
;
|
||||
options->ipv6Type = FF_LOCALIP_IPV6_TYPE_AUTO;
|
||||
ffStrbufInit(&options->namePrefix);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,26 @@ typedef enum __attribute__((__packed__)) FFLocalIpType
|
||||
} FFLocalIpType;
|
||||
static_assert(sizeof(FFLocalIpType) == sizeof(uint16_t), "");
|
||||
|
||||
typedef enum __attribute__((__packed__)) FFLocalIpIpv6Type
|
||||
{
|
||||
FF_LOCALIP_IPV6_TYPE_NONE = 0b00000000,
|
||||
FF_LOCALIP_IPV6_TYPE_GUA_BIT = 0b00000001,
|
||||
FF_LOCALIP_IPV6_TYPE_ULA_BIT = 0b00000010,
|
||||
FF_LOCALIP_IPV6_TYPE_LLA_BIT = 0b00000100,
|
||||
FF_LOCALIP_IPV6_TYPE_UNKNOWN_BIT = 0b00001000, // IPv4-mapped, loopback, etc.
|
||||
FF_LOCALIP_IPV6_TYPE_SECONDARY_BIT = 0b01000000, // Temporary, duplicated, etc.
|
||||
FF_LOCALIP_IPV6_TYPE_PREFERRED_BIT = 0b10000000, // PREFER_SOURCE (manually set)
|
||||
FF_LOCALIP_IPV6_TYPE_TYPE_MASK = 0b00011111,
|
||||
FF_LOCALIP_IPV6_TYPE_AUTO = 0b11111111, // Used for detect option
|
||||
} FFLocalIpIpv6Type;
|
||||
static_assert(sizeof(FFLocalIpIpv6Type) == sizeof(uint8_t), "");
|
||||
|
||||
typedef struct FFLocalIpOptions
|
||||
{
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFLocalIpType showType;
|
||||
FFLocalIpIpv6Type ipv6Type;
|
||||
FFstrbuf namePrefix;
|
||||
} FFLocalIpOptions;
|
||||
|
||||
|
||||
@@ -39,15 +39,48 @@ bool ffPrintMouse(FFMouseOptions* options)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t index = 0;
|
||||
FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFMouseDevice*));
|
||||
FF_LIST_FOR_EACH(FFMouseDevice, device, result)
|
||||
{
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!ignored)
|
||||
{
|
||||
FFMouseDevice** ptr = ffListAdd(&filtered);
|
||||
*ptr = device;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
if(!filtered.length)
|
||||
{
|
||||
ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t index = 0;
|
||||
FF_LIST_FOR_EACH(FFMouseDevice*, pdevice, filtered)
|
||||
{
|
||||
FFMouseDevice* device = *pdevice;
|
||||
printDevice(options, device, filtered.length > 1 ? ++index : 0);
|
||||
}
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFMouseDevice, device, result)
|
||||
{
|
||||
printDevice(options, device, result.length > 1 ? ++index : 0);
|
||||
ffStrbufDestroy(&device->serial);
|
||||
ffStrbufDestroy(&device->name);
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module)
|
||||
@@ -59,6 +92,21 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module)
|
||||
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
|
||||
continue;
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "ignores"))
|
||||
{
|
||||
yyjson_val *elem;
|
||||
size_t eidx, emax;
|
||||
yyjson_arr_foreach(val, eidx, emax, elem)
|
||||
{
|
||||
if (yyjson_is_str(elem))
|
||||
{
|
||||
FFstrbuf* strbuf = ffListAdd(&options->ignores);
|
||||
ffStrbufInitJsonVal(strbuf, elem);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
@@ -66,6 +114,13 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module)
|
||||
void ffGenerateMouseJsonConfig(FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs);
|
||||
|
||||
if (options->ignores.length > 0)
|
||||
{
|
||||
yyjson_mut_val* ignores = yyjson_mut_obj_add_arr(doc, module, "ignores");
|
||||
FF_LIST_FOR_EACH(FFstrbuf, strbuf, options->ignores)
|
||||
yyjson_mut_arr_append(ignores, yyjson_mut_strncpy(doc, strbuf->chars, strbuf->length));
|
||||
}
|
||||
}
|
||||
|
||||
bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
@@ -86,6 +141,17 @@ bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_m
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
|
||||
|
||||
bool ignored = false;
|
||||
FF_LIST_FOR_EACH(FFstrbuf, ignore, options->ignores)
|
||||
{
|
||||
if(ffStrbufStartsWithIgnCase(&device->name, ignore))
|
||||
{
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
yyjson_mut_obj_add_bool(doc, obj, "ignored", ignored);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFMouseDevice, device, result)
|
||||
@@ -100,11 +166,17 @@ bool ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_m
|
||||
void ffInitMouseOptions(FFMouseOptions* options)
|
||||
{
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
|
||||
ffListInit(&options->ignores, sizeof(FFstrbuf));
|
||||
}
|
||||
|
||||
void ffDestroyMouseOptions(FFMouseOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, options->ignores)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&options->ignores);
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffMouseModuleInfo = {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/option.h"
|
||||
#include "util/FFlist.h"
|
||||
|
||||
typedef struct FFMouseOptions
|
||||
{
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFlist ignores; // List of FFstrbuf
|
||||
} FFMouseOptions;
|
||||
|
||||
static_assert(sizeof(FFMouseOptions) <= FF_OPTION_MAX_SIZE, "FFMouseOptions size exceeds maximum allowed size");
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef struct FFSeparatorOptions
|
||||
{
|
||||
FFstrbuf string;
|
||||
FFstrbuf outputColor;
|
||||
uint32_t length;
|
||||
uint32_t times;
|
||||
} FFSeparatorOptions;
|
||||
|
||||
static_assert(sizeof(FFSeparatorOptions) <= FF_OPTION_MAX_SIZE, "FFSeparatorOptions size exceeds maximum allowed size");
|
||||
|
||||
@@ -9,27 +9,52 @@
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
static inline uint32_t max(uint32_t a, uint32_t b)
|
||||
#if __SIZEOF_WCHAR_T__ == 4
|
||||
static inline size_t mbrtoc32(uint32_t* restrict pc32, const char* restrict s, size_t n, mbstate_t* restrict ps)
|
||||
{
|
||||
return mbrtowc((wchar_t*) pc32, s, n, ps);
|
||||
}
|
||||
#else
|
||||
#include <uchar.h>
|
||||
#endif
|
||||
|
||||
static uint8_t getMbrWidth(const char* mbstr, uint32_t length, const char** next, mbstate_t* state)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
if (__builtin_expect((uint8_t) *mbstr < 0x80, true)) // ASCII fast path
|
||||
{
|
||||
if (next) *next = mbstr + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t c32;
|
||||
uint32_t len = (uint32_t) mbrtoc32(&c32, mbstr, length, state);
|
||||
if (len >= (uint32_t) -3)
|
||||
{
|
||||
// Invalid or incomplete multibyte sequence
|
||||
if (next) *next = mbstr + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (next) *next = mbstr + len;
|
||||
int width = mk_wcwidth(c32);
|
||||
return width < 0 ? 0 : (uint8_t) width;
|
||||
}
|
||||
|
||||
static inline uint32_t getWcsWidth(const FFstrbuf* mbstr, wchar_t* wstr, mbstate_t* state)
|
||||
static uint32_t getWcsWidth(const FFstrbuf* mbstr)
|
||||
{
|
||||
int result = 1;
|
||||
for (uint32_t i = 0; i < mbstr->length; i++)
|
||||
{
|
||||
if (!isascii(mbstr->chars[i]))
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__builtin_expect(result, 1)) return mbstr->length;
|
||||
mbstate_t state = {};
|
||||
uint32_t remainLength = mbstr->length;
|
||||
uint32_t result = 0;
|
||||
|
||||
const char* ptr = mbstr->chars;
|
||||
while (remainLength > 0 && *ptr != '\0')
|
||||
{
|
||||
const char* lastPtr = NULL;
|
||||
result += getMbrWidth(ptr, remainLength, &lastPtr, &state);
|
||||
remainLength -= (uint32_t)(lastPtr - ptr);
|
||||
ptr = lastPtr;
|
||||
}
|
||||
|
||||
const char* str = mbstr->chars;
|
||||
uint32_t wstrLength = (uint32_t) mbsrtowcs(wstr, &str, mbstr->length, state);
|
||||
result = mk_wcswidth(wstr, wstrLength);
|
||||
return result > 0 ? (uint32_t) result : mbstr->length;
|
||||
}
|
||||
|
||||
@@ -40,13 +65,13 @@ bool ffPrintSeparator(FFSeparatorOptions* options)
|
||||
if(options->outputColor.length && !instance.config.display.pipe)
|
||||
ffPrintColor(&options->outputColor);
|
||||
|
||||
if (options->length > 0)
|
||||
if (options->times > 0)
|
||||
{
|
||||
if(__builtin_expect(options->string.length == 1, 1))
|
||||
ffPrintCharTimes(options->string.chars[0], options->length);
|
||||
ffPrintCharTimes(options->string.chars[0], options->times);
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < options->length; i++)
|
||||
for (uint32_t i = 0; i < options->times; i++)
|
||||
{
|
||||
fputs(options->string.chars, stdout);
|
||||
}
|
||||
@@ -55,14 +80,10 @@ bool ffPrintSeparator(FFSeparatorOptions* options)
|
||||
else
|
||||
{
|
||||
setlocale(LC_CTYPE, "");
|
||||
mbstate_t state = {};
|
||||
const FFPlatform* platform = &instance.state.platform;
|
||||
|
||||
FF_AUTO_FREE wchar_t* wstr = malloc((max(
|
||||
platform->userName.length, options->string.length) + 1) * sizeof(*wstr));
|
||||
|
||||
uint32_t titleLength = 1 // @
|
||||
+ getWcsWidth(&platform->userName, wstr, &state) // user name
|
||||
+ getWcsWidth(&platform->userName) // user name
|
||||
+ (instance.state.titleFqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name
|
||||
|
||||
if(__builtin_expect(options->string.length == 1, 1))
|
||||
@@ -71,7 +92,7 @@ bool ffPrintSeparator(FFSeparatorOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t wcsLength = getWcsWidth(&options->string, wstr, &state);
|
||||
uint32_t wcsLength = getWcsWidth(&options->string);
|
||||
|
||||
int remaining = (int) titleLength;
|
||||
//Write the whole separator as often as it fits fully into titleLength
|
||||
@@ -84,24 +105,19 @@ bool ffPrintSeparator(FFSeparatorOptions* options)
|
||||
if (wcsLength != options->string.length)
|
||||
{
|
||||
// Unicode chars
|
||||
for(int i = 0; remaining > 0; ++i)
|
||||
const char* ptr = options->string.chars;
|
||||
mbstate_t state = {};
|
||||
const char* next = NULL;
|
||||
while (remaining > 0 && *ptr != '\0')
|
||||
{
|
||||
#ifdef __linux__
|
||||
// https://stackoverflow.com/questions/75126743/i-have-difficulties-with-putwchar-in-c#answer-75137784
|
||||
char wch[16] = "";
|
||||
uint32_t wchLength = (uint32_t) wcrtomb(wch, wstr[i], &state);
|
||||
fwrite(wch, wchLength, 1, stdout);
|
||||
#else
|
||||
putwchar(wstr[i]);
|
||||
#endif
|
||||
int width = mk_wcwidth(wstr[i]);
|
||||
remaining -= width < 0 ? 0 : width;
|
||||
remaining -= (int) getMbrWidth(ptr, (uint32_t)(options->string.length - (ptr - options->string.chars)), &next, &state);
|
||||
ptr = next;
|
||||
}
|
||||
fwrite(options->string.chars, (size_t) (ptr - options->string.chars), 1, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < remaining; i++)
|
||||
putchar(options->string.chars[i]);
|
||||
fwrite(options->string.chars, (size_t) remaining, 1, stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,9 +152,15 @@ void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "times"))
|
||||
{
|
||||
options->times = (uint32_t) yyjson_get_uint(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "length"))
|
||||
{
|
||||
options->length = (uint32_t) yyjson_get_uint(val);
|
||||
ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "The option length has been renamed to times.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -150,14 +172,14 @@ void ffGenerateSeparatorJsonConfig(FFSeparatorOptions* options, yyjson_mut_doc*
|
||||
{
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "string", &options->string);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "outputColor", &options->outputColor);
|
||||
yyjson_mut_obj_add_uint(doc, module, "length", options->length);
|
||||
yyjson_mut_obj_add_uint(doc, module, "times", options->times);
|
||||
}
|
||||
|
||||
void ffInitSeparatorOptions(FFSeparatorOptions* options)
|
||||
{
|
||||
ffStrbufInitStatic(&options->string, "-");
|
||||
ffStrbufInit(&options->outputColor);
|
||||
options->length = 0;
|
||||
options->times = 0;
|
||||
}
|
||||
|
||||
void ffDestroySeparatorOptions(FFSeparatorOptions* options)
|
||||
|
||||
+65
-1
@@ -730,7 +730,7 @@ bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf)
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// @brief Check if a separated string contains a substring.
|
||||
/// @brief Check if a separated string (comp) contains a substring (strbuf).
|
||||
/// @param strbuf The substring to check.
|
||||
/// @param compLength The length of the separated string to check.
|
||||
/// @param comp The separated string to check.
|
||||
@@ -759,6 +759,31 @@ bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Case insensitive version of ffStrbufMatchSeparatedNS.
|
||||
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator)
|
||||
{
|
||||
if (strbuf->length == 0)
|
||||
return true;
|
||||
|
||||
if (compLength == 0)
|
||||
return false;
|
||||
|
||||
for (const char* p = comp; p < comp + compLength;)
|
||||
{
|
||||
const char* colon = memchr(p, separator, compLength);
|
||||
if (colon == NULL)
|
||||
return strcasecmp(strbuf->chars, p) == 0;
|
||||
|
||||
uint32_t substrLength = (uint32_t) (colon - p);
|
||||
if (strbuf->length == substrLength && strncasecmp(strbuf->chars, p, substrLength) == 0)
|
||||
return true;
|
||||
|
||||
p = colon + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint)
|
||||
{
|
||||
if (codepoint <= 0x7F) {
|
||||
@@ -790,3 +815,42 @@ int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint)
|
||||
ffStrbufAppendS(strbuf, "�"); // U+FFFD REPLACEMENT CHARACTER
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// @brief Check if a separated string (strbuf) contains a substring (comp).
|
||||
/// @param strbuf The separated to check.
|
||||
/// @param compLength The length of the separated string to check.
|
||||
/// @param comp The substring to check.
|
||||
/// @param separator The separator character.
|
||||
bool ffStrbufSeparatedContainNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator)
|
||||
{
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < strbuf->length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(strbuf, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == compLength && memcmp(strbuf->chars + startIndex, comp, compLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator)
|
||||
{
|
||||
uint32_t startIndex = 0;
|
||||
while(startIndex < strbuf->length)
|
||||
{
|
||||
uint32_t colonIndex = ffStrbufNextIndexC(strbuf, startIndex, separator);
|
||||
|
||||
uint32_t folderLength = colonIndex - startIndex;
|
||||
if (folderLength == compLength && strncasecmp(strbuf->chars + startIndex, comp, compLength) == 0)
|
||||
return true;
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,9 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
|
||||
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufSeparatedContainNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
|
||||
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
|
||||
|
||||
@@ -566,4 +569,34 @@ static inline bool ffStrbufMatchSeparated(const FFstrbuf* strbuf, const FFstrbuf
|
||||
return ffStrbufMatchSeparatedNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparatedIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator)
|
||||
{
|
||||
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufMatchSeparatedIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator)
|
||||
{
|
||||
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainS(const FFstrbuf* strbuf, const char* comp, char separator)
|
||||
{
|
||||
return ffStrbufSeparatedContainNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContain(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator)
|
||||
{
|
||||
return ffStrbufSeparatedContainNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator)
|
||||
{
|
||||
return ffStrbufSeparatedContainIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
|
||||
}
|
||||
|
||||
static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator)
|
||||
{
|
||||
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
|
||||
}
|
||||
|
||||
#define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy)))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "wcwidth.h"
|
||||
#include "3rdparty/widecharwidth/widechar_width_c.h"
|
||||
|
||||
int mk_wcwidth(uint32_t wc)
|
||||
{
|
||||
// // We render U+1F6E1 (🛡) with a width of 2,
|
||||
// // but widechar_width says it has a width of 1 because Unicode classifies it as "neutral".
|
||||
// //
|
||||
// // So we simply decide the width ourselves
|
||||
// if (wc == 0x1F6E1) return 2;
|
||||
//
|
||||
// Well terminals do show it as width 1 after all
|
||||
|
||||
int width = widechar_wcwidth(wc);
|
||||
|
||||
switch (width) {
|
||||
case widechar_ambiguous:
|
||||
case widechar_private_use:
|
||||
return 1;
|
||||
case widechar_widened_in_9:
|
||||
// Our renderer supports Unicode 9
|
||||
return 2;
|
||||
// case widechar_nonprint:
|
||||
// case widechar_combining:
|
||||
// case widechar_unassigned:
|
||||
// case widechar_non_character:
|
||||
// return -1;
|
||||
default:
|
||||
// Use the width widechar_width gave us.
|
||||
return width;
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <wchar.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FF_HAVE_WCWIDTH
|
||||
static inline int mk_wcwidth(wchar_t ucs) {
|
||||
return wcwidth(ucs);
|
||||
}
|
||||
static inline int mk_wcswidth(const wchar_t *pwcs, size_t n) {
|
||||
return wcswidth(pwcs, n);
|
||||
#include <wchar.h>
|
||||
|
||||
// Should be char32_t but it's not defined on macOS
|
||||
static_assert(sizeof(wchar_t) == sizeof(uint32_t), "wcwidth implementation requires wchar_t to be 32 bits");
|
||||
|
||||
static inline int mk_wcwidth(uint32_t ucs) {
|
||||
return wcwidth((wchar_t) ucs);
|
||||
}
|
||||
#else
|
||||
// https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
int mk_wcwidth(wchar_t ucs);
|
||||
int mk_wcswidth(const wchar_t *pwcs, size_t n);
|
||||
int mk_wcwidth(uint32_t wc);
|
||||
#endif
|
||||
|
||||
@@ -663,6 +663,48 @@ int main(void)
|
||||
VERIFY(ffStrbufMatchSeparatedS(&strbuf, ":abc:", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedS(&strbuf, "abc:", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedS(&strbuf, ":abc", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedS(&strbuf, ":ABC", ':') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedS(&strbuf, ":abcdef", ':') == false);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufSetStatic(&strbuf, "ABC");
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "abc:def:ghi", ' ') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "abc:def:ghi", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "def:ghi", ' ') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "def:ghi", ':') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "def", ':') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "abc", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "", ' ') == false);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, ":abc:", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, "abc:", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, ":abc", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, ":ABC", ':') == true);
|
||||
VERIFY(ffStrbufMatchSeparatedIgnCaseS(&strbuf, ":abcdef", ':') == false);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufSetStatic(&strbuf, "abc:def:ghi");
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "abc", ' ') == false);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "abc", ':') == true);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "def", ' ') == false);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "def", ':') == true);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "DEF", ':') == false);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "a", ':') == false);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "e", ':') == false);
|
||||
VERIFY(ffStrbufSeparatedContainS(&strbuf, "i", ':') == false);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufSetStatic(&strbuf, "ABC:DEF:GHI");
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "abc", ' ') == false);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "abc", ':') == true);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "def", ' ') == false);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "def", ':') == true);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "DEF", ':') == true);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "a", ':') == false);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "e", ':') == false);
|
||||
VERIFY(ffStrbufSeparatedContainIgnCaseS(&strbuf, "i", ':') == false);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user