aboutsummaryrefslogtreecommitdiff
path: root/core/sys/windows/comdlg32.odin
blob: a9800b47a26f65ad9808460e91e4c798a579b660 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#+build windows
package sys_windows

foreign import "system:Comdlg32.lib"

LPOFNHOOKPROC :: #type proc "system" (hdlg: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> UINT_PTR

OPENFILENAMEW :: struct {
	lStructSize: 	        DWORD,
	hwndOwner: 	        HWND,
	hInstance: 	        HINSTANCE,
	lpstrFilter: 	        wstring,
	lpstrCustomFilter: 	wstring,
	nMaxCustFilter: 	DWORD,
	nFilterIndex: 	        DWORD,
	lpstrFile: 	        wstring,
	nMaxFile: 	        DWORD,
	lpstrFileTitle: 	wstring,
	nMaxFileTitle: 	        DWORD,
	lpstrInitialDir: 	wstring,
	lpstrTitle: 	        wstring,
	Flags: 	                DWORD,
	nFileOffset: 	        WORD,
	nFileExtension: 	WORD,
	lpstrDefExt: 	        wstring,
	lCustData: 	        LPARAM,
	lpfnHook: 	        LPOFNHOOKPROC,
	lpTemplateName: 	wstring,
	pvReserved:             rawptr,
	dwReserved:             DWORD,
	FlagsEx:                DWORD,
}

@(default_calling_convention="system")
foreign Comdlg32 {
	GetOpenFileNameW     :: proc(arg1: ^OPENFILENAMEW) -> BOOL ---
	GetSaveFileNameW     :: proc(arg1: ^OPENFILENAMEW) -> BOOL ---
	CommDlgExtendedError :: proc() -> u32 ---
}

OPEN_TITLE :: "Select file to open"
OPEN_FLAGS :: u32(OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST)
OPEN_FLAGS_MULTI :: OPEN_FLAGS | OFN_ALLOWMULTISELECT | OFN_EXPLORER

SAVE_TITLE :: "Select file to save"
SAVE_FLAGS :: u32(OFN_OVERWRITEPROMPT | OFN_EXPLORER)
SAVE_EXT   :: "txt"

/*
import "core:strings"

Open_Save_Mode :: enum {
	Open = 0,
	Save = 1,
}

_open_file_dialog :: proc(title: string, dir: string,
                          filters: []string, default_filter: u32,
                          flags: u32, default_ext: string,
                          mode: Open_Save_Mode, allocator := context.temp_allocator) -> (path: string, ok: bool = true) {
	context.allocator = allocator
	file_buf := make([]u16, MAX_PATH_WIDE)
	defer if !ok {
		delete(file_buf)
	}

	// Filters need to be passed as a pair of strings (title, filter)
	filter_len := u32(len(filters))
	if filter_len % 2 != 0 {
		return "", false
	}

	filter: string
	filter = strings.join(filters, "\u0000", context.temp_allocator)
	filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator)

	ofn := OPENFILENAMEW{
		lStructSize     = size_of(OPENFILENAMEW),
		lpstrFile       = wstring(&file_buf[0]),
		nMaxFile        = MAX_PATH_WIDE,
		lpstrTitle      = utf8_to_wstring(title, context.temp_allocator),
		lpstrFilter     = utf8_to_wstring(filter, context.temp_allocator),
		lpstrInitialDir = utf8_to_wstring(dir, context.temp_allocator),
		nFilterIndex    = u32(clamp(default_filter, 1, filter_len / 2)),
		lpstrDefExt     = utf8_to_wstring(default_ext, context.temp_allocator),
		Flags           = u32(flags),
	}

	switch mode {
	case .Open:
		ok = bool(GetOpenFileNameW(&ofn))
	case .Save:
		ok = bool(GetSaveFileNameW(&ofn))
	case:
		ok = false
	}

	if !ok {
		return
	}


	file_name, _ := utf16_to_utf8(file_buf[:], allocator)
	path = strings.trim_right_null(file_name)
	return
}

select_file_to_open :: proc(title := OPEN_TITLE, dir := ".",
                            filters := []string{"All Files", "*.*"}, default_filter := u32(1),
                            flags := OPEN_FLAGS, allocator := context.temp_allocator) -> (path: string, ok: bool) {

	path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", Open_Save_Mode.Open, allocator)
	return
}

select_file_to_save :: proc(title := SAVE_TITLE, dir := ".",
                            filters := []string{"All Files", "*.*"}, default_filter := u32(1),
                            flags := SAVE_FLAGS, default_ext := SAVE_EXT,
                            allocator := context.temp_allocator) -> (path: string, ok: bool) {

	path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, Open_Save_Mode.Save, allocator)
	return
}
*/

// TODO: Implement convenience function for select_file_to_open with ALLOW_MULTI_SELECT that takes
//       it output of the form "path\u0000\file1u\0000file2" and turns it into []string with the path + file pre-concatenated for you.

OFN_ALLOWMULTISELECT     :: 0x00000200 // NOTE(Jeroen): Without OFN_EXPLORER it uses the Win3 dialog.
OFN_CREATEPROMPT         :: 0x00002000
OFN_DONTADDTORECENT      :: 0x02000000
OFN_ENABLEHOOK           :: 0x00000020
OFN_ENABLEINCLUDENOTIFY  :: 0x00400000
OFN_ENABLESIZING         :: 0x00800000
OFN_ENABLETEMPLATE       :: 0x00000040
OFN_ENABLETEMPLATEHANDLE :: 0x00000080
OFN_EXPLORER             :: 0x00080000
OFN_EXTENSIONDIFFERENT   :: 0x00000400
OFN_FILEMUSTEXIST        :: 0x00001000
OFN_FORCESHOWHIDDEN      :: 0x10000000
OFN_HIDEREADONLY         :: 0x00000004
OFN_LONGNAMES            :: 0x00200000
OFN_NOCHANGEDIR          :: 0x00000008
OFN_NODEREFERENCELINKS   :: 0x00100000
OFN_NOLONGNAMES          :: 0x00040000
OFN_NONETWORKBUTTON      :: 0x00020000
OFN_NOREADONLYRETURN     :: 0x00008000
OFN_NOTESTFILECREATE     :: 0x00010000
OFN_NOVALIDATE           :: 0x00000100
OFN_OVERWRITEPROMPT      :: 0x00000002
OFN_PATHMUSTEXIST        :: 0x00000800
OFN_READONLY             :: 0x00000001
OFN_SHAREAWARE           :: 0x00004000
OFN_SHOWHELP             :: 0x00000010

CDERR_DIALOGFAILURE      :: 0x0000FFFF
CDERR_GENERALCODES       :: 0x00000000
CDERR_STRUCTSIZE         :: 0x00000001
CDERR_INITIALIZATION     :: 0x00000002
CDERR_NOTEMPLATE         :: 0x00000003
CDERR_NOHINSTANCE        :: 0x00000004
CDERR_LOADSTRFAILURE     :: 0x00000005
CDERR_FINDRESFAILURE     :: 0x00000006
CDERR_LOADRESFAILURE     :: 0x00000007
CDERR_LOCKRESFAILURE     :: 0x00000008
CDERR_MEMALLOCFAILURE    :: 0x00000009
CDERR_MEMLOCKFAILURE     :: 0x0000000A
CDERR_NOHOOK             :: 0x0000000B
CDERR_REGISTERMSGFAIL    :: 0x0000000C