summaryrefslogtreecommitdiffhomepage
path: root/public
diff options
context:
space:
mode:
authorAmlal <amlal@nekernel.org>2025-04-25 13:08:33 +0200
committerAmlal <amlal@nekernel.org>2025-04-25 13:08:33 +0200
commitfb790b07aeba8e22e4190cf3e1834d11ecde6c96 (patch)
tree4cec7d1b321307b1d5935577631dae116a658a37 /public
parent63a2d92c5dfe976175cda024ec01905d11b43738 (diff)
dev: better .clang-format, ran format command.
Signed-off-by: Amlal <amlal@nekernel.org>
Diffstat (limited to 'public')
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Array.h105
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Atom.h64
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Foundation.h100
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Object.h22
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Property.h80
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/Ref.h169
-rw-r--r--public/frameworks/CoreFoundation.fwrk/headers/String.h16
-rw-r--r--public/frameworks/CoreFoundation.fwrk/src/Foundation.cc29
-rw-r--r--public/frameworks/DiskImage.fwrk/headers/DiskImage.h76
-rw-r--r--public/frameworks/DiskImage.fwrk/src/DiskImage+EPM.cc51
-rw-r--r--public/frameworks/DiskImage.fwrk/src/DiskImage+NeFS.cc61
-rw-r--r--public/frameworks/KernelTest.fwrk/headers/KernelTest.h29
-rw-r--r--public/tools/cc/src/CommandLine.cc8
-rw-r--r--public/tools/diutil/src/CommandLine.cc101
-rw-r--r--public/tools/diutil/vendor/Dialogs.h3287
-rw-r--r--public/tools/ld.dyn/src/CommandLine.cc66
-rw-r--r--public/tools/ld.fwrk/src/CommandLine.cc13
-rw-r--r--public/tools/mk.fwrk/Common.h8
-rw-r--r--public/tools/mk.fwrk/Framework.h10
-rw-r--r--public/tools/mk.fwrk/Steps.h29
-rw-r--r--public/tools/mk.fwrk/src/CommandLine.cc142
-rw-r--r--public/tools/mk.hefs/src/CommandLine.cc9
-rw-r--r--public/tools/mk.nefs/src/CommandLine.cc9
-rw-r--r--public/tools/open/src/CommandLine.cc52
24 files changed, 2083 insertions, 2453 deletions
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Array.h b/public/frameworks/CoreFoundation.fwrk/headers/Array.h
index e9a36ac4..0b4a8dbf 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Array.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Array.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -8,64 +8,45 @@
#include <user/SystemCalls.h>
-namespace CF
-{
- template <typename T, SizeT N>
- class CFArray final
- {
- public:
- explicit CFArray() = default;
- ~CFArray() = default;
-
- CFArray& operator=(const CFArray&) = default;
- CFArray(const CFArray&) = default;
-
- T& operator[](SizeT at)
- {
- MUST_PASS(at < this->Count());
- return fArray[at];
- }
-
- Bool Empty()
- {
- return this->Count() > 0;
- }
-
- SizeT Capacity()
- {
- return N;
- }
-
- SizeT Count()
- {
- auto cnt = 0UL;
-
- for (auto i = 0UL; i < N; ++i)
- {
- if (fArray[i])
- ++cnt;
- }
-
- return cnt;
- }
-
- const T* CData()
- {
- return fArray;
- }
-
- operator bool()
- {
- return !Empty();
- }
-
- private:
- T fArray[N] = {nullptr};
- };
-
- template <typename ValueType>
- auto make_array(ValueType val)
- {
- return CFArray<ValueType, ARRAY_SIZE(val)>{val};
- }
-} // namespace CF
+namespace CF {
+template <typename T, SizeT N>
+class CFArray final {
+ public:
+ explicit CFArray() = default;
+ ~CFArray() = default;
+
+ CFArray& operator=(const CFArray&) = default;
+ CFArray(const CFArray&) = default;
+
+ T& operator[](SizeT at) {
+ MUST_PASS(at < this->Count());
+ return fArray[at];
+ }
+
+ Bool Empty() { return this->Count() > 0; }
+
+ SizeT Capacity() { return N; }
+
+ SizeT Count() {
+ auto cnt = 0UL;
+
+ for (auto i = 0UL; i < N; ++i) {
+ if (fArray[i]) ++cnt;
+ }
+
+ return cnt;
+ }
+
+ const T* CData() { return fArray; }
+
+ operator bool() { return !Empty(); }
+
+ private:
+ T fArray[N] = {nullptr};
+};
+
+template <typename ValueType>
+auto make_array(ValueType val) {
+ return CFArray<ValueType, ARRAY_SIZE(val)>{val};
+}
+} // namespace CF
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Atom.h b/public/frameworks/CoreFoundation.fwrk/headers/Atom.h
index 923d6bce..f279f0b1 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Atom.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Atom.h
@@ -1,47 +1,33 @@
/* -------------------------------------------
- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#pragma once
#include <CoreFoundation.fwrk/headers/Foundation.h>
-namespace CF
-{
- template <typename T>
- class CFAtom final
- {
- public:
- explicit CFAtom() = default;
- ~CFAtom() = default;
-
- public:
- CFAtom& operator=(const CFAtom&) = delete;
- CFAtom(const CFAtom&) = delete;
-
- public:
- T operator[](SizeT bit)
- {
- return (fArrayOfAtoms & (1 << bit));
- }
-
- void operator|(SizeT bit)
- {
- fArrayOfAtoms |= (1 << bit);
- }
-
- friend Boolean operator==(CFAtom<T>& atomic, const T& idx)
- {
- return atomic[idx] == idx;
- }
-
- friend Boolean operator!=(CFAtom<T>& atomic, const T& idx)
- {
- return atomic[idx] == idx;
- }
-
- private:
- T fArrayOfAtoms;
- };
-} // namespace CF
+namespace CF {
+template <typename T>
+class CFAtom final {
+ public:
+ explicit CFAtom() = default;
+ ~CFAtom() = default;
+
+ public:
+ CFAtom& operator=(const CFAtom&) = delete;
+ CFAtom(const CFAtom&) = delete;
+
+ public:
+ T operator[](SizeT bit) { return (fArrayOfAtoms & (1 << bit)); }
+
+ void operator|(SizeT bit) { fArrayOfAtoms |= (1 << bit); }
+
+ friend Boolean operator==(CFAtom<T>& atomic, const T& idx) { return atomic[idx] == idx; }
+
+ friend Boolean operator!=(CFAtom<T>& atomic, const T& idx) { return atomic[idx] == idx; }
+
+ private:
+ T fArrayOfAtoms;
+};
+} // namespace CF
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Foundation.h b/public/frameworks/CoreFoundation.fwrk/headers/Foundation.h
index b1c37635..194b7bb7 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Foundation.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Foundation.h
@@ -1,10 +1,10 @@
/* -------------------------------------------
- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
- FILE: Foundation.h
- PURPOSE: Foundation header of the CF framework.
+ FILE: Foundation.h
+ PURPOSE: Foundation header of the CF framework.
------------------------------------------- */
@@ -12,68 +12,64 @@
#include <user/SystemCalls.h>
-namespace CF
-{
- class CFString;
- class CFGUID;
- class CFProperty;
- class CFObject;
+namespace CF {
+class CFString;
+class CFGUID;
+class CFProperty;
+class CFObject;
- template <typename T>
- class CFRef;
- class CFFont;
- struct CFPoint;
- struct CFRect;
- struct CFColor;
+template <typename T>
+class CFRef;
+class CFFont;
+struct CFPoint;
+struct CFRect;
+struct CFColor;
#ifndef __LP64__
- typedef SInt32 CFInteger;
- typedef float CFReal;
+typedef SInt32 CFInteger;
+typedef float CFReal;
#else
- typedef SInt64 CFInteger;
- typedef double CFReal;
+typedef SInt64 CFInteger;
+typedef double CFReal;
#endif
- typedef SInt32 CFInteger32;
- typedef SInt64 CFInteger64;
+typedef SInt32 CFInteger32;
+typedef SInt64 CFInteger64;
- typedef Char CFChar8;
- typedef char16_t CFChar16;
+typedef Char CFChar8;
+typedef char16_t CFChar16;
- struct CFPoint
- {
- CFInteger64 x_1{0UL};
- CFInteger64 y_1{0UL};
+struct CFPoint {
+ CFInteger64 x_1{0UL};
+ CFInteger64 y_1{0UL};
- CFInteger64 x_2{0UL};
- CFInteger64 y_2{0UL};
- CFReal ang{0UL};
+ CFInteger64 x_2{0UL};
+ CFInteger64 y_2{0UL};
+ CFReal ang{0UL};
- operator bool();
+ operator bool();
- /// @brief Check if point is within the current CFPoint.
- /// @param point the current point to check.
- /// @retval true if point is within this point.
- /// @retval validations failed.
- bool IsWithin(CFPoint& point);
- };
+ /// @brief Check if point is within the current CFPoint.
+ /// @param point the current point to check.
+ /// @retval true if point is within this point.
+ /// @retval validations failed.
+ bool IsWithin(CFPoint& point);
+};
- struct CFColor final
- {
- CFInteger64 r, g, b, a{0};
- };
+struct CFColor final {
+ CFInteger64 r, g, b, a{0};
+};
- struct CFRect final
- {
- CFInteger64 x{0UL};
- CFInteger64 y{0UL};
+struct CFRect final {
+ CFInteger64 x{0UL};
+ CFInteger64 y{0UL};
- CFInteger64 width{0UL};
- CFInteger64 height{0UL};
+ CFInteger64 width{0UL};
+ CFInteger64 height{0UL};
- operator bool();
+ operator bool();
- BOOL SizeMatches(CFRect& rect) noexcept;
- BOOL PositionMatches(CFRect& rect) noexcept;
- };
-} // namespace CF \ No newline at end of file
+ BOOL SizeMatches(CFRect& rect) noexcept;
+ BOOL PositionMatches(CFRect& rect) noexcept;
+};
+} // namespace CF \ No newline at end of file
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Object.h b/public/frameworks/CoreFoundation.fwrk/headers/Object.h
index 733512b1..1692f20e 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Object.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Object.h
@@ -1,7 +1,7 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -11,16 +11,14 @@
#define CF_OBJECT : public CF::CFObject
-namespace CF
-{
- class CFObject;
+namespace CF {
+class CFObject;
- class CFObject
- {
- public:
- explicit CFObject() = default;
- virtual ~CFObject() = default;
+class CFObject {
+ public:
+ explicit CFObject() = default;
+ virtual ~CFObject() = default;
- SCI_COPY_DEFAULT(CFObject);
- };
-} // namespace CF \ No newline at end of file
+ SCI_COPY_DEFAULT(CFObject);
+};
+} // namespace CF \ No newline at end of file
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Property.h b/public/frameworks/CoreFoundation.fwrk/headers/Property.h
index b999c54e..58e881e5 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Property.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Property.h
@@ -1,53 +1,51 @@
/* -------------------------------------------
- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#ifndef _PROPS_H
#define _PROPS_H
-#include <user/SystemCalls.h>
#include <CoreFoundation.fwrk/headers/Ref.h>
+#include <user/SystemCalls.h>
#define kMaxPropLen (256U)
-namespace CF
-{
- class CFString;
- class CFProperty;
- class CFGUID;
-
- template <typename Cls, SizeT N>
- class CFArray;
-
- /// @brief handle to anything (number, ptr, string...)
- using CFPropertyId = UIntPtr;
-
- /// @brief User property class.
- /// @example /prop/foo or /prop/bar
- class CFProperty final CF_OBJECT
- {
- public:
- CFProperty();
- virtual ~CFProperty();
-
- public:
- CFProperty& operator=(const CFProperty&) = default;
- CFProperty(const CFProperty&) = default;
-
- Bool StringEquals(CFString& name);
- CFPropertyId& GetValue();
- CFString& GetKey();
-
- private:
- CFString* fName{nullptr};
- CFPropertyId fValue{0UL};
- Ref<CFGUID> fGUID{};
- };
-
- template <SizeT N>
- using CFPropertyArray = CFArray<CFProperty, N>;
-} // namespace CF
-
-#endif // !CFKIT_PROPS_H
+namespace CF {
+class CFString;
+class CFProperty;
+class CFGUID;
+
+template <typename Cls, SizeT N>
+class CFArray;
+
+/// @brief handle to anything (number, ptr, string...)
+using CFPropertyId = UIntPtr;
+
+/// @brief User property class.
+/// @example /prop/foo or /prop/bar
+class CFProperty final CF_OBJECT {
+ public:
+ CFProperty();
+ virtual ~CFProperty();
+
+ public:
+ CFProperty& operator=(const CFProperty&) = default;
+ CFProperty(const CFProperty&) = default;
+
+ Bool StringEquals(CFString& name);
+ CFPropertyId& GetValue();
+ CFString& GetKey();
+
+ private:
+ CFString* fName{nullptr};
+ CFPropertyId fValue{0UL};
+ Ref<CFGUID> fGUID{};
+};
+
+template <SizeT N>
+using CFPropertyArray = CFArray<CFProperty, N>;
+} // namespace CF
+
+#endif // !CFKIT_PROPS_H
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/Ref.h b/public/frameworks/CoreFoundation.fwrk/headers/Ref.h
index 2a4ec452..c18c6161 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/Ref.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/Ref.h
@@ -1,110 +1,81 @@
/* -------------------------------------------
- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
#ifndef _REF_H_
#define _REF_H_
-#include <user/SystemCalls.h>
#include <CoreFoundation.fwrk/headers/Object.h>
+#include <user/SystemCalls.h>
+
+namespace CF {
+template <typename T>
+class CFRef;
+
+template <typename T>
+class CFRef final CF_OBJECT {
+ public:
+ CFRef() = default;
+
+ ~CFRef() {
+ if (MmGetHeapFlags(fClass) != -1) delete fClass;
+ }
+
+ public:
+ CFRef(T* cls) : fClass(cls) {}
+
+ CFRef(T cls) : fClass(&cls) {}
+
+ CFRef& operator=(T ref) {
+ if (!fClass) return *this;
+
+ fClass = &ref;
+ return *this;
+ }
+
+ public:
+ T operator->() const {
+ MUST_PASS(*fClass);
+ return *fClass;
+ }
+
+ T& Leak() noexcept { return *fClass; }
+
+ T& TryLeak() const noexcept {
+ MUST_PASS(*fClass);
+ return *fClass;
+ }
+
+ T operator*() { return *fClass; }
+
+ operator bool() noexcept { return fClass; }
+
+ private:
+ T* fClass{nullptr};
+};
+
+template <typename T>
+class CFNonNullRef final {
+ public:
+ CFNonNullRef() = delete;
+ CFNonNullRef(nullPtr) = delete;
+
+ CFNonNullRef(T* ref) : fRef(ref) { MUST_PASS(ref); }
+
+ CFRef<T>& operator->() {
+ MUST_PASS(fRef);
+ return fRef;
+ }
+
+ CFNonNullRef& operator=(const CFNonNullRef<T>& ref) = delete;
+ CFNonNullRef(const CFNonNullRef<T>& ref) = default;
+
+ private:
+ CFRef<T> fRef{nullptr};
+};
+} // namespace CF
-namespace CF
-{
- template <typename T>
- class CFRef;
-
- template <typename T>
- class CFRef final CF_OBJECT
- {
- public:
- CFRef() = default;
-
- ~CFRef()
- {
- if (MmGetHeapFlags(fClass) != -1)
- delete fClass;
- }
-
- public:
- CFRef(T* cls)
- : fClass(cls)
- {
- }
-
- CFRef(T cls)
- : fClass(&cls)
- {
- }
-
- CFRef& operator=(T ref)
- {
- if (!fClass)
- return *this;
-
- fClass = &ref;
- return *this;
- }
-
- public:
- T operator->() const
- {
- MUST_PASS(*fClass);
- return *fClass;
- }
-
- T& Leak() noexcept
- {
- return *fClass;
- }
-
- T& TryLeak() const noexcept
- {
- MUST_PASS(*fClass);
- return *fClass;
- }
-
- T operator*()
- {
- return *fClass;
- }
-
- operator bool() noexcept
- {
- return fClass;
- }
-
- private:
- T* fClass{nullptr};
- };
-
- template <typename T>
- class CFNonNullRef final
- {
- public:
- CFNonNullRef() = delete;
- CFNonNullRef(nullPtr) = delete;
-
- CFNonNullRef(T* ref)
- : fRef(ref)
- {
- MUST_PASS(ref);
- }
-
- CFRef<T>& operator->()
- {
- MUST_PASS(fRef);
- return fRef;
- }
-
- CFNonNullRef& operator=(const CFNonNullRef<T>& ref) = delete;
- CFNonNullRef(const CFNonNullRef<T>& ref) = default;
-
- private:
- CFRef<T> fRef{nullptr};
- };
-} // namespace CF
-
-#endif // ifndef _NEWKIT_REF_H_
+#endif // ifndef _NEWKIT_REF_H_
diff --git a/public/frameworks/CoreFoundation.fwrk/headers/String.h b/public/frameworks/CoreFoundation.fwrk/headers/String.h
index e420ac91..c28c05cd 100644
--- a/public/frameworks/CoreFoundation.fwrk/headers/String.h
+++ b/public/frameworks/CoreFoundation.fwrk/headers/String.h
@@ -1,7 +1,7 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -9,12 +9,10 @@
#include <CoreFoundation.fwrk/headers/Object.h>
-namespace CF
-{
- class CFString;
+namespace CF {
+class CFString;
- class CFString final CF_OBJECT
- {
- public:
- };
-} // namespace CF \ No newline at end of file
+class CFString final CF_OBJECT {
+ public:
+};
+} // namespace CF \ No newline at end of file
diff --git a/public/frameworks/CoreFoundation.fwrk/src/Foundation.cc b/public/frameworks/CoreFoundation.fwrk/src/Foundation.cc
index 89adf665..a4b84abf 100644
--- a/public/frameworks/CoreFoundation.fwrk/src/Foundation.cc
+++ b/public/frameworks/CoreFoundation.fwrk/src/Foundation.cc
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2024 Amlal El Mahrouss, all rights reserved
+ Copyright (C) 2024 Amlal El Mahrouss, all rights reserved
------------------------------------------- */
@@ -9,25 +9,22 @@
/***********************************************************************************/
/// @brief returns true if the proportions are valid.
/***********************************************************************************/
-CF::CFRect::operator bool()
-{
- return width > 0 && height > 0;
+CF::CFRect::operator bool() {
+ return width > 0 && height > 0;
}
/***********************************************************************************/
/// @brief returns true if size matches.
/***********************************************************************************/
-BOOL CF::CFRect::SizeMatches(CF::CFRect& rect) noexcept
-{
- return rect.height == height && rect.width == width;
+BOOL CF::CFRect::SizeMatches(CF::CFRect& rect) noexcept {
+ return rect.height == height && rect.width == width;
}
/***********************************************************************************/
/// @brief returns true if position matches.
/***********************************************************************************/
-BOOL CF::CFRect::PositionMatches(CF::CFRect& rect) noexcept
-{
- return rect.y == y && rect.x == x;
+BOOL CF::CFRect::PositionMatches(CF::CFRect& rect) noexcept {
+ return rect.y == y && rect.x == x;
}
/***********************************************************************************/
@@ -36,16 +33,14 @@ BOOL CF::CFRect::PositionMatches(CF::CFRect& rect) noexcept
/// @retval true if point is within this point.
/// @retval the validations have failed, false otherwise true.
/***********************************************************************************/
-BOOL CF::CFPoint::IsWithin(CF::CFPoint& withinOf)
-{
- return x_1 >= withinOf.x_1 && x_2 <= (withinOf.x_2) &&
- y_1 >= withinOf.y_1 && y_2 <= (withinOf.y_2);
+BOOL CF::CFPoint::IsWithin(CF::CFPoint& withinOf) {
+ return x_1 >= withinOf.x_1 && x_2 <= (withinOf.x_2) && y_1 >= withinOf.y_1 &&
+ y_2 <= (withinOf.y_2);
}
/***********************************************************************************/
/// @brief if Point object is correctly set up.
/***********************************************************************************/
-CF::CFPoint::operator bool()
-{
- return x_1 > x_2 && y_1 > y_2;
+CF::CFPoint::operator bool() {
+ return x_1 > x_2 && y_1 > y_2;
} \ No newline at end of file
diff --git a/public/frameworks/DiskImage.fwrk/headers/DiskImage.h b/public/frameworks/DiskImage.fwrk/headers/DiskImage.h
index c0566485..78b39bf8 100644
--- a/public/frameworks/DiskImage.fwrk/headers/DiskImage.h
+++ b/public/frameworks/DiskImage.fwrk/headers/DiskImage.h
@@ -1,51 +1,49 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+
+ FILE: DiskImage.h
+ PURPOSE: Disk Imaging framework.
- FILE: DiskImage.h
- PURPOSE: Disk Imaging framework.
-
------------------------------------------- */
#pragma once
#include <user/SystemCalls.h>
-#define kDISectorSz (512)
-#define kDIMinDiskSz mib_cast(1)
+#define kDISectorSz (512)
+#define kDIMinDiskSz mib_cast(1)
#define kDIDefaultOutputName "disk.eimg"
-#define kDIDefaultDiskName "Disk"
-#define kDISuccessStatus (0)
-#define kDIFailureStatus (1)
+#define kDIDefaultDiskName "Disk"
+#define kDISuccessStatus (0)
+#define kDIFailureStatus (1)
#define kDIDiskNameLen (16)
-#define kDIOutNameLen (256)
-
-namespace DI
-{
- /// @brief Disk Image file structure.
- /// @param disk_name Disk partition name.
- /// @param sector_sz Disk sector_sz.
- /// @param block_cnt Disk block count.
- /// @param disk_sz Disk size.
- /// @param out_name Output file name.
- struct DI_DISK_IMAGE
- {
- Char disk_name[kDIDiskNameLen] = kDIDefaultDiskName;
- SInt32 sector_sz = kDISectorSz;
- SInt32 block_cnt = 0;
- SizeT disk_sz = kDIMinDiskSz;
- Char out_name[kDIOutNameLen] = kDIDefaultOutputName;
- };
-
- /// @brief Format with an EPM partition.
- /// @param img disk image structure.
- /// @return Status code upon completion.
- SInt32 DIFormatPartitionEPM(struct DI_DISK_IMAGE& img) noexcept;
-
- /// @brief NeFS format over EPM.
- /// @param img disk image structure.
- /// @return Status code upon completion.
- SInt32 DIFormatFilesystemNeFS(struct DI_DISK_IMAGE& img) noexcept;
-
-} // namespace DI
+#define kDIOutNameLen (256)
+
+namespace DI {
+/// @brief Disk Image file structure.
+/// @param disk_name Disk partition name.
+/// @param sector_sz Disk sector_sz.
+/// @param block_cnt Disk block count.
+/// @param disk_sz Disk size.
+/// @param out_name Output file name.
+struct DI_DISK_IMAGE {
+ Char disk_name[kDIDiskNameLen] = kDIDefaultDiskName;
+ SInt32 sector_sz = kDISectorSz;
+ SInt32 block_cnt = 0;
+ SizeT disk_sz = kDIMinDiskSz;
+ Char out_name[kDIOutNameLen] = kDIDefaultOutputName;
+};
+
+/// @brief Format with an EPM partition.
+/// @param img disk image structure.
+/// @return Status code upon completion.
+SInt32 DIFormatPartitionEPM(struct DI_DISK_IMAGE& img) noexcept;
+
+/// @brief NeFS format over EPM.
+/// @param img disk image structure.
+/// @return Status code upon completion.
+SInt32 DIFormatFilesystemNeFS(struct DI_DISK_IMAGE& img) noexcept;
+
+} // namespace DI
diff --git a/public/frameworks/DiskImage.fwrk/src/DiskImage+EPM.cc b/public/frameworks/DiskImage.fwrk/src/DiskImage+EPM.cc
index 4d2a6694..a1182e64 100644
--- a/public/frameworks/DiskImage.fwrk/src/DiskImage+EPM.cc
+++ b/public/frameworks/DiskImage.fwrk/src/DiskImage+EPM.cc
@@ -1,53 +1,46 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
- FILE: DiskImage+EPM.cc
- PURPOSE: Disk Imaging framework.
+ FILE: DiskImage+EPM.cc
+ PURPOSE: Disk Imaging framework.
------------------------------------------- */
#include <DiskImage.fwrk/headers/DiskImage.h>
-#include <FirmwareKit/EPM.h>
#include <FSKit/NeFS.h>
+#include <FirmwareKit/EPM.h>
/// @brief EPM format disk
/// @param img disk image structure.
/// @return Status code upon completion.
-SInt32 DI::DIFormatPartitionEPM(struct DI_DISK_IMAGE& img) noexcept
-{
- if (!img.sector_sz || (img.sector_sz % 512 != 0))
- return kDIFailureStatus;
+SInt32 DI::DIFormatPartitionEPM(struct DI_DISK_IMAGE& img) noexcept {
+ if (!img.sector_sz || (img.sector_sz % 512 != 0)) return kDIFailureStatus;
- if (*img.out_name == 0 ||
- *img.disk_name == 0)
- return kDIFailureStatus;
+ if (*img.out_name == 0 || *img.disk_name == 0) return kDIFailureStatus;
- struct ::EPM_PART_BLOCK block
- {
- };
+ struct ::EPM_PART_BLOCK block {};
- block.NumBlocks = img.block_cnt;
- block.SectorSz = img.sector_sz;
- block.Version = kEPMRevisionBcd;
- block.LbaStart = sizeof(struct ::EPM_PART_BLOCK);
- block.LbaEnd = img.disk_sz - block.LbaStart;
- block.FsVersion = kNeFSVersionInteger;
+ block.NumBlocks = img.block_cnt;
+ block.SectorSz = img.sector_sz;
+ block.Version = kEPMRevisionBcd;
+ block.LbaStart = sizeof(struct ::EPM_PART_BLOCK);
+ block.LbaEnd = img.disk_sz - block.LbaStart;
+ block.FsVersion = kNeFSVersionInteger;
- ::MmCopyMemory(block.Name, (VoidPtr)img.disk_name, ::MmStrLen(img.disk_name));
- ::MmCopyMemory(block.Magic, (VoidPtr)kEPMMagic86, ::MmStrLen(kEPMMagic86));
+ ::MmCopyMemory(block.Name, (VoidPtr) img.disk_name, ::MmStrLen(img.disk_name));
+ ::MmCopyMemory(block.Magic, (VoidPtr) kEPMMagic86, ::MmStrLen(kEPMMagic86));
- IORef handle = IoOpenFile(img.out_name, nullptr);
+ IORef handle = IoOpenFile(img.out_name, nullptr);
- if (!handle)
- return kDIFailureStatus;
+ if (!handle) return kDIFailureStatus;
- ::IoWriteFile(handle, (Char*)&block, sizeof(struct ::EPM_PART_BLOCK));
+ ::IoWriteFile(handle, (Char*) &block, sizeof(struct ::EPM_PART_BLOCK));
- ::IoCloseFile(handle);
+ ::IoCloseFile(handle);
- handle = nullptr;
+ handle = nullptr;
- return kDISuccessStatus;
+ return kDISuccessStatus;
}
diff --git a/public/frameworks/DiskImage.fwrk/src/DiskImage+NeFS.cc b/public/frameworks/DiskImage.fwrk/src/DiskImage+NeFS.cc
index 4928c878..bee84cca 100644
--- a/public/frameworks/DiskImage.fwrk/src/DiskImage+NeFS.cc
+++ b/public/frameworks/DiskImage.fwrk/src/DiskImage+NeFS.cc
@@ -1,64 +1,57 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
- FILE: DiskImage+NeFS.cc
- PURPOSE: Disk Imaging framework.
+ FILE: DiskImage+NeFS.cc
+ PURPOSE: Disk Imaging framework.
------------------------------------------- */
#include <DiskImage.fwrk/headers/DiskImage.h>
-#include <FirmwareKit/EPM.h>
#include <FSKit/NeFS.h>
+#include <FirmwareKit/EPM.h>
/// @brief NeFS format over EPM.
/// @param img disk image structure.
/// @return Status code upon completion.
-SInt32 DI::DIFormatFilesystemNeFS(struct DI_DISK_IMAGE& img) noexcept
-{
- if (!img.sector_sz || (img.sector_sz % 512 != 0))
- return kDIFailureStatus;
+SInt32 DI::DIFormatFilesystemNeFS(struct DI_DISK_IMAGE& img) noexcept {
+ if (!img.sector_sz || (img.sector_sz % 512 != 0)) return kDIFailureStatus;
- if (*img.out_name == 0 ||
- *img.disk_name == 0)
- return kDIFailureStatus;
+ if (*img.out_name == 0 || *img.disk_name == 0) return kDIFailureStatus;
- struct ::NEFS_ROOT_PARTITION_BLOCK rpb
- {
- };
+ struct ::NEFS_ROOT_PARTITION_BLOCK rpb {};
- ::MmCopyMemory(rpb.PartitionName, (VoidPtr)img.disk_name, ::MmStrLen(img.disk_name));
- ::MmCopyMemory(rpb.Ident, (VoidPtr)kNeFSIdent, ::MmStrLen(kNeFSIdent));
+ ::MmCopyMemory(rpb.PartitionName, (VoidPtr) img.disk_name, ::MmStrLen(img.disk_name));
+ ::MmCopyMemory(rpb.Ident, (VoidPtr) kNeFSIdent, ::MmStrLen(kNeFSIdent));
- rpb.Version = kNeFSVersionInteger;
- rpb.EpmBlock = kEPMBootBlockLba;
+ rpb.Version = kNeFSVersionInteger;
+ rpb.EpmBlock = kEPMBootBlockLba;
- rpb.StartCatalog = kNeFSCatalogStartAddress;
- rpb.CatalogCount = 0;
+ rpb.StartCatalog = kNeFSCatalogStartAddress;
+ rpb.CatalogCount = 0;
- rpb.DiskSize = img.disk_sz;
+ rpb.DiskSize = img.disk_sz;
- rpb.SectorSize = img.sector_sz;
- rpb.SectorCount = rpb.DiskSize / rpb.SectorSize;
+ rpb.SectorSize = img.sector_sz;
+ rpb.SectorCount = rpb.DiskSize / rpb.SectorSize;
- rpb.FreeSectors = rpb.SectorCount;
- rpb.FreeCatalog = rpb.DiskSize / sizeof(NEFS_CATALOG_STRUCT);
+ rpb.FreeSectors = rpb.SectorCount;
+ rpb.FreeCatalog = rpb.DiskSize / sizeof(NEFS_CATALOG_STRUCT);
- IORef handle = IoOpenFile(img.out_name, nullptr);
+ IORef handle = IoOpenFile(img.out_name, nullptr);
- if (!handle)
- return kDIFailureStatus;
+ if (!handle) return kDIFailureStatus;
- UInt64 p_prev = ::IoTellFile(handle);
+ UInt64 p_prev = ::IoTellFile(handle);
- ::IoWriteFile(handle, (Char*)&rpb, sizeof(struct ::NEFS_ROOT_PARTITION_BLOCK));
+ ::IoWriteFile(handle, (Char*) &rpb, sizeof(struct ::NEFS_ROOT_PARTITION_BLOCK));
- ::IoSeekFile(handle, p_prev);
+ ::IoSeekFile(handle, p_prev);
- ::IoCloseFile(handle);
+ ::IoCloseFile(handle);
- handle = nullptr;
+ handle = nullptr;
- return kDISuccessStatus;
+ return kDISuccessStatus;
} \ No newline at end of file
diff --git a/public/frameworks/KernelTest.fwrk/headers/KernelTest.h b/public/frameworks/KernelTest.fwrk/headers/KernelTest.h
index e3200032..808d127e 100644
--- a/public/frameworks/KernelTest.fwrk/headers/KernelTest.h
+++ b/public/frameworks/KernelTest.fwrk/headers/KernelTest.h
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
------------------------------------------- */
@@ -12,27 +12,24 @@
/// @file KernelTest.h
#define KT_TEST_VERSION_BCD (0x0001)
-#define KT_TEST_VERSION "0.0.1"
+#define KT_TEST_VERSION "0.0.1"
#define KT_TEST_FAILURE (1)
#define KT_TEST_SUCCESS (0)
#define KT_DECL_TEST(NAME, FN) \
- class KT_##NAME final \
- { \
- public: \
- void Run(); \
- const char* ToString(); \
- }; \
- inline void KT_##NAME::Run() \
- { \
- MUST_PASS(FN() == true); \
- } \
- inline const char* KT_##NAME::ToString() \
- { \
- return #FN; \
- }
+ class KT_##NAME final { \
+ public: \
+ void Run(); \
+ const char* ToString(); \
+ }; \
+ inline void KT_##NAME::Run() { \
+ MUST_PASS(FN() == true); \
+ } \
+ inline const char* KT_##NAME::ToString() { \
+ return #FN; \
+ }
KT_DECL_TEST(ALWAYS_BREAK, []() -> bool { return false; });
KT_DECL_TEST(ALWAYS_GOOD, []() -> bool { return true; }); \ No newline at end of file
diff --git a/public/tools/cc/src/CommandLine.cc b/public/tools/cc/src/CommandLine.cc
index d9420c47..719a1555 100644
--- a/public/tools/cc/src/CommandLine.cc
+++ b/public/tools/cc/src/CommandLine.cc
@@ -8,8 +8,8 @@
/// @brief Placeholder program.
-SInt32 main(SInt32 argc, Char* argv[])
-{
- PrintOut(nullptr, "cc: A C++ compiler to be installed.\rcc: This program is present as a placeholder.");
- return EXIT_FAILURE;
+SInt32 main(SInt32 argc, Char* argv[]) {
+ PrintOut(nullptr,
+ "cc: A C++ compiler to be installed.\rcc: This program is present as a placeholder.");
+ return EXIT_FAILURE;
}
diff --git a/public/tools/diutil/src/CommandLine.cc b/public/tools/diutil/src/CommandLine.cc
index ef0aaa2e..dd23f532 100644
--- a/public/tools/diutil/src/CommandLine.cc
+++ b/public/tools/diutil/src/CommandLine.cc
@@ -1,67 +1,58 @@
/* -------------------------------------------
- Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
+ Copyright (C) 2025, Amlal El Mahrouss, all rights reserved.
- FILE: CommandLine.cc
- PURPOSE: DIUTIL CLI.
+ FILE: CommandLine.cc
+ PURPOSE: DIUTIL CLI.
------------------------------------------- */
#include <DiskImage.fwrk/headers/DiskImage.h>
static const Char kDiskName[kDIDiskNameLen] = "Empty Disk";
-static SInt32 kDiskSectorSz = kDISectorSz;
-static SizeT kDiskSz = gib_cast(4);
-static const Char kOutDisk[kDIOutNameLen] = "disk.eimg";
+static SInt32 kDiskSectorSz = kDISectorSz;
+static SizeT kDiskSz = gib_cast(4);
+static const Char kOutDisk[kDIOutNameLen] = "disk.eimg";
/// @brief Disk Utility entrypoint.
-SInt32 _NeMain(SInt32 argc, Char** argv)
-{
- for (SInt32 arg = 0; arg < argc; ++arg)
- {
- const Char* arg_s = argv[arg];
-
- if (MmCmpMemory((VoidPtr)arg_s, (VoidPtr) "-diutil-output-name", MmStrLen("-diutil-output-name") == 0))
- {
- if ((arg + 1) < argc)
- {
- MmCopyMemory((VoidPtr)kOutDisk, argv[arg + 1], kDIDiskNameLen);
- }
- }
- else if (MmCmpMemory((VoidPtr)arg_s, (VoidPtr) "-diutil-output-size", MmStrLen("-diutil-output-size") == 0))
- {
- if ((arg + 1) < argc)
- {
- kDiskSz = StrMathToNumber(argv[arg + 1], nullptr, 10);
- }
- }
- else if (MmCmpMemory((VoidPtr)arg_s, (VoidPtr) "-diutil-sector-size", MmStrLen("-diutil-sector-size") == 0))
- {
- if ((arg + 1) < argc)
- {
- kDiskSectorSz = StrMathToNumber(argv[arg + 1], nullptr, 10);
- }
- }
- else if (MmCmpMemory((VoidPtr)arg_s, (VoidPtr) "-diutil-part-name", MmStrLen("-diutil-part-name") == 0))
- {
- if ((arg + 1) < argc)
- {
- MmCopyMemory((VoidPtr)kDiskName, argv[arg + 1], kDIDiskNameLen);
- }
- }
- }
-
- // create disk image, by appending an EPM partition to it.
-
- DI::DI_DISK_IMAGE img{};
-
- img.disk_sz = kDiskSz;
- img.sector_sz = kDiskSectorSz;
- img.block_cnt = 0;
-
- MmCopyMemory((VoidPtr)img.disk_name, (VoidPtr)kDiskName, kDIDiskNameLen);
- MmCopyMemory((VoidPtr)img.out_name, (VoidPtr)kOutDisk, kDIDiskNameLen);
-
- // format disk image to explicit partition map.
- return DI::DIFormatPartitionEPM(img);
+SInt32 _NeMain(SInt32 argc, Char** argv) {
+ for (SInt32 arg = 0; arg < argc; ++arg) {
+ const Char* arg_s = argv[arg];
+
+ if (MmCmpMemory((VoidPtr) arg_s, (VoidPtr) "-diutil-output-name",
+ MmStrLen("-diutil-output-name") == 0)) {
+ if ((arg + 1) < argc) {
+ MmCopyMemory((VoidPtr) kOutDisk, argv[arg + 1], kDIDiskNameLen);
+ }
+ } else if (MmCmpMemory((VoidPtr) arg_s, (VoidPtr) "-diutil-output-size",
+ MmStrLen("-diutil-output-size") == 0)) {
+ if ((arg + 1) < argc) {
+ kDiskSz = StrMathToNumber(argv[arg + 1], nullptr, 10);
+ }
+ } else if (MmCmpMemory((VoidPtr) arg_s, (VoidPtr) "-diutil-sector-size",
+ MmStrLen("-diutil-sector-size") == 0)) {
+ if ((arg + 1) < argc) {
+ kDiskSectorSz = StrMathToNumber(argv[arg + 1], nullptr, 10);
+ }
+ } else if (MmCmpMemory((VoidPtr) arg_s, (VoidPtr) "-diutil-part-name",
+ MmStrLen("-diutil-part-name") == 0)) {
+ if ((arg + 1) < argc) {
+ MmCopyMemory((VoidPtr) kDiskName, argv[arg + 1], kDIDiskNameLen);
+ }
+ }
+ }
+
+ // create disk image, by appending an EPM partition to it.
+
+ DI::DI_DISK_IMAGE img{};
+
+ img.disk_sz = kDiskSz;
+ img.sector_sz = kDiskSectorSz;
+ img.block_cnt = 0;
+
+ MmCopyMemory((VoidPtr) img.disk_name, (VoidPtr) kDiskName, kDIDiskNameLen);
+ MmCopyMemory((VoidPtr) img.out_name, (VoidPtr) kOutDisk, kDIDiskNameLen);
+
+ // format disk image to explicit partition map.
+ return DI::DIFormatPartitionEPM(img);
} \ No newline at end of file
diff --git a/public/tools/diutil/vendor/Dialogs.h b/public/tools/diutil/vendor/Dialogs.h
index fd64026b..ce50b811 100644
--- a/public/tools/diutil/vendor/Dialogs.h
+++ b/public/tools/diutil/vendor/Dialogs.h
@@ -16,45 +16,45 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
-#include <windows.h>
#include <commdlg.h>
-#include <shlobj.h>
-#include <shobjidl.h> // IFileDialog
#include <shellapi.h>
+#include <shlobj.h>
+#include <shobjidl.h> // IFileDialog
#include <strsafe.h>
-#include <future> // std::async
-#include <userenv.h> // GetUserProfileDirectory()
+#include <userenv.h> // GetUserProfileDirectory()
+#include <windows.h>
+#include <future> // std::async
#elif __EMSCRIPTEN__
#include <emscripten.h>
#else
#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 2 // for popen()
+#define _POSIX_C_SOURCE 2 // for popen()
#endif
#ifdef __APPLE__
#ifndef _DARWIN_C_SOURCE
#define _DARWIN_C_SOURCE
#endif
#endif
-#include <cstdio> // popen()
-#include <cstdlib> // std::getenv()
-#include <fcntl.h> // fcntl()
-#include <unistd.h> // read(), pipe(), dup2(), getuid()
-#include <csignal> // ::kill, std::signal
-#include <sys/stat.h> // stat()
-#include <sys/wait.h> // waitpid()
-#include <pwd.h> // getpwnam()
+#include <fcntl.h> // fcntl()
+#include <pwd.h> // getpwnam()
+#include <sys/stat.h> // stat()
+#include <sys/wait.h> // waitpid()
+#include <unistd.h> // read(), pipe(), dup2(), getuid()
+#include <csignal> // ::kill, std::signal
+#include <cstdio> // popen()
+#include <cstdlib> // std::getenv()
#endif
-#include <string> // std::string
-#include <memory> // std::shared_ptr
-#include <iostream> // std::ostream
-#include <map> // std::map
-#include <set> // std::set
-#include <regex> // std::regex
-#include <thread> // std::mutex, std::this_thread
-#include <chrono> // std::chrono
+#include <chrono> // std::chrono
+#include <iostream> // std::ostream
+#include <map> // std::map
+#include <memory> // std::shared_ptr
+#include <regex> // std::regex
+#include <set> // std::set
+#include <string> // std::string
+#include <thread> // std::mutex, std::this_thread
// Versions of mingw64 g++ up to 9.3.0 do not have a complete IFileDialog
#ifndef PFD_HAS_IFILEDIALOG
@@ -67,1915 +67,1672 @@
#endif
#endif
-namespace pfd
-{
-
- enum class button
- {
- cancel = -1,
- ok,
- yes,
- no,
- abort,
- retry,
- ignore,
- };
-
- enum class choice
- {
- ok = 0,
- ok_cancel,
- yes_no,
- yes_no_cancel,
- retry_cancel,
- abort_retry_ignore,
- };
-
- enum class icon
- {
- info = 0,
- warning,
- error,
- question,
- };
-
- // Additional option flags for various dialog constructors
- enum class opt : uint8_t
- {
- none = 0,
- // For file open, allow multiselect.
- multiselect = 0x1,
- // For file save, force overwrite and disable the confirmation dialog.
- force_overwrite = 0x2,
- // For folder select, force path to be the provided argument instead
- // of the last opened directory, which is the Microsoft-recommended,
- // user-friendly behaviour.
- force_path = 0x4,
- };
-
- inline opt operator|(opt a, opt b)
- {
- return opt(uint8_t(a) | uint8_t(b));
- }
- inline bool operator&(opt a, opt b)
- {
- return bool(uint8_t(a) & uint8_t(b));
- }
-
- // The settings class, only exposing to the user a way to set verbose mode
- // and to force a rescan of installed desktop helpers (zenity, kdialog…).
- class settings
- {
- public:
- static bool available();
-
- static void verbose(bool value);
- static void rescan();
-
- protected:
- explicit settings(bool resync = false);
-
- bool check_program(std::string const& program);
-
- inline bool is_osascript() const;
- inline bool is_zenity() const;
- inline bool is_kdialog() const;
-
- enum class flag
- {
- is_scanned = 0,
- is_verbose,
-
- has_zenity,
- has_matedialog,
- has_qarma,
- has_kdialog,
- is_vista,
-
- max_flag,
- };
-
- // Static array of flags for internal state
- bool const& flags(flag in_flag) const;
-
- // Non-const getter for the static array of flags
- bool& flags(flag in_flag);
- };
-
- // Internal classes, not to be used by client applications
- namespace internal
- {
-
- // Process wait timeout, in milliseconds
- static int const default_wait_timeout = 20;
-
- class executor
- {
- friend class dialog;
-
- public:
- // High level function to get the result of a command
- std::string result(int* exit_code = nullptr);
-
- // High level function to abort
- bool kill();
+namespace pfd {
+
+enum class button {
+ cancel = -1,
+ ok,
+ yes,
+ no,
+ abort,
+ retry,
+ ignore,
+};
+
+enum class choice {
+ ok = 0,
+ ok_cancel,
+ yes_no,
+ yes_no_cancel,
+ retry_cancel,
+ abort_retry_ignore,
+};
+
+enum class icon {
+ info = 0,
+ warning,
+ error,
+ question,
+};
+
+// Additional option flags for various dialog constructors
+enum class opt : uint8_t {
+ none = 0,
+ // For file open, allow multiselect.
+ multiselect = 0x1,
+ // For file save, force overwrite and disable the confirmation dialog.
+ force_overwrite = 0x2,
+ // For folder select, force path to be the provided argument instead
+ // of the last opened directory, which is the Microsoft-recommended,
+ // user-friendly behaviour.
+ force_path = 0x4,
+};
+
+inline opt operator|(opt a, opt b) {
+ return opt(uint8_t(a) | uint8_t(b));
+}
+inline bool operator&(opt a, opt b) {
+ return bool(uint8_t(a) & uint8_t(b));
+}
+
+// The settings class, only exposing to the user a way to set verbose mode
+// and to force a rescan of installed desktop helpers (zenity, kdialog…).
+class settings {
+ public:
+ static bool available();
+
+ static void verbose(bool value);
+ static void rescan();
+
+ protected:
+ explicit settings(bool resync = false);
+
+ bool check_program(std::string const& program);
+
+ inline bool is_osascript() const;
+ inline bool is_zenity() const;
+ inline bool is_kdialog() const;
+
+ enum class flag {
+ is_scanned = 0,
+ is_verbose,
+
+ has_zenity,
+ has_matedialog,
+ has_qarma,
+ has_kdialog,
+ is_vista,
+
+ max_flag,
+ };
+
+ // Static array of flags for internal state
+ bool const& flags(flag in_flag) const;
+
+ // Non-const getter for the static array of flags
+ bool& flags(flag in_flag);
+};
+
+// Internal classes, not to be used by client applications
+namespace internal {
+
+ // Process wait timeout, in milliseconds
+ static int const default_wait_timeout = 20;
+
+ class executor {
+ friend class dialog;
+
+ public:
+ // High level function to get the result of a command
+ std::string result(int* exit_code = nullptr);
+
+ // High level function to abort
+ bool kill();
#if _WIN32
- void start_func(std::function<std::string(int*)> const& fun);
- static BOOL CALLBACK enum_windows_callback(HWND hwnd, LPARAM lParam);
+ void start_func(std::function<std::string(int*)> const& fun);
+ static BOOL CALLBACK enum_windows_callback(HWND hwnd, LPARAM lParam);
#elif __EMSCRIPTEN__
- void start(int exit_code);
+ void start(int exit_code);
#else
- void start_process(std::vector<std::string> const& command);
+ void start_process(std::vector<std::string> const& command);
#endif
- ~executor();
+ ~executor();
- protected:
- bool ready(int timeout = default_wait_timeout);
- void stop();
+ protected:
+ bool ready(int timeout = default_wait_timeout);
+ void stop();
- private:
- bool m_running = false;
- std::string m_stdout;
- int m_exit_code = -1;
+ private:
+ bool m_running = false;
+ std::string m_stdout;
+ int m_exit_code = -1;
#if _WIN32
- std::future<std::string> m_future;
- std::set<HWND> m_windows;
- std::condition_variable m_cond;
- std::mutex m_mutex;
- DWORD m_tid;
+ std::future<std::string> m_future;
+ std::set<HWND> m_windows;
+ std::condition_variable m_cond;
+ std::mutex m_mutex;
+ DWORD m_tid;
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
+ // FIXME: do something
#else
- pid_t m_pid = 0;
- int m_fd = -1;
+ pid_t m_pid = 0;
+ int m_fd = -1;
#endif
- };
+ };
- class platform
- {
- protected:
+ class platform {
+ protected:
#if _WIN32
- // Helper class around LoadLibraryA() and GetProcAddress() with some safety
- class dll
- {
- public:
- dll(std::string const& name);
- ~dll();
-
- template <typename T>
- class proc
- {
- public:
- proc(dll const& lib, std::string const& sym)
- : m_proc(reinterpret_cast<T*>((void*)::GetProcAddress(lib.handle, sym.c_str())))
- {
- }
-
- operator bool() const
- {
- return m_proc != nullptr;
- }
- operator T*() const
- {
- return m_proc;
- }
-
- private:
- T* m_proc;
- };
-
- private:
- HMODULE handle;
- };
-
- // Helper class around CoInitialize() and CoUnInitialize()
- class ole32_dll : public dll
- {
- public:
- ole32_dll();
- ~ole32_dll();
- bool is_initialized();
-
- private:
- HRESULT m_state;
- };
-
- // Helper class around CreateActCtx() and ActivateActCtx()
- class new_style_context
- {
- public:
- new_style_context();
- ~new_style_context();
-
- private:
- HANDLE create();
- ULONG_PTR m_cookie = 0;
- };
+ // Helper class around LoadLibraryA() and GetProcAddress() with some safety
+ class dll {
+ public:
+ dll(std::string const& name);
+ ~dll();
+
+ template <typename T>
+ class proc {
+ public:
+ proc(dll const& lib, std::string const& sym)
+ : m_proc(reinterpret_cast<T*>((void*) ::GetProcAddress(lib.handle, sym.c_str()))) {}
+
+ operator bool() const { return m_proc != nullptr; }
+ operator T*() const { return m_proc; }
+
+ private:
+ T* m_proc;
+ };
+
+ private:
+ HMODULE handle;
+ };
+
+ // Helper class around CoInitialize() and CoUnInitialize()
+ class ole32_dll : public dll {
+ public:
+ ole32_dll();
+ ~ole32_dll();
+ bool is_initialized();
+
+ private:
+ HRESULT m_state;
+ };
+
+ // Helper class around CreateActCtx() and ActivateActCtx()
+ class new_style_context {
+ public:
+ new_style_context();
+ ~new_style_context();
+
+ private:
+ HANDLE create();
+ ULONG_PTR m_cookie = 0;
+ };
#endif
- };
-
- class dialog : protected settings, protected platform
- {
- public:
- bool ready(int timeout = default_wait_timeout) const;
- bool kill() const;
-
- protected:
- explicit dialog();
-
- std::vector<std::string> desktop_helper() const;
- static std::string buttons_to_name(choice _choice);
- static std::string get_icon_name(icon _icon);
-
- std::string powershell_quote(std::string const& str) const;
- std::string osascript_quote(std::string const& str) const;
- std::string shell_quote(std::string const& str) const;
-
- // Keep handle to executing command
- std::shared_ptr<executor> m_async;
- };
-
- class file_dialog : public dialog
- {
- protected:
- enum type
- {
- open,
- save,
- folder,
- };
-
- file_dialog(type in_type,
- std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {},
- opt options = opt::none);
-
- protected:
- std::string string_result();
- std::vector<std::string> vector_result();
+ };
+
+ class dialog : protected settings, protected platform {
+ public:
+ bool ready(int timeout = default_wait_timeout) const;
+ bool kill() const;
+
+ protected:
+ explicit dialog();
+
+ std::vector<std::string> desktop_helper() const;
+ static std::string buttons_to_name(choice _choice);
+ static std::string get_icon_name(icon _icon);
+
+ std::string powershell_quote(std::string const& str) const;
+ std::string osascript_quote(std::string const& str) const;
+ std::string shell_quote(std::string const& str) const;
+
+ // Keep handle to executing command
+ std::shared_ptr<executor> m_async;
+ };
+
+ class file_dialog : public dialog {
+ protected:
+ enum type {
+ open,
+ save,
+ folder,
+ };
+
+ file_dialog(type in_type, std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {}, opt options = opt::none);
+
+ protected:
+ std::string string_result();
+ std::vector<std::string> vector_result();
#if _WIN32
- static int CALLBACK bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData);
+ static int CALLBACK bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData);
#if PFD_HAS_IFILEDIALOG
- std::string select_folder_vista(IFileDialog* ifd, bool force_path);
+ std::string select_folder_vista(IFileDialog* ifd, bool force_path);
#endif
- std::wstring m_wtitle;
- std::wstring m_wdefault_path;
+ std::wstring m_wtitle;
+ std::wstring m_wdefault_path;
- std::vector<std::string> m_vector_result;
+ std::vector<std::string> m_vector_result;
#endif
- };
-
- } // namespace internal
-
- //
- // The path class provides some platform-specific path constants
- //
-
- class path : protected internal::platform
- {
- public:
- static std::string home();
- static std::string separator();
- };
-
- //
- // The notify widget
- //
-
- class notify : public internal::dialog
- {
- public:
- notify(std::string const& title,
- std::string const& message,
- icon _icon = icon::info);
- };
-
- //
- // The message widget
- //
-
- class message : public internal::dialog
- {
- public:
- message(std::string const& title,
- std::string const& text,
- choice _choice = choice::ok_cancel,
- icon _icon = icon::info);
-
- button result();
-
- private:
- // Some extra logic to map the exit code to button number
- std::map<int, button> m_mappings;
- };
-
- //
- // The open_file, save_file, and open_folder widgets
- //
-
- class open_file : public internal::file_dialog
- {
- public:
- open_file(std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {"All Files", "*"},
- opt options = opt::none);
+ };
+
+} // namespace internal
+
+//
+// The path class provides some platform-specific path constants
+//
+
+class path : protected internal::platform {
+ public:
+ static std::string home();
+ static std::string separator();
+};
+
+//
+// The notify widget
+//
+
+class notify : public internal::dialog {
+ public:
+ notify(std::string const& title, std::string const& message, icon _icon = icon::info);
+};
+
+//
+// The message widget
+//
+
+class message : public internal::dialog {
+ public:
+ message(std::string const& title, std::string const& text, choice _choice = choice::ok_cancel,
+ icon _icon = icon::info);
+
+ button result();
+
+ private:
+ // Some extra logic to map the exit code to button number
+ std::map<int, button> m_mappings;
+};
+
+//
+// The open_file, save_file, and open_folder widgets
+//
+
+class open_file : public internal::file_dialog {
+ public:
+ open_file(std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {"All Files", "*"}, opt options = opt::none);
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(deprecated)
- // Backwards compatibility
- [[deprecated("Use pfd::opt::multiselect instead of allow_multiselect")]]
+ // Backwards compatibility
+ [[deprecated("Use pfd::opt::multiselect instead of allow_multiselect")]]
#endif
#endif
- open_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool allow_multiselect);
-
- std::vector<std::string> result();
- };
-
- class save_file : public internal::file_dialog
- {
- public:
- save_file(std::string const& title,
- std::string const& default_path = "",
- std::vector<std::string> const& filters = {"All Files", "*"},
- opt options = opt::none);
+ open_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool allow_multiselect);
+
+ std::vector<std::string> result();
+};
+
+class save_file : public internal::file_dialog {
+ public:
+ save_file(std::string const& title, std::string const& default_path = "",
+ std::vector<std::string> const& filters = {"All Files", "*"}, opt options = opt::none);
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(deprecated)
- // Backwards compatibility
- [[deprecated("Use pfd::opt::force_overwrite instead of confirm_overwrite")]]
+ // Backwards compatibility
+ [[deprecated("Use pfd::opt::force_overwrite instead of confirm_overwrite")]]
#endif
#endif
- save_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool confirm_overwrite);
-
- std::string result();
- };
-
- class select_folder : public internal::file_dialog
- {
- public:
- select_folder(std::string const& title,
- std::string const& default_path = "",
- opt options = opt::none);
-
- std::string result();
- };
-
- //
- // Below this are all the method implementations. You may choose to define the
- // macro PFD_SKIP_IMPLEMENTATION everywhere before including this header except
- // in one place. This may reduce compilation times.
- //
+ save_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool confirm_overwrite);
+
+ std::string result();
+};
+
+class select_folder : public internal::file_dialog {
+ public:
+ select_folder(std::string const& title, std::string const& default_path = "",
+ opt options = opt::none);
+
+ std::string result();
+};
+
+//
+// Below this are all the method implementations. You may choose to define the
+// macro PFD_SKIP_IMPLEMENTATION everywhere before including this header except
+// in one place. This may reduce compilation times.
+//
#if !defined PFD_SKIP_IMPLEMENTATION
- // internal free functions implementations
+// internal free functions implementations
- namespace internal
- {
+namespace internal {
#if _WIN32
- static inline std::wstring str2wstr(std::string const& str)
- {
- int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0);
- std::wstring ret(len, '\0');
- MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), (LPWSTR)ret.data(), (int)ret.size());
- return ret;
- }
-
- static inline std::string wstr2str(std::wstring const& str)
- {
- int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0, nullptr, nullptr);
- std::string ret(len, '\0');
- WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.size(), (LPSTR)ret.data(), (int)ret.size(), nullptr, nullptr);
- return ret;
- }
-
- static inline bool is_vista()
- {
- OSVERSIONINFOEXW osvi;
- memset(&osvi, 0, sizeof(osvi));
- DWORDLONG const mask = VerSetConditionMask(
- VerSetConditionMask(
- VerSetConditionMask(
- 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
- VER_MINORVERSION, VER_GREATER_EQUAL),
- VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
- osvi.dwOSVersionInfoSize = sizeof(osvi);
- osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
- osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
- osvi.wServicePackMajor = 0;
-
- return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, mask) != FALSE;
- }
+ static inline std::wstring str2wstr(std::string const& str) {
+ int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.size(), nullptr, 0);
+ std::wstring ret(len, '\0');
+ MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int) str.size(), (LPWSTR) ret.data(),
+ (int) ret.size());
+ return ret;
+ }
+
+ static inline std::string wstr2str(std::wstring const& str) {
+ int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int) str.size(), nullptr, 0, nullptr,
+ nullptr);
+ std::string ret(len, '\0');
+ WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int) str.size(), (LPSTR) ret.data(),
+ (int) ret.size(), nullptr, nullptr);
+ return ret;
+ }
+
+ static inline bool is_vista() {
+ OSVERSIONINFOEXW osvi;
+ memset(&osvi, 0, sizeof(osvi));
+ DWORDLONG const mask = VerSetConditionMask(
+ VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
+ VER_MINORVERSION, VER_GREATER_EQUAL),
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
+ osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
+ osvi.wServicePackMajor = 0;
+
+ return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
+ mask) != FALSE;
+ }
#endif
- // This is necessary until C++20 which will have std::string::ends_with() etc.
+ // This is necessary until C++20 which will have std::string::ends_with() etc.
- static inline bool ends_with(std::string const& str, std::string const& suffix)
- {
- return suffix.size() <= str.size() &&
- str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
- }
+ static inline bool ends_with(std::string const& str, std::string const& suffix) {
+ return suffix.size() <= str.size() &&
+ str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
+ }
- static inline bool starts_with(std::string const& str, std::string const& prefix)
- {
- return prefix.size() <= str.size() &&
- str.compare(0, prefix.size(), prefix) == 0;
- }
+ static inline bool starts_with(std::string const& str, std::string const& prefix) {
+ return prefix.size() <= str.size() && str.compare(0, prefix.size(), prefix) == 0;
+ }
- // This is necessary until C++17 which will have std::filesystem::is_directory
+ // This is necessary until C++17 which will have std::filesystem::is_directory
- static inline bool is_directory(std::string const& path)
- {
+ static inline bool is_directory(std::string const& path) {
#if _WIN32
- auto attr = GetFileAttributesA(path.c_str());
- return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
+ auto attr = GetFileAttributesA(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
#elif __EMSCRIPTEN__
- // TODO
- return false;
+ // TODO
+ return false;
#else
- struct stat s;
- return stat(path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
+ struct stat s;
+ return stat(path.c_str(), &s) == 0 && S_ISDIR(s.st_mode);
#endif
- }
+ }
- // This is necessary because getenv is not thread-safe
+ // This is necessary because getenv is not thread-safe
- static inline std::string getenv(std::string const& str)
- {
+ static inline std::string getenv(std::string const& str) {
#if _MSC_VER
- char* buf = nullptr;
- size_t size = 0;
- if (_dupenv_s(&buf, &size, str.c_str()) == 0 && buf)
- {
- std::string ret(buf);
- free(buf);
- return ret;
- }
- return "";
+ char* buf = nullptr;
+ size_t size = 0;
+ if (_dupenv_s(&buf, &size, str.c_str()) == 0 && buf) {
+ std::string ret(buf);
+ free(buf);
+ return ret;
+ }
+ return "";
#else
- auto buf = std::getenv(str.c_str());
- return buf ? buf : "";
+ auto buf = std::getenv(str.c_str());
+ return buf ? buf : "";
#endif
- }
+ }
- } // namespace internal
+} // namespace internal
- // settings implementation
+// settings implementation
- inline settings::settings(bool resync)
- {
- flags(flag::is_scanned) &= !resync;
+inline settings::settings(bool resync) {
+ flags(flag::is_scanned) &= !resync;
- if (flags(flag::is_scanned))
- return;
+ if (flags(flag::is_scanned)) return;
- auto pfd_verbose = internal::getenv("PFD_VERBOSE");
- auto match_no = std::regex("(|0|no|false)", std::regex_constants::icase);
- if (!std::regex_match(pfd_verbose, match_no))
- flags(flag::is_verbose) = true;
+ auto pfd_verbose = internal::getenv("PFD_VERBOSE");
+ auto match_no = std::regex("(|0|no|false)", std::regex_constants::icase);
+ if (!std::regex_match(pfd_verbose, match_no)) flags(flag::is_verbose) = true;
#if _WIN32
- flags(flag::is_vista) = internal::is_vista();
+ flags(flag::is_vista) = internal::is_vista();
#elif !__APPLE__
- flags(flag::has_zenity) = check_program("zenity");
- flags(flag::has_matedialog) = check_program("matedialog");
- flags(flag::has_qarma) = check_program("qarma");
- flags(flag::has_kdialog) = check_program("kdialog");
-
- // If multiple helpers are available, try to default to the best one
- if (flags(flag::has_zenity) && flags(flag::has_kdialog))
- {
- auto desktop_name = internal::getenv("XDG_SESSION_DESKTOP");
- if (desktop_name == std::string("gnome"))
- flags(flag::has_kdialog) = false;
- else if (desktop_name == std::string("KDE"))
- flags(flag::has_zenity) = false;
- }
+ flags(flag::has_zenity) = check_program("zenity");
+ flags(flag::has_matedialog) = check_program("matedialog");
+ flags(flag::has_qarma) = check_program("qarma");
+ flags(flag::has_kdialog) = check_program("kdialog");
+
+ // If multiple helpers are available, try to default to the best one
+ if (flags(flag::has_zenity) && flags(flag::has_kdialog)) {
+ auto desktop_name = internal::getenv("XDG_SESSION_DESKTOP");
+ if (desktop_name == std::string("gnome"))
+ flags(flag::has_kdialog) = false;
+ else if (desktop_name == std::string("KDE"))
+ flags(flag::has_zenity) = false;
+ }
#endif
- flags(flag::is_scanned) = true;
- }
+ flags(flag::is_scanned) = true;
+}
- inline bool settings::available()
- {
+inline bool settings::available() {
#if _WIN32
- return true;
+ return true;
#elif __APPLE__
- return true;
+ return true;
#elif __EMSCRIPTEN__
- // FIXME: Return true after implementation is complete.
- return false;
+ // FIXME: Return true after implementation is complete.
+ return false;
#else
- settings tmp;
- return tmp.flags(flag::has_zenity) ||
- tmp.flags(flag::has_matedialog) ||
- tmp.flags(flag::has_qarma) ||
- tmp.flags(flag::has_kdialog);
+ settings tmp;
+ return tmp.flags(flag::has_zenity) || tmp.flags(flag::has_matedialog) ||
+ tmp.flags(flag::has_qarma) || tmp.flags(flag::has_kdialog);
#endif
- }
+}
- inline void settings::verbose(bool value)
- {
- settings().flags(flag::is_verbose) = value;
- }
+inline void settings::verbose(bool value) {
+ settings().flags(flag::is_verbose) = value;
+}
- inline void settings::rescan()
- {
- settings(/* resync = */ true);
- }
+inline void settings::rescan() {
+ settings(/* resync = */ true);
+}
- // Check whether a program is present using “which”.
- inline bool settings::check_program(std::string const& program)
- {
+// Check whether a program is present using “which”.
+inline bool settings::check_program(std::string const& program) {
#if _WIN32
- (void)program;
- return false;
+ (void) program;
+ return false;
#elif __EMSCRIPTEN__
- (void)program;
- return false;
+ (void) program;
+ return false;
#else
- int exit_code = -1;
- internal::executor async;
- async.start_process({"/bin/sh", "-c", "which " + program});
- async.result(&exit_code);
- return exit_code == 0;
+ int exit_code = -1;
+ internal::executor async;
+ async.start_process({"/bin/sh", "-c", "which " + program});
+ async.result(&exit_code);
+ return exit_code == 0;
#endif
- }
+}
- inline bool settings::is_osascript() const
- {
+inline bool settings::is_osascript() const {
#if __APPLE__
- return true;
+ return true;
#else
- return false;
+ return false;
#endif
- }
-
- inline bool settings::is_zenity() const
- {
- return flags(flag::has_zenity) ||
- flags(flag::has_matedialog) ||
- flags(flag::has_qarma);
- }
-
- inline bool settings::is_kdialog() const
- {
- return flags(flag::has_kdialog);
- }
-
- inline bool const& settings::flags(flag in_flag) const
- {
- static bool flags[size_t(flag::max_flag)];
- return flags[size_t(in_flag)];
- }
-
- inline bool& settings::flags(flag in_flag)
- {
- return const_cast<bool&>(static_cast<settings const*>(this)->flags(in_flag));
- }
-
- // path implementation
- inline std::string path::home()
- {
+}
+
+inline bool settings::is_zenity() const {
+ return flags(flag::has_zenity) || flags(flag::has_matedialog) || flags(flag::has_qarma);
+}
+
+inline bool settings::is_kdialog() const {
+ return flags(flag::has_kdialog);
+}
+
+inline bool const& settings::flags(flag in_flag) const {
+ static bool flags[size_t(flag::max_flag)];
+ return flags[size_t(in_flag)];
+}
+
+inline bool& settings::flags(flag in_flag) {
+ return const_cast<bool&>(static_cast<settings const*>(this)->flags(in_flag));
+}
+
+// path implementation
+inline std::string path::home() {
#if _WIN32
- // First try the USERPROFILE environment variable
- auto user_profile = internal::getenv("USERPROFILE");
- if (user_profile.size() > 0)
- return user_profile;
- // Otherwise, try GetUserProfileDirectory()
- HANDLE token = nullptr;
- DWORD len = MAX_PATH;
- char buf[MAX_PATH] = {'\0'};
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
- {
- dll userenv("userenv.dll");
- dll::proc<BOOL WINAPI(HANDLE, LPSTR, LPDWORD)> get_user_profile_directory(userenv, "GetUserProfileDirectoryA");
- get_user_profile_directory(token, buf, &len);
- CloseHandle(token);
- if (*buf)
- return buf;
- }
+ // First try the USERPROFILE environment variable
+ auto user_profile = internal::getenv("USERPROFILE");
+ if (user_profile.size() > 0) return user_profile;
+ // Otherwise, try GetUserProfileDirectory()
+ HANDLE token = nullptr;
+ DWORD len = MAX_PATH;
+ char buf[MAX_PATH] = {'\0'};
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
+ dll userenv("userenv.dll");
+ dll::proc<BOOL WINAPI(HANDLE, LPSTR, LPDWORD)> get_user_profile_directory(
+ userenv, "GetUserProfileDirectoryA");
+ get_user_profile_directory(token, buf, &len);
+ CloseHandle(token);
+ if (*buf) return buf;
+ }
#elif __EMSCRIPTEN__
- return "/";
+ return "/";
#else
- // First try the HOME environment variable
- auto home = internal::getenv("HOME");
- if (home.size() > 0)
- return home;
- // Otherwise, try getpwuid_r()
- size_t len = 4096;
+ // First try the HOME environment variable
+ auto home = internal::getenv("HOME");
+ if (home.size() > 0) return home;
+ // Otherwise, try getpwuid_r()
+ size_t len = 4096;
#if defined(_SC_GETPW_R_SIZE_MAX)
- auto size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (size_max != -1)
- len = size_t(size_max);
+ auto size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (size_max != -1) len = size_t(size_max);
#endif
- std::vector<char> buf(len);
- struct passwd pwd, *result;
- if (getpwuid_r(getuid(), &pwd, buf.data(), buf.size(), &result) == 0)
- return result->pw_dir;
+ std::vector<char> buf(len);
+ struct passwd pwd, *result;
+ if (getpwuid_r(getuid(), &pwd, buf.data(), buf.size(), &result) == 0) return result->pw_dir;
#endif
- return "/";
- }
+ return "/";
+}
- inline std::string path::separator()
- {
+inline std::string path::separator() {
#if _WIN32
- return "\\";
+ return "\\";
#else
- return "/";
+ return "/";
#endif
- }
+}
- // executor implementation
+// executor implementation
- inline std::string internal::executor::result(int* exit_code /* = nullptr */)
- {
- stop();
- if (exit_code)
- *exit_code = m_exit_code;
- return m_stdout;
- }
+inline std::string internal::executor::result(int* exit_code /* = nullptr */) {
+ stop();
+ if (exit_code) *exit_code = m_exit_code;
+ return m_stdout;
+}
- inline bool internal::executor::kill()
- {
+inline bool internal::executor::kill() {
#if _WIN32
- if (m_future.valid())
- {
- // Close all windows that weren’t open when we started the future
- auto previous_windows = m_windows;
- EnumWindows(&enum_windows_callback, (LPARAM)this);
- for (auto hwnd : m_windows)
- if (previous_windows.find(hwnd) == previous_windows.end())
- {
- SendMessage(hwnd, WM_CLOSE, 0, 0);
- // Also send IDNO in case of a Yes/No or Abort/Retry/Ignore messagebox
- SendMessage(hwnd, WM_COMMAND, IDNO, 0);
- }
- }
+ if (m_future.valid()) {
+ // Close all windows that weren’t open when we started the future
+ auto previous_windows = m_windows;
+ EnumWindows(&enum_windows_callback, (LPARAM) this);
+ for (auto hwnd : m_windows)
+ if (previous_windows.find(hwnd) == previous_windows.end()) {
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ // Also send IDNO in case of a Yes/No or Abort/Retry/Ignore messagebox
+ SendMessage(hwnd, WM_COMMAND, IDNO, 0);
+ }
+ }
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
- return false; // cannot kill
+ // FIXME: do something
+ return false; // cannot kill
#else
- ::kill(m_pid, SIGKILL);
+ ::kill(m_pid, SIGKILL);
#endif
- stop();
- return true;
- }
+ stop();
+ return true;
+}
#if _WIN32
- inline BOOL CALLBACK internal::executor::enum_windows_callback(HWND hwnd, LPARAM lParam)
- {
- auto that = (executor*)lParam;
-
- DWORD pid;
- auto tid = GetWindowThreadProcessId(hwnd, &pid);
- if (tid == that->m_tid)
- that->m_windows.insert(hwnd);
- return TRUE;
- }
+inline BOOL CALLBACK internal::executor::enum_windows_callback(HWND hwnd, LPARAM lParam) {
+ auto that = (executor*) lParam;
+
+ DWORD pid;
+ auto tid = GetWindowThreadProcessId(hwnd, &pid);
+ if (tid == that->m_tid) that->m_windows.insert(hwnd);
+ return TRUE;
+}
#endif
#if _WIN32
- inline void internal::executor::start_func(std::function<std::string(int*)> const& fun)
- {
- stop();
-
- auto trampoline = [fun, this]() {
- // Save our thread id so that the caller can cancel us
- m_tid = GetCurrentThreadId();
- EnumWindows(&enum_windows_callback, (LPARAM)this);
- m_cond.notify_all();
- return fun(&m_exit_code);
- };
-
- std::unique_lock<std::mutex> lock(m_mutex);
- m_future = std::async(std::launch::async, trampoline);
- m_cond.wait(lock);
- m_running = true;
- }
+inline void internal::executor::start_func(std::function<std::string(int*)> const& fun) {
+ stop();
+
+ auto trampoline = [fun, this]() {
+ // Save our thread id so that the caller can cancel us
+ m_tid = GetCurrentThreadId();
+ EnumWindows(&enum_windows_callback, (LPARAM) this);
+ m_cond.notify_all();
+ return fun(&m_exit_code);
+ };
+
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_future = std::async(std::launch::async, trampoline);
+ m_cond.wait(lock);
+ m_running = true;
+}
#elif __EMSCRIPTEN__
- inline void internal::executor::start(int exit_code)
- {
- m_exit_code = exit_code;
- }
+inline void internal::executor::start(int exit_code) {
+ m_exit_code = exit_code;
+}
#else
- inline void internal::executor::start_process(std::vector<std::string> const& command)
- {
- stop();
- m_stdout.clear();
- m_exit_code = -1;
-
- int in[2], out[2];
- if (pipe(in) != 0 || pipe(out) != 0)
- return;
-
- m_pid = fork();
- if (m_pid < 0)
- return;
-
- close(in[m_pid ? 0 : 1]);
- close(out[m_pid ? 1 : 0]);
-
- if (m_pid == 0)
- {
- dup2(in[0], STDIN_FILENO);
- dup2(out[1], STDOUT_FILENO);
-
- // Ignore stderr so that it doesn’t pollute the console (e.g. GTK+ errors from zenity)
- int fd = open("/dev/null", O_WRONLY);
- dup2(fd, STDERR_FILENO);
- close(fd);
-
- std::vector<char*> args;
- std::transform(command.cbegin(), command.cend(), std::back_inserter(args),
- [](std::string const& s) { return const_cast<char*>(s.c_str()); });
- args.push_back(nullptr); // null-terminate argv[]
-
- execvp(args[0], args.data());
- exit(1);
- }
-
- close(in[1]);
- m_fd = out[0];
- auto flags = fcntl(m_fd, F_GETFL);
- fcntl(m_fd, F_SETFL, flags | O_NONBLOCK);
-
- m_running = true;
- }
+inline void internal::executor::start_process(std::vector<std::string> const& command) {
+ stop();
+ m_stdout.clear();
+ m_exit_code = -1;
+
+ int in[2], out[2];
+ if (pipe(in) != 0 || pipe(out) != 0) return;
+
+ m_pid = fork();
+ if (m_pid < 0) return;
+
+ close(in[m_pid ? 0 : 1]);
+ close(out[m_pid ? 1 : 0]);
+
+ if (m_pid == 0) {
+ dup2(in[0], STDIN_FILENO);
+ dup2(out[1], STDOUT_FILENO);
+
+ // Ignore stderr so that it doesn’t pollute the console (e.g. GTK+ errors from zenity)
+ int fd = open("/dev/null", O_WRONLY);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+
+ std::vector<char*> args;
+ std::transform(command.cbegin(), command.cend(), std::back_inserter(args),
+ [](std::string const& s) { return const_cast<char*>(s.c_str()); });
+ args.push_back(nullptr); // null-terminate argv[]
+
+ execvp(args[0], args.data());
+ exit(1);
+ }
+
+ close(in[1]);
+ m_fd = out[0];
+ auto flags = fcntl(m_fd, F_GETFL);
+ fcntl(m_fd, F_SETFL, flags | O_NONBLOCK);
+
+ m_running = true;
+}
#endif
- inline internal::executor::~executor()
- {
- stop();
- }
+inline internal::executor::~executor() {
+ stop();
+}
- inline bool internal::executor::ready(int timeout /* = default_wait_timeout */)
- {
- if (!m_running)
- return true;
+inline bool internal::executor::ready(int timeout /* = default_wait_timeout */) {
+ if (!m_running) return true;
#if _WIN32
- if (m_future.valid())
- {
- auto status = m_future.wait_for(std::chrono::milliseconds(timeout));
- if (status != std::future_status::ready)
- {
- // On Windows, we need to run the message pump. If the async
- // thread uses a Windows API dialog, it may be attached to the
- // main thread and waiting for messages that only we can dispatch.
- MSG msg;
- while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return false;
- }
-
- m_stdout = m_future.get();
- }
+ if (m_future.valid()) {
+ auto status = m_future.wait_for(std::chrono::milliseconds(timeout));
+ if (status != std::future_status::ready) {
+ // On Windows, we need to run the message pump. If the async
+ // thread uses a Windows API dialog, it may be attached to the
+ // main thread and waiting for messages that only we can dispatch.
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ return false;
+ }
+
+ m_stdout = m_future.get();
+ }
#elif __EMSCRIPTEN__ || __NX__
- // FIXME: do something
- (void)timeout;
+ // FIXME: do something
+ (void) timeout;
#else
- char buf[BUFSIZ];
- ssize_t received = read(m_fd, buf, BUFSIZ); // Flawfinder: ignore
- if (received > 0)
- {
- m_stdout += std::string(buf, received);
- return false;
- }
-
- // Reap child process if it is dead. It is possible that the system has already reaped it
- // (this happens when the calling application handles or ignores SIG_CHLD) and results in
- // waitpid() failing with ECHILD. Otherwise we assume the child is running and we sleep for
- // a little while.
- int status;
- pid_t child = waitpid(m_pid, &status, WNOHANG);
- if (child != m_pid && (child >= 0 || errno != ECHILD))
- {
- // FIXME: this happens almost always at first iteration
- std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
- return false;
- }
-
- close(m_fd);
- m_exit_code = WEXITSTATUS(status);
+ char buf[BUFSIZ];
+ ssize_t received = read(m_fd, buf, BUFSIZ); // Flawfinder: ignore
+ if (received > 0) {
+ m_stdout += std::string(buf, received);
+ return false;
+ }
+
+ // Reap child process if it is dead. It is possible that the system has already reaped it
+ // (this happens when the calling application handles or ignores SIG_CHLD) and results in
+ // waitpid() failing with ECHILD. Otherwise we assume the child is running and we sleep for
+ // a little while.
+ int status;
+ pid_t child = waitpid(m_pid, &status, WNOHANG);
+ if (child != m_pid && (child >= 0 || errno != ECHILD)) {
+ // FIXME: this happens almost always at first iteration
+ std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+ return false;
+ }
+
+ close(m_fd);
+ m_exit_code = WEXITSTATUS(status);
#endif
- m_running = false;
- return true;
- }
+ m_running = false;
+ return true;
+}
- inline void internal::executor::stop()
- {
- // Loop until the user closes the dialog
- while (!ready())
- ;
- }
+inline void internal::executor::stop() {
+ // Loop until the user closes the dialog
+ while (!ready());
+}
- // dll implementation
+// dll implementation
#if _WIN32
- inline internal::platform::dll::dll(std::string const& name)
- : handle(::LoadLibraryA(name.c_str()))
- {
- }
+inline internal::platform::dll::dll(std::string const& name)
+ : handle(::LoadLibraryA(name.c_str())) {}
- inline internal::platform::dll::~dll()
- {
- if (handle)
- ::FreeLibrary(handle);
- }
-#endif // _WIN32
+inline internal::platform::dll::~dll() {
+ if (handle) ::FreeLibrary(handle);
+}
+#endif // _WIN32
- // ole32_dll implementation
+// ole32_dll implementation
#if _WIN32
- inline internal::platform::ole32_dll::ole32_dll()
- : dll("ole32.dll")
- {
- // Use COINIT_MULTITHREADED because COINIT_APARTMENTTHREADED causes crashes.
- // See https://github.com/samhocevar/portable-file-dialogs/issues/51
- auto coinit = proc<HRESULT WINAPI(LPVOID, DWORD)>(*this, "CoInitializeEx");
- m_state = coinit(nullptr, COINIT_MULTITHREADED);
- }
-
- inline internal::platform::ole32_dll::~ole32_dll()
- {
- if (is_initialized())
- proc<void WINAPI()>(*this, "CoUninitialize")();
- }
-
- inline bool internal::platform::ole32_dll::is_initialized()
- {
- return m_state == S_OK || m_state == S_FALSE;
- }
+inline internal::platform::ole32_dll::ole32_dll() : dll("ole32.dll") {
+ // Use COINIT_MULTITHREADED because COINIT_APARTMENTTHREADED causes crashes.
+ // See https://github.com/samhocevar/portable-file-dialogs/issues/51
+ auto coinit = proc<HRESULT WINAPI(LPVOID, DWORD)>(*this, "CoInitializeEx");
+ m_state = coinit(nullptr, COINIT_MULTITHREADED);
+}
+
+inline internal::platform::ole32_dll::~ole32_dll() {
+ if (is_initialized()) proc<void WINAPI()>(*this, "CoUninitialize")();
+}
+
+inline bool internal::platform::ole32_dll::is_initialized() {
+ return m_state == S_OK || m_state == S_FALSE;
+}
#endif
- // new_style_context implementation
+// new_style_context implementation
#if _WIN32
- inline internal::platform::new_style_context::new_style_context()
- {
- // Only create one activation context for the whole app lifetime.
- static HANDLE hctx = create();
-
- if (hctx != INVALID_HANDLE_VALUE)
- ActivateActCtx(hctx, &m_cookie);
- }
-
- inline internal::platform::new_style_context::~new_style_context()
- {
- DeactivateActCtx(0, m_cookie);
- }
-
- inline HANDLE internal::platform::new_style_context::create()
- {
- // This “hack” seems to be necessary for this code to work on windows XP.
- // Without it, dialogs do not show and close immediately. GetError()
- // returns 0 so I don’t know what causes this. I was not able to reproduce
- // this behavior on Windows 7 and 10 but just in case, let it be here for
- // those versions too.
- // This hack is not required if other dialogs are used (they load comdlg32
- // automatically), only if message boxes are used.
- dll comdlg32("comdlg32.dll");
-
- // Using approach as shown here: https://stackoverflow.com/a/10444161
- UINT len = ::GetSystemDirectoryA(nullptr, 0);
- std::string sys_dir(len, '\0');
- ::GetSystemDirectoryA(&sys_dir[0], len);
-
- ACTCTXA act_ctx =
- {
- // Do not set flag ACTCTX_FLAG_SET_PROCESS_DEFAULT, since it causes a
- // crash with error “default context is already set”.
- sizeof(act_ctx),
- ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
- "shell32.dll",
- 0,
- 0,
- sys_dir.c_str(),
- (LPCSTR)124,
- nullptr,
- 0,
- };
-
- return ::CreateActCtxA(&act_ctx);
- }
-#endif // _WIN32
-
- // dialog implementation
-
- inline bool internal::dialog::ready(int timeout /* = default_wait_timeout */) const
- {
- return m_async->ready(timeout);
- }
-
- inline bool internal::dialog::kill() const
- {
- return m_async->kill();
- }
-
- inline internal::dialog::dialog()
- : m_async(std::make_shared<executor>())
- {
- }
-
- inline std::vector<std::string> internal::dialog::desktop_helper() const
- {
+inline internal::platform::new_style_context::new_style_context() {
+ // Only create one activation context for the whole app lifetime.
+ static HANDLE hctx = create();
+
+ if (hctx != INVALID_HANDLE_VALUE) ActivateActCtx(hctx, &m_cookie);
+}
+
+inline internal::platform::new_style_context::~new_style_context() {
+ DeactivateActCtx(0, m_cookie);
+}
+
+inline HANDLE internal::platform::new_style_context::create() {
+ // This “hack” seems to be necessary for this code to work on windows XP.
+ // Without it, dialogs do not show and close immediately. GetError()
+ // returns 0 so I don’t know what causes this. I was not able to reproduce
+ // this behavior on Windows 7 and 10 but just in case, let it be here for
+ // those versions too.
+ // This hack is not required if other dialogs are used (they load comdlg32
+ // automatically), only if message boxes are used.
+ dll comdlg32("comdlg32.dll");
+
+ // Using approach as shown here: https://stackoverflow.com/a/10444161
+ UINT len = ::GetSystemDirectoryA(nullptr, 0);
+ std::string sys_dir(len, '\0');
+ ::GetSystemDirectoryA(&sys_dir[0], len);
+
+ ACTCTXA act_ctx = {
+ // Do not set flag ACTCTX_FLAG_SET_PROCESS_DEFAULT, since it causes a
+ // crash with error “default context is already set”.
+ sizeof(act_ctx),
+ ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
+ "shell32.dll",
+ 0,
+ 0,
+ sys_dir.c_str(),
+ (LPCSTR) 124,
+ nullptr,
+ 0,
+ };
+
+ return ::CreateActCtxA(&act_ctx);
+}
+#endif // _WIN32
+
+// dialog implementation
+
+inline bool internal::dialog::ready(int timeout /* = default_wait_timeout */) const {
+ return m_async->ready(timeout);
+}
+
+inline bool internal::dialog::kill() const {
+ return m_async->kill();
+}
+
+inline internal::dialog::dialog() : m_async(std::make_shared<executor>()) {}
+
+inline std::vector<std::string> internal::dialog::desktop_helper() const {
#if __APPLE__
- return {"osascript"};
+ return {"osascript"};
#else
- return {flags(flag::has_zenity) ? "zenity"
- : flags(flag::has_matedialog) ? "matedialog"
- : flags(flag::has_qarma) ? "qarma"
- : flags(flag::has_kdialog) ? "kdialog"
- : "echo"};
+ return {flags(flag::has_zenity) ? "zenity"
+ : flags(flag::has_matedialog) ? "matedialog"
+ : flags(flag::has_qarma) ? "qarma"
+ : flags(flag::has_kdialog) ? "kdialog"
+ : "echo"};
#endif
- }
-
- inline std::string internal::dialog::buttons_to_name(choice _choice)
- {
- switch (_choice)
- {
- case choice::ok_cancel:
- return "okcancel";
- case choice::yes_no:
- return "yesno";
- case choice::yes_no_cancel:
- return "yesnocancel";
- case choice::retry_cancel:
- return "retrycancel";
- case choice::abort_retry_ignore:
- return "abortretryignore";
- /* case choice::ok: */ default:
- return "ok";
- }
- }
-
- inline std::string internal::dialog::get_icon_name(icon _icon)
- {
- switch (_icon)
- {
- case icon::warning:
- return "warning";
- case icon::error:
- return "error";
- case icon::question:
- return "question";
- // Zenity wants "information" but WinForms wants "info"
- /* case icon::info: */ default:
+}
+
+inline std::string internal::dialog::buttons_to_name(choice _choice) {
+ switch (_choice) {
+ case choice::ok_cancel:
+ return "okcancel";
+ case choice::yes_no:
+ return "yesno";
+ case choice::yes_no_cancel:
+ return "yesnocancel";
+ case choice::retry_cancel:
+ return "retrycancel";
+ case choice::abort_retry_ignore:
+ return "abortretryignore";
+ /* case choice::ok: */ default:
+ return "ok";
+ }
+}
+
+inline std::string internal::dialog::get_icon_name(icon _icon) {
+ switch (_icon) {
+ case icon::warning:
+ return "warning";
+ case icon::error:
+ return "error";
+ case icon::question:
+ return "question";
+ // Zenity wants "information" but WinForms wants "info"
+ /* case icon::info: */ default:
#if _WIN32
- return "info";
+ return "info";
#else
- return "information";
+ return "information";
#endif
- }
- }
-
- // This is only used for debugging purposes
- inline std::ostream& operator<<(std::ostream& s, std::vector<std::string> const& v)
- {
- int not_first = 0;
- for (auto& e : v)
- s << (not_first++ ? " " : "") << e;
- return s;
- }
-
- // Properly quote a string for Powershell: replace ' or " with '' or ""
- // FIXME: we should probably get rid of newlines!
- // FIXME: the \" sequence seems unsafe, too!
- // XXX: this is no longer used but I would like to keep it around just in case
- inline std::string internal::dialog::powershell_quote(std::string const& str) const
- {
- return "'" + std::regex_replace(str, std::regex("['\"]"), "$&$&") + "'";
- }
-
- // Properly quote a string for osascript: replace \ or " with \\ or \"
- // XXX: this also used to replace ' with \' when popen was used, but it would be
- // smarter to do shell_quote(osascript_quote(...)) if this is needed again.
- inline std::string internal::dialog::osascript_quote(std::string const& str) const
- {
- return "\"" + std::regex_replace(str, std::regex("[\\\\\"]"), "\\$&") + "\"";
- }
-
- // Properly quote a string for the shell: just replace ' with '\''
- // XXX: this is no longer used but I would like to keep it around just in case
- inline std::string internal::dialog::shell_quote(std::string const& str) const
- {
- return "'" + std::regex_replace(str, std::regex("'"), "'\\''") + "'";
- }
-
- // file_dialog implementation
-
- inline internal::file_dialog::file_dialog(type in_type,
- std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = {} */,
- opt options /* = opt::none */)
- {
+ }
+}
+
+// This is only used for debugging purposes
+inline std::ostream& operator<<(std::ostream& s, std::vector<std::string> const& v) {
+ int not_first = 0;
+ for (auto& e : v) s << (not_first++ ? " " : "") << e;
+ return s;
+}
+
+// Properly quote a string for Powershell: replace ' or " with '' or ""
+// FIXME: we should probably get rid of newlines!
+// FIXME: the \" sequence seems unsafe, too!
+// XXX: this is no longer used but I would like to keep it around just in case
+inline std::string internal::dialog::powershell_quote(std::string const& str) const {
+ return "'" + std::regex_replace(str, std::regex("['\"]"), "$&$&") + "'";
+}
+
+// Properly quote a string for osascript: replace \ or " with \\ or \"
+// XXX: this also used to replace ' with \' when popen was used, but it would be
+// smarter to do shell_quote(osascript_quote(...)) if this is needed again.
+inline std::string internal::dialog::osascript_quote(std::string const& str) const {
+ return "\"" + std::regex_replace(str, std::regex("[\\\\\"]"), "\\$&") + "\"";
+}
+
+// Properly quote a string for the shell: just replace ' with '\''
+// XXX: this is no longer used but I would like to keep it around just in case
+inline std::string internal::dialog::shell_quote(std::string const& str) const {
+ return "'" + std::regex_replace(str, std::regex("'"), "'\\''") + "'";
+}
+
+// file_dialog implementation
+
+inline internal::file_dialog::file_dialog(type in_type, std::string const& title,
+ std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = {} */,
+ opt options /* = opt::none */) {
#if _WIN32
- std::string filter_list;
- std::regex whitespace(" *");
- for (size_t i = 0; i + 1 < filters.size(); i += 2)
- {
- filter_list += filters[i] + '\0';
- filter_list += std::regex_replace(filters[i + 1], whitespace, ";") + '\0';
- }
- filter_list += '\0';
-
- m_async->start_func([this, in_type, title, default_path, filter_list,
- options](int* exit_code) -> std::string {
- (void)exit_code;
- m_wtitle = internal::str2wstr(title);
- m_wdefault_path = internal::str2wstr(default_path);
- auto wfilter_list = internal::str2wstr(filter_list);
-
- // Initialise COM. This is required for the new folder selection window,
- // (see https://github.com/samhocevar/portable-file-dialogs/pull/21)
- // and to avoid random crashes with GetOpenFileNameW() (see
- // https://github.com/samhocevar/portable-file-dialogs/issues/51)
- ole32_dll ole32;
-
- // Folder selection uses a different method
- if (in_type == type::folder)
- {
+ std::string filter_list;
+ std::regex whitespace(" *");
+ for (size_t i = 0; i + 1 < filters.size(); i += 2) {
+ filter_list += filters[i] + '\0';
+ filter_list += std::regex_replace(filters[i + 1], whitespace, ";") + '\0';
+ }
+ filter_list += '\0';
+
+ m_async->start_func(
+ [this, in_type, title, default_path, filter_list, options](int* exit_code) -> std::string {
+ (void) exit_code;
+ m_wtitle = internal::str2wstr(title);
+ m_wdefault_path = internal::str2wstr(default_path);
+ auto wfilter_list = internal::str2wstr(filter_list);
+
+ // Initialise COM. This is required for the new folder selection window,
+ // (see https://github.com/samhocevar/portable-file-dialogs/pull/21)
+ // and to avoid random crashes with GetOpenFileNameW() (see
+ // https://github.com/samhocevar/portable-file-dialogs/issues/51)
+ ole32_dll ole32;
+
+ // Folder selection uses a different method
+ if (in_type == type::folder) {
#if PFD_HAS_IFILEDIALOG
- if (flags(flag::is_vista))
- {
- // On Vista and higher we should be able to use IFileDialog for folder selection
- IFileDialog* ifd;
- HRESULT hr = dll::proc<HRESULT WINAPI(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>(ole32, "CoCreateInstance")(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ifd));
-
- // In case CoCreateInstance fails (which it should not), try legacy approach
- if (SUCCEEDED(hr))
- return select_folder_vista(ifd, options & opt::force_path);
- }
+ if (flags(flag::is_vista)) {
+ // On Vista and higher we should be able to use IFileDialog for folder selection
+ IFileDialog* ifd;
+ HRESULT hr = dll::proc<HRESULT WINAPI(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*)>(
+ ole32, "CoCreateInstance")(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&ifd));
+
+ // In case CoCreateInstance fails (which it should not), try legacy approach
+ if (SUCCEEDED(hr)) return select_folder_vista(ifd, options & opt::force_path);
+ }
#endif
- BROWSEINFOW bi;
- memset(&bi, 0, sizeof(bi));
-
- bi.lpfn = &bffcallback;
- bi.lParam = (LPARAM)this;
-
- if (flags(flag::is_vista))
- {
- if (ole32.is_initialized())
- bi.ulFlags |= BIF_NEWDIALOGSTYLE;
- bi.ulFlags |= BIF_EDITBOX;
- bi.ulFlags |= BIF_STATUSTEXT;
- }
-
- auto* list = SHBrowseForFolderW(&bi);
- std::string ret;
- if (list)
- {
- auto buffer = new wchar_t[MAX_PATH];
- SHGetPathFromIDListW(list, buffer);
- dll::proc<void WINAPI(LPVOID)>(ole32, "CoTaskMemFree")(list);
- ret = internal::wstr2str(buffer);
- delete[] buffer;
- }
- return ret;
- }
-
- OPENFILENAMEW ofn;
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAMEW);
- ofn.hwndOwner = GetActiveWindow();
-
- ofn.lpstrFilter = wfilter_list.c_str();
-
- auto woutput = std::wstring(MAX_PATH * 256, L'\0');
- ofn.lpstrFile = (LPWSTR)woutput.data();
- ofn.nMaxFile = (DWORD)woutput.size();
- if (!m_wdefault_path.empty())
- {
- // If a directory was provided, use it as the initial directory. If
- // a valid path was provided, use it as the initial file. Otherwise,
- // let the Windows API decide.
- auto path_attr = GetFileAttributesW(m_wdefault_path.c_str());
- if (path_attr != INVALID_FILE_ATTRIBUTES && (path_attr & FILE_ATTRIBUTE_DIRECTORY))
- ofn.lpstrInitialDir = m_wdefault_path.c_str();
- else if (m_wdefault_path.size() <= woutput.size())
- //second argument is size of buffer, not length of string
- StringCchCopyW(ofn.lpstrFile, MAX_PATH * 256 + 1, m_wdefault_path.c_str());
- else
- {
- ofn.lpstrFileTitle = (LPWSTR)m_wdefault_path.data();
- ofn.nMaxFileTitle = (DWORD)m_wdefault_path.size();
- }
- }
- ofn.lpstrTitle = m_wtitle.c_str();
- ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
-
- dll comdlg32("comdlg32.dll");
-
- // Apply new visual style (required for windows XP)
- new_style_context ctx;
-
- if (in_type == type::save)
- {
- if (!(options & opt::force_overwrite))
- ofn.Flags |= OFN_OVERWRITEPROMPT;
-
- dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_save_file_name(comdlg32, "GetSaveFileNameW");
- if (get_save_file_name(&ofn) == 0)
- return "";
- return internal::wstr2str(woutput.c_str());
- }
- else
- {
- if (options & opt::multiselect)
- ofn.Flags |= OFN_ALLOWMULTISELECT;
- ofn.Flags |= OFN_PATHMUSTEXIST;
-
- dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_open_file_name(comdlg32, "GetOpenFileNameW");
- if (get_open_file_name(&ofn) == 0)
- return "";
- }
-
- std::string prefix;
- for (wchar_t const* p = woutput.c_str(); *p;)
- {
- auto filename = internal::wstr2str(p);
- p += wcslen(p);
- // In multiselect mode, we advance p one wchar further and
- // check for another filename. If there is one and the
- // prefix is empty, it means we just read the prefix.
- if ((options & opt::multiselect) && *++p && prefix.empty())
- {
- prefix = filename + "/";
- continue;
- }
-
- m_vector_result.push_back(prefix + filename);
- }
-
- return "";
- });
+ BROWSEINFOW bi;
+ memset(&bi, 0, sizeof(bi));
+
+ bi.lpfn = &bffcallback;
+ bi.lParam = (LPARAM) this;
+
+ if (flags(flag::is_vista)) {
+ if (ole32.is_initialized()) bi.ulFlags |= BIF_NEWDIALOGSTYLE;
+ bi.ulFlags |= BIF_EDITBOX;
+ bi.ulFlags |= BIF_STATUSTEXT;
+ }
+
+ auto* list = SHBrowseForFolderW(&bi);
+ std::string ret;
+ if (list) {
+ auto buffer = new wchar_t[MAX_PATH];
+ SHGetPathFromIDListW(list, buffer);
+ dll::proc<void WINAPI(LPVOID)>(ole32, "CoTaskMemFree")(list);
+ ret = internal::wstr2str(buffer);
+ delete[] buffer;
+ }
+ return ret;
+ }
+
+ OPENFILENAMEW ofn;
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(OPENFILENAMEW);
+ ofn.hwndOwner = GetActiveWindow();
+
+ ofn.lpstrFilter = wfilter_list.c_str();
+
+ auto woutput = std::wstring(MAX_PATH * 256, L'\0');
+ ofn.lpstrFile = (LPWSTR) woutput.data();
+ ofn.nMaxFile = (DWORD) woutput.size();
+ if (!m_wdefault_path.empty()) {
+ // If a directory was provided, use it as the initial directory. If
+ // a valid path was provided, use it as the initial file. Otherwise,
+ // let the Windows API decide.
+ auto path_attr = GetFileAttributesW(m_wdefault_path.c_str());
+ if (path_attr != INVALID_FILE_ATTRIBUTES && (path_attr & FILE_ATTRIBUTE_DIRECTORY))
+ ofn.lpstrInitialDir = m_wdefault_path.c_str();
+ else if (m_wdefault_path.size() <= woutput.size())
+ // second argument is size of buffer, not length of string
+ StringCchCopyW(ofn.lpstrFile, MAX_PATH * 256 + 1, m_wdefault_path.c_str());
+ else {
+ ofn.lpstrFileTitle = (LPWSTR) m_wdefault_path.data();
+ ofn.nMaxFileTitle = (DWORD) m_wdefault_path.size();
+ }
+ }
+ ofn.lpstrTitle = m_wtitle.c_str();
+ ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
+
+ dll comdlg32("comdlg32.dll");
+
+ // Apply new visual style (required for windows XP)
+ new_style_context ctx;
+
+ if (in_type == type::save) {
+ if (!(options & opt::force_overwrite)) ofn.Flags |= OFN_OVERWRITEPROMPT;
+
+ dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_save_file_name(comdlg32, "GetSaveFileNameW");
+ if (get_save_file_name(&ofn) == 0) return "";
+ return internal::wstr2str(woutput.c_str());
+ } else {
+ if (options & opt::multiselect) ofn.Flags |= OFN_ALLOWMULTISELECT;
+ ofn.Flags |= OFN_PATHMUSTEXIST;
+
+ dll::proc<BOOL WINAPI(LPOPENFILENAMEW)> get_open_file_name(comdlg32, "GetOpenFileNameW");
+ if (get_open_file_name(&ofn) == 0) return "";
+ }
+
+ std::string prefix;
+ for (wchar_t const* p = woutput.c_str(); *p;) {
+ auto filename = internal::wstr2str(p);
+ p += wcslen(p);
+ // In multiselect mode, we advance p one wchar further and
+ // check for another filename. If there is one and the
+ // prefix is empty, it means we just read the prefix.
+ if ((options & opt::multiselect) && *++p && prefix.empty()) {
+ prefix = filename + "/";
+ continue;
+ }
+
+ m_vector_result.push_back(prefix + filename);
+ }
+
+ return "";
+ });
#elif __EMSCRIPTEN__
- // FIXME: do something
- (void)in_type;
- (void)title;
- (void)default_path;
- (void)filters;
- (void)options;
+ // FIXME: do something
+ (void) in_type;
+ (void) title;
+ (void) default_path;
+ (void) filters;
+ (void) options;
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- std::string script = "set ret to choose";
- switch (in_type)
- {
- case type::save:
- script += " file name";
- break;
- case type::open:
- default:
- script += " file";
- if (options & opt::multiselect)
- script += " with multiple selections allowed";
- break;
- case type::folder:
- script += " folder";
- break;
- }
-
- if (default_path.size())
- {
- if (in_type == type::folder || is_directory(default_path))
- script += " default location ";
- else
- script += " default name ";
- script += osascript_quote(default_path);
- }
-
- script += " with prompt " + osascript_quote(title);
-
- if (in_type == type::open)
- {
- // Concatenate all user-provided filter patterns
- std::string patterns;
- for (size_t i = 0; i < filters.size() / 2; ++i)
- patterns += " " + filters[2 * i + 1];
-
- // Split the pattern list to check whether "*" is in there; if it
- // is, we have to disable filters because there is no mechanism in
- // OS X for the user to override the filter.
- std::regex sep("\\s+");
- std::string filter_list;
- bool has_filter = true;
- std::sregex_token_iterator iter(patterns.begin(), patterns.end(), sep, -1);
- std::sregex_token_iterator end;
- for (; iter != end; ++iter)
- {
- auto pat = iter->str();
- if (pat == "*" || pat == "*.*")
- has_filter = false;
- else if (internal::starts_with(pat, "*."))
- filter_list += "," + osascript_quote(pat.substr(2, pat.size() - 2));
- }
-
- if (has_filter && filter_list.size() > 0)
- {
- // There is a weird AppleScript bug where file extensions of length != 3 are
- // ignored, e.g. type{"txt"} works, but type{"json"} does not. Fortunately if
- // the whole list starts with a 3-character extension, everything works again.
- // We use "///" for such an extension because we are sure it cannot appear in
- // an actual filename.
- script += " of type {\"///\"" + filter_list + "}";
- }
- }
-
- if (in_type == type::open && (options & opt::multiselect))
- {
- script += "\nset s to \"\"";
- script += "\nrepeat with i in ret";
- script += "\n set s to s & (POSIX path of i) & \"\\n\"";
- script += "\nend repeat";
- script += "\ncopy s to stdout";
- }
- else
- {
- script += "\nPOSIX path of ret";
- }
-
- command.push_back("-e");
- command.push_back(script);
- }
- else if (is_zenity())
- {
- command.push_back("--file-selection");
-
- // If the default path is a directory, make sure it ends with "/" otherwise zenity will
- // open the file dialog in the parent directory.
- auto filename_arg = "--filename=" + default_path;
- if (in_type != type::folder && !ends_with(default_path, "/") && internal::is_directory(default_path))
- filename_arg += "/";
- command.push_back(filename_arg);
-
- command.push_back("--title");
- command.push_back(title);
- command.push_back("--separator=\n");
-
- for (size_t i = 0; i < filters.size() / 2; ++i)
- {
- command.push_back("--file-filter");
- command.push_back(filters[2 * i] + "|" + filters[2 * i + 1]);
- }
-
- if (in_type == type::save)
- command.push_back("--save");
- if (in_type == type::folder)
- command.push_back("--directory");
- if (!(options & opt::force_overwrite))
- command.push_back("--confirm-overwrite");
- if (options & opt::multiselect)
- command.push_back("--multiple");
- }
- else if (is_kdialog())
- {
- switch (in_type)
- {
- case type::save:
- command.push_back("--getsavefilename");
- break;
- case type::open:
- command.push_back("--getopenfilename");
- break;
- case type::folder:
- command.push_back("--getexistingdirectory");
- break;
- }
- if (options & opt::multiselect)
- {
- command.push_back("--multiple");
- command.push_back("--separate-output");
- }
-
- command.push_back(default_path);
-
- std::string filter;
- for (size_t i = 0; i < filters.size() / 2; ++i)
- filter += (i == 0 ? "" : " | ") + filters[2 * i] + "(" + filters[2 * i + 1] + ")";
- command.push_back(filter);
-
- command.push_back("--title");
- command.push_back(title);
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ std::string script = "set ret to choose";
+ switch (in_type) {
+ case type::save:
+ script += " file name";
+ break;
+ case type::open:
+ default:
+ script += " file";
+ if (options & opt::multiselect) script += " with multiple selections allowed";
+ break;
+ case type::folder:
+ script += " folder";
+ break;
+ }
+
+ if (default_path.size()) {
+ if (in_type == type::folder || is_directory(default_path))
+ script += " default location ";
+ else
+ script += " default name ";
+ script += osascript_quote(default_path);
+ }
+
+ script += " with prompt " + osascript_quote(title);
+
+ if (in_type == type::open) {
+ // Concatenate all user-provided filter patterns
+ std::string patterns;
+ for (size_t i = 0; i < filters.size() / 2; ++i) patterns += " " + filters[2 * i + 1];
+
+ // Split the pattern list to check whether "*" is in there; if it
+ // is, we have to disable filters because there is no mechanism in
+ // OS X for the user to override the filter.
+ std::regex sep("\\s+");
+ std::string filter_list;
+ bool has_filter = true;
+ std::sregex_token_iterator iter(patterns.begin(), patterns.end(), sep, -1);
+ std::sregex_token_iterator end;
+ for (; iter != end; ++iter) {
+ auto pat = iter->str();
+ if (pat == "*" || pat == "*.*")
+ has_filter = false;
+ else if (internal::starts_with(pat, "*."))
+ filter_list += "," + osascript_quote(pat.substr(2, pat.size() - 2));
+ }
+
+ if (has_filter && filter_list.size() > 0) {
+ // There is a weird AppleScript bug where file extensions of length != 3 are
+ // ignored, e.g. type{"txt"} works, but type{"json"} does not. Fortunately if
+ // the whole list starts with a 3-character extension, everything works again.
+ // We use "///" for such an extension because we are sure it cannot appear in
+ // an actual filename.
+ script += " of type {\"///\"" + filter_list + "}";
+ }
+ }
+
+ if (in_type == type::open && (options & opt::multiselect)) {
+ script += "\nset s to \"\"";
+ script += "\nrepeat with i in ret";
+ script += "\n set s to s & (POSIX path of i) & \"\\n\"";
+ script += "\nend repeat";
+ script += "\ncopy s to stdout";
+ } else {
+ script += "\nPOSIX path of ret";
+ }
+
+ command.push_back("-e");
+ command.push_back(script);
+ } else if (is_zenity()) {
+ command.push_back("--file-selection");
+
+ // If the default path is a directory, make sure it ends with "/" otherwise zenity will
+ // open the file dialog in the parent directory.
+ auto filename_arg = "--filename=" + default_path;
+ if (in_type != type::folder && !ends_with(default_path, "/") &&
+ internal::is_directory(default_path))
+ filename_arg += "/";
+ command.push_back(filename_arg);
+
+ command.push_back("--title");
+ command.push_back(title);
+ command.push_back("--separator=\n");
+
+ for (size_t i = 0; i < filters.size() / 2; ++i) {
+ command.push_back("--file-filter");
+ command.push_back(filters[2 * i] + "|" + filters[2 * i + 1]);
+ }
+
+ if (in_type == type::save) command.push_back("--save");
+ if (in_type == type::folder) command.push_back("--directory");
+ if (!(options & opt::force_overwrite)) command.push_back("--confirm-overwrite");
+ if (options & opt::multiselect) command.push_back("--multiple");
+ } else if (is_kdialog()) {
+ switch (in_type) {
+ case type::save:
+ command.push_back("--getsavefilename");
+ break;
+ case type::open:
+ command.push_back("--getopenfilename");
+ break;
+ case type::folder:
+ command.push_back("--getexistingdirectory");
+ break;
+ }
+ if (options & opt::multiselect) {
+ command.push_back("--multiple");
+ command.push_back("--separate-output");
+ }
+
+ command.push_back(default_path);
+
+ std::string filter;
+ for (size_t i = 0; i < filters.size() / 2; ++i)
+ filter += (i == 0 ? "" : " | ") + filters[2 * i] + "(" + filters[2 * i + 1] + ")";
+ command.push_back(filter);
+
+ command.push_back("--title");
+ command.push_back(title);
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
+}
- inline std::string internal::file_dialog::string_result()
- {
+inline std::string internal::file_dialog::string_result() {
#if _WIN32
- return m_async->result();
+ return m_async->result();
#else
- auto ret = m_async->result();
- // Strip potential trailing newline (zenity). Also strip trailing slash
- // added by osascript for consistency with other backends.
- while (!ret.empty() && (ret.back() == '\n' || ret.back() == '/'))
- ret.pop_back();
- return ret;
+ auto ret = m_async->result();
+ // Strip potential trailing newline (zenity). Also strip trailing slash
+ // added by osascript for consistency with other backends.
+ while (!ret.empty() && (ret.back() == '\n' || ret.back() == '/')) ret.pop_back();
+ return ret;
#endif
- }
+}
- inline std::vector<std::string> internal::file_dialog::vector_result()
- {
+inline std::vector<std::string> internal::file_dialog::vector_result() {
#if _WIN32
- m_async->result();
- return m_vector_result;
+ m_async->result();
+ return m_vector_result;
#else
- std::vector<std::string> ret;
- auto result = m_async->result();
- for (;;)
- {
- // Split result along newline characters
- auto i = result.find('\n');
- if (i == 0 || i == std::string::npos)
- break;
- ret.push_back(result.substr(0, i));
- result = result.substr(i + 1, result.size());
- }
- return ret;
+ std::vector<std::string> ret;
+ auto result = m_async->result();
+ for (;;) {
+ // Split result along newline characters
+ auto i = result.find('\n');
+ if (i == 0 || i == std::string::npos) break;
+ ret.push_back(result.substr(0, i));
+ result = result.substr(i + 1, result.size());
+ }
+ return ret;
#endif
- }
+}
#if _WIN32
- // Use a static function to pass as BFFCALLBACK for legacy folder select
- inline int CALLBACK internal::file_dialog::bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData)
- {
- auto inst = (file_dialog*)pData;
- switch (uMsg)
- {
- case BFFM_INITIALIZED:
- SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM)inst->m_wdefault_path.c_str());
- break;
- }
- return 0;
- }
+// Use a static function to pass as BFFCALLBACK for legacy folder select
+inline int CALLBACK internal::file_dialog::bffcallback(HWND hwnd, UINT uMsg, LPARAM, LPARAM pData) {
+ auto inst = (file_dialog*) pData;
+ switch (uMsg) {
+ case BFFM_INITIALIZED:
+ SendMessage(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) inst->m_wdefault_path.c_str());
+ break;
+ }
+ return 0;
+}
#if PFD_HAS_IFILEDIALOG
- inline std::string internal::file_dialog::select_folder_vista(IFileDialog* ifd, bool force_path)
- {
- std::string result;
-
- IShellItem* folder;
-
- // Load library at runtime so app doesn't link it at load time (which will fail on windows XP)
- dll shell32("shell32.dll");
- dll::proc<HRESULT WINAPI(PCWSTR, IBindCtx*, REFIID, void**)>
- create_item(shell32, "SHCreateItemFromParsingName");
-
- if (!create_item)
- return "";
-
- auto hr = create_item(m_wdefault_path.c_str(),
- nullptr,
- IID_PPV_ARGS(&folder));
-
- // Set default folder if found. This only sets the default folder. If
- // Windows has any info about the most recently selected folder, it
- // will display it instead. Generally, calling SetFolder() to set the
- // current directory “is not a good or expected user experience and
- // should therefore be avoided”:
- // https://docs.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setfolder
- if (SUCCEEDED(hr))
- {
- if (force_path)
- ifd->SetFolder(folder);
- else
- ifd->SetDefaultFolder(folder);
- folder->Release();
- }
-
- // Set the dialog title and option to select folders
- ifd->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
- ifd->SetTitle(m_wtitle.c_str());
-
- hr = ifd->Show(GetActiveWindow());
- if (SUCCEEDED(hr))
- {
- IShellItem* item;
- hr = ifd->GetResult(&item);
- if (SUCCEEDED(hr))
- {
- wchar_t* wname = nullptr;
- // This is unlikely to fail because we use FOS_FORCEFILESYSTEM, but try
- // to output a debug message just in case.
- if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH, &wname)))
- {
- result = internal::wstr2str(std::wstring(wname));
- dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
- }
- else
- {
- if (SUCCEEDED(item->GetDisplayName(SIGDN_NORMALDISPLAY, &wname)))
- {
- auto name = internal::wstr2str(std::wstring(wname));
- dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
- std::cerr << "pfd: failed to get path for " << name << std::endl;
- }
- else
- std::cerr << "pfd: item of unknown type selected" << std::endl;
- }
-
- item->Release();
- }
- }
-
- ifd->Release();
-
- return result;
- }
+inline std::string internal::file_dialog::select_folder_vista(IFileDialog* ifd, bool force_path) {
+ std::string result;
+
+ IShellItem* folder;
+
+ // Load library at runtime so app doesn't link it at load time (which will fail on windows XP)
+ dll shell32("shell32.dll");
+ dll::proc<HRESULT WINAPI(PCWSTR, IBindCtx*, REFIID, void**)> create_item(
+ shell32, "SHCreateItemFromParsingName");
+
+ if (!create_item) return "";
+
+ auto hr = create_item(m_wdefault_path.c_str(), nullptr, IID_PPV_ARGS(&folder));
+
+ // Set default folder if found. This only sets the default folder. If
+ // Windows has any info about the most recently selected folder, it
+ // will display it instead. Generally, calling SetFolder() to set the
+ // current directory “is not a good or expected user experience and
+ // should therefore be avoided”:
+ // https://docs.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialog-setfolder
+ if (SUCCEEDED(hr)) {
+ if (force_path)
+ ifd->SetFolder(folder);
+ else
+ ifd->SetDefaultFolder(folder);
+ folder->Release();
+ }
+
+ // Set the dialog title and option to select folders
+ ifd->SetOptions(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM);
+ ifd->SetTitle(m_wtitle.c_str());
+
+ hr = ifd->Show(GetActiveWindow());
+ if (SUCCEEDED(hr)) {
+ IShellItem* item;
+ hr = ifd->GetResult(&item);
+ if (SUCCEEDED(hr)) {
+ wchar_t* wname = nullptr;
+ // This is unlikely to fail because we use FOS_FORCEFILESYSTEM, but try
+ // to output a debug message just in case.
+ if (SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH, &wname))) {
+ result = internal::wstr2str(std::wstring(wname));
+ dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
+ } else {
+ if (SUCCEEDED(item->GetDisplayName(SIGDN_NORMALDISPLAY, &wname))) {
+ auto name = internal::wstr2str(std::wstring(wname));
+ dll::proc<void WINAPI(LPVOID)>(ole32_dll(), "CoTaskMemFree")(wname);
+ std::cerr << "pfd: failed to get path for " << name << std::endl;
+ } else
+ std::cerr << "pfd: item of unknown type selected" << std::endl;
+ }
+
+ item->Release();
+ }
+ }
+
+ ifd->Release();
+
+ return result;
+}
#endif
#endif
- // notify implementation
+// notify implementation
- inline notify::notify(std::string const& title,
- std::string const& message,
- icon _icon /* = icon::info */)
- {
- if (_icon == icon::question) // Not supported by notifications
- _icon = icon::info;
+inline notify::notify(std::string const& title, std::string const& message,
+ icon _icon /* = icon::info */) {
+ if (_icon == icon::question) // Not supported by notifications
+ _icon = icon::info;
#if _WIN32
- // Use a static shared pointer for notify_icon so that we can delete
- // it whenever we need to display a new one, and we can also wait
- // until the program has finished running.
- struct notify_icon_data : public NOTIFYICONDATAW
- {
- ~notify_icon_data()
- {
- Shell_NotifyIconW(NIM_DELETE, this);
- }
- };
-
- static std::shared_ptr<notify_icon_data> nid;
-
- // Release the previous notification icon, if any, and allocate a new
- // one. Note that std::make_shared() does value initialization, so there
- // is no need to memset the structure.
- nid = nullptr;
- nid = std::make_shared<notify_icon_data>();
-
- // For XP support
- nid->cbSize = NOTIFYICONDATAW_V2_SIZE;
- nid->hWnd = nullptr;
- nid->uID = 0;
-
- // Flag Description:
- // - NIF_ICON The hIcon member is valid.
- // - NIF_MESSAGE The uCallbackMessage member is valid.
- // - NIF_TIP The szTip member is valid.
- // - NIF_STATE The dwState and dwStateMask members are valid.
- // - NIF_INFO Use a balloon ToolTip instead of a standard ToolTip. The szInfo, uTimeout, szInfoTitle, and dwInfoFlags members are valid.
- // - NIF_GUID Reserved.
- nid->uFlags = NIF_MESSAGE | NIF_ICON | NIF_INFO;
-
- // Flag Description
- // - NIIF_ERROR An error icon.
- // - NIIF_INFO An information icon.
- // - NIIF_NONE No icon.
- // - NIIF_WARNING A warning icon.
- // - NIIF_ICON_MASK Version 6.0. Reserved.
- // - NIIF_NOSOUND Version 6.0. Do not play the associated sound. Applies only to balloon ToolTips
- switch (_icon)
- {
- case icon::warning:
- nid->dwInfoFlags = NIIF_WARNING;
- break;
- case icon::error:
- nid->dwInfoFlags = NIIF_ERROR;
- break;
- /* case icon::info: */ default:
- nid->dwInfoFlags = NIIF_INFO;
- break;
- }
-
- ENUMRESNAMEPROC icon_enum_callback = [](HMODULE, LPCTSTR, LPTSTR lpName, LONG_PTR lParam) -> BOOL {
- ((NOTIFYICONDATAW*)lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
- return false;
- };
-
- nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
- ::EnumResourceNames(nullptr, RT_GROUP_ICON, icon_enum_callback, (LONG_PTR)nid.get());
-
- nid->uTimeout = 5000;
-
- StringCchCopyW(nid->szInfoTitle, ARRAYSIZE(nid->szInfoTitle), internal::str2wstr(title).c_str());
- StringCchCopyW(nid->szInfo, ARRAYSIZE(nid->szInfo), internal::str2wstr(message).c_str());
-
- // Display the new icon
- Shell_NotifyIconW(NIM_ADD, nid.get());
+ // Use a static shared pointer for notify_icon so that we can delete
+ // it whenever we need to display a new one, and we can also wait
+ // until the program has finished running.
+ struct notify_icon_data : public NOTIFYICONDATAW {
+ ~notify_icon_data() { Shell_NotifyIconW(NIM_DELETE, this); }
+ };
+
+ static std::shared_ptr<notify_icon_data> nid;
+
+ // Release the previous notification icon, if any, and allocate a new
+ // one. Note that std::make_shared() does value initialization, so there
+ // is no need to memset the structure.
+ nid = nullptr;
+ nid = std::make_shared<notify_icon_data>();
+
+ // For XP support
+ nid->cbSize = NOTIFYICONDATAW_V2_SIZE;
+ nid->hWnd = nullptr;
+ nid->uID = 0;
+
+ // Flag Description:
+ // - NIF_ICON The hIcon member is valid.
+ // - NIF_MESSAGE The uCallbackMessage member is valid.
+ // - NIF_TIP The szTip member is valid.
+ // - NIF_STATE The dwState and dwStateMask members are valid.
+ // - NIF_INFO Use a balloon ToolTip instead of a standard ToolTip. The szInfo, uTimeout,
+ // szInfoTitle, and dwInfoFlags members are valid.
+ // - NIF_GUID Reserved.
+ nid->uFlags = NIF_MESSAGE | NIF_ICON | NIF_INFO;
+
+ // Flag Description
+ // - NIIF_ERROR An error icon.
+ // - NIIF_INFO An information icon.
+ // - NIIF_NONE No icon.
+ // - NIIF_WARNING A warning icon.
+ // - NIIF_ICON_MASK Version 6.0. Reserved.
+ // - NIIF_NOSOUND Version 6.0. Do not play the associated sound. Applies only to balloon
+ // ToolTips
+ switch (_icon) {
+ case icon::warning:
+ nid->dwInfoFlags = NIIF_WARNING;
+ break;
+ case icon::error:
+ nid->dwInfoFlags = NIIF_ERROR;
+ break;
+ /* case icon::info: */ default:
+ nid->dwInfoFlags = NIIF_INFO;
+ break;
+ }
+
+ ENUMRESNAMEPROC icon_enum_callback = [](HMODULE, LPCTSTR, LPTSTR lpName,
+ LONG_PTR lParam) -> BOOL {
+ ((NOTIFYICONDATAW*) lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
+ return false;
+ };
+
+ nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
+ ::EnumResourceNames(nullptr, RT_GROUP_ICON, icon_enum_callback, (LONG_PTR) nid.get());
+
+ nid->uTimeout = 5000;
+
+ StringCchCopyW(nid->szInfoTitle, ARRAYSIZE(nid->szInfoTitle), internal::str2wstr(title).c_str());
+ StringCchCopyW(nid->szInfo, ARRAYSIZE(nid->szInfo), internal::str2wstr(message).c_str());
+
+ // Display the new icon
+ Shell_NotifyIconW(NIM_ADD, nid.get());
#elif __EMSCRIPTEN__
- // FIXME: do something
- (void)title;
- (void)message;
+ // FIXME: do something
+ (void) title;
+ (void) message;
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- command.push_back("-e");
- command.push_back("display notification " + osascript_quote(message) +
- " with title " + osascript_quote(title));
- }
- else if (is_zenity())
- {
- command.push_back("--notification");
- command.push_back("--window-icon");
- command.push_back(get_icon_name(_icon));
- command.push_back("--text");
- command.push_back(title + "\n" + message);
- }
- else if (is_kdialog())
- {
- command.push_back("--icon");
- command.push_back(get_icon_name(_icon));
- command.push_back("--title");
- command.push_back(title);
- command.push_back("--passivepopup");
- command.push_back(message);
- command.push_back("5");
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ command.push_back("-e");
+ command.push_back("display notification " + osascript_quote(message) + " with title " +
+ osascript_quote(title));
+ } else if (is_zenity()) {
+ command.push_back("--notification");
+ command.push_back("--window-icon");
+ command.push_back(get_icon_name(_icon));
+ command.push_back("--text");
+ command.push_back(title + "\n" + message);
+ } else if (is_kdialog()) {
+ command.push_back("--icon");
+ command.push_back(get_icon_name(_icon));
+ command.push_back("--title");
+ command.push_back(title);
+ command.push_back("--passivepopup");
+ command.push_back(message);
+ command.push_back("5");
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
+}
- // message implementation
+// message implementation
- inline message::message(std::string const& title,
- std::string const& text,
- choice _choice /* = choice::ok_cancel */,
- icon _icon /* = icon::info */)
- {
+inline message::message(std::string const& title, std::string const& text,
+ choice _choice /* = choice::ok_cancel */, icon _icon /* = icon::info */) {
#if _WIN32
- // Use MB_SYSTEMMODAL rather than MB_TOPMOST to ensure the message window is brought
- // to front. See https://github.com/samhocevar/portable-file-dialogs/issues/52
- UINT style = MB_SYSTEMMODAL;
- switch (_icon)
- {
- case icon::warning:
- style |= MB_ICONWARNING;
- break;
- case icon::error:
- style |= MB_ICONERROR;
- break;
- case icon::question:
- style |= MB_ICONQUESTION;
- break;
- /* case icon::info: */ default:
- style |= MB_ICONINFORMATION;
- break;
- }
-
- switch (_choice)
- {
- case choice::ok_cancel:
- style |= MB_OKCANCEL;
- break;
- case choice::yes_no:
- style |= MB_YESNO;
- break;
- case choice::yes_no_cancel:
- style |= MB_YESNOCANCEL;
- break;
- case choice::retry_cancel:
- style |= MB_RETRYCANCEL;
- break;
- case choice::abort_retry_ignore:
- style |= MB_ABORTRETRYIGNORE;
- break;
- /* case choice::ok: */ default:
- style |= MB_OK;
- break;
- }
-
- m_mappings[IDCANCEL] = button::cancel;
- m_mappings[IDOK] = button::ok;
- m_mappings[IDYES] = button::yes;
- m_mappings[IDNO] = button::no;
- m_mappings[IDABORT] = button::abort;
- m_mappings[IDRETRY] = button::retry;
- m_mappings[IDIGNORE] = button::ignore;
-
- m_async->start_func([text, title, style](int* exit_code) -> std::string {
- auto wtext = internal::str2wstr(text);
- auto wtitle = internal::str2wstr(title);
- // Apply new visual style (required for all Windows versions)
- new_style_context ctx;
- *exit_code = MessageBoxW(GetActiveWindow(), wtext.c_str(), wtitle.c_str(), style);
- return "";
- });
+ // Use MB_SYSTEMMODAL rather than MB_TOPMOST to ensure the message window is brought
+ // to front. See https://github.com/samhocevar/portable-file-dialogs/issues/52
+ UINT style = MB_SYSTEMMODAL;
+ switch (_icon) {
+ case icon::warning:
+ style |= MB_ICONWARNING;
+ break;
+ case icon::error:
+ style |= MB_ICONERROR;
+ break;
+ case icon::question:
+ style |= MB_ICONQUESTION;
+ break;
+ /* case icon::info: */ default:
+ style |= MB_ICONINFORMATION;
+ break;
+ }
+
+ switch (_choice) {
+ case choice::ok_cancel:
+ style |= MB_OKCANCEL;
+ break;
+ case choice::yes_no:
+ style |= MB_YESNO;
+ break;
+ case choice::yes_no_cancel:
+ style |= MB_YESNOCANCEL;
+ break;
+ case choice::retry_cancel:
+ style |= MB_RETRYCANCEL;
+ break;
+ case choice::abort_retry_ignore:
+ style |= MB_ABORTRETRYIGNORE;
+ break;
+ /* case choice::ok: */ default:
+ style |= MB_OK;
+ break;
+ }
+
+ m_mappings[IDCANCEL] = button::cancel;
+ m_mappings[IDOK] = button::ok;
+ m_mappings[IDYES] = button::yes;
+ m_mappings[IDNO] = button::no;
+ m_mappings[IDABORT] = button::abort;
+ m_mappings[IDRETRY] = button::retry;
+ m_mappings[IDIGNORE] = button::ignore;
+
+ m_async->start_func([text, title, style](int* exit_code) -> std::string {
+ auto wtext = internal::str2wstr(text);
+ auto wtitle = internal::str2wstr(title);
+ // Apply new visual style (required for all Windows versions)
+ new_style_context ctx;
+ *exit_code = MessageBoxW(GetActiveWindow(), wtext.c_str(), wtitle.c_str(), style);
+ return "";
+ });
#elif __EMSCRIPTEN__
- std::string full_message;
- switch (_icon)
- {
- case icon::warning:
- full_message = "⚠️";
- break;
- case icon::error:
- full_message = "⛔";
- break;
- case icon::question:
- full_message = "❓";
- break;
- /* case icon::info: */ default:
- full_message = "ℹ";
- break;
- }
-
- full_message += ' ' + title + "\n\n" + text;
-
- // This does not really start an async task; it just passes the
- // EM_ASM_INT return value to a fake start() function.
- m_async->start(EM_ASM_INT(
- {
- if ($1)
- return window.confirm(UTF8ToString($0)) ? 0 : -1;
- alert(UTF8ToString($0));
- return 0;
- },
- full_message.c_str(), _choice == choice::ok_cancel));
+ std::string full_message;
+ switch (_icon) {
+ case icon::warning:
+ full_message = "⚠️";
+ break;
+ case icon::error:
+ full_message = "⛔";
+ break;
+ case icon::question:
+ full_message = "❓";
+ break;
+ /* case icon::info: */ default:
+ full_message = "ℹ";
+ break;
+ }
+
+ full_message += ' ' + title + "\n\n" + text;
+
+ // This does not really start an async task; it just passes the
+ // EM_ASM_INT return value to a fake start() function.
+ m_async->start(EM_ASM_INT(
+ {
+ if ($1) return window.confirm(UTF8ToString($0)) ? 0 : -1;
+ alert(UTF8ToString($0));
+ return 0;
+ },
+ full_message.c_str(), _choice == choice::ok_cancel));
#else
- auto command = desktop_helper();
-
- if (is_osascript())
- {
- std::string script = "display dialog " + osascript_quote(text) +
- " with title " + osascript_quote(title);
- auto if_cancel = button::cancel;
- switch (_choice)
- {
- case choice::ok_cancel:
- script += "buttons {\"OK\", \"Cancel\"}"
- " default button \"OK\""
- " cancel button \"Cancel\"";
- break;
- case choice::yes_no:
- script += "buttons {\"Yes\", \"No\"}"
- " default button \"Yes\""
- " cancel button \"No\"";
- if_cancel = button::no;
- break;
- case choice::yes_no_cancel:
- script += "buttons {\"Yes\", \"No\", \"Cancel\"}"
- " default button \"Yes\""
- " cancel button \"Cancel\"";
- break;
- case choice::retry_cancel:
- script += "buttons {\"Retry\", \"Cancel\"}"
- " default button \"Retry\""
- " cancel button \"Cancel\"";
- break;
- case choice::abort_retry_ignore:
- script += "buttons {\"Abort\", \"Retry\", \"Ignore\"}"
- " default button \"Abort\""
- " cancel button \"Retry\"";
- if_cancel = button::retry;
- break;
- case choice::ok:
- default:
- script += "buttons {\"OK\"}"
- " default button \"OK\""
- " cancel button \"OK\"";
- if_cancel = button::ok;
- break;
- }
- m_mappings[1] = if_cancel;
- m_mappings[256] = if_cancel; // XXX: I think this was never correct
- script += " with icon ";
- switch (_icon)
- {
-#define PFD_OSX_ICON(n) "alias ((path to library folder from system domain) as text " \
- "& \"CoreServices:CoreTypes.bundle:Contents:Resources:" n ".icns\")"
- case icon::info:
- default:
- script += PFD_OSX_ICON("ToolBarInfo");
- break;
- case icon::warning:
- script += "caution";
- break;
- case icon::error:
- script += "stop";
- break;
- case icon::question:
- script += PFD_OSX_ICON("GenericQuestionMarkIcon");
- break;
+ auto command = desktop_helper();
+
+ if (is_osascript()) {
+ std::string script =
+ "display dialog " + osascript_quote(text) + " with title " + osascript_quote(title);
+ auto if_cancel = button::cancel;
+ switch (_choice) {
+ case choice::ok_cancel:
+ script +=
+ "buttons {\"OK\", \"Cancel\"}"
+ " default button \"OK\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::yes_no:
+ script +=
+ "buttons {\"Yes\", \"No\"}"
+ " default button \"Yes\""
+ " cancel button \"No\"";
+ if_cancel = button::no;
+ break;
+ case choice::yes_no_cancel:
+ script +=
+ "buttons {\"Yes\", \"No\", \"Cancel\"}"
+ " default button \"Yes\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::retry_cancel:
+ script +=
+ "buttons {\"Retry\", \"Cancel\"}"
+ " default button \"Retry\""
+ " cancel button \"Cancel\"";
+ break;
+ case choice::abort_retry_ignore:
+ script +=
+ "buttons {\"Abort\", \"Retry\", \"Ignore\"}"
+ " default button \"Abort\""
+ " cancel button \"Retry\"";
+ if_cancel = button::retry;
+ break;
+ case choice::ok:
+ default:
+ script +=
+ "buttons {\"OK\"}"
+ " default button \"OK\""
+ " cancel button \"OK\"";
+ if_cancel = button::ok;
+ break;
+ }
+ m_mappings[1] = if_cancel;
+ m_mappings[256] = if_cancel; // XXX: I think this was never correct
+ script += " with icon ";
+ switch (_icon) {
+#define PFD_OSX_ICON(n) \
+ "alias ((path to library folder from system domain) as text " \
+ "& \"CoreServices:CoreTypes.bundle:Contents:Resources:" n ".icns\")"
+ case icon::info:
+ default:
+ script += PFD_OSX_ICON("ToolBarInfo");
+ break;
+ case icon::warning:
+ script += "caution";
+ break;
+ case icon::error:
+ script += "stop";
+ break;
+ case icon::question:
+ script += PFD_OSX_ICON("GenericQuestionMarkIcon");
+ break;
#undef PFD_OSX_ICON
- }
-
- command.push_back("-e");
- command.push_back(script);
- }
- else if (is_zenity())
- {
- switch (_choice)
- {
- case choice::ok_cancel:
- command.insert(command.end(), {"--question", "--cancel-label=Cancel", "--ok-label=OK"});
- break;
- case choice::yes_no:
- // Do not use standard --question because it causes “No” to return -1,
- // which is inconsistent with the “Yes/No/Cancel” mode below.
- command.insert(command.end(), {"--question", "--switch", "--extra-button=No", "--extra-button=Yes"});
- break;
- case choice::yes_no_cancel:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel", "--extra-button=No", "--extra-button=Yes"});
- break;
- case choice::retry_cancel:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel", "--extra-button=Retry"});
- break;
- case choice::abort_retry_ignore:
- command.insert(command.end(), {"--question", "--switch", "--extra-button=Ignore", "--extra-button=Abort", "--extra-button=Retry"});
- break;
- case choice::ok:
- default:
- switch (_icon)
- {
- case icon::error:
- command.push_back("--error");
- break;
- case icon::warning:
- command.push_back("--warning");
- break;
- default:
- command.push_back("--info");
- break;
- }
- }
-
- command.insert(command.end(), {"--title", title,
- "--width=300", "--height=0", // sensible defaults
- "--no-markup", // do not interpret text as Pango markup
- "--text", text,
- "--icon-name=dialog-" + get_icon_name(_icon)});
- }
- else if (is_kdialog())
- {
- if (_choice == choice::ok)
- {
- switch (_icon)
- {
- case icon::error:
- command.push_back("--error");
- break;
- case icon::warning:
- command.push_back("--sorry");
- break;
- default:
- command.push_back("--msgbox");
- break;
- }
- }
- else
- {
- std::string flag = "--";
- if (_icon == icon::warning || _icon == icon::error)
- flag += "warning";
- flag += "yesno";
- if (_choice == choice::yes_no_cancel)
- flag += "cancel";
- command.push_back(flag);
- if (_choice == choice::yes_no || _choice == choice::yes_no_cancel)
- {
- m_mappings[0] = button::yes;
- m_mappings[256] = button::no;
- }
- }
-
- command.push_back(text);
- command.push_back("--title");
- command.push_back(title);
-
- // Must be after the above part
- if (_choice == choice::ok_cancel)
- command.insert(command.end(), {"--yes-label", "OK", "--no-label", "Cancel"});
- }
-
- if (flags(flag::is_verbose))
- std::cerr << "pfd: " << command << std::endl;
-
- m_async->start_process(command);
+ }
+
+ command.push_back("-e");
+ command.push_back(script);
+ } else if (is_zenity()) {
+ switch (_choice) {
+ case choice::ok_cancel:
+ command.insert(command.end(), {"--question", "--cancel-label=Cancel", "--ok-label=OK"});
+ break;
+ case choice::yes_no:
+ // Do not use standard --question because it causes “No” to return -1,
+ // which is inconsistent with the “Yes/No/Cancel” mode below.
+ command.insert(command.end(),
+ {"--question", "--switch", "--extra-button=No", "--extra-button=Yes"});
+ break;
+ case choice::yes_no_cancel:
+ command.insert(command.end(), {"--question", "--switch", "--extra-button=Cancel",
+ "--extra-button=No", "--extra-button=Yes"});
+ break;
+ case choice::retry_cancel:
+ command.insert(command.end(),
+ {"--question", "--switch", "--extra-button=Cancel", "--extra-button=Retry"});
+ break;
+ case choice::abort_retry_ignore:
+ command.insert(command.end(), {"--question", "--switch", "--extra-button=Ignore",
+ "--extra-button=Abort", "--extra-button=Retry"});
+ break;
+ case choice::ok:
+ default:
+ switch (_icon) {
+ case icon::error:
+ command.push_back("--error");
+ break;
+ case icon::warning:
+ command.push_back("--warning");
+ break;
+ default:
+ command.push_back("--info");
+ break;
+ }
+ }
+
+ command.insert(command.end(),
+ {"--title", title, "--width=300", "--height=0", // sensible defaults
+ "--no-markup", // do not interpret text as Pango markup
+ "--text", text, "--icon-name=dialog-" + get_icon_name(_icon)});
+ } else if (is_kdialog()) {
+ if (_choice == choice::ok) {
+ switch (_icon) {
+ case icon::error:
+ command.push_back("--error");
+ break;
+ case icon::warning:
+ command.push_back("--sorry");
+ break;
+ default:
+ command.push_back("--msgbox");
+ break;
+ }
+ } else {
+ std::string flag = "--";
+ if (_icon == icon::warning || _icon == icon::error) flag += "warning";
+ flag += "yesno";
+ if (_choice == choice::yes_no_cancel) flag += "cancel";
+ command.push_back(flag);
+ if (_choice == choice::yes_no || _choice == choice::yes_no_cancel) {
+ m_mappings[0] = button::yes;
+ m_mappings[256] = button::no;
+ }
+ }
+
+ command.push_back(text);
+ command.push_back("--title");
+ command.push_back(title);
+
+ // Must be after the above part
+ if (_choice == choice::ok_cancel)
+ command.insert(command.end(), {"--yes-label", "OK", "--no-label", "Cancel"});
+ }
+
+ if (flags(flag::is_verbose)) std::cerr << "pfd: " << command << std::endl;
+
+ m_async->start_process(command);
#endif
- }
-
- inline button message::result()
- {
- int exit_code;
- auto ret = m_async->result(&exit_code);
- // osascript will say "button returned:Cancel\n"
- // and others will just say "Cancel\n"
- if (internal::ends_with(ret, "Cancel\n"))
- return button::cancel;
- if (internal::ends_with(ret, "OK\n"))
- return button::ok;
- if (internal::ends_with(ret, "Yes\n"))
- return button::yes;
- if (internal::ends_with(ret, "No\n"))
- return button::no;
- if (internal::ends_with(ret, "Abort\n"))
- return button::abort;
- if (internal::ends_with(ret, "Retry\n"))
- return button::retry;
- if (internal::ends_with(ret, "Ignore\n"))
- return button::ignore;
- if (m_mappings.count(exit_code) != 0)
- return m_mappings[exit_code];
- return exit_code == 0 ? button::ok : button::cancel;
- }
-
- // open_file implementation
-
- inline open_file::open_file(std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = { "All Files", "*" } */,
- opt options /* = opt::none */)
- : file_dialog(type::open, title, default_path, filters, options)
- {
- }
-
- inline open_file::open_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool allow_multiselect)
- : open_file(title, default_path, filters, (allow_multiselect ? opt::multiselect : opt::none))
- {
- }
-
- inline std::vector<std::string> open_file::result()
- {
- return vector_result();
- }
-
- // save_file implementation
-
- inline save_file::save_file(std::string const& title,
- std::string const& default_path /* = "" */,
- std::vector<std::string> const& filters /* = { "All Files", "*" } */,
- opt options /* = opt::none */)
- : file_dialog(type::save, title, default_path, filters, options)
- {
- }
-
- inline save_file::save_file(std::string const& title,
- std::string const& default_path,
- std::vector<std::string> const& filters,
- bool confirm_overwrite)
- : save_file(title, default_path, filters, (confirm_overwrite ? opt::none : opt::force_overwrite))
- {
- }
-
- inline std::string save_file::result()
- {
- return string_result();
- }
-
- // select_folder implementation
-
- inline select_folder::select_folder(std::string const& title,
- std::string const& default_path /* = "" */,
- opt options /* = opt::none */)
- : file_dialog(type::folder, title, default_path, {}, options)
- {
- }
-
- inline std::string select_folder::result()
- {
- return string_result();
- }
-
-#endif // PFD_SKIP_IMPLEMENTATION
-
-} // namespace pfd \ No newline at end of file
+}
+
+inline button message::result() {
+ int exit_code;
+ auto ret = m_async->result(&exit_code);
+ // osascript will say "button returned:Cancel\n"
+ // and others will just say "Cancel\n"
+ if (internal::ends_with(ret, "Cancel\n")) return button::cancel;
+ if (internal::ends_with(ret, "OK\n")) return button::ok;
+ if (internal::ends_with(ret, "Yes\n")) return button::yes;
+ if (internal::ends_with(ret, "No\n")) return button::no;
+ if (internal::ends_with(ret, "Abort\n")) return button::abort;
+ if (internal::ends_with(ret, "Retry\n")) return button::retry;
+ if (internal::ends_with(ret, "Ignore\n")) return button::ignore;
+ if (m_mappings.count(exit_code) != 0) return m_mappings[exit_code];
+ return exit_code == 0 ? button::ok : button::cancel;
+}
+
+// open_file implementation
+
+inline open_file::open_file(std::string const& title, std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = { "All Files", "*" } */,
+ opt options /* = opt::none */)
+ : file_dialog(type::open, title, default_path, filters, options) {}
+
+inline open_file::open_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool allow_multiselect)
+ : open_file(title, default_path, filters, (allow_multiselect ? opt::multiselect : opt::none)) {}
+
+inline std::vector<std::string> open_file::result() {
+ return vector_result();
+}
+
+// save_file implementation
+
+inline save_file::save_file(std::string const& title, std::string const& default_path /* = "" */,
+ std::vector<std::string> const& filters /* = { "All Files", "*" } */,
+ opt options /* = opt::none */)
+ : file_dialog(type::save, title, default_path, filters, options) {}
+
+inline save_file::save_file(std::string const& title, std::string const& default_path,
+ std::vector<std::string> const& filters, bool confirm_overwrite)
+ : save_file(title, default_path, filters,
+ (confirm_overwrite ? opt::none : opt::force_overwrite)) {}
+
+inline std::string save_file::result() {
+ return string_result();
+}
+
+// select_folder implementation
+
+inline select_folder::select_folder(std::string const& title,
+ std::string const& default_path /* = "" */,
+ opt options /* = opt::none */)
+ : file_dialog(type::folder, title, default_path, {}, options) {}
+
+inline std::string select_folder::result() {
+ return string_result();
+}
+
+#endif // PFD_SKIP_IMPLEMENTATION
+
+} // namespace pfd \ No newline at end of file
diff --git a/public/tools/ld.dyn/src/CommandLine.cc b/public/tools/ld.dyn/src/CommandLine.cc
index 90a79796..377f22fa 100644
--- a/public/tools/ld.dyn/src/CommandLine.cc
+++ b/public/tools/ld.dyn/src/CommandLine.cc
@@ -8,40 +8,34 @@
/// @brief Library loader.
-#define DYNLIB_FLAG "-dyn"
-
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- SCI_UNUSED(argc);
- SCI_UNUSED(argv);
-
- PrintOut(nullptr, "%s", "ld.dyn: Dynamic Loader.\n");
- PrintOut(nullptr, "%s", "ld.dyn: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
-
- for (SInt32 i = 1U; i < argc; ++i)
- {
- if (MmStrCmp(argv[i], DYNLIB_FLAG) == 0)
- {
- UIntPtr ret = RtlSpawnProcess(argv[i], 0, nullptr, nullptr, 0);
-
- if (0 < ret)
- {
- return RtlSpawnIB(ret);
- }
-
- PrintOut(nullptr, "%s", "ld.dyn: Failed to load the library.\n");
- PrintOut(nullptr, "%s", "ld.dyn: Make sure the library is valid.\n");
-
- break;
- }
- else
- {
- PrintOut(nullptr, "%s", "ld.dyn: Invalid argument.\n");
- PrintOut(nullptr, "%s", "ld.dyn: Use -dyn <path> to load a dynamic library.\n");
-
- break;
- }
- }
-
- return EXIT_FAILURE;
+#define DYNLIB_FLAG "-dyn"
+
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ SCI_UNUSED(argc);
+ SCI_UNUSED(argv);
+
+ PrintOut(nullptr, "%s", "ld.dyn: Dynamic Loader.\n");
+ PrintOut(nullptr, "%s", "ld.dyn: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
+
+ for (SInt32 i = 1U; i < argc; ++i) {
+ if (MmStrCmp(argv[i], DYNLIB_FLAG) == 0) {
+ UIntPtr ret = RtlSpawnProcess(argv[i], 0, nullptr, nullptr, 0);
+
+ if (0 < ret) {
+ return RtlSpawnIB(ret);
+ }
+
+ PrintOut(nullptr, "%s", "ld.dyn: Failed to load the library.\n");
+ PrintOut(nullptr, "%s", "ld.dyn: Make sure the library is valid.\n");
+
+ break;
+ } else {
+ PrintOut(nullptr, "%s", "ld.dyn: Invalid argument.\n");
+ PrintOut(nullptr, "%s", "ld.dyn: Use -dyn <path> to load a dynamic library.\n");
+
+ break;
+ }
+ }
+
+ return EXIT_FAILURE;
}
diff --git a/public/tools/ld.fwrk/src/CommandLine.cc b/public/tools/ld.fwrk/src/CommandLine.cc
index cdb57133..0fbaaf2e 100644
--- a/public/tools/ld.fwrk/src/CommandLine.cc
+++ b/public/tools/ld.fwrk/src/CommandLine.cc
@@ -8,13 +8,12 @@
/// @brief This program loads a code framework into Kernel's memory.
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- SCI_UNUSED(argc);
- SCI_UNUSED(argv);
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ SCI_UNUSED(argc);
+ SCI_UNUSED(argv);
- PrintOut(nullptr, "%s", "ld.fwrk: Framework Loader.\n");
- PrintOut(nullptr, "%s", "ld.fwrk: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
+ PrintOut(nullptr, "%s", "ld.fwrk: Framework Loader.\n");
+ PrintOut(nullptr, "%s", "ld.fwrk: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
}
diff --git a/public/tools/mk.fwrk/Common.h b/public/tools/mk.fwrk/Common.h
index 09e374ee..be016be6 100644
--- a/public/tools/mk.fwrk/Common.h
+++ b/public/tools/mk.fwrk/Common.h
@@ -1,12 +1,12 @@
/**
- Sat Oct 26 07:03:28 AM CEST 2024
- (c) Amlal El Mahrouss.
+ Sat Oct 26 07:03:28 AM CEST 2024
+ (c) Amlal El Mahrouss.
*/
#ifndef APPS_COMMON_H
#define APPS_COMMON_H
-#include <user/SystemCalls.h>
#include <CoreFoundation.fwrk/headers/Foundation.h>
+#include <user/SystemCalls.h>
-#endif // APPS_COMMON_H
+#endif // APPS_COMMON_H
diff --git a/public/tools/mk.fwrk/Framework.h b/public/tools/mk.fwrk/Framework.h
index ab03d0bc..9beb6da4 100644
--- a/public/tools/mk.fwrk/Framework.h
+++ b/public/tools/mk.fwrk/Framework.h
@@ -1,6 +1,6 @@
/**
- Thu Oct 17 07:57:43 CEST 2024
- (c) Amlal El Mahrouss.
+ Thu Oct 17 07:57:43 CEST 2024
+ (c) Amlal El Mahrouss.
*/
#ifndef APPS_FRAMEWORK_H
@@ -11,7 +11,7 @@
#define kExecDirectory "bin/"
#define kRsrcDirectory "xml/"
#define kRootDirectory "/"
-#define kFKExtension ".fwrk"
-#define kAppExtension ".app"
+#define kFKExtension ".fwrk"
+#define kAppExtension ".app"
-#endif // !APPS_FRAMEWORK_H
+#endif // !APPS_FRAMEWORK_H
diff --git a/public/tools/mk.fwrk/Steps.h b/public/tools/mk.fwrk/Steps.h
index 51927def..3017b92e 100644
--- a/public/tools/mk.fwrk/Steps.h
+++ b/public/tools/mk.fwrk/Steps.h
@@ -1,6 +1,6 @@
/**
- Thu Oct 17 07:57:43 CEST 2024
- (c) Amlal El Mahrouss.
+ Thu Oct 17 07:57:43 CEST 2024
+ (c) Amlal El Mahrouss.
*/
#ifndef APPS_STEPS_H
@@ -10,23 +10,22 @@
#include <Framework.h>
#define kStepsExtension ".stp"
-#define kStepsStrLen (256U)
+#define kStepsStrLen (256U)
-#define kStepsMagic " pls"
+#define kStepsMagic " pls"
#define kStepsMagicLen (4U)
-#define kStepsVersion (0x0100)
+#define kStepsVersion (0x0100)
#define kStepsMime "ne-application-kind/steps"
-struct STEPS_COMMON_RECORD final
-{
- Char magic[kStepsMagicLen];
- Char name[kStepsStrLen];
- Char company[kStepsStrLen];
- Char author[kStepsStrLen];
- SInt32 version;
- SInt32 pages;
- SInt32 check_page, eula_page;
+struct STEPS_COMMON_RECORD final {
+ Char magic[kStepsMagicLen];
+ Char name[kStepsStrLen];
+ Char company[kStepsStrLen];
+ Char author[kStepsStrLen];
+ SInt32 version;
+ SInt32 pages;
+ SInt32 check_page, eula_page;
};
-#endif // ifndef APPS_STEPS_H \ No newline at end of file
+#endif // ifndef APPS_STEPS_H \ No newline at end of file
diff --git a/public/tools/mk.fwrk/src/CommandLine.cc b/public/tools/mk.fwrk/src/CommandLine.cc
index 8f142dfb..202f21bb 100644
--- a/public/tools/mk.fwrk/src/CommandLine.cc
+++ b/public/tools/mk.fwrk/src/CommandLine.cc
@@ -13,107 +13,97 @@
/// @brief This program makes a framework/app/steps directory for NeKernel OS.
-static const Char* kStepsName = "Steps";
+static const Char* kStepsName = "Steps";
static const Char* kStepsAuthor = "John Doe";
static const Char* kStepsCompany = "Company, Inc";
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- CF::CFArray<const char*, 256U> files;
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ CF::CFArray<const char*, 256U> files;
- auto ext = kFKExtension;
+ auto ext = kFKExtension;
- for (SInt32 i = 2UL; i < argc; ++i)
- {
- if (MmStrCmp(argv[i], "-h") == 0)
- {
- PrintOut(nullptr, "%s", "make_app: Framework/Application Creation Tool.\n");
- PrintOut(nullptr, "%s", "make_app: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
+ for (SInt32 i = 2UL; i < argc; ++i) {
+ if (MmStrCmp(argv[i], "-h") == 0) {
+ PrintOut(nullptr, "%s", "make_app: Framework/Application Creation Tool.\n");
+ PrintOut(nullptr, "%s", "make_app: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
- PrintOut(nullptr, "%s", "make_app: -a: Application Directory.\n");
- PrintOut(nullptr, "%s", "make_app: -s: Steps (Setup pages) Directory.\n");
- PrintOut(nullptr, "%s", "make_app: -f: Framework Directory.\n");
+ PrintOut(nullptr, "%s", "make_app: -a: Application Directory.\n");
+ PrintOut(nullptr, "%s", "make_app: -s: Steps (Setup pages) Directory.\n");
+ PrintOut(nullptr, "%s", "make_app: -f: Framework Directory.\n");
- return kErrorSuccess;
- }
+ return kErrorSuccess;
+ }
- if (MmStrCmp(argv[i], "--author") == 0)
- {
- MmCopyMemory(const_cast<Char*>(kStepsAuthor), const_cast<Char*>(argv[i + 1]), MmStrLen(argv[i + 1]));
- continue;
- }
+ if (MmStrCmp(argv[i], "--author") == 0) {
+ MmCopyMemory(const_cast<Char*>(kStepsAuthor), const_cast<Char*>(argv[i + 1]),
+ MmStrLen(argv[i + 1]));
+ continue;
+ }
- if (MmStrCmp(argv[i], "--company") == 0)
- {
- MmCopyMemory(const_cast<Char*>(kStepsCompany), const_cast<Char*>(argv[i + 1]), MmStrLen(argv[i + 1]));
- continue;
- }
+ if (MmStrCmp(argv[i], "--company") == 0) {
+ MmCopyMemory(const_cast<Char*>(kStepsCompany), const_cast<Char*>(argv[i + 1]),
+ MmStrLen(argv[i + 1]));
+ continue;
+ }
- if (MmStrCmp(argv[i], "--name") == 0)
- {
- MmCopyMemory(const_cast<Char*>(kStepsName), const_cast<Char*>(argv[i + 1]), MmStrLen(argv[i + 1]));
- continue;
- }
+ if (MmStrCmp(argv[i], "--name") == 0) {
+ MmCopyMemory(const_cast<Char*>(kStepsName), const_cast<Char*>(argv[i + 1]),
+ MmStrLen(argv[i + 1]));
+ continue;
+ }
- if (MmStrCmp(argv[i], "-a") == 0)
- {
- ext = kAppExtension;
- continue;
- }
- else if (MmStrCmp(argv[i], "-s") == 0)
- {
- ext = kStepsExtension;
- continue;
- }
- else if (MmStrCmp(argv[i], "-f") == 0)
- {
- ext = kFKExtension;
- continue;
- }
+ if (MmStrCmp(argv[i], "-a") == 0) {
+ ext = kAppExtension;
+ continue;
+ } else if (MmStrCmp(argv[i], "-s") == 0) {
+ ext = kStepsExtension;
+ continue;
+ } else if (MmStrCmp(argv[i], "-f") == 0) {
+ ext = kFKExtension;
+ continue;
+ }
- files[i] = argv[i];
- }
+ files[i] = argv[i];
+ }
- auto path = argv[1];
+ auto path = argv[1];
- if (FsCreateDir(path))
- {
- FsCreateDir(StrFmt("{}{}", path, kRootDirectory));
- FsCreateDir(StrFmt("{}{}", path, kExecDirectory));
+ if (FsCreateDir(path)) {
+ FsCreateDir(StrFmt("{}{}", path, kRootDirectory));
+ FsCreateDir(StrFmt("{}{}", path, kExecDirectory));
- if (MmStrCmp(ext, kStepsExtension) == 0)
- {
- FsCreateFile(StrFmt("{}{}{}{}", path, kRootDirectory, "_setup"));
+ if (MmStrCmp(ext, kStepsExtension) == 0) {
+ FsCreateFile(StrFmt("{}{}{}{}", path, kRootDirectory, "_setup"));
- auto handle = IoOpenFile(StrFmt("{}{}{}{}", path, kRootDirectory, "_setup", kStepsExtension), nullptr);
+ auto handle =
+ IoOpenFile(StrFmt("{}{}{}{}", path, kRootDirectory, "_setup", kStepsExtension), nullptr);
- struct STEPS_COMMON_RECORD record;
+ struct STEPS_COMMON_RECORD record;
- MmFillMemory(&record, sizeof(STEPS_COMMON_RECORD), 0);
+ MmFillMemory(&record, sizeof(STEPS_COMMON_RECORD), 0);
- MmCopyMemory(record.name, const_cast<Char*>(kStepsName), kStepsStrLen);
- MmCopyMemory(record.author, const_cast<Char*>(kStepsAuthor), kStepsStrLen);
- MmCopyMemory(record.company, const_cast<Char*>(kStepsCompany), kStepsStrLen);
+ MmCopyMemory(record.name, const_cast<Char*>(kStepsName), kStepsStrLen);
+ MmCopyMemory(record.author, const_cast<Char*>(kStepsAuthor), kStepsStrLen);
+ MmCopyMemory(record.company, const_cast<Char*>(kStepsCompany), kStepsStrLen);
- MmCopyMemory(record.magic, const_cast<Char*>(kStepsMagic), kStepsMagicLen);
+ MmCopyMemory(record.magic, const_cast<Char*>(kStepsMagic), kStepsMagicLen);
- record.version = kStepsVersion;
+ record.version = kStepsVersion;
- IoWriteFile(handle, (void*)&record, sizeof(STEPS_COMMON_RECORD));
- IoCloseFile(handle);
+ IoWriteFile(handle, (void*) &record, sizeof(STEPS_COMMON_RECORD));
+ IoCloseFile(handle);
- handle = nullptr;
- }
+ handle = nullptr;
+ }
- for (auto i = 0UL; i < files.Count(); ++i)
- {
- auto& file = files[i];
+ for (auto i = 0UL; i < files.Count(); ++i) {
+ auto& file = files[i];
- FsCopy(path, StrFmt("{}{}", path, file));
- }
+ FsCopy(path, StrFmt("{}{}", path, file));
+ }
- return kErrorSuccess;
- }
+ return kErrorSuccess;
+ }
- return kErrorInternal;
+ return kErrorInternal;
}
diff --git a/public/tools/mk.hefs/src/CommandLine.cc b/public/tools/mk.hefs/src/CommandLine.cc
index 0c30e1b1..dd8be97f 100644
--- a/public/tools/mk.hefs/src/CommandLine.cc
+++ b/public/tools/mk.hefs/src/CommandLine.cc
@@ -8,10 +8,9 @@
/// @brief Placeholder program.
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- SCI_UNUSED(argc);
- SCI_UNUSED(argv);
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ SCI_UNUSED(argc);
+ SCI_UNUSED(argv);
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
}
diff --git a/public/tools/mk.nefs/src/CommandLine.cc b/public/tools/mk.nefs/src/CommandLine.cc
index 0c30e1b1..dd8be97f 100644
--- a/public/tools/mk.nefs/src/CommandLine.cc
+++ b/public/tools/mk.nefs/src/CommandLine.cc
@@ -8,10 +8,9 @@
/// @brief Placeholder program.
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- SCI_UNUSED(argc);
- SCI_UNUSED(argv);
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ SCI_UNUSED(argc);
+ SCI_UNUSED(argv);
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
}
diff --git a/public/tools/open/src/CommandLine.cc b/public/tools/open/src/CommandLine.cc
index b3779c71..f2378599 100644
--- a/public/tools/open/src/CommandLine.cc
+++ b/public/tools/open/src/CommandLine.cc
@@ -9,41 +9,39 @@
/// @brief This program opens an application from **OPEN_APP_BASE_PATH**
/// @file CommandLine.cc
-#define OPEN_APP_APP_FLAG "-a"
+#define OPEN_APP_APP_FLAG "-a"
#define OPEN_APP_HELP_FLAG "-h"
#define OPEN_APP_BASE_PATH "/app/"
-SInt32 _NeMain(SInt32 argc, Char* argv[])
-{
- if (argc == 1)
- return EXIT_FAILURE;
+SInt32 _NeMain(SInt32 argc, Char* argv[]) {
+ if (argc == 1) return EXIT_FAILURE;
- PrintOut(nullptr, "open: Open Loader.\n");
- PrintOut(nullptr, "open: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
+ PrintOut(nullptr, "open: Open Loader.\n");
+ PrintOut(nullptr, "open: © 2024-2025 Amlal El Mahrouss, All rights reserved.\n");
- for (SInt32 i = 1U; i < argc; ++i)
- {
- if (MmStrCmp(argv[i], OPEN_APP_HELP_FLAG) == 0)
- {
- PrintOut(nullptr, "open: %s: Application is being taken as the input (opens a PEF/PE32+ program depending on the CPU architecture).\n", OPEN_APP_APP_FLAG);
+ for (SInt32 i = 1U; i < argc; ++i) {
+ if (MmStrCmp(argv[i], OPEN_APP_HELP_FLAG) == 0) {
+ PrintOut(nullptr,
+ "open: %s: Application is being taken as the input (opens a PEF/PE32+ program "
+ "depending on the CPU architecture).\n",
+ OPEN_APP_APP_FLAG);
- return EXIT_SUCCESS;
- }
- else if (MmStrCmp(argv[i], OPEN_APP_APP_FLAG) == 0)
- {
- if ((i + 1) == argc)
- return EXIT_FAILURE;
- else if ((i + 2) == argc)
- return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ } else if (MmStrCmp(argv[i], OPEN_APP_APP_FLAG) == 0) {
+ if ((i + 1) == argc)
+ return EXIT_FAILURE;
+ else if ((i + 2) == argc)
+ return EXIT_FAILURE;
- Char base_path[FILE_MAX_LEN] = OPEN_APP_BASE_PATH;
- MmCopyMemory(base_path + MmStrLen(OPEN_APP_BASE_PATH), argv[i + 1], MmStrLen(argv[i + 1]));
+ Char base_path[FILE_MAX_LEN] = OPEN_APP_BASE_PATH;
+ MmCopyMemory(base_path + MmStrLen(OPEN_APP_BASE_PATH), argv[i + 1], MmStrLen(argv[i + 1]));
- UIntPtr ret = RtlSpawnProcess(StrFmt("{}/dist/{]}", base_path, argv[i + 2]), 0, nullptr, nullptr, 0);
+ UIntPtr ret =
+ RtlSpawnProcess(StrFmt("{}/dist/{]}", base_path, argv[i + 2]), 0, nullptr, nullptr, 0);
- return ret;
- }
- }
+ return ret;
+ }
+ }
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
}