mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[ui] add positioning, resizing & filling of the persistence controls
* Also add a test ISO to display these controls * The intent is to use the next round of translation to get these new UI elements localized, as any translation work takes _months_, and it is a precondition to start working on #691. * Also fix new issues with image options when switching language
This commit is contained in:
parent
05f8400451
commit
a394b9731a
9 changed files with 113 additions and 19 deletions
|
@ -18,6 +18,7 @@ For instance, MSG_114, that was introduced in v1.0.8 is MORE than one line!
|
|||
o Version 1.0.24 (2018.??.??)
|
||||
- *NEW* MSG_087
|
||||
- *NEW* MSG_172
|
||||
- *NEW* MSG_199
|
||||
|
||||
o Version 1.0.23 (2018.03.27)
|
||||
- All positioning ('m', 's') has now been removed as well as some controls, for the 3.0 UI redesign
|
||||
|
|
BIN
res/localization/casper_test.iso
Normal file
BIN
res/localization/casper_test.iso
Normal file
Binary file not shown.
|
@ -424,6 +424,7 @@ t MSG_196 "IMPORTANT: THIS DRIVE USES A NONSTANDARD SECTOR SIZE!\n\n"
|
|||
t MSG_197 "Nonstandard sector size detected"
|
||||
t MSG_198 "'Windows To Go' can only be installed on a GPT partitioned drive if it has "
|
||||
"the FIXED attribute set. The current drive was not detected as FIXED."
|
||||
t MSG_199 "Persistent partition size"
|
||||
|
||||
# Status messages - these messages will appear on the status bar
|
||||
t MSG_201 "Cancelling - Please wait..."
|
||||
|
|
|
@ -89,6 +89,7 @@ static const char* pe_file[] = { "ntdetect.com", "setupldr.bin", "txtsetup.sif"
|
|||
static const char* reactos_name = "setupldr.sys"; // TODO: freeldr.sys doesn't seem to work
|
||||
static const char* kolibri_name = "kolibri.img";
|
||||
static const char* autorun_name = "autorun.inf";
|
||||
static const char* casper_name = "CASPER";
|
||||
static const char* stupid_antivirus = " NOTE: This is usually caused by a poorly designed security solution. "
|
||||
"See https://rufus.akeo.ie/compatibility.\r\n This file will be skipped for now, but you should really "
|
||||
"look into using a *SMARTER* antivirus solution.";
|
||||
|
@ -193,6 +194,9 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const
|
|||
if (safe_stricmp(psz_basename, kolibri_name) == 0) {
|
||||
img_report.has_kolibrios = TRUE;
|
||||
}
|
||||
if (safe_stricmp(psz_basename, casper_name) == 0) {
|
||||
img_report.has_casper = TRUE;
|
||||
}
|
||||
if (safe_stricmp(psz_basename, bootmgr_efi_name) == 0) {
|
||||
img_report.has_efi |= 1;
|
||||
}
|
||||
|
|
32
src/rufus.c
32
src/rufus.c
|
@ -105,7 +105,7 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa
|
|||
BOOL use_fake_units, preserve_timestamps = FALSE;
|
||||
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE, write_as_image = FALSE;
|
||||
float fScale = 1.0f;
|
||||
int dialog_showing = 0, selection_default, windows_to_go_selection = 0;
|
||||
int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = 0;
|
||||
int default_fs, fs, bt, pt, tt; // file system, boot type, partition type, target type
|
||||
char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH];
|
||||
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
||||
|
@ -1568,7 +1568,6 @@ static void InitDialog(HWND hDlg)
|
|||
uprintf("If you think you can help update this translation, please e-mail the author of this application");
|
||||
}
|
||||
|
||||
selection_default = BT_IMAGE;
|
||||
CreateTaskbarList();
|
||||
SetTaskbarProgressState(TASKBAR_NORMAL);
|
||||
|
||||
|
@ -1591,6 +1590,11 @@ static void InitDialog(HWND hDlg)
|
|||
IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_117)), FALSE));
|
||||
IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_118)), TRUE));
|
||||
|
||||
// Fill up the Persistence Units dropdown
|
||||
hCtrl = GetDlgItem(hMainDialog, IDC_PERSISTENCE_UNITS);
|
||||
for (i = 0; i < 3; i++)
|
||||
IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_022 + i)), i));
|
||||
|
||||
// Fill up the MBR masqueraded disk IDs ("8 disks should be enough for anybody")
|
||||
IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_030, LEFT_TO_RIGHT_EMBEDDING "0x80" POP_DIRECTIONAL_FORMATTING)), 0x80));
|
||||
for (i=1; i<=7; i++) {
|
||||
|
@ -1614,6 +1618,8 @@ static void InitDialog(HWND hDlg)
|
|||
AdjustForLowDPI(hDlg);
|
||||
// Because we created the log dialog before we computed our sizes, we need to send a custom message
|
||||
SendMessage(hLogDialog, UM_RESIZE_BUTTONS, 0, 0);
|
||||
// Limit the amount of characters for the Persistence size field
|
||||
SendMessage(GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE), EM_LIMITTEXT, 7, 0);
|
||||
// Create the status line and initialize the taskbar icon for progress overlay
|
||||
CreateStatusBar();
|
||||
|
||||
|
@ -1856,9 +1862,10 @@ out:
|
|||
static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static DWORD DeviceNum = 0;
|
||||
static uint64_t LastRefresh = 0;
|
||||
static uint64_t LastRefresh = 0, pos;
|
||||
static BOOL first_log_display = TRUE, isMarquee = FALSE, queued_hotplug_event = FALSE;
|
||||
static ULONG ulRegister = 0;
|
||||
static LONG lPos;
|
||||
static LPITEMIDLIST pidlDesktop = NULL;
|
||||
static SHChangeNotifyEntry NotifyEntry;
|
||||
static DWORD_PTR thread_affinity[4];
|
||||
|
@ -2039,6 +2046,19 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
SetFileSystemAndClusterSize(NULL);
|
||||
windows_to_go_selection = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_IMAGE_OPTION));
|
||||
break;
|
||||
case IDC_PERSISTENCE_UNITS:
|
||||
if (HIWORD(wParam) != CBN_SELCHANGE)
|
||||
break;
|
||||
if (ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS)) == persistence_unit_selection)
|
||||
break;
|
||||
GetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp, sizeof(tmp));
|
||||
pos = atol(tmp) * MB;
|
||||
for (i = 0; i < persistence_unit_selection; i++)
|
||||
pos *= 1024;
|
||||
persistence_unit_selection = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS));
|
||||
// TODO: Use projected size. For now force the selected ISO to a 4 GB size
|
||||
SetPersistenceSlider(pos, SelectedDrive.DiskSize - 4 * GB);
|
||||
break;
|
||||
case IDC_NB_PASSES:
|
||||
if (HIWORD(wParam) != CBN_SELCHANGE)
|
||||
break;
|
||||
|
@ -2379,6 +2399,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_HSCROLL:
|
||||
lPos = (LONG)SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_GETPOS, 0, 0);
|
||||
sprintf(tmp, "%ld", lPos);
|
||||
SetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp);
|
||||
break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
droppedFileInfo = (HDROP)wParam;
|
||||
wbuffer = calloc(MAX_PATH, sizeof(wchar_t));
|
||||
|
|
|
@ -282,12 +282,7 @@ enum checksum_type {
|
|||
#define IS_EFI_BOOTABLE(r) (r.has_efi != 0)
|
||||
#define IS_BIOS_BOOTABLE(r) (HAS_BOOTMGR(r) || HAS_SYSLINUX(r) || HAS_WINPE(r) || HAS_GRUB(r) || HAS_REACTOS(r) || HAS_KOLIBRIOS(r))
|
||||
#define HAS_WINTOGO(r) (HAS_BOOTMGR(r) && IS_EFI_BOOTABLE(r) && HAS_INSTALL_WIM(r) && (r.install_wim_version < MAX_WIM_VERSION))
|
||||
#ifdef RUFUS_TEST
|
||||
// TODO: have a better test for persistence/Linux
|
||||
#define HAS_PERSISTENCE(r) HAS_SYSLINUX(r)
|
||||
#else
|
||||
#define HAS_PERSISTENCE(r) FALSE
|
||||
#endif
|
||||
#define HAS_PERSISTENCE(r) (r.has_casper)
|
||||
#define IS_FAT(fs) ((fs == FS_FAT16) || (fs == FS_FAT32))
|
||||
|
||||
typedef struct {
|
||||
|
@ -320,6 +315,7 @@ typedef struct {
|
|||
BOOLEAN uses_minint;
|
||||
BOOLEAN compression_type;
|
||||
BOOLEAN is_vhd;
|
||||
BOOLEAN has_casper;
|
||||
uint16_t sl_version; // Syslinux/Isolinux version
|
||||
char sl_version_str[12];
|
||||
char sl_version_ext[32];
|
||||
|
|
12
src/rufus.rc
12
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 3.2.1330"
|
||||
CAPTION "Rufus 3.2.1331"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -47,7 +47,7 @@ BEGIN
|
|||
LTEXT "Image option",IDS_IMAGE_OPTION_TXT,8,65,216,8
|
||||
COMBOBOX IDC_IMAGE_OPTION,8,74,96,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "",IDC_PERSISTENCE_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,125,76,34,8
|
||||
EDITTEXT IDC_PERSISTENCE_SIZE,160,74,36,12,ES_AUTOHSCROLL
|
||||
EDITTEXT IDC_PERSISTENCE_SIZE,160,74,36,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
|
||||
COMBOBOX IDC_PERSISTENCE_UNITS,200,74,24,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Partition scheme",IDS_PARTITION_TYPE_TXT,8,87,96,8
|
||||
COMBOBOX IDC_PARTITION_TYPE,8,96,96,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
@ -392,8 +392,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,2,1330,0
|
||||
PRODUCTVERSION 3,2,1330,0
|
||||
FILEVERSION 3,2,1331,0
|
||||
PRODUCTVERSION 3,2,1331,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -410,13 +410,13 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "3.2.1330"
|
||||
VALUE "FileVersion", "3.2.1331"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||
VALUE "OriginalFilename", "rufus.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "3.2.1330"
|
||||
VALUE "ProductVersion", "3.2.1331"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
70
src/ui.c
70
src/ui.c
|
@ -30,7 +30,6 @@
|
|||
#include <string.h>
|
||||
#include <winioctl.h>
|
||||
#include <assert.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include "rufus.h"
|
||||
#include "drive.h"
|
||||
|
@ -287,7 +286,7 @@ void PositionMainControls(HWND hDlg)
|
|||
// Don't forget to add the dialog border width, since we resize the whole dialog
|
||||
SetWindowPos(hDlg, NULL, -1, -1, fw + 2 * mw + dbw, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
|
||||
|
||||
// Resize the height of the label and progress bar to the height of standard dropdowns
|
||||
// Resize the height of the label, persistence size and progress bar to the height of standard dropdowns
|
||||
hCtrl = GetDlgItem(hDlg, IDC_DEVICE);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
|
@ -298,6 +297,10 @@ void PositionMainControls(HWND hDlg)
|
|||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
SetWindowPos(hCtrl, hAdvancedFormatToolbar, rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER);
|
||||
hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
SetWindowPos(hCtrl, GetDlgItem(hDlg, IDC_PERSISTENCE_SLIDER), rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER);
|
||||
GetWindowRect(hProgress, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
SetWindowPos(hProgress, hNBPasses, rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER);
|
||||
|
@ -392,6 +395,25 @@ void PositionMainControls(HWND hDlg)
|
|||
SendMessage(hHashToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2));
|
||||
SetWindowPos(hHashToolbar, hBootType, mw + bsw + ssw, rc.top, sbw, ddbh, 0);
|
||||
|
||||
// Reposition the Persistence slider and resize it to the boot selection width
|
||||
hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SLIDER);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
SetWindowPos(hCtrl, hTargetSystem, mw, rc.top, bsw, rc.bottom - rc.top, 0);
|
||||
|
||||
// Reposition the Persistence Units dropdown (no need to resize)
|
||||
hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
sz.cx = fw - (rc.right - rc.left);
|
||||
SetWindowPos(hCtrl, hTargetSystem, mw + sz.cx, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
|
||||
|
||||
// Reposition and resize the Persistence Size edit
|
||||
hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
|
||||
SetWindowPos(hCtrl, hTargetSystem, mw + bsw + ssw, rc.top, sz.cx - bsw - 2*ssw, rc.bottom - rc.top, 0);
|
||||
|
||||
// Reposition the CSM help tip
|
||||
hCtrl = GetDlgItem(hDlg, IDS_CSM_HELP_TXT);
|
||||
GetWindowRect(hCtrl, &rc);
|
||||
|
@ -613,13 +635,45 @@ void ToggleAdvancedFormatOptions(BOOL enable)
|
|||
InvalidateRect(hMainDialog, NULL, TRUE);
|
||||
}
|
||||
|
||||
void SetPersistenceSlider(uint64_t pos, uint64_t max)
|
||||
{
|
||||
char tmp[12];
|
||||
int i;
|
||||
IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_PERSISTENCE_UNITS), persistence_unit_selection));
|
||||
pos /= MB;
|
||||
max /= MB;
|
||||
for (i = 0; i < persistence_unit_selection; i++) {
|
||||
pos /= 1024;
|
||||
max /= 1024;
|
||||
}
|
||||
SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETRANGEMIN, (WPARAM)FALSE, (LPARAM)0);
|
||||
SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETRANGEMAX, (WPARAM)FALSE, (LPARAM)max);
|
||||
SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
|
||||
static_sprintf(tmp, "%ld", (LONG)pos);
|
||||
SetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp);
|
||||
}
|
||||
|
||||
// Toggle the Image Option dropdown (Windows To Go or persistence settings)
|
||||
void ToggleImageOption(uint8_t mask)
|
||||
{
|
||||
static BOOL relaunch = FALSE;
|
||||
static char image_option_txt[128] = "";
|
||||
int i, shift = (popcnt8(image_options) >= 2) ? 0 : rh;
|
||||
|
||||
assert(popcnt8(mask) <= 1);
|
||||
|
||||
// mask is set to 0 when called during (re)init
|
||||
if (mask == 0) {
|
||||
if (relaunch) {
|
||||
if ((selection_default == BT_IMAGE) && (image_path != NULL))
|
||||
goto skip;
|
||||
} else {
|
||||
relaunch = TRUE;
|
||||
// Keep a copy of the original image option translation, as it'll be easier to toggle
|
||||
GetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), image_option_txt, sizeof(image_option_txt));
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & IMOP_WINTOGO) {
|
||||
if (nWindowsVersion < WINDOWS_8)
|
||||
return;
|
||||
|
@ -649,12 +703,22 @@ void ToggleImageOption(uint8_t mask)
|
|||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
// Hide or show the boot options
|
||||
for (i = 0; i < ARRAYSIZE(image_option_toggle_ids); i++) {
|
||||
ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]),
|
||||
(image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE);
|
||||
}
|
||||
|
||||
// Set the dropdown default selection
|
||||
if (image_options & IMOP_WINTOGO) {
|
||||
SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), image_option_txt);
|
||||
IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION), windows_to_go_selection));
|
||||
} else if (image_options & IMOP_PERSISTENCE) {
|
||||
SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), lmprintf(MSG_199));
|
||||
// TODO: Use projected size and reuse existing pos. For now force the selected ISO to a 4 GB size
|
||||
uint64_t max_size = SelectedDrive.DiskSize - 4 * GB;
|
||||
SetPersistenceSlider(max_size / 2, max_size);
|
||||
}
|
||||
// If you don't force a redraw here, all kind of bad UI artifacts happen...
|
||||
InvalidateRect(hMainDialog, NULL, TRUE);
|
||||
}
|
||||
|
|
4
src/ui.h
4
src/ui.h
|
@ -50,7 +50,8 @@ extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32;
|
|||
extern loc_cmd* selected_locale;
|
||||
extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES];
|
||||
extern char *short_image_path;
|
||||
extern int advanced_device_section_height, advanced_format_section_height, windows_to_go_selection;
|
||||
extern int advanced_device_section_height, advanced_format_section_height;
|
||||
extern int windows_to_go_selection, persistence_unit_selection;
|
||||
extern int selection_default, cbw, ddw, ddbh, bh;
|
||||
|
||||
extern void SetComboEntry(HWND hDlg, int data);
|
||||
|
@ -61,6 +62,7 @@ extern void GetFullWidth(HWND hDlg);
|
|||
extern void PositionMainControls(HWND hDlg);
|
||||
extern void AdjustForLowDPI(HWND hDlg);
|
||||
extern void SetSectionHeaders(HWND hDlg);
|
||||
extern void SetPersistenceSlider(uint64_t pos, uint64_t max);
|
||||
extern void ToggleAdvancedDeviceOptions(BOOL enable);
|
||||
extern void ToggleAdvancedFormatOptions(BOOL enable);
|
||||
extern void ToggleImageOption(uint8_t mask);
|
||||
|
|
Loading…
Reference in a new issue