Mercurial > msvpvf
comparison src/gui.c @ 81:c06dcab17923 v2.1
*: change license to BSD, update README for Unicode
src/gui: use tchar.h for unicode instead of our own macros
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Fri, 22 Mar 2024 22:04:16 -0400 |
| parents | 8f90d5addda9 |
| children | af4ed765c1ac |
comparison
equal
deleted
inserted
replaced
| 80:719570851563 | 81:c06dcab17923 |
|---|---|
| 1 /** | 1 /* mingw hack */ |
| 2 * msvpvf GUI for Windows | |
| 3 * Copyright (c) Paper 2022-2024 | |
| 4 * | |
| 5 * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 6 * of this software and associated documentation files (the "Software"), to deal | |
| 7 * in the Software without restriction, including without limitation the rights | |
| 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 9 * copies of the Software, and to permit persons to whom the Software is | |
| 10 * furnished to do so, subject to the following conditions: | |
| 11 * | |
| 12 * The above copyright notice and this permission notice shall be included in all | |
| 13 * copies or substantial portions of the Software. | |
| 14 * | |
| 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 21 * SOFTWARE. | |
| 22 **/ | |
| 23 | |
| 24 /* change these macros to configure the window size */ | |
| 25 #define WINDOW_WIDTH 225 | |
| 26 #define WINDOW_HEIGHT 200 | |
| 27 | |
| 28 /* mingw */ | |
| 29 #ifdef UNICODE | 2 #ifdef UNICODE |
| 30 #define NTDDI_VERSION 0x06000000 | 3 #define NTDDI_VERSION 0x06000000 |
| 31 #define _WIN32_WINNT 0x0600 | 4 #define _WIN32_WINNT 0x0600 |
| 32 #else | 5 #else |
| 33 #define _WIN32_WINNT 0x0400 | 6 #define _WIN32_WINNT 0x0400 |
| 34 #endif | 7 #endif |
| 35 | 8 |
| 36 #include <windef.h> | 9 #include <windef.h> |
| 37 #include <winbase.h> | 10 #include <winbase.h> |
| 38 #include <shlwapi.h> | 11 #include <shlwapi.h> |
| 39 #include <shobjidl.h> | |
| 40 | 12 |
| 41 #include <stdint.h> | 13 #include <stdint.h> |
| 42 #include <stdio.h> | 14 #include <stdio.h> |
| 43 | 15 |
| 16 #include <tchar.h> /* tchar versions of string.h functions */ | |
| 17 | |
| 44 #include "common.h" | 18 #include "common.h" |
| 45 | 19 |
| 46 /* we use COM when `UNICODE=1` to avoid file paths being cut off */ | 20 /* make sure this is defined... */ |
| 47 #define COM_INITFLAGS (COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE) | 21 #ifndef _MAX_ULTOSTR_BASE10_COUNT |
| 48 | 22 #define _MAX_ULTOSTR_BASE10_COUNT (10 + 1) |
| 49 #define OPEN_FILE_BUTTON 0 | 23 #endif |
| 50 #define COMBOBOX 1 | 24 |
| 51 #define LISTBOX 2 | 25 /* put all of our types in an array */ |
| 52 #define SAVE_FILE_BUTTON 3 | 26 static const enum types types[] = { TYPES_VF, TYPES_VEG }; |
| 53 #define VERSION 4 | 27 |
| 54 | 28 /* HWND ids */ |
| 55 /* adjust for these functions for Unicode */ | 29 enum { |
| 56 #if UNICODE | 30 OPEN_FILE_BUTTON = 0, |
| 57 #define _tstrncpy wcsncpy | 31 COMBOBOX, |
| 58 #define _tstrdup _wcsdup | 32 LISTBOX, |
| 59 #define _tfopen _wfopen | 33 SAVE_FILE_BUTTON, |
| 60 #define _sntprintf _snwprintf | 34 VERSION |
| 61 #else | 35 }; |
| 62 #define _tstrncpy strncpy | 36 |
| 63 #define _tstrdup _strdup | 37 #if UNICODE |
| 64 #define _tfopen fopen | 38 /* use COM when `UNICODE=1` to avoid file paths being cut off */ |
| 65 #define _sntprintf _snprintf | 39 #include <shobjidl.h> |
| 66 #endif | 40 |
| 67 | 41 static const DWORD COM_INITFLAGS = (COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); |
| 68 /* enumerate over this */ | 42 #endif |
| 69 static const enum types types[] = {TYPES_VF, TYPES_VEG}; | 43 |
| 44 /* user-adjustable. set these values to whatever you want, the GUI will scale */ | |
| 45 #define WINDOW_WIDTH 225U | |
| 46 #define WINDOW_HEIGHT 200U | |
| 70 | 47 |
| 71 static LPTSTR file_path = NULL; | 48 static LPTSTR file_path = NULL; |
| 72 static uint8_t version = 13; | 49 |
| 50 /* these values are loaded by AddControls() if they're valid */ | |
| 51 static uint8_t version = 11; | |
| 73 static enum types type = TYPES_VEG; | 52 static enum types type = TYPES_VEG; |
| 74 | 53 |
| 75 /* we edit this from display_file() */ | 54 /* we edit this from display_file() */ |
| 76 static HWND hwnd_version = NULL; | 55 static HWND hwnd_version = NULL; |
| 77 | 56 |
| 241 free(output_template); | 220 free(output_template); |
| 242 } else { | 221 } else { |
| 243 #endif | 222 #endif |
| 244 /* fallback to OPENFILENAME if COM fucks up for whatever reason (or we're on ANSI)... */ | 223 /* fallback to OPENFILENAME if COM fucks up for whatever reason (or we're on ANSI)... */ |
| 245 output = calloc(MAX_PATH + 1, sizeof(TCHAR)); | 224 output = calloc(MAX_PATH + 1, sizeof(TCHAR)); |
| 246 _tstrncpy(output, output_template, MAX_PATH); | 225 _tcsncpy(output, output_template, MAX_PATH); |
| 247 free(output_template); | 226 free(output_template); |
| 248 | 227 |
| 249 OPENFILENAME ofn = {0}; | 228 OPENFILENAME ofn = {0}; |
| 250 | 229 |
| 251 ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; | 230 ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; |
| 296 HWND combobox = CreateWindow(TEXT("ComboBox"), NULL, | 275 HWND combobox = CreateWindow(TEXT("ComboBox"), NULL, |
| 297 CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_VSCROLL, | 276 CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_VSCROLL, |
| 298 WINDOW_WIDTH * 7 / 18, WINDOW_HEIGHT * 3 / 20, WINDOW_WIDTH * 2 / 9, WINDOW_HEIGHT, | 277 WINDOW_WIDTH * 7 / 18, WINDOW_HEIGHT * 3 / 20, WINDOW_WIDTH * 2 / 9, WINDOW_HEIGHT, |
| 299 hWnd, (HMENU)COMBOBOX, NULL, NULL); | 278 hWnd, (HMENU)COMBOBOX, NULL, NULL); |
| 300 | 279 |
| 301 static LPCTSTR versions[] = {TEXT("8"), TEXT("9"), TEXT("10"), | 280 for (size_t v = 8; v <= 21; v++) { |
| 302 TEXT("11"), TEXT("12"), TEXT("13"), | 281 TCHAR v_str[_MAX_ULTOSTR_BASE10_COUNT] = {'\0'}; |
| 303 TEXT("14"), TEXT("15"), TEXT("16"), | 282 |
| 304 TEXT("17"), TEXT("18"), TEXT("19"), | 283 _ultot(v, v_str, 10); |
| 305 TEXT("20"), TEXT("21")}; /* wuss 9+10 */ | 284 |
| 306 | 285 LRESULT pos = SendMessage(combobox, CB_ADDSTRING, 0, (LPARAM)v_str); |
| 307 for (size_t i = 0; i < ARRAYSIZE(versions); i++) | 286 SendMessage(combobox, CB_SETITEMDATA, pos, v); |
| 308 SendMessage(combobox, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)versions[i]); | 287 if (v == version) |
| 309 | 288 SendMessage(combobox, CB_SETCURSEL, pos, 0); |
| 310 SendMessage(combobox, CB_SETCURSEL, (WPARAM)3, (LPARAM)0); | 289 } |
| 311 | 290 |
| 312 /* Type */ | 291 /* Type */ |
| 313 HWND listbox = CreateWindow(TEXT("Listbox"), NULL, WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, WINDOW_WIDTH * 5 / 18, WINDOW_HEIGHT * 11 / 40, WINDOW_WIDTH * 4 / 9, WINDOW_HEIGHT / 5, hWnd, (HMENU)LISTBOX, NULL, NULL); | 292 HWND listbox = CreateWindow(TEXT("Listbox"), NULL, WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY, WINDOW_WIDTH * 5 / 18, WINDOW_HEIGHT * 11 / 40, WINDOW_WIDTH * 4 / 9, WINDOW_HEIGHT / 5, hWnd, (HMENU)LISTBOX, NULL, NULL); |
| 314 | 293 |
| 315 for (size_t i = 0; i < ARRAYSIZE(types); i++) { | 294 for (size_t i = 0; i < ARRAYSIZE(types); i++) { |
| 316 LRESULT pos = SendMessage(listbox, LB_ADDSTRING, i, (LPARAM)type_to_string(types[i])); | 295 LRESULT pos = SendMessage(listbox, LB_ADDSTRING, i, (LPARAM)type_to_string(types[i])); |
| 317 SendMessage(listbox, LB_SETITEMDATA, pos, (LPARAM)types[i]); | 296 SendMessage(listbox, LB_SETITEMDATA, pos, types[i]); |
| 318 if (types[i] == type) | 297 if (types[i] == type) |
| 319 SendMessage(listbox, LB_SETCURSEL, (WPARAM)pos, (LPARAM)0); | 298 SendMessage(listbox, LB_SETCURSEL, pos, 0); |
| 320 } | 299 } |
| 321 | 300 |
| 322 /* Save File */ | 301 /* Save File */ |
| 323 HWND save_button = CreateWindow(TEXT("Button"), TEXT("Save"), WS_VISIBLE | WS_CHILD, WINDOW_WIDTH * 7 / 18, WINDOW_HEIGHT * 9 / 20, WINDOW_WIDTH * 2 / 9, WINDOW_HEIGHT / 10, hWnd, (HMENU)SAVE_FILE_BUTTON, NULL, NULL); | 302 HWND save_button = CreateWindow(TEXT("Button"), TEXT("Save"), WS_VISIBLE | WS_CHILD, WINDOW_WIDTH * 7 / 18, WINDOW_HEIGHT * 9 / 20, WINDOW_WIDTH * 2 / 9, WINDOW_HEIGHT / 10, hWnd, (HMENU)SAVE_FILE_BUTTON, NULL, NULL); |
| 324 | 303 |
| 325 /* Version and Type display */ | 304 /* Version and Type display */ |
| 326 hwnd_version = CreateWindow(TEXT("Edit"), TEXT(""), WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_CENTER | ES_MULTILINE | SS_CENTER, WINDOW_WIDTH / 6, WINDOW_HEIGHT * 3 / 5, WINDOW_WIDTH * 2 / 3, WINDOW_HEIGHT / 5, hWnd, (HMENU)VERSION, NULL, NULL); | 305 hwnd_version = CreateWindow(TEXT("Edit"), TEXT("No file opened!"), WS_VISIBLE | WS_CHILD | WS_BORDER | ES_READONLY | ES_CENTER | ES_MULTILINE | SS_CENTER, WINDOW_WIDTH / 6, WINDOW_HEIGHT * 3 / 5, WINDOW_WIDTH * 2 / 3, WINDOW_HEIGHT / 5, hWnd, (HMENU)VERSION, NULL, NULL); |
| 327 if (!open_button || !save_button || !listbox || !combobox || !hwnd_version) | 306 if (!open_button || !save_button || !listbox || !combobox || !hwnd_version) |
| 328 MessageBox(hWnd, TEXT("how did you even trigger this"), TEXT("GUI could not be initialized!"), MB_ICONEXCLAMATION); | 307 MessageBox(hWnd, TEXT("how did you even trigger this"), TEXT("GUI could not be initialized!"), MB_ICONEXCLAMATION); |
| 329 } | 308 } |
| 330 | 309 |
| 331 int CALLBACK SetFont(HWND child, LPARAM font) { | 310 /* Make the fonts not as ugly */ |
| 311 BOOL CALLBACK SetFont(HWND child, LPARAM font) { | |
| 332 SendMessage(child, WM_SETFONT, font, 1); | 312 SendMessage(child, WM_SETFONT, font, 1); |
| 333 return 1; | 313 return 1; |
| 334 } | 314 } |
| 335 | 315 |
| 336 LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { | 316 LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { |
| 337 switch(msg) { | 317 switch(msg) { |
| 338 case WM_COMMAND: | 318 case WM_COMMAND: |
| 339 if (HIWORD(wParam) == CBN_SELCHANGE) { | 319 if (HIWORD(wParam) == CBN_SELCHANGE) { |
| 340 switch (LOWORD(wParam)) { | 320 switch (LOWORD(wParam)) { |
| 341 case COMBOBOX: | 321 case COMBOBOX: { |
| 342 version = (uint8_t)(8+SendMessage((HWND)lParam, (UINT)CB_GETCURSEL, (WPARAM)0, (LPARAM)0)); | 322 LRESULT i = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); |
| 323 version = (uint8_t)SendMessage((HWND)lParam, CB_GETITEMDATA, i, 0); | |
| 343 break; | 324 break; |
| 325 } | |
| 344 case LISTBOX: { | 326 case LISTBOX: { |
| 345 LRESULT i = SendMessage((HWND)lParam, (UINT)LB_GETCURSEL, (WPARAM)0, (LPARAM)0); | 327 LRESULT i = SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0); |
| 346 type = (enum types)SendMessage((HWND)lParam, (UINT)LB_GETITEMDATA, (WPARAM)i, (LPARAM)0); | 328 type = (enum types)SendMessage((HWND)lParam, LB_GETITEMDATA, i, 0); |
| 347 break; | 329 break; |
| 348 } | 330 } |
| 349 default: | 331 default: |
| 350 break; | 332 break; |
| 351 } | 333 } |
| 364 break; | 346 break; |
| 365 } | 347 } |
| 366 break; | 348 break; |
| 367 case WM_CREATE: | 349 case WM_CREATE: |
| 368 AddControls(hWnd); | 350 AddControls(hWnd); |
| 369 EnumChildWindows(hWnd, (WNDENUMPROC)SetFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT)); | 351 EnumChildWindows(hWnd, SetFont, (LPARAM)GetStockObject(DEFAULT_GUI_FONT)); |
| 370 break; | 352 break; |
| 371 case WM_DESTROY: | 353 case WM_DESTROY: |
| 372 PostQuitMessage(0); | 354 PostQuitMessage(0); |
| 373 break; | 355 break; |
| 374 case WM_DROPFILES: { | 356 case WM_DROPFILES: { |
